Przeglądaj źródła

fix(MAPatternStrategy): 更新策略品种选择和持仓检查逻辑

- 增加未完成订单的撤销逻辑,确保交易状态的准确性
- 新增同步函数以清理过期的交易记录,保持g.trade_history与实际持仓一致
maxfeng 1 miesiąc temu
rodzic
commit
3955341360
1 zmienionych plików z 53 dodań i 4 usunięć
  1. 53 4
      Lib/future/MAPatternStrategy_v002.py

+ 53 - 4
Lib/future/MAPatternStrategy_v002.py

@@ -206,7 +206,7 @@ def initialize(context):
     
     # 策略品种选择策略配置
     # 方案1:全品种策略 - 考虑所有配置的期货品种
-    g.strategy_focus_symbols = ['AO']  # 空列表表示考虑所有品种
+    g.strategy_focus_symbols = ['P']  # 空列表表示考虑所有品种
     
     # 方案2:精选品种策略 - 只交易流动性较好的特定品种(如需使用请取消下行注释)
     # g.strategy_focus_symbols = ['RM', 'CJ', 'CY', 'JD', 'L', 'LC', 'SF', 'SI']
@@ -369,7 +369,7 @@ def check_ma_trend_and_open_gap(context):
                     del g.excluded_contracts[dominant_future]
             
             # 步骤3.4:检查是否已有持仓
-            if check_symbol_prefix_match(dominant_future, set(g.trade_history.keys())):
+            if check_symbol_prefix_match(dominant_future, context, set(g.trade_history.keys())):
                 log.info(f"{symbol} 已有持仓,跳过")
                 continue
             
@@ -556,6 +556,16 @@ def check_open_and_stop(context):
         if blocked_trading_day == current_trading_day_normalized:
             log.info(f"当晚操作已被禁止(订单状态为'new',无夜盘),跳过所有操作")
             return
+
+    # 得到当前未完成订单
+    orders = get_open_orders()
+    # 循环,撤销订单
+    if len(orders) == 0:
+        log.debug(f"无未完成订单")
+    else:
+        for _order in orders.values():
+            log.debug(f"order: {_order}")
+            cancel_order(_order)
     
     # 第一步:检查开仓条件
     log.info(f"检查开仓条件:")
@@ -575,7 +585,7 @@ def check_open_and_stop(context):
                 yesterday_open = candidate_info.get('yesterday_open')
                 
                 # 检查是否已有持仓
-                if check_symbol_prefix_match(dominant_future, set(g.trade_history.keys())):
+                if check_symbol_prefix_match(dominant_future, context, set(g.trade_history.keys())):
                     log.info(f"{symbol} 已有持仓,从候选列表移除")
                     candidates_to_remove.append(dominant_future)
                     continue
@@ -1251,6 +1261,9 @@ def close_position(context, security, direction):
             # 从交易历史中移除
             if security in g.trade_history:
                 del g.trade_history[security]
+                log.debug(f"从交易历史中移除: {security}")
+        else:
+            log.info(f"平仓失败: {security} {direction} {order.filled}手")
             return True
             
     except Exception as e:
@@ -1356,9 +1369,14 @@ def calculate_target_hands(context, security, direction):
         
         return actual_hands, single_hand_margin
 
-def check_symbol_prefix_match(symbol, hold_symbols):
+def check_symbol_prefix_match(symbol, context, hold_symbols):
     """检查是否有相似的持仓品种"""
+    log.debug(f"检查持仓")
     symbol_prefix = symbol[:-9]
+
+    long_positions = context.subportfolios[0].long_positions
+    short_positions = context.subportfolios[0].short_positions
+    log.debug(f"long_positions: {long_positions}, short_positions: {short_positions}")
     
     for hold_symbol in hold_symbols:
         hold_symbol_prefix = hold_symbol[:-9] if len(hold_symbol) > 9 else hold_symbol
@@ -1381,10 +1399,41 @@ def calculate_realtime_ma_values(security, ma_periods):
     ma_values = {f'ma{period}': sum(close_prices[-period:]) / period for period in ma_periods}
     return ma_values
 
+def sync_trade_history_with_positions(context):
+    """同步g.trade_history与实际持仓,清理已平仓但记录未删除的持仓"""
+    if not g.trade_history:
+        return
+    
+    subportfolio = context.subportfolios[0]
+    actual_positions = set(subportfolio.long_positions.keys()) | set(subportfolio.short_positions.keys())
+    
+    # 找出g.trade_history中有记录但实际已平仓的合约
+    stale_records = []
+    for security in g.trade_history.keys():
+        if security not in actual_positions:
+            stale_records.append(security)
+    
+    # 清理这些过期记录
+    if stale_records:
+        log.info("=" * 60)
+        log.info("发现持仓记录与实际持仓不同步,进行清理:")
+        for security in stale_records:
+            trade_info = g.trade_history[security]
+            underlying_symbol = security.split('.')[0][:-4]
+            log.info(f"  清理过期记录: {underlying_symbol}({security}) {trade_info['direction']}, "
+                    f"成本价: {trade_info['entry_price']:.2f}, "
+                    f"入场时间: {trade_info['entry_time']}")
+            del g.trade_history[security]
+        log.info(f"共清理 {len(stale_records)} 条过期持仓记录")
+        log.info("=" * 60)
+
 def after_market_close(context):
     """收盘后运行函数"""
     log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
     
+    # 同步检查:清理g.trade_history中已平仓但记录未删除的持仓
+    sync_trade_history_with_positions(context)
+    
     # 清空候选列表(每天重新检查)
     g.daily_ma_candidates = {}