summaryrefslogtreecommitdiff
path: root/frontend/src/pages/ProjectResultsTab.svelte
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-18 09:51:10 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-18 09:51:10 +0800
commitac55af50d93427b91db9f52415c3e7a749943420 (patch)
tree5590b7e1792df20b57eb0f48e409b3edec9c820b /frontend/src/pages/ProjectResultsTab.svelte
parent4390ca3472b8a4a201835e358ad0ad2065e8b7c6 (diff)
downloadstrategy-lab-ac55af50d93427b91db9f52415c3e7a749943420.tar.gz
feat(frontend): 图表增强——网格、hover 当日净值/回撤、回测区间阴影带
[变更性质] 图表层能力扩展,前端重设计第二轮之三。 [新增功能] Chart 网格线使用主题 border 色;hover 手柄提示补充"当日净值+回撤";回测区间 belowMarks 渲染半透明阴影带(bandShaded 可关);series 支持 dashed/opacity,Area 填充渲染;equity 行内合并回撤列,drawdown 图改为百分比格式化。 [实现方案] 基于 layerchart marks/belowMarks 泳道与自定义 tooltip snippet(lcExtras 透传绕开字面量类型检查),宽度扩展点保持 resolvedWidth 合同不变。 [影响范围] Chart.svelte、ProjectResultsTab.svelte;图表 probe 断言(svgs 渲染、溢出为 0)不变。
Diffstat (limited to 'frontend/src/pages/ProjectResultsTab.svelte')
-rw-r--r--frontend/src/pages/ProjectResultsTab.svelte26
1 files changed, 16 insertions, 10 deletions
diff --git a/frontend/src/pages/ProjectResultsTab.svelte b/frontend/src/pages/ProjectResultsTab.svelte
index 5ff03c0..f479116 100644
--- a/frontend/src/pages/ProjectResultsTab.svelte
+++ b/frontend/src/pages/ProjectResultsTab.svelte
@@ -55,16 +55,22 @@
const result = $derived<BacktestResult | null>(run?.result ?? null);
const hasEquity = $derived(!!result && result.equity.length > 0);
- // long-format rows for the layerchart renderer ({ i, date, ...columns })
+ // long-format rows for the layerchart renderer ({ i, date, ...columns });
+ // equity rows同时携带 dd(当日回撤%),供 hover 提示读数
const equityData = $derived.by(() => {
if (!result || !hasEquity) return [];
- return result.equity.map((p, i) => ({
- i,
- date: p.date,
- equity: p.equity,
- cash: p.cash,
- benchmark: p.benchmark ?? undefined
- }));
+ let peak = -Infinity;
+ return result.equity.map((p, i) => {
+ peak = Math.max(peak, p.equity);
+ return {
+ i,
+ date: p.date,
+ equity: p.equity,
+ cash: p.cash,
+ benchmark: p.benchmark ?? undefined,
+ dd: peak <= 0 ? 0 : -((peak - p.equity) / peak) * 100
+ };
+ });
});
const hasBench = $derived(equityData.some((r) => r.benchmark !== undefined && r.benchmark !== null));
@@ -193,9 +199,9 @@
<Button variant={chartMode === "drawdown" ? "default" : "outline"} size="sm" aria-pressed={chartMode === "drawdown"} onclick={() => (chartMode = "drawdown")}>回撤曲线</Button>
</div>
{#if chartMode === "equity"}
- <Chart data={equityData} series={equitySeries} ariaLabel="策略权益曲线" height={340} />
+ <Chart data={equityData} series={equitySeries} ariaLabel="策略权益曲线" height={340} extras={[{ key: 'dd', label: '回撤', color: '#134e4a' }]} />
{:else}
- <Chart data={drawdownData} series={drawdownSeries} ariaLabel="回撤曲线" height={300} />
+ <Chart data={drawdownData} series={drawdownSeries} ariaLabel="回撤曲线" height={300} valueFormatter={(v) => (typeof v === 'number' ? `${v.toFixed(2)}%` : String(v))} />
{/if}
</div>