HoldoutValidation 阶段 - 详细展开

对应摘要版:../简介/Holdout阶段.md 第一次阅读建议先看:./英文术语表.md

1. 先说人话:Holdout 是终审,不是补考

HoldoutValidation 是整条研究线里治理要求最严的一层。

它不是:

  • 再多拿一点数据看看
  • 再延长几个月观察一下
  • 看结果不理想时再调一调

它真正回答的问题是:

在完全未参与设计、调参、组合选择的最终窗口上,已经冻结好的方案还能不能成立?

所以 Holdout 的本质是:

终审,不是补考。


2. HoldoutValidation 回答的核心问题

2.1 冻结方案在未见窗口是否还能站住

这里不是看“有没有局部亮点”,而是看:

  • 方向是否还一致
  • 表现是否仍可解释
  • 与 Backtest 的偏离是否在可接受范围内

2.2 如果不一致,原因是什么

Holdout 不只是给 verdict,还要做解释。

解释通常要分几类:

  • 实现错误
  • 市场环境漂移
  • 策略本身失效

这一步非常重要,因为“结果差”不是唯一问题,结果差而解释混乱才是治理灾难。

2.3 如果失败,应该怎么处理

Holdout 失败之后,不是只有“全盘否定”一种路径。

常见合法结论有:

  • PASS
  • CONDITIONAL PASS
  • NO_GO
  • CHILD LINEAGE

关键是:

哪种情况触发哪种结论,必须在结果出来前就定义清楚。


3. 本阶段冻结的五组内容怎么理解

3.1 window_contract

这组定义:

  • Holdout 的起止窗口
  • 这一窗口是否只允许单次消费
  • 单窗口结果和合并窗口结果怎么产出

这里最重要的是:窗口必须是事先冻结好的,不能看结果再决定取哪里。

3.2 reuse_contract

这组定义:

  • Holdout 可以复用什么
  • Holdout 绝对不能改什么

例如:

  • factor selection 不可改
  • portfolio rules 不可改
  • cost model 不可改

这一步不是形式主义,而是在防止“结果不好就偷偷修一下”的冲动。

3.3 drift_audit

这组解决的是:

如果 Holdout 和 Backtest 不一致,我们要如何解释这种偏离?

这里通常要看:

  • rolling OOS 一致性
  • 方向是否翻转
  • 具体失败时段在哪里
  • 是否有可识别的市场环境变化

这一步不是为了帮策略找借口,而是为了避免团队在失败时只会说“市场变了”。

3.4 failure_governance

这组定义:

  • 什么叫方向翻转
  • 发生方向翻转后如何处置
  • 什么情况必须 NO_GO
  • 什么情况必须开 CHILD LINEAGE

重点是:

这些规则必须在结果出来前就写好。
不能等到结果出来后,看是有利还是不利再改处置口径。

3.5 delivery_contract

这组定义:

  • 哪些产物必须落盘
  • 什么文件能证明 Holdout 只跑过一次
  • 后续 Shadow / 实盘要继承哪些结论

4. 为什么 Holdout 绝对不能被当成可延期窗口

这是最重要的一条。

很多团队在这里会犯一个看似合理、实际上非常危险的错:

  • 先跑三个月 Holdout
  • 如果不好,就说“市场不匹配”
  • 再延三个月
  • 然后说“延期观察不算新的 Holdout”

这在治理上是站不住的。

原因是:

  • 你已经消费了未见窗口信息
  • 后面的任何继续观察,都会带着前面结果的影响
  • 这和真正的一次性未见验证已经不是一回事

所以:

Holdout 一旦开始消费,窗口就已经被使用了。

边界情况最多只能给出:

  • CONDITIONAL PASS
  • NO_GO
  • CHILD LINEAGE

不能把它包装成“只是继续观察”。


5. 这一阶段应如何落地

5.1 先确认复用对象

Holdout 开始时,首先要明确:

  • 当前复用的是哪一版 frozen_portfolio_spec
  • 对应哪一版 strategy_combo_ledger
  • 时间窗边界是否与 Mandate 一致

如果这一层都不清楚,后面的结果比较就没有意义。

5.2 生成单窗口结果

