fix: 进化面板完整版——基线对比+健康度+迭代历史+回测教训(标注来源)

This commit is contained in:
hmo
2026-08-01 01:03:30 +08:00
parent 1448bcd35d
commit 4b877fb26a
+32 -9
View File
@@ -1979,24 +1979,47 @@ async function loadEvolutionBox() {
try {
const r = await fetch('/api/evolution/dashboard');
const d = await r.json();
let h = '<div class="flex items-center justify-between mb-1"><span class="text-sm font-semibold text-emerald-400">🧬 策略自我进化</span><button onclick="loadEvolutionBox()" class="text-xs text-blue-400 hover:text-blue-300">刷新</button></div>';
let h = '<div class="flex items-center justify-between mb-2"><span class="text-base font-semibold text-emerald-400">🧬 策略自我进化</span><button onclick="loadEvolutionBox()" class="text-sm text-blue-400 hover:text-blue-300">刷新</button></div>';
// ── 基线对比 ──
if (d.baseline) {
h += '<div class="grid grid-cols-3 gap-2 mb-2 text-sm">';
h += '<div class="grid grid-cols-3 gap-2 mb-3"><span class="text-sm text-slate-500 col-span-3">5年回测基线:</span>';
for (const [v, b] of Object.entries(d.baseline)) {
const clr = v === 'v_next4' ? 'text-emerald-400' : 'text-slate-300';
h += '<div class="bg-slate-900/50 rounded px-2 py-1"><span class="'+clr+' font-mono font-bold">'+v+'</span><br><span class="text-slate-500 text-xs">胜率'+b.win_rate+'% 收益'+b.total_return+'% 回撤'+b.max_dd+'%</span></div>';
h += '<div class="bg-slate-900/50 rounded px-2 py-1"><span class="'+clr+' font-mono font-bold text-sm">'+v+'</span><br><span class="text-slate-500 text-xs">胜率'+b.win_rate+'% 收益'+b.total_return+'% 回撤'+b.max_dd+'%</span></div>';
}
h += '</div>';
}
if (d.health && d.health.length > 0) { const hs = d.health[0]; const sc = hs.health_score;
// ── 健康度 ──
if (d.health && d.health.length > 0) {
const hs = d.health[0]; const sc = hs.health_score;
const color = sc >= 70 ? 'text-emerald-400' : sc >= 50 ? 'text-amber-400' : 'text-red-400';
h += '<div class="text-sm '+color+'">健康度: '+sc+'分 (实盘'+hs.live_trades+'笔)</div>'; }
if (d.lessons && d.lessons.length > 0) {
h += '<div class="text-sm text-slate-400 mt-2">📝 最近教训:</div>';
for (const l of d.lessons.slice(0,3)) h += '<div class="text-sm text-slate-300">'+(l.lesson_type==='win_pattern'?'✅':'❌')+' '+l.lesson_text+'</div>';
h += '<div class="mb-2 text-sm"><span class="'+color+' font-bold">健康度: '+sc+'分</span><span class="text-slate-500"> (实盘'+hs.live_trades+'笔 vs 回测'+hs.backtest_wr+'%胜率)</span>';
if (hs.live_trades === 0) h += '<span class="text-slate-600 text-xs"> [暂无实盘数据, 分数为中性]</span>';
h += '</div>';
}
// ── 进化历史 ──
if (d.evolution && d.evolution.length > 0) {
h += '<div class="text-sm text-slate-400 mb-1">🔄 迭代历史:</div>';
for (const e of d.evolution.slice(0,5)) {
h += '<div class="text-sm text-slate-300 mb-0.5">'+e.parent_version+' → '+e.child_version+' <span class="text-slate-500">'+e.change_description+'</span>'+(e.promoted?' <span class="text-emerald-400 text-xs">✅采纳</span>':'')+'</div>';
}
} else {
h += '<div class="text-sm text-slate-600 mb-1">🔄 迭代历史: 暂无 (auto_iterator 待触发)</div>';
}
// ── 教训 ──
if (d.lessons && d.lessons.length > 0) {
h += '<div class="text-sm text-slate-400 mt-2 mb-1">📝 回测教训 (基于v_next4 5y交易分析):</div>';
for (const l of d.lessons.slice(0,5)) {
h += '<div class="text-sm text-slate-300 mb-0.5">'+(l.lesson_type==='win_pattern'?'✅盈利规律':'❌亏损规律')+' '+l.lesson_text+' <span class="text-slate-600 text-xs">'+Math.round(l.confidence*100)+'%置信</span></div>';
}
}
box.innerHTML = h;
} catch (e) { box.innerHTML = '<div class="text-xs text-red-400">加载失败</div>'; }
} catch (e) { box.innerHTML = '<div class="text-sm text-red-400">进化模块加载失败: '+e.message+'</div>'; }
}
// 研究Tab活跃时加载进化模块
new MutationObserver(()=>{if(!document.getElementById('tab-research')?.classList?.contains('hidden'))loadEvolutionBox();}).observe(document.body,{attributes:true,subtree:true});