feat: 枢轴S/R注入回测引擎+v11系列——枢轴波段(v11.0)4仓+86.3%/回撤1.3%碾压MA10波段,证明复合强弱支撑优于简单均线;固定15%/ATR仍优于裸枢轴强压止盈
This commit is contained in:
+25
-1
@@ -170,9 +170,32 @@ def prepare_bars(code, start_date, end_date):
|
||||
trend_strength = calc_trend_strength(highs, lows, closes)
|
||||
obv = calc_obv(closes, volumes)
|
||||
roc = calc_roc(closes)
|
||||
|
||||
|
||||
bars = []
|
||||
for i in range(len(dates)):
|
||||
# ── 枢轴S/R(与实盘 technical_analysis.calc_support_resistance 同算法)──
|
||||
piv = {}
|
||||
if i >= 1:
|
||||
h, l, c = highs[i], lows[i], closes[i]
|
||||
yc = closes[i-1]
|
||||
# 多日波幅(近20日)
|
||||
win = bars[max(0, i-19):i] if i > 0 else []
|
||||
multi_high = max([h] + [x.get('high', 0) or 0 for x in win])
|
||||
multi_low = min([l] + [x.get('low', 1e9) or 1e9 for x in win])
|
||||
eff_range = max(h - l, multi_high - multi_low, c * 0.05)
|
||||
tp = (c - multi_low) / (multi_high - multi_low) if multi_high > multi_low else 0.5
|
||||
if tp > 0.8 or tp < 0.2:
|
||||
eff_range = max(eff_range, c * 0.08)
|
||||
pp = (h + l + c) / 3
|
||||
s1 = 2 * pp - h
|
||||
s2 = pp - eff_range
|
||||
r1 = 2 * pp - l
|
||||
r2 = pp + eff_range
|
||||
if yc < s1: s1 = yc
|
||||
if yc > r1: r1 = yc
|
||||
piv = {'pivot': pp, 'weak_support': s1, 'strong_support': s2,
|
||||
'weak_resist': r1, 'strong_resist': r2}
|
||||
|
||||
bars.append({
|
||||
'date': dates[i],
|
||||
'open': opens[i],
|
||||
@@ -192,6 +215,7 @@ def prepare_bars(code, start_date, end_date):
|
||||
'adx': trend_strength[i] if i < len(trend_strength) else None,
|
||||
'obv': obv[i] if i < len(obv) else None,
|
||||
'roc': roc[i] if i < len(roc) else None,
|
||||
**piv,
|
||||
})
|
||||
return bars
|
||||
|
||||
|
||||
+68
-7
@@ -258,6 +258,19 @@ STRATEGIES.update({
|
||||
"v9归因反用:v7.1交易中weekly_up=False胜率78.4% vs True 60.9%——周线级回调中的日线动量回归正是本策略的核心边缘",
|
||||
entry_overrides={"vol_ratio_min": 0.9, "vol_ratio_max": 2.0, "sector_slope_max": 1.0,
|
||||
"hl_only": True, "rsi_delta_min": 6, "weekly_down_only": True}),
|
||||
# I组: 枢轴S/R出场(与实盘technical_analysis同算法)
|
||||
"v11.0": _v40_branch("v11.0", "波段·枢轴版",
|
||||
"v8.1入场;出场改枢轴体系:破弱支撑先出,收复弱压且创新高再进",
|
||||
"v8.1的MA10只是弱支撑的粗糙代理——用实盘同款枢轴S/R验证复合技术位是否优于简单均线",
|
||||
entry_overrides={"vol_ratio_min": 0.9, "vol_ratio_max": 2.0, "sector_slope_max": 1.0,
|
||||
"hl_only": True, "rsi_delta_min": 6},
|
||||
exit_overrides={"tp_pct": None, "exit_mode": "swing_pivot", "sl_atr": 1.5, "max_hold_days": 60, "reentry_days": 10}),
|
||||
"v11.1": _v40_branch("v11.1", "强压止盈弱撑止损",
|
||||
"v7.1入场;出场改实盘口径:强压止盈+弱支撑止损(枢轴点体系,替代固定15%/1.5ATR)",
|
||||
"实盘策略的真实出场方式就是枢轴S/R——回测必须验证这个口径而非固定百分比",
|
||||
entry_overrides={"vol_ratio_min": 0.9, "vol_ratio_max": 2.0, "sector_slope_max": 1.0,
|
||||
"hl_only": True, "rsi_delta_min": 6},
|
||||
exit_overrides={"tp_pct": None, "use_pivot_sr": True, "max_hold_days": 20}),
|
||||
# ── 港股专用版本(港股通宇宙归因推导,2026-07-29)──
|
||||
"h1.0": {
|
||||
"version": "h1.0",
|
||||
@@ -694,7 +707,13 @@ def run_backtest(strategy_version, start_date, end_date, capital=1000000, save=T
|
||||
|
||||
if pass_filters(factors, filters):
|
||||
atr_val = last.get('atr') or 0
|
||||
if exit_cfg.get('tp_pct'):
|
||||
if exit_cfg.get('use_pivot_sr'):
|
||||
# 实盘口径:强压止盈 + 弱支撑止损(枢轴点体系)
|
||||
target = last.get('strong_resist') if (last.get('strong_resist') or 0) > close else None
|
||||
stop = last.get('weak_support') if (last.get('weak_support') or 0) < close else (close - atr_val * exit_cfg.get('sl_atr', 1.5) if atr_val > 0 else close * 0.93)
|
||||
if target is None:
|
||||
target = close * (1 + exit_cfg.get('tp_pct', 0.15))
|
||||
elif exit_cfg.get('tp_pct'):
|
||||
target = close * (1 + exit_cfg['tp_pct'])
|
||||
elif exit_cfg.get('tp_atr') and atr_val > 0:
|
||||
target = close + atr_val * exit_cfg['tp_atr']
|
||||
@@ -702,12 +721,13 @@ def run_backtest(strategy_version, start_date, end_date, capital=1000000, save=T
|
||||
target = None # 移动止盈模式无固定目标
|
||||
else:
|
||||
target = close * 1.10
|
||||
if exit_cfg.get('sl_atr') and atr_val > 0:
|
||||
stop = close - atr_val * exit_cfg['sl_atr']
|
||||
elif exit_cfg.get('sl_pct'):
|
||||
stop = close * (1 - exit_cfg['sl_pct'])
|
||||
else:
|
||||
stop = close * 0.93
|
||||
if not exit_cfg.get('use_pivot_sr'):
|
||||
if exit_cfg.get('sl_atr') and atr_val > 0:
|
||||
stop = close - atr_val * exit_cfg['sl_atr']
|
||||
elif exit_cfg.get('sl_pct'):
|
||||
stop = close * (1 - exit_cfg['sl_pct'])
|
||||
else:
|
||||
stop = close * 0.93
|
||||
|
||||
kelly = 0
|
||||
if cfg['sizing'].get('kelly'):
|
||||
@@ -832,6 +852,47 @@ def run_backtest(strategy_version, start_date, end_date, capital=1000000, save=T
|
||||
pnl = (total_ret - 1) * 100
|
||||
exit_price = close * total_ret
|
||||
hold_days = len(future) if future else 0
|
||||
elif exit_cfg.get('exit_mode') == 'swing_pivot':
|
||||
# ── 波段·枢轴版:破弱支撑先出,收复弱压且创新高再进 ──
|
||||
reentry_window = exit_cfg.get('reentry_days', 10)
|
||||
legs = []
|
||||
in_pos = True
|
||||
entry_p = close
|
||||
stop_cur = stop
|
||||
wait = 0
|
||||
exit_reason = 'keep'
|
||||
for k, fb in enumerate(future):
|
||||
fh, fl, fc = fb.get('high') or 0, fb.get('low') or 0, fb.get('close') or 0
|
||||
fws, fwr = fb.get('weak_support') or 0, fb.get('weak_resist') or 0
|
||||
if in_pos:
|
||||
if fl <= stop_cur:
|
||||
legs.append(fc/entry_p - 1)
|
||||
exit_reason = 'stop'
|
||||
in_pos = False
|
||||
break
|
||||
if fws > 0 and fc < fws:
|
||||
legs.append(fc/entry_p - 1)
|
||||
in_pos = False
|
||||
wait = reentry_window
|
||||
exit_reason = 'swing_out'
|
||||
else:
|
||||
wait -= 1
|
||||
if wait < 0:
|
||||
break
|
||||
prev_high = future[k-1].get('high') or 0 if k > 0 else 0
|
||||
if fwr > 0 and fc > fwr and fh > prev_high:
|
||||
in_pos = True
|
||||
entry_p = fc
|
||||
stop_cur = fb.get('weak_support') or (fc - atr_val * exit_cfg.get('sl_atr', 1.5) if atr_val > 0 else fc * 0.93)
|
||||
exit_reason = 'swing_re'
|
||||
if in_pos:
|
||||
legs.append((future[-1].get('close') if future else entry_p)/entry_p - 1)
|
||||
total_ret = 1.0
|
||||
for l in legs:
|
||||
total_ret *= (1 + l)
|
||||
pnl = (total_ret - 1) * 100
|
||||
exit_price = close * total_ret
|
||||
hold_days = len(future) if future else 0
|
||||
else:
|
||||
exit_price = exit_reason = None
|
||||
hold_days = 0
|
||||
|
||||
Reference in New Issue
Block a user