2026年八月20日 · 优化

三种让你在不知不觉中搞砸滚动前推优化的方式

三种让你在不知不觉中搞砸滚动前推优化的方式

滚动前推优化素有"诚实调参法"的名声,而且当真配得上——至少相比在全部数据上调参然后欣赏结果要好得多。但这套方法有它的隐性失效模式,而每一种最终都会产出同一件产物:一份写着"稳健"的验证报告,钉在一个并不稳健的策略上。下面是我们不得不用工程手段防住的三种,按它们留下的残骸来归类。

失效之一:窗口发生泄漏

错误的做法:用 1 月到 6 月调参,用 7 月验证,然后放任任何来自 7 月的信息影响第二轮——看到样本外数字之后再跑一遍、对参数网格做个"小调整"、用整段序列做标准化的特征。每一步看起来都很无辜。合在一起,它们把样本外窗口变成了延迟到账的样本内数据。

残骸:样本外 Sharpe 会诡异地跟着样本内 Sharpe 走。真正的样本外结果是嘈杂且令人失望的;IS/OOS 之间关系过于平滑,说明信息在倒着流。我们会显式盯住这个比值——样本内超过样本外 3 倍就标记该次运行,样本外小于等于零则直接判死,不管样本内有多漂亮。

失效之二:跨窗口挑指标

跑三个滚动前推窗口,拿到三个嘈杂的结果,然后开始做汇总:平均 Sharpe?中位数?以"市场状态切换"为由把最差的那个窗口剔掉?每一个选择都是一个自由度,而一个执着的优化器(人或贝叶斯)总能找到那个让本策略看起来最好的汇总口径。每个窗口 75 次 Optuna 试验,就是 75 次拟合噪声的机会,再乘以你愿意考虑的汇总口径数量。

残骸:一个通过了验证、上线后却交出最差那个窗口表现的策略——因为最差的窗口才是唯一诚实的那个。我们的规则是:汇总方式在开跑前就写死在配置里,试验预算固定,分析师读的是逐窗口结果并且必须看到离散度。一个非得靠友好口径才能过关的策略,就是没过关。

失效之三:不再是留出集的留出集

留出集只管用一次。当一个策略第二次拿它来评估时——在参数微调之后、在信号改动之后、在一句"就看一眼"之后——它就不再是留出集了;它变成了一个慢速验证集。在迭代压力到来之前,保住 15 天未被触碰的数据听起来轻而易举,而一旦压力来了,再查一次就显得人畜无害。

这里的残骸很微妙:同一策略的多轮迭代中,留出集结果居然在稳步变好。全新的样本外数据没有任何理由偏爱第三轮胜过第一轮,一旦出现这种情况,就说明留出集已经被挖过了。我们用机制强制一次性:留出集在每次流水线运行中只评估一次,结果写入记录,需要再来一次的策略必须从头走完整套关卡——包括全新的窗口。它必须保住滚动前推样本外 Sharpe 的至少 70%,而这枚骰子没有第二次机会。

三种失效都躲不过的那个破绽

在这一切之前,我们会先跑一遍朴素的敏感性扫描:把每个参数上下拨动 ±20%,看指标的反应。真正的 edge 会平滑地退化;巧合则会跌落悬崖。这是整条流水线里最便宜的测试,而它否决掉的策略,本来是能一路顺风通过上面所有环节的——因为参数悬崖正是过拟合它有机会藏进验证机制之前的样子。

3.0×IS/OOS Sharpe 比值上限
70%留出集须保住的 WF OOS 占比
±20%每个参数的敏感性拨动幅度
1留出集评估次数,一生仅此

这些都不能让优化变得安全。它们只是让失效模式变得吵闹——而这已经是你能诚实地向一套验证流程索取的全部了。

优化滚动前推过拟合留出集敏感性
← 全部文章