halo 的技术博客

返回

你跑了 40 个策略变体,挑出夏普最高的那个准备上仓位。问题来了:这个「最优」,是真有 edge,还是 40 次抽奖里运气最好的那张彩票?传统回测无法回答,因为它只给你一个夏普数字,不告诉你这个数字里有多少是运气。Bailey 和 López de Prado 在 2014 年提出的回测过拟合概率(Probability of Backtest Overfitting,PBO),用一套叫组合对称交叉验证(Combinatorially Symmetric Cross-Validation,CSCV)的方法,把「你选出的最优在样本外其实是平庸货」这件事,算成一个 0 到 1 之间的概率。这篇讲清 PBO 到底在算什么、怎么算、以及为什么它应该和夏普一起出现在每一份策略报告里。

过拟合的本质:选择偏差#

先厘清一个常被混淆的概念。这里说的「过拟合」,不是单个模型参数太多那种过拟合,而是选择偏差(selection bias)造成的过拟合。机制是这样的:

假设你有 NN 个策略,它们真实的 alpha 全是零——纯噪声。你在样本内(in-sample,IS)比较它们的夏普,总会有一个碰巧最高。你把它选出来。但它样本内高,纯粹因为它在这段历史里噪声运气最好,到了样本外(out-of-sample,OOS),它的运气会均值回归,掉回平庸。「在一堆随机变量里取最大值」这个动作本身,就是过拟合的来源——搜的变体越多,选出来的「最优」越可能只是极值噪声。

一个简单的数字能吓到你:假设 NN 个策略真实夏普都是 0,你测 N=100N=100 次,「至少有一个样本内夏普看起来显著」的概率高得离谱。这就是为什么「一晚跑几百个变体挑最好的」是量化里最隐蔽、也最致命的坑——你不是在发现 alpha,你是在挖掘噪声。

CSCV:用组合把「一次样本外」变成「几千次样本外」#

要量化选择偏差,你需要反复问「样本内选出的最优,在样本外表现如何」。传统做法切一段样本外,只能问一次。CSCV 的核心思想是:把时间轴切成 SS 块,然后穷举「一半块做训练、一半块做测试」的所有对称组合,每种组合都问一次。

SS 块里取 S/2S/2 块做训练集,剩下 S/2S/2 块做测试集,一共有 (SS/2)\binom{S}{S/2} 种分法。S=14S=14 时是 (147)=3432\binom{14}{7}=3432 种——一次回测数据,硬是榨出 3432 条独立的「样本内 vs 样本外」对照。下图用 S=8S=8(84)=70\binom{8}{4}=70 种,方便看)画出这个组合结构:

CSCV 组合对称分块

每一行是一种划分,蓝色「训」是训练块、红色「测」是测试块。对称性体现在:训练和测试各占一半,且每一种「取一半」的组合都被枚举到。这保证了不偏袒任何特定的时间切分方式。

PBO 的算法:logit 排名分布#

有了这几千种划分,PBO 的计算流程干净利落。对每一种划分 cc

  1. 在训练集上算出所有 NN 个策略的夏普,找出样本内最优的那个,记它的序号为 nn^*
  2. 到测试集上,看这个 nn^* 号策略的样本外夏普,在全部 NN 个策略的样本外夏普里排第几。用相对排名 ωˉc(0,1)\bar{\omega}_c \in (0,1) 表示(1 = 样本外也最好,0 = 样本外最差)。
  3. 把相对排名转成 logit:λc=lnωˉc1ωˉc\lambda_c = \ln\frac{\bar{\omega}_c}{1-\bar{\omega}_c}。样本外排在中位数以上,λc>0\lambda_c>0;掉到中位数以下,λc<0\lambda_c<0

PBO 就是样本内最优策略、在样本外掉到中位数以下的组合占比

PBO=#{c: λc<0}组合总数\mathrm{PBO} = \frac{\#\{c:\ \lambda_c < 0\}}{\text{组合总数}}

直觉很清楚:如果你选出的「最优」是真本事,它样本外也该排在前面,λc\lambda_c 大多为正,PBO 低;如果它只是噪声运气,样本外会随机散开、常常掉到下半区,PBO 高(接近甚至超过 0.5)。

两个对照实验:噪声池 vs 真 alpha 池#

