diff --git a/server.py b/server.py index 4aa3ae6f..80520d5e 100644 --- a/server.py +++ b/server.py @@ -628,6 +628,7 @@ def api_research_strategies(): _c2.close() except Exception: pass + _candidate_pool |= set(_regime_winrates.keys()) for s in strats: # 2026-08-15 温区加权综合/普适:整体行的综合/普适 = 按温区时长占比加权各温区表现 # (业务逻辑:策略只在特定温区激活,评估应该限定在温区范围才值得参考) @@ -684,6 +685,19 @@ def api_research_strategies(): s['current'] = s['version'] in _active_set # 2026-08-15 证伪数据驱动:从 strategy_research.deprecated 读(替代前端硬编码) s['deprecated'] = _deprecated.get(s['version']) + # 2026-08-15 三状态(派生,不存储):激活/可用未激活/不可用 + if s['version'] in _active_set: + s['state'] = 'active' + s['state_reason'] = '当前温区路由激活' + elif s.get('deprecated'): + s['state'] = 'unavailable' + s['state_reason'] = '已证伪: ' + str(s['deprecated'])[:80] + elif s['version'] in _candidate_pool: + s['state'] = 'available' + s['state_reason'] = '候选池内,当前温区未激活(温区切换即可激活)' + else: + s['state'] = 'unavailable' + s['state_reason'] = '不在候选池(历史版本,路由不会选中)' # 2026-08-13 关键修复:激活策略必须始终在列表中(即使该 period 无回测记录) # 否则 2y 等默认周期下激活策略缺失(只显示 v_oversold)。 @@ -712,6 +726,8 @@ def api_research_strategies(): } _entry['regime_winrates'] = _regime_winrates.get(_mv, {}) _entry['current'] = True + _entry['state'] = 'active' + _entry['state_reason'] = '当前温区路由激活' _entry['note'] = f"({pt or '当前周期'}无回测记录,显示10y数据)" strats.append(_entry) return jsonify({'strategies': strats, 'regime_active': sorted(_active_set)}) diff --git a/static/index.html b/static/index.html index ec899efc..7f5420e8 100644 --- a/static/index.html +++ b/static/index.html @@ -2401,7 +2401,8 @@ function renderStrategyTable(strategies) { // 2026-08-13 温区自适应:按"适应温区"展开——每策略每温区一行 // 当前 = 当前温区激活(后端 s.current 已改为 regime_weights.active 判断);历史 = 其余,默认折叠 const currentStrats = strategies.filter(s => s.current === true); - const historyStrats = strategies.filter(s => s.current !== true); + const availableStrats = strategies.filter(s => s.current !== true && s.state === 'available'); + const unavailableStrats = strategies.filter(s => s.current !== true && s.state !== 'available'); const REGIME_META = {trend_up:{icon:'📈',name:'趋势市'}, choppy:{icon:'〰️',name:'震荡市'}, trend_down:{icon:'📉',name:'下跌市'}}; const renderGroup = (groupStrats, groupTitle, groupIcon, collapsed) => { let ghtml = '
' + @@ -2471,7 +2472,7 @@ function renderStrategyTable(strategies) { (rw && rw.avg_pnl != null ? ' ' + (rw.avg_pnl >= 0 ? '+' : '') + rw.avg_pnl + '%' : '') + (rw && rw.trades != null ? ' ' + rw.trades + '笔' : '') + '' + - '' + + '' + '' + '' + '' + @@ -2503,14 +2504,21 @@ function renderStrategyTable(strategies) { renderGroup(currentStrats, '当前', '🟢', false) + ''; } - if (historyStrats.length) { + if (availableStrats.length) { html += '
' + '' + - '' + + '🔵 可用未激活(' + availableStrats.length + '个)' + + '' + '
'; } - if (!currentStrats.length && !historyStrats.length) { + if (unavailableStrats.length) { + html += '
' + + '' + + '' + + '
'; + } + if (!currentStrats.length && !availableStrats.length && !unavailableStrats.length) { html = '
暂无策略版本
'; } html += '
总收益/最终资产 = 100万本金·最多10等分仓位·24个月组合模拟 · ⚠️样本<40笔 · 绿色=该列最优 · 悬停名称查看改进假设
';
' + s.version + (rgActive ? ' 激活' : '') + (deprecatedReason ? ' 已证伪' : '') + ((s.market && s.market !== 'all') ? ' ' + (s.market === 'hk' ? '港' : 'A') + '' : '') + '' + s.version + (rgActive ? ' 激活' : '') + (s.state === 'available' && !rgActive ? ' 可用' : '') + (deprecatedReason ? ' 已证伪' : '') + ((s.market && s.market !== 'all') ? ' ' + (s.market === 'hk' ? '港' : 'A') + '' : '') + '' + (s.name || '') + (smallSample ? ' ⚠️' : '') + '' + (st.sizing_slots ? st.sizing_slots + '仓' : '10仓') + (st.conviction_model ? '' : '') + '' + ((s.description && s.description.title) ? '' : '') + '