|
|
@@ -61,6 +61,7 @@ def initialize(context):
|
|
|
g.ma_distribution_min_ratio = 0.4 # MA5分布满足比例阈值
|
|
|
g.enable_ma_distribution_filter = True # 是否启用MA5分布过滤
|
|
|
g.ma_cross_threshold = 1 # 均线穿越数量阈值
|
|
|
+ g.enable_open_gap_filter = True # 是否启用开盘价差过滤
|
|
|
|
|
|
# 均线价差策略方案选择
|
|
|
g.ma_gap_strategy_mode = 3 # 策略模式选择(1: 原方案, 2: 新方案, 3: 方案3)
|
|
|
@@ -89,6 +90,7 @@ def initialize(context):
|
|
|
log.info(f" 启用MA5分布过滤: {g.enable_ma_distribution_filter}")
|
|
|
log.info(f" 是否检查日内价差: {g.check_intraday_spread}")
|
|
|
log.info(f" 均线穿越阈值: {g.ma_cross_threshold}")
|
|
|
+ log.info(f" 是否启用开盘价差过滤: {g.enable_open_gap_filter}")
|
|
|
log.info(f" 固定止损: {g.fixed_stop_loss_rate:.1%}")
|
|
|
log.info(f" 均线跟踪止盈常规偏移: {g.ma_offset_ratio_normal:.1%}")
|
|
|
log.info(f" 均线跟踪止盈收盘前偏移: {g.ma_offset_ratio_close:.1%}")
|
|
|
@@ -496,33 +498,20 @@ def check_ma_trend_and_open_gap(context):
|
|
|
log.info(f" {symbol}({dominant_future}) ✓ 历史均线模式一致性检查通过 "
|
|
|
f"({consistency_ratio:.1%} >= {g.ma_pattern_consistency_threshold:.1%})")
|
|
|
|
|
|
- # 步骤9:计算开盘价差并检查(合并优化)
|
|
|
- open_gap_ratio = (today_open - yesterday_close) / yesterday_close
|
|
|
- log.info(f" 开盘价差检查: 昨收 {yesterday_close:.2f}, 今开 {today_open:.2f}, "
|
|
|
- f"价差比例 {open_gap_ratio:.2%}")
|
|
|
-
|
|
|
- # 检查开盘价差是否符合方向要求
|
|
|
- gap_check_passed = False
|
|
|
- if g.ma_gap_strategy_mode == 1:
|
|
|
- # 方案1:多头检查上跳,空头检查下跳
|
|
|
- if direction == 'long' and open_gap_ratio >= g.ma_open_gap_threshold:
|
|
|
- log.info(f" {symbol}({dominant_future}) ✓ 方案1多头开盘价差检查通过 ({open_gap_ratio:.2%} >= {g.ma_open_gap_threshold:.2%})")
|
|
|
- gap_check_passed = True
|
|
|
- elif direction == 'short' and open_gap_ratio <= -g.ma_open_gap_threshold:
|
|
|
- log.info(f" {symbol}({dominant_future}) ✓ 方案1空头开盘价差检查通过 ({open_gap_ratio:.2%} <= {-g.ma_open_gap_threshold:.2%})")
|
|
|
- gap_check_passed = True
|
|
|
- elif g.ma_gap_strategy_mode == 2 or g.ma_gap_strategy_mode == 3:
|
|
|
- # 方案2和方案3:多头检查下跳,空头检查上跳
|
|
|
- if direction == 'long' and open_gap_ratio <= -g.ma_open_gap_threshold2:
|
|
|
- log.info(f" {symbol}({dominant_future}) ✓ 方案{g.ma_gap_strategy_mode}多头开盘价差检查通过 ({open_gap_ratio:.2%} <= {-g.ma_open_gap_threshold2:.2%})")
|
|
|
- gap_check_passed = True
|
|
|
- elif direction == 'short' and open_gap_ratio >= g.ma_open_gap_threshold2:
|
|
|
- log.info(f" {symbol}({dominant_future}) ✓ 方案{g.ma_gap_strategy_mode}空头开盘价差检查通过 ({open_gap_ratio:.2%} >= {g.ma_open_gap_threshold2:.2%})")
|
|
|
- gap_check_passed = True
|
|
|
-
|
|
|
- if not gap_check_passed:
|
|
|
- add_to_excluded_contracts(dominant_future, 'open_gap', current_trading_day)
|
|
|
- continue
|
|
|
+ # 步骤9:检查开盘价差(可配置开关)
|
|
|
+ if g.enable_open_gap_filter:
|
|
|
+ gap_check_passed = check_open_gap_filter(
|
|
|
+ symbol=symbol,
|
|
|
+ dominant_future=dominant_future,
|
|
|
+ direction=direction,
|
|
|
+ yesterday_close=yesterday_close,
|
|
|
+ today_open=today_open,
|
|
|
+ current_trading_day=current_trading_day
|
|
|
+ )
|
|
|
+ if not gap_check_passed:
|
|
|
+ continue
|
|
|
+ else:
|
|
|
+ log.info(" 已关闭开盘价差过滤(enable_open_gap_filter=False),跳过该检查")
|
|
|
|
|
|
# 步骤10:将通过检查的品种加入候选列表
|
|
|
g.daily_ma_candidates[dominant_future] = {
|
|
|
@@ -1006,6 +995,67 @@ def check_ma5_distribution_filter(data, lookback_days, direction, min_ratio):
|
|
|
return stats['qualified_days'] >= stats['required_days'], stats
|
|
|
|
|
|
|
|
|
+def check_open_gap_filter(symbol, dominant_future, direction, yesterday_close, today_open, current_trading_day):
|
|
|
+ """开盘价差过滤辅助函数
|
|
|
+
|
|
|
+ 根据当前策略模式(`g.ma_gap_strategy_mode`)和对应阈值检查开盘价差是否符合方向要求。
|
|
|
+
|
|
|
+ Args:
|
|
|
+ symbol: 品种代码(如 'AO')
|
|
|
+ dominant_future: 主力合约代码(如 'AO2502.XSGE')
|
|
|
+ direction: 方向,'long' 或 'short'
|
|
|
+ yesterday_close: 前一交易日收盘价
|
|
|
+ today_open: 当日开盘价
|
|
|
+ current_trading_day: 当前期货交易日
|
|
|
+
|
|
|
+ Returns:
|
|
|
+ bool: True 表示通过开盘价差过滤,False 表示未通过(并已加入排除缓存)
|
|
|
+ """
|
|
|
+ open_gap_ratio = (today_open - yesterday_close) / yesterday_close
|
|
|
+ log.info(
|
|
|
+ f" 开盘价差检查: 昨收 {yesterday_close:.2f}, 今开 {today_open:.2f}, "
|
|
|
+ f"价差比例 {open_gap_ratio:.2%}"
|
|
|
+ )
|
|
|
+
|
|
|
+ gap_check_passed = False
|
|
|
+
|
|
|
+ if g.ma_gap_strategy_mode == 1:
|
|
|
+ # 方案1:多头检查上跳,空头检查下跳
|
|
|
+ if direction == 'long' and open_gap_ratio >= g.ma_open_gap_threshold:
|
|
|
+ log.info(
|
|
|
+ f" {symbol}({dominant_future}) ✓ 方案1多头开盘价差检查通过 "
|
|
|
+ f"({open_gap_ratio:.2%} >= {g.ma_open_gap_threshold:.2%})"
|
|
|
+ )
|
|
|
+ gap_check_passed = True
|
|
|
+ elif direction == 'short' and open_gap_ratio <= -g.ma_open_gap_threshold:
|
|
|
+ log.info(
|
|
|
+ f" {symbol}({dominant_future}) ✓ 方案1空头开盘价差检查通过 "
|
|
|
+ f"({open_gap_ratio:.2%} <= {-g.ma_open_gap_threshold:.2%})"
|
|
|
+ )
|
|
|
+ gap_check_passed = True
|
|
|
+ elif g.ma_gap_strategy_mode == 2 or g.ma_gap_strategy_mode == 3:
|
|
|
+ # 方案2和方案3:多头检查下跳,空头检查上跳
|
|
|
+ if direction == 'long' and open_gap_ratio <= -g.ma_open_gap_threshold2:
|
|
|
+ log.info(
|
|
|
+ f" {symbol}({dominant_future}) ✓ 方案{g.ma_gap_strategy_mode}多头开盘价差检查通过 "
|
|
|
+ f"({open_gap_ratio:.2%} <= {-g.ma_open_gap_threshold2:.2%})"
|
|
|
+ )
|
|
|
+ gap_check_passed = True
|
|
|
+ elif direction == 'short' and open_gap_ratio >= g.ma_open_gap_threshold2:
|
|
|
+ log.info(
|
|
|
+ f" {symbol}({dominant_future}) ✓ 方案{g.ma_gap_strategy_mode}空头开盘价差检查通过 "
|
|
|
+ f"({open_gap_ratio:.2%} >= {g.ma_open_gap_threshold2:.2%})"
|
|
|
+ )
|
|
|
+ gap_check_passed = True
|
|
|
+
|
|
|
+ if not gap_check_passed:
|
|
|
+ add_to_excluded_contracts(dominant_future, 'open_gap', current_trading_day)
|
|
|
+ return False
|
|
|
+
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
def check_ma_pattern(ma_values, direction):
|
|
|
"""检查均线排列模式是否符合方向要求
|
|
|
|