光有公式不够,得看它在「已知答案」的场景下是否给出正确判断。我构造了两个策略池,各 40 个策略、1000 期日收益:

  • 纯噪声池:所有 40 个策略真实 alpha 都是 0,只有随机波动。
  • 含真 alpha 池:其中 8 个策略注入了稳定的正 alpha,其余 32 个是噪声。

跑 CSCV(S=14S=14,3432 条路径),结果对比鲜明:

PBO logit 分布对比

左边纯噪声池,logit 分布大幅骑跨在红线(λ=0\lambda=0)两侧,左半区占了 PBO ≈ 0.39——近四成的组合里,你样本内挑的「最优」样本外掉进了下半区。这正确地告诉你:这个池子里的最优基本靠不住。右边含真 alpha 池,logit 分布整体被推到红线右侧,PBO ≈ 0.06——样本内最优几乎总是样本外也最优,说明这里的「最优」是真 edge。PBO 干净地区分了两种情形。

再看样本内夏普对样本外夏普的散点,退化过程一目了然:

样本内外夏普退化图

红色(纯噪声池)的点:样本内夏普再高,样本外都被打回零附近,完全偏离对角线(IS=OOS 理想线)——这就是过拟合的视觉签名。绿色(含真 alpha 池)的点:样本内高的,样本外也守在对角线附近,说明业绩能延续。一句话:过拟合的策略,样本内夏普对样本外夏普没有预测力,而 PBO 把这个「没有预测力」的程度量化成了一个概率。

PBO 相比「切一段样本外」强在哪#

传统验证切最后 20% 当样本外、跑一次。PBO 有三个实质提升。

一、它给分布,不给点。 单一样本外只有一个数字,你不知道它是运气还是本事。PBO 背后是几千条样本外路径,能看到整个 logit 分布的形状、均值、偏斜。

二、它直接量化选择偏差。 这是 PBO 最独特的地方。单一样本外无法回答「我搜了 40 个变体,选出的最优有多大概率是蒙的」——而 PBO 就是为这个问题设计的。做参数扫描、因子挖掘时,PBO 应该和夏普并列上报。

三、它对称、无偏。 传统样本外偏爱「最后那段时间」,如果那段恰好是特定市场环境,结论就有偏。CSCV 穷举所有对称划分,不押注任何单一时间切法。

一条实践准则:夏普 2.0 但 PBO 0.5 的策略,远不如夏普 1.2 但 PBO 0.1 的策略可信。前者告诉你「这个漂亮夏普有一半概率是自欺欺人」,后者告诉你「这个夏普虽然没那么炸裂,但很可能是真的」。

小结#

PBO 的一句话本质:用组合对称交叉验证榨出几千条样本外路径,量化『你从一堆策略里选出的最优,在样本外其实是平庸货』的概率。它不能让坏策略变好,但能在你上真金白银之前,诚实地告诉你「这个最优里有多少是选择偏差挖出来的噪声」。在参数越调越多、变体越跑越密的今天,PBO 这种把过拟合概率算成数字的工具,比又一个高夏普回测有价值得多——因为它戳破的,正是量化研究里最贵的那个幻觉。

诚实边界:CSCV 的组合数 (SS/2)\binom{S}{S/2}SS 爆炸增长(S=20S=20 就是 18 万种),对需要重训练的模型(深度学习)计算上不现实,需在分块数和算力间权衡。其次,PBO 假设你喂进去的策略集合能代表真实的搜索空间——那些没记录下来的隐性调参(试了但没保存的变体)若未计入,PBO 仍会系统性低估真实过拟合程度。第三,CSCV 打乱时间块的组合方式,隐含假设各分块间机制大致平稳;遇到强 regime 切换时,组合出来的训练/测试拼接可能包含现实中不会发生的时间顺序,使夏普估计失真。最后,PBO 用夏普作为绩效指标默认收益近似 i.i.d.,对强自相关或路径依赖的策略,块内夏普估计本身就有偏,会污染整个 PBO。(中阶)

回测过拟合概率 PBO:用组合对称检验量化『选出来的最优』有多假
https://blog.halo26812.eu.org/blog/pbo-overfitting-probability
Author halo
Published at 2026年7月27日
版权声明 CC BY-NC-SA 4.0
Comment seems to stuck. Try to refresh?✨