Files
tick-stock-panel/docs/robust-optimizer-plan.md
T
shy3130 da9dbca422 feat(backtest): 稳健参数筛选与滚动样本外检验重构 (P1-P4)
参数排名从单窗样本内得分改为 K 段折外稳健分 R = 0.6×中位 + 0.4×最差
(设计: docs/robust-optimizer-plan.md), 四阶段全部落地:

- guards 共享护栏: 主目标白名单 + 最小交易数门槛 (fail-closed, 缺交易数
  按不达标处理), 两模式一处实现
- robust_optimizer: 等分切窗 (2-6 段, 每段≥14天) / 稳健分 / 冠军收敛诊断
  (unanimous/majority/scattered) / Top-20 全窗 IS 细化与退化率 /
  高原判据 (邻域得分衰减, 零额外回测); worker 接线 robust_optimize 任务
- 滚动样本外检验补强: 每折 OOS 最小交易数门槛 (无效折透明跳过),
  前端折预览 / 参数漂移轨迹 / 采用最新折参数
- 前端: 冠军卡 (收敛/高原徽章/乐观偏差) + K 段排名表 + 验证窗预览 +
  应用参数闭环 (POST /strategies/config, 可逆); SSE 重连与跨设备接回
- P4 摒弃旧路径: 删 /optimize/stream 与 /optimize/cancel 端点及 worker
  optimize 任务类型; 白名单全面生效 (optimizer.VALID_OBJECTIVES 收敛到
  guards; walkforward 端点校验退化目标 400)
- 附带修复: 叠加条件×矩阵路径 SignalMatrix 只读违规 (np.where 产物
  可写), optimizer_trial 轻量统计恒保留 n_trades

实测: 126 组合全市场网格 1.71× 旧版耗时 (视图复用优化自 2.01×; 差额
为引擎层每 run 固定开销, 详见方案文档第九节); 全量回归 3131 通过。

api.ts 同时带入稳健优化折预览客户端与声效语音包 API 客户端
(语音包功能随后续提交落地界面)。

Signed-off-by: shy3130 <shy3130@qq.com>
2026-10-25 20:14:10 +08:00

