feat: 策略加best_regime(适应温区)字段+淘汰判定改用适应温区2y/10y年化都<0→历史
This commit is contained in:
@@ -661,6 +661,34 @@ def api_research_strategies():
|
||||
except Exception:
|
||||
pass
|
||||
_candidate_pool |= set(_regime_winrates.keys())
|
||||
# ── 2026-08-15 适应温区(best_regime):weights 优先,缺失从温区数据推断(2y最高胜率温区)──
|
||||
_best_regime_map = {}
|
||||
try:
|
||||
for _v, _w in (_weights.get("weights") or {}).items():
|
||||
_br = _w.get("best_regime")
|
||||
if _br:
|
||||
_best_regime_map[_v] = _br
|
||||
except Exception:
|
||||
pass
|
||||
# 推断缺失的(港股/历史策略)
|
||||
try:
|
||||
import sqlite3 as _sqb
|
||||
_cb = _sqb.connect(str(DATA_DIR / "mofin.db"), timeout=10)
|
||||
for _v, _rws in _regime_winrates.items():
|
||||
if _v in _best_regime_map or not _rws:
|
||||
continue
|
||||
_best_br = None
|
||||
_best_wr = -1
|
||||
for _reg, _rw in _rws.items():
|
||||
_wr = _rw.get("win_rate")
|
||||
if _wr is not None and _wr > _best_wr:
|
||||
_best_wr = _wr
|
||||
_best_br = _reg
|
||||
if _best_br:
|
||||
_best_regime_map[_v] = _best_br
|
||||
_cb.close()
|
||||
except Exception:
|
||||
pass
|
||||
for s in strats:
|
||||
# 2026-08-15 温区加权综合/普适:整体行的综合/普适 = 按温区时长占比加权各温区表现
|
||||
# (业务逻辑:策略只在特定温区激活,评估应该限定在温区范围才值得参考)
|
||||
@@ -715,6 +743,8 @@ def api_research_strategies():
|
||||
s['regime_winrates'] = _regime_winrates.get(s['version'], {})
|
||||
# current = 当前温区激活(替代旧的 CURRENT_VERSIONS 硬编码)
|
||||
s['current'] = s['version'] in _active_set
|
||||
# 2026-08-15 适应温区(前端方案A:策略只在适应温区表显示一行)
|
||||
s['best_regime'] = _best_regime_map.get(s['version'])
|
||||
# 2026-08-15 证伪数据驱动:从 strategy_research.deprecated 读(替代前端硬编码)
|
||||
s['deprecated'] = _deprecated.get(s['version'])
|
||||
# 2026-08-15 三状态(派生,不存储):激活/可用未激活/不可用
|
||||
@@ -725,27 +755,27 @@ def api_research_strategies():
|
||||
s['state'] = 'unavailable'
|
||||
s['state_reason'] = '已证伪: ' + str(s['deprecated'])[:80]
|
||||
elif s['version'] in _candidate_pool:
|
||||
# ── 2026-08-15 无价值淘汰:2y+10y 温区年化都跑不赢大盘 → 历史 ──
|
||||
# 只在 2y/10y 请求时判定;用当次数据(2y) + 缓存(10y),避免额外重算
|
||||
# ── 2026-08-15 无价值淘汰:适应温区(best_regime) 2y+10y 年化都<0 → 历史 ──
|
||||
# (老莫逻辑:温区表数据对应适应温区;适应温区都亏的策略无价值)
|
||||
_elim_reason = None
|
||||
try:
|
||||
_b2, _b10 = _get_benchmarks()
|
||||
if _b2 is not None and _b10 is not None:
|
||||
# 读表拿 2y/10y 温区数据(毫秒级,数据加工层预计算)
|
||||
_br_v = s.get('best_regime')
|
||||
if _br_v:
|
||||
_r2 = _compute_regime_winrates_cached('2y', _approx_regime_universality)
|
||||
_r10 = _compute_regime_winrates_cached('10y', _approx_regime_universality)
|
||||
_v2 = _r2.get(s['version']) or {}
|
||||
_v10 = _r10.get(s['version']) or {}
|
||||
if _v2 and _v10:
|
||||
_best2 = max(r.get('cagr_pct') or -999 for r in _v2.values())
|
||||
_best10 = max(r.get('cagr_pct') or -999 for r in _v10.values())
|
||||
if _best2 < _b2 and _best10 < _b10:
|
||||
_elim_reason = f'2y年化{round(_best2,1)}%<大盘{_b2}% 且 10y年化{round(_best10,1)}%<大盘{_b10}%'
|
||||
_rw2 = (_r2.get(s['version']) or {}).get(_br_v)
|
||||
_rw10 = (_r10.get(s['version']) or {}).get(_br_v)
|
||||
if _rw2 and _rw10:
|
||||
_c2 = _rw2.get('cagr_pct')
|
||||
_c10 = _rw10.get('cagr_pct')
|
||||
if _c2 is not None and _c10 is not None and _c2 < 0 and _c10 < 0:
|
||||
_elim_reason = (f'适应温区[{_br_v}] 2y年化{round(_c2,1)}%<0 '
|
||||
f'且 10y年化{round(_c10,1)}%<0')
|
||||
except Exception:
|
||||
_elim_reason = None
|
||||
if _elim_reason:
|
||||
s['state'] = 'unavailable'
|
||||
s['state_reason'] = '跑不赢大盘已淘汰: ' + _elim_reason
|
||||
s['state_reason'] = '适应温区亏损已淘汰: ' + _elim_reason
|
||||
else:
|
||||
s['state'] = 'available'
|
||||
s['state_reason'] = '候选池内,当前温区未激活(温区切换即可激活)'
|
||||
|
||||
Reference in New Issue
Block a user