Files
sanguo_vnpy_v2/docs/proposal_strategy_library_v2.html
T

398 lines
22 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>策略库布局两版提案</title>
<style>
:root {
--ground: #070b10;
--card: #0d141c;
--panel: #101923;
--panel-2: #0a1119;
--border: #1d2a36;
--border-2: #16202b;
--brand: #00e5ff;
--brand-soft: rgba(0, 229, 255, 0.10);
--amber: #ffb000;
--amber-soft: rgba(255, 176, 0, 0.10);
--ok: #2ee68a;
--ok-soft: rgba(46, 230, 138, 0.10);
--err: #ff5470;
--text: #cfdae2;
--text-2: #9fb2bf;
--text-3: #64798a;
--mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
--sans: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--ground);
color: var(--text);
font-family: var(--sans);
font-size: 14px;
line-height: 1.55;
padding: 28px 20px 60px;
}
.wrap { max-width: 1080px; margin: 0 auto; }
header.prop { margin-bottom: 26px; }
.eyebrow {
font-family: var(--mono); font-size: 10.5px; letter-spacing: 2px;
color: var(--brand); text-transform: uppercase; margin-bottom: 8px;
}
h1 { font-size: 22px; font-weight: 600; color: #e8f1f7; letter-spacing: 0.3px; }
.prop-sub { color: var(--text-3); font-size: 13px; margin-top: 6px; }
.pain {
margin-top: 14px; padding: 10px 14px; border-left: 2px solid var(--amber);
background: var(--amber-soft); border-radius: 0 6px 6px 0;
font-size: 12.5px; color: var(--text-2);
}
section.ver { margin-top: 34px; }
.ver-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 6px; }
.ver-tag {
font-family: var(--mono); font-size: 11px; font-weight: 700; color: var(--ground);
background: var(--brand); border-radius: 4px; padding: 2px 9px; letter-spacing: 1px;
}
.ver-name { font-size: 17px; font-weight: 600; color: #e8f1f7; }
.ver-pro { font-size: 12.5px; color: var(--text-3); }
.ver-desc { font-size: 13px; color: var(--text-2); margin-bottom: 12px; }
.ver-desc b { color: var(--text); font-weight: 600; }
/* ===== 通用 mock 部件(两版共用视觉语言)===== */
.mock {
border: 1px solid var(--border); border-radius: 10px; overflow: hidden;
background: var(--card);
}
.mock-bar {
display: flex; align-items: center; gap: 8px; padding: 8px 14px;
border-bottom: 1px solid var(--border); background: var(--panel-2);
}
.dot { width: 9px; height: 9px; border-radius: 50%; background: #233240; }
.mock-title { font-family: var(--mono); font-size: 11px; color: var(--text-3); margin-left: 8px; }
.chip {
display: inline-flex; align-items: center; font-family: var(--mono);
font-size: 10px; padding: 1px 7px; border-radius: 999px;
border: 1px solid var(--border); color: var(--text-3); white-space: nowrap;
}
.chip.pf { color: var(--brand); border-color: rgba(0,229,255,.35); background: var(--brand-soft); }
.chip.cta { color: var(--amber); border-color: rgba(255,176,0,.35); background: var(--amber-soft); }
.chip.drift { color: var(--amber); border-color: rgba(255,176,0,.5); background: var(--amber-soft); }
.pill {
display: inline-flex; align-items: center; gap: 5px; font-family: var(--mono);
font-size: 10.5px; padding: 3px 9px; border-radius: 5px;
border: 1px solid var(--border); color: var(--text-3); background: transparent;
cursor: default; transition: border-color .12s;
}
.pill:hover { border-color: rgba(0,229,255,.5); color: var(--brand); }
.pill .lamp { width: 5px; height: 5px; border-radius: 50%; background: #2a3946; flex-shrink: 0; }
.pill.run .lamp { background: var(--ok); box-shadow: 0 0 6px rgba(46,230,138,.8); }
.pill.done .lamp { background: var(--ok); }
.pill.stopped .lamp { background: #4a5f6e; }
.pill.run { color: var(--text-2); border-color: rgba(46,230,138,.3); }
.btn {
font-family: var(--mono); font-size: 10.5px; padding: 4px 11px;
border-radius: 5px; border: 1px solid var(--border); color: var(--text-2);
background: transparent; cursor: default;
}
.btn.primary { color: #06252b; background: var(--brand); border-color: var(--brand); font-weight: 700; }
.muted { color: var(--text-3); }
.mono { font-family: var(--mono); }
.up { color: var(--err); } .down { color: var(--ok); } /* A股红涨绿跌 */
/* ===== 方案A 主从工作台 ===== */
.a-body { display: grid; grid-template-columns: 216px 1fr; min-height: 470px; }
.a-tree {
border-right: 1px solid var(--border); background: var(--panel-2);
padding: 10px 0; display: flex; flex-direction: column;
}
.a-search {
margin: 0 10px 8px; padding: 5px 9px; border: 1px solid var(--border-2);
border-radius: 6px; background: var(--card); color: var(--text-3);
font-family: var(--mono); font-size: 11px;
}
.a-group {
padding: 8px 12px 4px; font-size: 10.5px; font-weight: 700; color: var(--text-3);
letter-spacing: 1px; display: flex; align-items: center; gap: 6px;
}
.a-group .mark { width: 3px; height: 10px; background: var(--brand); box-shadow: 0 0 7px rgba(0,229,255,.6); }
.a-item {
display: flex; align-items: center; justify-content: space-between; gap: 6px;
padding: 6px 12px; font-family: var(--mono); font-size: 11.5px; color: var(--text-2);
border-left: 2px solid transparent; cursor: pointer;
}
.a-item:hover { background: rgba(255,255,255,.03); }
.a-item.on {
background: var(--brand-soft); border-left-color: var(--brand); color: var(--brand);
}
.a-count {
font-size: 9.5px; color: var(--text-3); background: rgba(255,255,255,.05);
border-radius: 999px; padding: 0 6px;
}
.a-item.on .a-count { color: var(--brand); }
.a-main { display: flex; flex-direction: column; }
.a-codehead {
display: flex; align-items: center; gap: 12px; padding: 13px 18px;
border-bottom: 1px solid var(--border); background: var(--panel);
}
.a-fname { font-family: var(--mono); font-size: 14px; font-weight: 700; color: #e8f1f7; }
.a-insts { padding: 8px 12px; }
.a-row {
display: grid; grid-template-columns: 1.25fr 1.9fr 0.85fr 1.35fr 1.5fr auto;
gap: 10px; align-items: center; padding: 12px 10px;
border-bottom: 1px solid var(--border-2); border-radius: 6px;
}
.a-row:hover { background: rgba(255,255,255,.025); }
.a-iname { font-size: 13px; font-weight: 600; color: var(--text); cursor: pointer; }
.a-iname:hover { color: var(--brand); }
.a-iname .sub { display: block; font-size: 10px; font-weight: 400; color: var(--text-3); margin-top: 2px; }
.a-ret { font-family: var(--mono); font-weight: 700; font-size: 13.5px; }
.a-ret .sub { display: block; font-size: 9.5px; font-weight: 400; color: var(--text-3); }
.a-runs { display: flex; gap: 5px; flex-wrap: wrap; }
.a-ops { display: flex; gap: 5px; }
/* ===== 方案B 档案卡墙 ===== */
.b-body { padding: 14px 16px 16px; }
.b-stats { display: flex; gap: 10px; margin-bottom: 12px; }
.b-stat {
flex: 1; border: 1px solid var(--border); border-radius: 8px; background: var(--panel-2);
padding: 9px 14px; display: flex; align-items: baseline; gap: 10px;
}
.b-stat .n { font-family: var(--mono); font-size: 20px; font-weight: 700; color: #e8f1f7; }
.b-stat .n.brand { color: var(--brand); }
.b-stat .l { font-size: 11px; color: var(--text-3); }
.b-filter { display: flex; gap: 8px; align-items: center; margin-bottom: 14px; }
.b-tab {
font-size: 11.5px; padding: 4px 13px; border-radius: 999px;
border: 1px solid var(--border); color: var(--text-3); cursor: pointer;
}
.b-tab.on { color: var(--brand); border-color: rgba(0,229,255,.45); background: var(--brand-soft); }
.b-search {
margin-left: auto; padding: 5px 10px; border: 1px solid var(--border-2);
border-radius: 6px; color: var(--text-3); font-size: 11px; font-family: var(--mono);
}
.b-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
@media (max-width: 760px) { .b-grid { grid-template-columns: 1fr; } .a-body { grid-template-columns: 160px 1fr; } }
.b-card {
border: 1px solid var(--border); border-radius: 9px; background: var(--panel);
padding: 13px 15px; display: flex; flex-direction: column; gap: 10px;
transition: border-color .12s;
}
.b-card:hover { border-color: rgba(0,229,255,.35); }
.b-chead { display: flex; align-items: center; gap: 8px; }
.b-cname { font-size: 13.5px; font-weight: 700; color: #e8f1f7; }
.b-cfile { font-family: var(--mono); font-size: 10px; color: var(--text-3); margin-left: auto; }
.b-crest { display: flex; align-items: baseline; gap: 10px; }
.b-big { font-family: var(--mono); font-size: 24px; font-weight: 700; }
.b-since { font-size: 10.5px; color: var(--text-3); }
.b-params {
font-family: var(--mono); font-size: 10.5px; color: var(--text-3);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.b-params .sym { color: var(--amber); }
.b-cfoot { display: flex; align-items: center; gap: 5px; border-top: 1px solid var(--border-2); padding-top: 10px; }
table.cmp { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 12.5px; }
table.cmp th, table.cmp td { border: 1px solid var(--border-2); padding: 8px 12px; text-align: left; }
table.cmp th { background: var(--panel-2); color: var(--text-3); font-family: var(--mono); font-size: 10.5px; letter-spacing: 1px; font-weight: 600; }
table.cmp td { color: var(--text-2); }
table.cmp td:first-child { color: var(--text); font-weight: 600; }
</style>
</head>
<body>
<div class="wrap">
<header class="prop">
<div class="eyebrow">UI / UX PROPOSAL · 策略库</div>
<h1>策略库布局改版 · 两版对比</h1>
<p class="prop-sub">现状痛点:所有策略代码堆成一列长表,每行 9 列信息(实例/参数/标的/收益/4 运行灯/操作),密密麻麻、没有层级——不知道自己在看"哪个策略"还是"哪个档案"。</p>
<div class="pain">共同增强(两版都带):状态灯变真数据(§12.6 回写)· 在跑账户小标签 · 参数漂移角标 · 一键发起 · 发起即建档</div>
</header>
<!-- ============ 方案 A ============ -->
<section class="ver">
<div class="ver-head">
<span class="ver-tag">方案 A</span>
<span class="ver-name">主从工作台(IDE 范式)</span>
<span class="ver-pro">聚宽策略列表 / VS Code 同款交互</span>
</div>
<p class="ver-desc"><b>左侧代码树,右侧选中代码的实例区</b>。一眼一个策略,密度自动降下来;代码多时靠左栏导航,不滚动。层级 = 左(代码)选谁 → 右(档案)看谁。</p>
<div class="mock">
<div class="mock-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="mock-title">sanguo · 策略库</span></div>
<div class="a-body">
<aside class="a-tree">
<div class="a-search">⌕ 搜索策略 / 实例…</div>
<div class="a-group"><span class="mark"></span>组合策略 · 5</div>
<div class="a-item on">all_weather<span class="a-count">3</span></div>
<div class="a-item">momentum_timing<span class="a-count">1</span></div>
<div class="a-item">value_selection<span class="a-count">1</span></div>
<div class="a-item">small_cap<span class="a-count">0</span></div>
<div class="a-item">channel_test<span class="a-count">1</span></div>
<div class="a-group"><span class="mark"></span>个股策略 · 9</div>
<div class="a-item">double_ma<span class="a-count">2</span></div>
<div class="a-item">cci_strategy<span class="a-count">0</span></div>
<div class="a-item"></div>
</aside>
<div class="a-main">
<div class="a-codehead">
<span class="a-fname">all_weather.py</span>
<span class="chip pf">组合</span>
<span class="mono muted" style="font-size:11px">AllWeatherStrategy</span>
<span style="margin-left:auto"></span>
<span class="btn">编辑代码</span>
<span class="btn primary">+ 新实例</span>
</div>
<div class="a-insts">
<div class="a-row">
<div class="a-iname">全天候·基准版<span class="sub">#3 · 更新 08-15</span></div>
<div class="mono muted" style="font-size:11px">d · max_pool=30 · benchmark=000300</div>
<div class="mono" style="color:var(--amber);font-size:11.5px">hs300_subset</div>
<div class="a-ret up">+15.48%<span class="sub">模拟 · 最新</span></div>
<div class="a-runs">
<span class="pill done"><span class="lamp"></span>回测</span>
<span class="pill"><span class="lamp"></span>回放</span>
<span class="pill run"><span class="lamp"></span>实走×2</span>
<span class="pill"><span class="lamp"></span>实盘</span>
</div>
<div class="a-ops"><span class="btn">编辑</span><span class="btn primary">发起</span></div>
</div>
<div class="a-row">
<div class="a-iname">全天候·小池激进<span class="sub">#5 · 更新 08-14</span><span class="chip drift" style="margin-left:6px">参数已漂移</span></div>
<div class="mono muted" style="font-size:11px">d · max_pool=10 · benchmark=000905</div>
<div class="mono" style="color:var(--amber);font-size:11.5px">zz500</div>
<div class="a-ret down">-2.31%<span class="sub">回测 · 最新</span></div>
<div class="a-runs">
<span class="pill done"><span class="lamp"></span>回测</span>
<span class="pill"><span class="lamp"></span>回放</span>
<span class="pill"><span class="lamp"></span>实走</span>
<span class="pill"><span class="lamp"></span>实盘</span>
</div>
<div class="a-ops"><span class="btn">编辑</span><span class="btn primary">发起</span></div>
</div>
<div class="a-row">
<div class="a-iname">全天候·对照(影子)<span class="sub">#7 · 更新 08-15</span></div>
<div class="mono muted" style="font-size:11px">15m · max_pool=30 · benchmark=000300</div>
<div class="mono" style="color:var(--amber);font-size:11.5px">hs300_subset</div>
<div class="a-ret up">+0.42%<span class="sub">影子 · 最新</span></div>
<div class="a-runs">
<span class="pill done"><span class="lamp"></span>回测</span>
<span class="pill"><span class="lamp"></span>回放</span>
<span class="pill run"><span class="lamp"></span>影子</span>
<span class="pill run"><span class="lamp"></span>实盘</span>
</div>
<div class="a-ops"><span class="btn">编辑</span><span class="btn primary">发起</span></div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ============ 方案 B ============ -->
<section class="ver">
<div class="ver-head">
<span class="ver-tag">方案 B</span>
<span class="ver-name">档案卡墙(QuantConnect 范式)</span>
<span class="ver-pro">以"档案"为中心 · 一卡一档</span>
</div>
<p class="ver-desc"><b>顶部全局统计 + 类型筛选,下面每实例一张竖卡</b>。层级靠筛选不靠导航;每个档案的收益是大数字、状态一目了然,适合"以实例为中心"巡检在跑的东西。</p>
<div class="mock">
<div class="mock-bar"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="mock-title">sanguo · 策略库</span></div>
<div class="b-body">
<div class="b-stats">
<div class="b-stat"><span class="n brand">14</span><span class="l">策略代码</span></div>
<div class="b-stat"><span class="n">8</span><span class="l">实例档案</span></div>
<div class="b-stat"><span class="n">4</span><span class="l">在跑运行</span></div>
<div class="b-stat"><span class="n">2</span><span class="l">参数漂移</span></div>
</div>
<div class="b-filter">
<span class="b-tab on">全部 8</span>
<span class="b-tab">组合 6</span>
<span class="b-tab">CTA 2</span>
<span class="b-tab">在跑 4</span>
<span class="b-search">⌕ 搜索…</span>
</div>
<div class="b-grid">
<div class="b-card">
<div class="b-chead"><span class="b-cname">全天候·基准版</span><span class="chip pf">组合</span><span class="b-cfile">all_weather.py</span></div>
<div class="b-crest"><span class="b-big up">+15.48%</span><span class="b-since">模拟实走 · 至 08-14</span></div>
<div class="b-params"><span class="sym">hs300_subset</span> · d · max_pool=30 · benchmark=000300</div>
<div class="b-runs" style="display:flex;gap:5px;flex-wrap:wrap">
<span class="pill done"><span class="lamp"></span>回测</span>
<span class="pill run"><span class="lamp"></span>实走×2</span>
<span class="pill"><span class="lamp"></span>回放</span>
<span class="pill"><span class="lamp"></span>实盘</span>
</div>
<div class="b-cfoot">
<span class="btn">编辑</span><span class="btn">回测</span><span class="btn">实走</span><span class="btn">影子</span>
<span style="margin-left:auto"></span><span class="btn primary">实盘</span>
</div>
</div>
<div class="b-card">
<div class="b-chead"><span class="b-cname">通路测试·双轨</span><span class="chip pf">组合</span><span class="chip drift">参数已漂移</span><span class="b-cfile">channel_test.py</span></div>
<div class="b-crest"><span class="b-big up">+0.42%</span><span class="b-since">影子 · 至 08-15</span></div>
<div class="b-params"><span class="sym">hs300_subset</span> · 15m · 双轨对账进行中</div>
<div class="b-runs" style="display:flex;gap:5px;flex-wrap:wrap">
<span class="pill done"><span class="lamp"></span>回测</span>
<span class="pill run"><span class="lamp"></span>影子</span>
<span class="pill run"><span class="lamp"></span>实盘</span>
<span class="pill"><span class="lamp"></span>回放</span>
</div>
<div class="b-cfoot">
<span class="btn">编辑</span><span class="btn">回测</span><span class="btn">实走</span><span class="btn">影子</span>
<span style="margin-left:auto"></span><span class="btn primary">实盘</span>
</div>
</div>
<div class="b-card">
<div class="b-chead"><span class="b-cname">双均线·浦发</span><span class="chip cta">CTA</span><span class="b-cfile">double_ma.py</span></div>
<div class="b-crest"><span class="b-big down">-1.07%</span><span class="b-since">回测 · 07-30</span></div>
<div class="b-params"><span class="sym">600000</span> · d · fast=5 · slow=10 · next_open</div>
<div class="b-runs" style="display:flex;gap:5px;flex-wrap:wrap">
<span class="pill done"><span class="lamp"></span>回测</span>
<span class="pill stopped"><span class="lamp"></span>回放·已停</span>
<span class="pill"><span class="lamp"></span>实走</span>
<span class="pill"><span class="lamp"></span>实盘</span>
</div>
<div class="b-cfoot">
<span class="btn">编辑</span><span class="btn">回测</span><span class="btn">实走</span><span class="btn">影子</span>
<span style="margin-left:auto"></span><span class="btn primary">实盘</span>
</div>
</div>
<div class="b-card" style="opacity:.72">
<div class="b-chead"><span class="b-cname">价值精选·试参</span><span class="chip pf">组合</span><span class="b-cfile">value_selection.py</span></div>
<div class="b-crest"><span class="b-big" style="color:var(--text-3)"></span><span class="b-since">未运行过</span></div>
<div class="b-params"><span class="sym">zz1000</span> · d · roe&gt;0.05 · 30 只</div>
<div class="b-runs" style="display:flex;gap:5px;flex-wrap:wrap">
<span class="pill"><span class="lamp"></span>回测</span>
<span class="pill"><span class="lamp"></span>回放</span>
<span class="pill"><span class="lamp"></span>实走</span>
<span class="pill"><span class="lamp"></span>实盘</span>
</div>
<div class="b-cfoot">
<span class="btn">编辑</span><span class="btn">回测</span><span class="btn">实走</span><span class="btn">影子</span>
<span style="margin-left:auto"></span><span class="btn primary">实盘</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ============ 对比 ============ -->
<section class="ver">
<div class="ver-head"><span class="ver-tag">对比</span><span class="ver-name">怎么选</span></div>
<table class="cmp">
<tr><th>维度</th><th>方案 A · 主从工作台</th><th>方案 B · 档案卡墙</th></tr>
<tr><td>层级感</td><td>★ 强:左代码右档案,选中即聚焦</td><td>中:靠筛选 tab 分层</td></tr>
<tr><td>信息密度</td><td>中:一屏看一个策略的全部档案</td><td>低:一卡一档留白大,滚动更长</td></tr>
<tr><td>策略多时</td><td>★ 左栏天然导航 + 搜索</td><td>卡片墙越滚越长</td></tr>
<tr><td>巡检在跑</td><td>要逐个点开代码看</td><td>★ 顶部统计 +「在跑 4」一键过滤,全局巡检快</td></tr>
<tr><td>改造量</td><td>中(List.vue 重排 + 选中态)</td><td>中(List.vue 重排 + 统计/筛选)</td></tr>
<tr><td>适合的心智</td><td>"我在调这个策略"</td><td>"我的档案们现在都怎么样"</td></tr>
</table>
<p class="prop-sub" style="margin-top:10px">也可以 A 为主 + 顶部借 B 的统计条(全局数字 + 在跑过滤入口),两版优点合并。</p>
</section>
</div>
</body>
</html>