|
|
@@ -204,7 +204,7 @@ def initialize(context):
|
|
|
|
|
|
# 策略品种选择策略配置
|
|
|
# 方案1:全品种策略 - 考虑所有配置的期货品种
|
|
|
- g.strategy_focus_symbols = ['AU'] # 空列表表示考虑所有品种
|
|
|
+ g.strategy_focus_symbols = [] # 空列表表示考虑所有品种
|
|
|
|
|
|
# 方案2:精选品种策略 - 只交易流动性较好的特定品种(如需使用请取消下行注释)
|
|
|
# g.strategy_focus_symbols = ['RM', 'CJ', 'CY', 'JD', 'L', 'LC', 'SF', 'SI']
|
|
|
@@ -603,60 +603,13 @@ def check_open_and_stop(context):
|
|
|
log.info(f" 方向: {direction}, 开盘价: {open_price:.2f}, 当前价: {current_price:.2f}, "
|
|
|
f"当天价差: {intraday_diff:.2f}, 变化比例: {intraday_diff_ratio:.2%}")
|
|
|
|
|
|
- # 判断是否满足开仓条件
|
|
|
- should_open = False
|
|
|
-
|
|
|
- if g.ma_gap_strategy_mode == 1:
|
|
|
- # 方案1:根据参数决定是否检查日内价差
|
|
|
- if not g.check_intraday_spread:
|
|
|
- log.info(f" 方案1跳过日内价差检查(check_intraday_spread=False)")
|
|
|
- should_open = True
|
|
|
- elif direction == 'long' and intraday_diff > 0:
|
|
|
- log.info(f" ✓ 方案1多头当天价差检查通过 ({intraday_diff:.2f} > 0)")
|
|
|
- should_open = True
|
|
|
- elif direction == 'short' and intraday_diff < 0:
|
|
|
- log.info(f" ✓ 方案1空头当天价差检查通过 ({intraday_diff:.2f} < 0)")
|
|
|
- should_open = True
|
|
|
- else:
|
|
|
- log.info(f" ✗ 方案1当天价差不符合{direction}方向要求")
|
|
|
-
|
|
|
- elif g.ma_gap_strategy_mode == 2:
|
|
|
- # 方案2:强制检查日内变化,使用专用阈值
|
|
|
- if direction == 'long' and intraday_diff_ratio >= g.ma_intraday_threshold_scheme2:
|
|
|
- log.info(f" ✓ 方案2多头日内变化检查通过 ({intraday_diff_ratio:.2%} >= {g.ma_intraday_threshold_scheme2:.2%})")
|
|
|
- should_open = True
|
|
|
- elif direction == 'short' and intraday_diff_ratio <= -g.ma_intraday_threshold_scheme2:
|
|
|
- log.info(f" ✓ 方案2空头日内变化检查通过 ({intraday_diff_ratio:.2%} <= {-g.ma_intraday_threshold_scheme2:.2%})")
|
|
|
- should_open = True
|
|
|
- else:
|
|
|
- log.info(f" ✗ 方案2日内变化不符合{direction}方向要求(阈值: ±{g.ma_intraday_threshold_scheme2:.2%})")
|
|
|
-
|
|
|
- elif g.ma_gap_strategy_mode == 3:
|
|
|
- # 方案3:下跳后上涨(多头)或上跳后下跌(空头),并检查当前价格与前一日开盘收盘均值的关系
|
|
|
- if yesterday_open is not None and yesterday_close is not None:
|
|
|
- prev_day_avg = (yesterday_open + yesterday_close) / 2
|
|
|
- log.debug(f" 前一日开盘价: {yesterday_open:.2f}, 前一日收盘价: {yesterday_close:.2f}, 前一日开盘收盘均值: {prev_day_avg:.2f}")
|
|
|
-
|
|
|
- if direction == 'long':
|
|
|
- # 多头:当前价格 >= 前一日开盘收盘均值
|
|
|
- if current_price >= prev_day_avg:
|
|
|
- log.info(f" ✓ 方案3多头入场条件通过: 当前价 {current_price:.2f} >= 前日均值 {prev_day_avg:.2f}")
|
|
|
- should_open = True
|
|
|
- else:
|
|
|
- log.info(f" ✗ 方案3多头入场条件未通过: 当前价 {current_price:.2f} < 前日均值 {prev_day_avg:.2f}")
|
|
|
- elif direction == 'short':
|
|
|
- # 空头:当前价格 <= 前一日开盘收盘均值
|
|
|
- if current_price <= prev_day_avg:
|
|
|
- log.info(f" ✓ 方案3空头入场条件通过: 当前价 {current_price:.2f} <= 前日均值 {prev_day_avg:.2f}")
|
|
|
- should_open = True
|
|
|
- else:
|
|
|
- log.info(f" ✗ 方案3空头入场条件未通过: 当前价 {current_price:.2f} > 前日均值 {prev_day_avg:.2f}")
|
|
|
- else:
|
|
|
- log.info(f" ✗ 方案3缺少前一日开盘或收盘价数据")
|
|
|
+ # 判断是否满足开仓条件 - 仅检查均线穿越得分
|
|
|
+ should_open = True
|
|
|
+ log.info(f" 开仓条件简化:仅检查均线穿越得分,跳过策略1,2,3的判断")
|
|
|
|
|
|
if should_open:
|
|
|
ma_values = candidate_info.get('ma_values') or {}
|
|
|
- cross_score = calculate_ma_cross_score(open_price, current_price, ma_values, direction)
|
|
|
+ cross_score, score_details = calculate_ma_cross_score(open_price, current_price, ma_values, direction)
|
|
|
|
|
|
# 根据当前时间调整所需的均线穿越得分阈值
|
|
|
current_time_str = str(context.current_dt.time())[:5] # HH:MM格式
|
|
|
@@ -665,9 +618,26 @@ def check_open_and_stop(context):
|
|
|
# 在14:55以外的时间,需要更高的得分阈值
|
|
|
required_cross_score = g.ma_cross_threshold + 1
|
|
|
|
|
|
- log.info(f" 均线穿越得分: {cross_score}, 当前时间: {current_time_str}, 所需阈值: {required_cross_score}")
|
|
|
- if cross_score < required_cross_score:
|
|
|
- log.info(f" ✗ 均线穿越得分不足({cross_score} < {required_cross_score}),跳过开仓")
|
|
|
+ log.info(f" 均线穿越得分: {cross_score}, 得分详情: {score_details}, 当前时间: {current_time_str}, 所需阈值: {required_cross_score}")
|
|
|
+
|
|
|
+ # 检查得分是否满足条件
|
|
|
+ score_passed = False
|
|
|
+ if cross_score >= required_cross_score:
|
|
|
+ # 如果得分达到阈值,检查特殊情况:只有1分且来自MA5
|
|
|
+ if cross_score == 1 and required_cross_score == 1:
|
|
|
+ # 检查这一分是否来自MA5
|
|
|
+ from_ma5_only = len(score_details) == 1 and score_details[0]['period'] == 5
|
|
|
+ if not from_ma5_only:
|
|
|
+ score_passed = True
|
|
|
+ log.info(f" ✓ 均线穿越得分检查通过:1分且非来自MA5")
|
|
|
+ else:
|
|
|
+ log.info(f" ✗ 均线穿越得分检查未通过:1分且仅来自MA5")
|
|
|
+ else:
|
|
|
+ score_passed = True
|
|
|
+ log.info(f" ✓ 均线穿越得分检查通过")
|
|
|
+
|
|
|
+ if not score_passed:
|
|
|
+ log.info(f" ✗ 均线穿越得分不足或不符合条件({cross_score} < {required_cross_score} 或 1分来自MA5),跳过开仓")
|
|
|
continue
|
|
|
# 执行开仓
|
|
|
log.info(f" 准备开仓: {symbol} {direction}")
|
|
|
@@ -903,11 +873,15 @@ def calculate_ma_values(data, periods):
|
|
|
|
|
|
|
|
|
def calculate_ma_cross_score(open_price, current_price, ma_values, direction):
|
|
|
- """根据开盘价与当前价统计多周期均线穿越得分"""
|
|
|
+ """根据开盘价与当前价统计多周期均线穿越得分
|
|
|
+ 返回: (总得分, 得分详情列表)
|
|
|
+ 得分详情: [{'period': 5, 'delta': 1}, {'period': 10, 'delta': 1}, ...]
|
|
|
+ """
|
|
|
if not ma_values:
|
|
|
- return 0
|
|
|
+ return 0, []
|
|
|
assert direction in ('long', 'short')
|
|
|
score = 0
|
|
|
+ score_details = []
|
|
|
for period in g.ma_periods:
|
|
|
key = f'MA{period}'
|
|
|
ma_value = ma_values.get(key)
|
|
|
@@ -922,11 +896,12 @@ def calculate_ma_cross_score(open_price, current_price, ma_values, direction):
|
|
|
else:
|
|
|
delta = -1 if cross_up else 1
|
|
|
score += delta
|
|
|
+ score_details.append({'period': period, 'delta': delta})
|
|
|
log.debug(
|
|
|
f" 均线穿越[{key}] - 开盘 {open_price:.2f}, 当前 {current_price:.2f}, "
|
|
|
f"均线 {ma_value:.2f}, 方向 {direction}, 增量 {delta}, 当前得分 {score}"
|
|
|
)
|
|
|
- return score
|
|
|
+ return score, score_details
|
|
|
|
|
|
|
|
|
def calculate_ma_proximity_counts(data, periods, lookback_days):
|