alphax/static/strategy.html
2026-05-18 08:39:38 +08:00

33 lines
5.2 KiB
HTML

{% extends "base.html" %}
{% block title %}策略 — AlphaX Agent{% endblock %}
{% block extra_head_css %}
<style>
.shell{width:min(100% - 40px,1180px);margin:0 auto;padding:24px 0 48px}.page-head{margin-bottom:20px}.page-head h1{font-size:28px;letter-spacing:-.8px}.page-head p{color:var(--stone);font-size:14px;margin-top:4px}.metrics{display:grid;grid-template-columns:repeat(6,1fr);gap:12px;margin-bottom:12px}.metric{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-xl);padding:18px;text-align:center}.metric .num{font-size:30px;font-weight:900;letter-spacing:-.8px}.metric .lbl{font-size:12px;color:var(--stone);font-weight:700;margin-top:4px}.disclaimer{font-size:12px;color:var(--stone);background:var(--surface);border:1px solid var(--hairline-soft);border-radius:var(--radius-lg);padding:10px 14px;margin-bottom:16px}.flow{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:16px}.flow-step{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-lg);padding:12px}.flow-step b{display:block;color:var(--ink);font-size:13px;margin-bottom:5px}.flow-step span{display:block;color:var(--stone);font-size:12px;line-height:1.55}.flow-link{color:var(--primary);font-weight:900;text-decoration:none}.panel{border:1px solid var(--hairline-soft);background:var(--canvas);border-radius:var(--radius-xl);padding:18px;margin-bottom:16px}.panel h2{font-size:16px;margin-bottom:12px}.grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.table{width:100%;border-collapse:collapse}.table th,.table td{padding:9px 8px;border-bottom:1px solid var(--hairline-soft);font-size:12px;text-align:left}.table th{color:var(--stone);font-weight:800}.pos{color:var(--green);font-weight:800}.neg{color:var(--red);font-weight:800}.tag{display:inline-flex;border-radius:var(--radius-full);background:var(--surface);padding:3px 8px;font-weight:800}.empty{color:var(--stone);font-size:13px;padding:16px;background:var(--surface);border-radius:var(--radius-lg)}@media(max-width:980px){.metrics{grid-template-columns:repeat(2,1fr)}.flow{grid-template-columns:repeat(2,1fr)}}@media(max-width:820px){.grid{grid-template-columns:1fr}.shell{width:min(100% - 24px,1180px)}}@media(max-width:520px){.flow{grid-template-columns:1fr}}
</style>
{% endblock %}
{% block content %}
<div class="shell">
<div class="page-head"><h1>策略</h1><p>系统可信度、版本表现、因子归因与市场环境归因。</p></div>
<div class="metrics" id="metrics"></div>
<div class="disclaimer">数据基于历史信号跟踪,仅用于策略研究与模型评估,不构成收益承诺或投资建议。</div>
<div class="flow">
<div class="flow-step"><b>发现</b><span>粗筛只进观察/候选,不直接计交易绩效。</span></div>
<div class="flow-step"><b>确认</b><span>只有新鲜触发和入场计划达标才进入可交易口径。</span></div>
<div class="flow-step"><b>复盘</b><span>只用48h窗口样本更新有效表现。</span></div>
<div class="flow-step"><b>迭代</b><span>候选规则经发布闸门后才生效。<a class="flow-link" href="/iteration">查看迭代</a></span></div>
</div>
<div class="grid">
<section class="panel"><h2>版本表现</h2><div id="versionPerf"></div></section>
<section class="panel"><h2>市场环境归因</h2><div id="envPerf"></div></section>
</div>
<section class="panel"><h2>因子归因</h2><div id="factorPerf"></div></section>
</div>
{% endblock %}
{% block extra_script %}
<script>
function pct(x){x=Number(x||0);return (x>=0?'+':'')+x.toFixed(2)+'%'}function cls(x){return Number(x||0)>=0?'pos':'neg'}
function table(rows,key){if(!rows||!rows.length)return'<div class="empty">暂无数据</div>';return '<table class="table"><thead><tr><th>名称</th><th>次数</th><th>命中率</th><th>平均表现</th><th>最大表现</th><th>最大回撤</th></tr></thead><tbody>'+rows.map(r=>'<tr><td><span class="tag">'+(r[key]||'--')+'</span></td><td>'+r.total_count+'</td><td>'+Number(r.win_rate_pct||0).toFixed(1)+'%</td><td class="'+cls(r.avg_pnl_pct)+'">'+pct(r.avg_pnl_pct)+'</td><td class="pos">'+pct(r.max_gain_pct)+'</td><td class="neg">'+Number(r.max_drawdown_pct||0).toFixed(2)+'%</td></tr>').join('')+'</tbody></table>'}
async function load(){try{var d=await (await fetch('/api/strategy/insights')).json();var o=d.overview||{};var active=await (await fetch('/api/recommendations/active?actionable_only=false&hours=12')).json();metrics.innerHTML=['总信号|'+(o.total_signals||0)+'|','已验证|'+(o.resolved_count||0)+'|','信号命中率|'+Number(o.win_rate_pct||0).toFixed(1)+'%|green','当前有效机会|'+(Array.isArray(active)?active.length:0)+'|blue','最大表现|'+pct(o.max_gain_pct)+'|green','最大回撤|'+Number(o.max_drawdown_pct||0).toFixed(1)+'%|red'].map(s=>{var a=s.split('|');return '<div class="metric"><div class="num" '+(a[2]?'style="color:var(--'+a[2]+')"':'')+'>'+a[1]+'</div><div class="lbl">'+a[0]+'</div></div>'}).join('');versionPerf.innerHTML=table(d.version_performance,'strategy_version');envPerf.innerHTML=table(d.market_environment,'environment');factorPerf.innerHTML=table(d.factor_attribution,'factor')}catch(e){metrics.innerHTML='<div class="empty">加载失败</div>'}}load();
</script>
{% endblock %}