From 614b4570d6885f1ea0f6c13c2bde3f957f336450 Mon Sep 17 00:00:00 2001 From: hmo Date: Wed, 12 Aug 2026 00:40:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20v=5Fweak/v=5Foversold=E6=94=B9mr?= =?UTF-8?q?=E5=BC=95=E6=93=8Econfig=E2=80=94=E2=80=94=E7=94=A8run=5Fmr=5Fb?= =?UTF-8?q?acktest=E9=AB=98=E6=95=88=E5=9B=9E=E6=B5=8B(O(N)=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E6=9B=BF=E4=BB=A3compute=5Fsingle=5Fscore),=20?= =?UTF-8?q?=E6=89=A9=E5=B1=95run=5Fmr=5Fbacktest=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E5=9B=A0=E5=AD=90=E8=BF=87=E6=BB=A4(mkt=5Frs?= =?UTF-8?q?i/mkt=5Fdd60/mcap=5Fq/pe=5Fq/news3/sec=5Fret20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- strategy_lab.py | 69 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/strategy_lab.py b/strategy_lab.py index bb7f444d..f2a08da9 100644 --- a/strategy_lab.py +++ b/strategy_lab.py @@ -334,15 +334,14 @@ STRATEGIES.update({ "hypothesis": "弱市深超跌反弹,六步方法论+12维框架定稿", "parent": "v_mr", "config": { - "entry": {"min_score": 45, "min_momentum": 8, "filters": { - "bias60_min": -35, "bias60_max": -20, - "rsi_max": 25, - "r5f_max": -3, - "dist_lo20_max": 5, - "require_close_up": True, - "vol_shrink_max": 1.0, - "mkt_above_ma20": False, - "mkt_adx_min": 25, "mkt_adx_max": 30, + "entry": {"min_score": 0, "min_momentum": 0, "filters": {}, "mr": { + # run_mr_backtest 原生支持:bias60/RSI/60日跌幅/20日动量/成交额/RSI回升/大盘模式 + "bias_min": -35, "bias_max": -20, # 深超跌(MA60下方35%~20%) + "rsi_max": 25, # 极度超卖 + "ret_max": -5, # 60日跌超5%(单边下跌) + "mom20_max": 0, # 20日动量<=0(低动量) + "rsi_delta_min": 0, # RSI止跌回升 + "mkt_mode": "sideways", # 大盘震荡市(ADX<25 非趋势) }}, "exit": {"tp_pct": 0.30, "sl_pct": 0.12, "max_hold_days": 40}, "sizing": {"kelly": False}, @@ -356,14 +355,19 @@ STRATEGIES.update({ "hypothesis": "由果及因:预测超跌反弹", "parent": "v_weak", "config": { - "entry": {"min_score": 45, "min_momentum": 8, "filters": { - "mkt_rsi_max": 50, - "mkt_dd60_max": -5, - "mcap_q_max": 0.2, - "pe_q_max": 0.2, - "news3_min": 1, - "sec_ret20_max": 0, - "bias60_max": -20, + "entry": {"min_score": 0, "min_momentum": 0, "filters": {}, "mr": { + # run_mr_backtest 原生 + 外部因子(mkt_rsi/mkt_dd60/mcap_q/pe_q/news3/sec_ret20) + "bias_max": -20, # 深跌 + "rsi_max": 50, # 超卖 + "ret_max": -10, # 60日跌超10% + "mom20_max": 0, # 低动量 + "mkt_mode": "bear", # 弱市 + "mkt_rsi_max": 50, # 大盘RSI<50(弱) + "mkt_dd60_max": -5, # 大盘距60日高点回撤>5% + "mcap_q_max": 0.2, # 小市值(全市场后20%分位) + "pe_q_max": 0.2, # 低PE(全市场后20%分位) + "news3_min": 1, # 3日内有新闻 + "sec_ret20_max": 0, # 行业20日动量<=0(行业弱) }}, "exit": {"tp_pct": None, "sl_pct": 0.05, "max_hold_days": 40}, "sizing": {"kelly": False}, @@ -2260,6 +2264,33 @@ def run_mr_backtest(strategy_version, start_date, end_date, capital=913000, if mkt_above is True: skip_stats['mkt'] += 1; i += 1; continue + # 8. 大盘RSI/回撤 + 外部因子(mcap_q/pe_q/news3/sec_ret20,2026-08-11 支持 v_oversold) + if mr.get('mkt_rsi_max') is not None: + _mkt_rsi = mk.get('rsi') + if _mkt_rsi is None or _mkt_rsi > mr['mkt_rsi_max']: + skip_stats['mkt'] += 1; i += 1; continue + if mr.get('mkt_dd60_max') is not None: + _mkt_dd60 = mk.get('mkt_dd60') + if _mkt_dd60 is None or _mkt_dd60 > mr['mkt_dd60_max']: + skip_stats['mkt'] += 1; i += 1; continue + _ext = _get_external_factors(code, date) + if mr.get('mcap_q_max') is not None: + _mcap_q = _ext.get('mcap_q') + if _mcap_q is None or _mcap_q > mr['mcap_q_max']: + skip_stats['amount'] += 1; i += 1; continue + if mr.get('pe_q_max') is not None: + _pe_q = _ext.get('pe_q') + if _pe_q is None or _pe_q > mr['pe_q_max']: + skip_stats['amount'] += 1; i += 1; continue + if mr.get('news3_min') is not None: + _news3 = _ext.get('news3', 0) + if _news3 < mr['news3_min']: + skip_stats['amount'] += 1; i += 1; continue + if mr.get('sec_ret20_max') is not None: + _sec_ret20 = _ext.get('sec_ret20') + if _sec_ret20 is None or _sec_ret20 > mr['sec_ret20_max']: + skip_stats['amount'] += 1; i += 1; continue + # 次日开盘入场 if i + 1 >= len(bars): skip_stats['next_open'] += 1; i += 1; continue @@ -2299,6 +2330,10 @@ def run_mr_backtest(strategy_version, start_date, end_date, capital=913000, 'mkt_above_ma20': mkt_above, 'rsi_delta': round(rsi_delta, 2), }) + # 2026-08-11: 外部因子记录(v_oversold 12维因子可分析) + factors['mkt_rsi'] = mk.get('rsi') + factors['mkt_dd60'] = mk.get('mkt_dd60') + factors.update(_ext) sc_ctx = sector_ctx(code, date) factors['sector_change'] = sc_ctx.get('change') factors['sector_rank_pct'] = sc_ctx.get('rank_pct')