单窗口结果的意义是:

  • 看具体失败发生在什么时候
  • 看是否有局部方向翻转
  • 看波动是否集中在少数窗口

如果只有一份合并结果,很容易掩盖关键问题。

5.3 生成合并窗口结果

合并结果的意义是:

  • 给出整体判断
  • 便于和 Backtest 总结性结果比较

但它不能替代单窗口分析。

5.4 做 holdout_backtest_compare

这一层不是为了拼一条“大曲线”,而是为了做严肃对比。

应关注:

  • 整体方向是否一致
  • 退化幅度多大
  • rolling OOS 一致性如何
  • 是否出现特定时间段方向翻转

5.5 做 drift_audit

这一步的要求是:

  • 如果一致性低,必须明确指出是哪些窗口、什么原因
  • 解释必须有对象,不允许抽象空话

例如:

  • “2024-11 到 2024-12 的高波动 regime 中出现显著方向偏离”

比:

  • “市场风格变化了”

要有治理价值得多。


6. 输出物应该长什么样

典型输出物包括:

  • holdout_run_manifest.json
  • holdout_backtest_compare.csv
  • window_results/
  • holdout_gate_decision.md
  • artifact_catalog.md
  • field_dictionary.md

holdout_run_manifest.json

这类文件的重要性在于证明:

  • 跑的是哪一版冻结方案
  • 什么时候跑的
  • 是否只跑了一次

window_results/

这里必须保留单窗口结果,而不是只保留汇总。

holdout_backtest_compare.csv

这个文件只能用于比较,不能和 Backtest 曲线拼成一条“最终业绩曲线”。

这是非常重要的纪律。


7. 最常见的错误

7.1 根据 Holdout 结果回头调参

这是最严重的错误。

一旦发生,正确反应不是“修一下继续”,而是承认:

  • 这个 Holdout 已经被消费了
  • 后续若继续研究,应当按治理要求开新 lineage

7.2 把 Holdout 和 Backtest 拼成一条曲线

这会掩盖最终窗口的独立性,让人误以为整条曲线都是同等可信度。

实际上不是。

7.3 只看汇总,不看单窗口

只看合并结果,很容易忽略:

  • 方向翻转发生在哪几段
  • 是否只有极少数窗口在支撑整体结果

7.4 失败时只有情绪,没有治理结论

常见错误说法:

  • “最近行情不适合”
  • “再观察一下”
  • “这个阶段不代表真实水平”

这些话如果没有进入 drift_auditfailure_governance 的正式语义,就没有治理价值。


8. Holdout 失败后怎么判断是哪里出了问题

可以按三类分:

8.1 实现错误

比如:

  • 参数文件读错
  • 执行代码没复用 frozen spec
  • 时间戳对齐错误

这类问题允许按治理规则修复后重跑,因为它不是策略本身的问题,而是执行失败。

8.2 市场环境漂移

比如:

  • 极端波动 regime
  • 流动性结构变化
  • 某类资产集中异常

这类问题不一定等于策略无效,但必须在 drift_audit 中有明确解释。

8.3 策略本身失效

比如:

  • 方向持续反转
  • 多窗口一致性明显塌掉
  • 无法给出合理 drift 解释

这类情况通常不能再靠“观察一下”解决,应进入 NO_GOCHILD LINEAGE 路径。


9. 与 Shadow / 实盘的衔接

只有 HoldoutValidation 完成后,才有资格讨论 Shadow 或实盘。

交接时最重要的不是“最好看的指标”,而是:

  • 复用的是哪套冻结方案
  • Holdout 与 Backtest 的对比结论
  • drift audit
  • 失败治理规则
  • 若为 CONDITIONAL PASS,初始资金约束和退出条件是什么

否则实盘团队拿到的就只是“一个看起来还行的故事”,而不是正式结论。


10. 最后给一个判断标准

合格的 HoldoutValidation,应该满足:

即使结果不理想,团队也不能靠继续观察或回头调参来掩盖它;他们只能解释、裁决,然后决定是进入 Shadow,还是终止,还是另开 lineage。

如果这点做不到,那就说明 Holdout 还没真正成为终审。