{savedComboId ? "更新组合" : "保存为回测组合"}
}
>
setDraft({ ...draft, name: e.target.value })}
/>
setDraft({ ...draft, description: e.target.value })}
/>
setDraft({ ...draft, initialCapital: Number(e.target.value) })}
/>
setDraft({ ...draft, holdCount: Number(e.target.value) })}
/>
setDraft({ ...draft, holdMinDays: Number(e.target.value) })}
/>
setDraft({ ...draft, holdMaxDays: e.target.value === "" ? null : Number(e.target.value) })}
/>
setDraft({ ...draft, start: e.target.value })} />
setDraft({ ...draft, end: e.target.value })} />
{showErr("period") &&
{showErr("period")}
}
{running ? "后台运行中…" : "运行回测组合"}
N={draft.holdCount} · [{draft.holdMinDays}, {draft.holdMaxDays ?? "∞"}] 天 ·{" "}
{draft.rebalanceFreq === "daily" ? "日频" : draft.rebalanceFreq === "weekly" ? "周频" : "月频"} ·{" "}
{draft.start} ~ {draft.end} · {draft.strategyIds.length} 个策略
{blocking.length ? (
有 {blocking.length} 处需要修正
) : (
参数校验通过
)}
{running ? (
{["data_loading", "backtesting", "analysis"].map((st) => {
const order = ["queued", "data_loading", "backtesting", "analysis", "done"];
const cur = order.indexOf(stage);
const mine = order.indexOf(st);
const cls = mine < cur ? "stage is-done" : mine === cur ? "stage is-active" : "stage";
return (
{mine < cur ? "✓" : mine === cur ? "●" : "○"} {STAGE_LABEL[st] ?? st}
);
})}
作业 {jobId || "排队中…"} · 已用 {Math.round(elapsed / 1000)}s
(全市场多年区间约 3~5 分钟,可离开本页,结果会归档)
) : null}
{!result && !running && !error ? (