98 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 稳健参数优化与滚动样本外检验 · 重设计方案
> 状态: 设计已定稿, 待实施 (P1-P4)。取代原"参数优化"的样本内网格排名实现。
## 一、问题定义
原"参数优化"(optimizer.py) 在用户选定的**整段区间**上对每组参数回测并按单一目标排序——
排名即"对这段历史噪声的拟合度排名", 选出的必然是尖峰参数, 未来失效是设计使然。
原"步进优化"方法论骨架正确 (防前视折切分 + 复利 OOS 净值 + IS→OOS 退化), 但缺护栏与闭环。
## 二、命名 (已定稿)
| 旧名 | 新名 | 职责 |
| --- | --- | --- |
| 参数优化 | **稳健优化** | 选参数: 多段互不重叠验证窗上的稳健分排名, 产出一组参数 |
| 步进优化 | **滚动样本外检验** | 验流程: 每折重优化→紧邻样本外检验, 产出流程可信度判据 (Walk-Forward Analysis) |
命名原则: 按产出物命名。稳健优化的产出是参数, 叫优化合理; 滚动样本外检验的优化只是
内部工序, 产出是判定, 不叫优化。内部路由/任务类型 id 不改 (保任务注册表断线重连),
只改展示名与文档。
## 三、稳健优化 · 评估协议
**K 段锚定验证 + 两阶段预算**。区间 [S,E]:
1. 切窗: 等分为 K 个互不重叠验证段 V₁…V_K (默认 K=4, 可配 3-6)。每组参数**固定不变**
地在每个 Vᵢ 上独立回测 (复用 walkforward 折工具 + prepare_matrix_optimization 矩阵缓存)。
2. 稳健分: **R(p) = 0.6 × median(oos₁…K) + 0.4 × worst(oos₁…K)**
—— 中位数扛单段运气, 最差段惩罚"只在一段行情好用"; 各段得分与离散度并排展示
(离散度本身就是过拟合警报)。
3. 两阶段预算: 阶段一全网格只跑 K 个短验证窗 (总数据量 ≈ 一次全窗, 计算量与旧版持平);
阶段二仅 Top-20 跑全窗 IS 得分 (算 IS→OOS 退化率) + 邻域细化。
4. 免费诊断: 阶段一持有"每组×每段"完整得分矩阵 → 各段冠军收敛度直接可得。
各段冠军收敛 → 参数可信; 散落 → 策略本身参数不稳定, 任何"最优"都别信。
5. 高原判据: 冠军周围网格点的得分衰减率 (数据来自阶段一, 零额外计算)。
## 四、护栏 (两模式共用一处实现)
- 最小交易数门槛 (稳健优化默认 30 笔整体 / 滚动检验默认 10 笔每折 OOS 段):
不足的组合/折标记降序垫底, 不静默剔除。
- 主目标白名单收紧: sortino / sharpe / calmar / 年化 / 盈亏比 / 蒙卡回撤P95 / 最大回撤。
**删除 win_rate、平均持仓天数作主目标** (退化目标), 降级为展示列。
- 每段数据覆盖检查 (段内无数据/长停牌明确标注)。
## 五、滚动样本外检验 · 设计补强
保留: generate_folds 滚动切窗 (+1 天防前视隔断)、每折独立网格重优化、
aggregate_oos (复利 OOS 净值 / 退化 / 一致性)。补:
1. 每折 OOS 段最小交易数门槛 → 无效折排除出聚合 (沿用"只聚合有效折"机制)。
2. 折预览: 运行前实时显示折数/窗口/覆盖; 折数 < 3 警告"统计意义不足"。
3. 闭环「采用最新折参数」: 滚动检验的标准实践是拿最后一折训练参数上实盘,
走 /strategy/config override 通道 (带确认弹窗, 注明来源折)。
4. 参数漂移轨迹: 各折 best_params 逐参数轨迹 (如 ma_fast: 5→5→8→10) + 收敛度徽章;
与稳健优化的"各段冠军收敛度"同一诊断模块的两种呈现。
不做: 滚动检验不加"参数固定模式" — 那正是稳健优化阶段一 (避免重复), 文档写清分工。
## 六、闭环 (应用通道)
两模式的落地动作统一走现有 `POST /strategy/config` override 通道 (与优化器运行时同路,
策略页可查看/还原, 可逆、零新端点):
```
稳健优化 ──选参──▶ 滚动样本外检验 ──验流程──▶ 应用(override) ──▶ 回测/监控
└────────── 也可直接应用(带退化/高原判据) ──────────────┘
```
## 七、共享件 (一处实现, 两模式使用)
折工具函数 / 目标白名单+护栏 / 稳健分组件(median/worst/离散度) / 参数漂移诊断 /
矩阵缓存与 worker 隔离 / SSE+断线重连框架 / override 应用通道 / paramSweep 网格 UI。
## 八、落地阶段 (每阶段独立提交、独立验证)
| 阶段 | 内容 | 验证标准 |
| --- | --- | --- |
| P1 | 后端 robust_optimizer 模块: 切窗/稳健分/护栏/SSE v2; 共享护栏与漂移诊断模块; 滚动检验折有效性门槛 | 单测覆盖切窗边界/稳健分/门槛/取消; 实测 200 组×4 折耗时与 worker 内存 |
| P2 | 两阶段细化 + 稳定性诊断 + 高原比 + 折预览 | 性能 ≤ 旧版全量跑的 1.3 倍 |
| P3 | 前端: 稳健优化结果面板(排名表/冠军卡/高原视图/应用按钮) + 滚动检验新组件(折预览/漂移轨迹/采用最新折参数) | tsc/构建/vitest + 端到端 |
| P4 | 摒弃旧逻辑: 删 optimizer.py 单窗全量排名路径; 目标白名单收紧生效; README/docs 同步 | 全量回归绿 |
摒弃清单: 单窗样本内排名 / 退化主目标 / 纯展示无闭环的结果面板。
复用清单: worker 隔离 / 矩阵缓存 / SSE 任务框架与断线重连 / 网格 UI / override 通道 / 折工具函数。
## 九、已知权衡
- 验证段比全窗短 → 单段统计更噪; median+worst 聚合为此设计, 且这正是"未来任意一段行情"
的真实压力测试。
- 结果不再有单一"历史冠军"的爽感 — 特性而非缺陷, UI 文案引导解读。
- Top-20 细化增加约 10% 计算, 换高原判据。
- 性能实测偏离 1.3× 目标 (P2 验收): 126 组合×全市场网格实测稳健优化 (K=4+阶段二)
为旧版全量跑的 **1.71×** (视图复用优化后, 优化前 2.01×)。数据量比只有 1.16×
(146 窗口当量 / 126), 差额来自引擎层每 run 固定开销 (~28ms/段: 信号延迟矩阵重建
`_delay_signal_matrix` + 矩阵缓存 token 哈希 `_array_token`), 与窗口长度无关。
修它属于引擎级手术 (影响所有回测路径), 不在本次重构范围; 绝对值 44s/126 组合
完全可用。若未来引擎把 per-run 固定开销降到 ~10ms, 比值自然回到 ~1.3×。