diff --git a/evolution/evolution_api.py b/evolution/evolution_api.py index 6238d802..ac754e51 100644 --- a/evolution/evolution_api.py +++ b/evolution/evolution_api.py @@ -119,6 +119,7 @@ def get_combo_dashboard(): res = json.loads(r[0]) s = res.get("summary", {}) pf = s.get("portfolio_full", {}) + p5 = s.get("portfolio", {}) members[v] = { "role": "趋势市主战" if v == "v_next4" else "震荡/下跌市接管", "trades": s.get("total_trades"), @@ -129,6 +130,9 @@ def get_combo_dashboard(): "return_pct": pf.get("total_return_pct"), "max_dd_pct": pf.get("portfolio_max_dd_pct"), "universality": s.get("universality", {}), + # 组合模拟实际执行笔数(扣费后) + 年均(手工可行性参考) + "positions_taken_5slot": p5.get("positions_taken"), + "positions_taken_full": pf.get("positions_taken"), } conn.close() diff --git a/static/index.html b/static/index.html index 142f314e..b8a1ddaa 100644 --- a/static/index.html +++ b/static/index.html @@ -2084,20 +2084,28 @@ async function renderResearchCombo() { // ── 2. 组合成员策略指标 ── const members = d.members || {}; if (Object.keys(members).length) { - h += '
成员策略(10年回测)
' + + h += '
成员策略(10年回测,组合收益已扣费)
' + '
'; for (const [v, m] of Object.entries(members)) { const u = m.universality || {}; - h += '
' + - '
' + v + '' + + const yearly5 = m.positions_taken_5slot && m.positions_taken_5slot > 0 ? Math.round(m.positions_taken_5slot / 10) : '—'; + h += '
' + + '
' + v + '' + '' + (m.role || '') + '
' + - '
' + - '
年化
' + (m.cagr_pct != null ? m.cagr_pct + '%' : '—') + '
' + - '
胜率
' + (m.win_rate != null ? m.win_rate + '%' : '—') + '
' + - '
笔数
' + (m.trades != null ? (m.trades > 999 ? Math.round(m.trades/1000) + 'k' : m.trades) : '—') + '
' + - '
覆盖
' + (u.months || '—') + '月
' + + // 盈利率大字突出(用户关注的核心指标) + '
' + + '
单笔均收益(毛利)
' + (m.avg_profit_pct != null ? m.avg_profit_pct + '%' : '—') + '
' + + '
组合年化(扣费)
' + (m.cagr_pct != null ? m.cagr_pct + '%' : '—') + '
' + + '
组合10年收益
' + (m.return_pct != null ? m.return_pct + '%' : '—') + '
' + '
' + - '
均持' + (m.avg_hold_days != null ? m.avg_hold_days + '天' : '—') + ' · 均收益' + (m.avg_profit_pct != null ? m.avg_profit_pct + '%' : '—') + ' · 回撤' + (m.max_dd_pct != null ? m.max_dd_pct + '%' : '—') + '
' + + '
' + + '
胜率
' + (m.win_rate != null ? m.win_rate + '%' : '—') + '
' + + '
信号总数
' + (m.trades != null ? (m.trades > 999 ? Math.round(m.trades/1000) + 'k' : m.trades) : '—') + '
' + + '
组合执行
' + (m.positions_taken_5slot != null ? m.positions_taken_5slot + '笔' : '—') + '
' + + '
覆盖月
' + (u.months || '—') + '
' + + '
' + + '
均持' + (m.avg_hold_days != null ? m.avg_hold_days + '天' : '—') + ' · 回撤' + (m.max_dd_pct != null ? m.max_dd_pct + '%' : '—') + ' · 组合年均' + yearly5 + '笔(人工可操作)
' + + (v === 'v_mr' ? '
📋 实盘链路:22k信号 → 组合模拟只执行' + (m.positions_taken_5slot || 0) + '笔 → 每日扫描器只挑最超跌少数候选(2026-08-02首跑仅3只)→ 人工确认建仓。22k是候选池,不是操作量。
' : '') + '
'; } h += '
';