先说结论:在同一份历史数据上测试过的策略越多,“最优策略”的样本内表现就越不可信——而 White Reality Check(WRC)是第一个把这句话变成可计算 p 值的检验。本文的模拟里,100 个真实期望收益为零的纯噪声策略,最优者年化夏普达到 1.26,单独看足以说服大多数人上仓位;但 WRC 用平稳自助法重建”运气能有多好”的零分布后,给出 p 值 0.21——不显著,纯属数据窥探。而当池子里混入一个夏普 2.0 的真 alpha 时,WRC 的 p 值在任何池规模下都压在 0.00,真信号稳稳存活。
数据窥探:量化研究的原罪#
Halbert White 在 2000 年的论文《A Reality Check for Data Snooping》(Econometrica)开篇就点破了问题:当一份数据被反复用于推断和模型选择时,“找到满意结果”这件事本身就有可能纯粹出于运气。这就是数据窥探(data snooping)。
它在量化研究中无处不在且难以避免:你调了 20 组参数、试了 5 种入场条件、换了 3 个持有期——就算每次只保留”最好的那个”,你实际上已经做了上百次隐性检验。问题的数学本质是极值统计:设 个策略的真实期望超额收益全部为零,每个策略的样本夏普近似服从均值为零的正态分布,那么” 个里挑最大”的期望值随 增长。、5 年日频数据时,最大样本夏普的期望就在 1.0 附近——不需要任何真实预测能力,光靠挑,就能挑出一个夏普 1 的策略。
传统的单策略 t 检验对此完全失效,因为它回答的问题是”这个策略的收益是否显著异于零”,而你实际问的问题是”我从 M 个策略里挑出来的最优者是否显著异于零”。这两个问题的零分布天差地别。
WRC 的核心构造:检验”最大值”而不是”单个值”#
White 的洞察是:既然你挑的是最大值,那就直接为最大值构造零分布。
设第 个策略在第 期相对基准的超额收益为 (基准可以是持有现金、买入持有指数等),样本均值为 。零假设是:
即”所有候选策略都不优于基准”。检验统计量取:
关键在于 的零分布没有解析形式——它取决于 个策略收益之间的全部相关结构(同一份数据上的参数变体往往高度相关)。White 的解法是自助法(bootstrap):对收益序列重采样,在”强制均值为零”的世界里重建 的分布,然后看观测到的 落在这个分布的哪个位置。
由于金融收益有序列相关,普通 i.i.d. 重采样会破坏时间结构,WRC 采用 Politis-Romano 的平稳自助法(stationary bootstrap):以概率 跳到随机新位置、以概率 顺延下一个观测,生成期望块长为 的随机块拼接序列,兼顾时间依赖与平稳性。
完整算法四步:
- 计算每个策略的去均值收益 (这一步把世界”拉回零假设”);
- 用平稳自助法生成 条重采样索引路径,对每条路径计算 ;
- p 值 = 的比例;
- p 值小于阈值 → 拒绝零假设,最优策略的超额表现不太可能纯靠运气。
注意它检验的对象是”整个策略池的搜索过程”,而非某个单独策略——这正是它和普通 t 检验的本质区别。
实验一:100 个纯噪声策略,最优者夏普 1.26#
import numpy as np
rng = np.random.default_rng(42)
M, T = 100, 1260 # 100 个策略,5 年日频
noise = rng.normal(0, 0.01, (T, M)) # 真实期望收益全部为 0
sharpes = noise.mean(0) / noise.std(0) * np.sqrt(252)
print(f"最大样本夏普: {sharpes.max():.2f}") # ≈ 1.26python
100 个策略的夏普大致对称分布在零附近,但最右端那个达到了 1.26。如果这是你参数扫描的输出,你几乎肯定会选它——而它的真实期望收益是精确的零。
实验二:WRC 判决——p 值 0.21,不显著#
def stationary_bootstrap_idx(T, avg_block=20, rng=None):
"""Politis-Romano 平稳自助法索引"""
p = 1.0 / avg_block
idx = np.empty(T, dtype=int)
idx[0] = rng.integers(T)
for t in range(1, T):
if rng.random() < p:
idx[t] = rng.integers(T) # 开新块
else:
idx[t] = (idx[t - 1] + 1) % T # 顺延(循环边界)
return idx
B = 500
demeaned = noise - noise.mean(0) # 强制回到零假设
obs_stat = np.sqrt(T) * noise.mean(0).max() # 观测到的最大统计量
br = np.random.default_rng(2024)
boot_max = np.array([
np.sqrt(T) * demeaned[stationary_bootstrap_idx(T, 20, br)].mean(0).max()
for _ in range(B)
])
p_value = (boot_max >= obs_stat).mean()
print(f"WRC p 值: {p_value:.2f}") # ≈ 0.21python
自助分布回答的问题是:“在所有策略真实收益为零的世界里,‘100 选 1 的最大值’通常有多大?“答案是:观测到的 1.26 夏普完全落在这个”运气分布”的正常范围内——21% 的纯运气路径能产生同样好或更好的最优者。单策略 t 检验会给这个策略 p≈0.01 的假显著,WRC 给出 0.21 的诚实答案。
实验三:真 alpha 能存活吗?#
把一个日均超额 13bp(年化夏普约 2.0)的真 alpha 策略混入池中,扫描池规模 从 5 到 100:
noise2 = rng.normal(0, 0.01, (T, M))
noise2[:, 0] += 0.0013 # 注入真 alpha:年化夏普约 2.0
# 对每个池规模 m,分别对纯噪声池和含 alpha 池跑 WRCpython结果(B=500):
| 池规模 M | 纯噪声池 p 值 | 含真 alpha 池 p 值 |
|---|---|---|
| 5 | 0.98 | 0.00 |
| 10 | 0.28 | 0.00 |
| 25 | 0.53 | 0.00 |
| 50 | 0.77 | 0.00 |
| 100 | 0.92 | 0.00 |

两个关键观察:
- 真 alpha 在任何池规模下都稳稳通过(p=0.00):夏普 2.0 的真信号足够强,即使被 99 个噪声策略稀释、即使检验为”100 选 1”的运气留足了余量,它仍然显著;
- 纯噪声池的 p 值高低起伏但从不显著:p 值本身是随机变量,0.28 到 0.98 的波动正常,重要的是它们都远离 0.05。
这就是 WRC 的价值主张:它不惩罚你搜索,它只要求你的最优者好到”超越搜索本身能带来的运气”。
WRC 的后继者:Hansen SPA 与 StepM#
WRC 有两个已知弱点,催生了两个重要改进:
- Hansen 的 SPA 检验(2005):WRC 对”池中存在大量明显很差的策略”敏感——垃圾策略会推高自助分布的方差、稀释检验功效(这也是实验三纯噪声 p 值波动的部分原因)。SPA 用样本依赖的均值调整把”深度负收益”的策略从零分布中剔除,功效更高,是目前文献中的默认选择;
- Romano-Wolf StepM(2005):WRC 只回答”最优者是否显著”这一个问题,StepM 用逐步下降法回答”哪些策略显著”,在控制族错误率的前提下给出整个显著策略集合。
工程实践中的组合拳:粗筛用 WRC/SPA 判断”这轮搜索有没有捞到真东西”,有则用 StepM 定位具体是哪几个,再对幸存者做样本外验证。
A. 实现细节#
- 超额收益 以零基准(现金)计算;若检验”是否跑赢指数”,应先逐期减去基准收益再进入同一流程,结论对象随之改变;
- 平稳自助法期望块长取 20 个交易日(约一个月),这是日频金融数据的常用默认值;块长应大致匹配收益的自相关衰减尺度,对策略收益几乎无自相关的场景(如本文模拟)结果对块长不敏感,真实动量/趋势策略收益自相关强,块长选择影响 p 值,建议做 10/20/40 三档敏感性;
- 去均值步骤 是 WRC 的灵魂:它保证自助世界严格服从零假设,同时保留策略间的相关结构与各自的方差——这正是解析方法给不出的东西;
- 在演示中够用,正式报告建议 以稳定 p 值的第二位小数;统计量用 而非夏普本身,与 White 原文一致(夏普版本需额外处理方差估计的自助一致性)。
B. 已知偏差#
- 策略池必须完整:WRC 只对”你申报的 M 个策略”负责。如果你实际试过 500 个、只把最后 100 个喂给检验,p 值依然被低估——隐性搜索无法被任何统计方法追溯,这是纪律问题不是技术问题;
- 模拟数据无波动聚集:真实收益的 GARCH 效应会让自助分布的尾部更肥,本文模拟下的 p 值相比真实场景可能整体偏小;对真实数据应确认块长足以覆盖波动聚集尺度;
- 功效随池规模衰减是真实代价:实验三中真 alpha 夏普 2.0 才能在 M=100 下保持 p=0.00;若真 alpha 只有夏普 0.8,大池子里它可能通不过 WRC——检验保守性的另一面就是漏检温和信号,这也是 SPA 改进的动机。
C. 结果解读#
- “选出来的夏普”必须打极值折扣:100 个零期望策略选出夏普 1.26,这个数字与 的理论尺度吻合——任何参数扫描的最优结果,先减去这个”运气基线”再谈价值;
- p=0.21 与 p=0.01 的天壤之别:同一个策略,单独检验显著、放回搜索背景下不显著,说明显著性不是策略的属性,而是”策略 + 发现过程”的联合属性。报告回测结果时不附带搜索规模 M,等于隐瞒了检验所需的关键参数;
- 真 alpha 的鲁棒存活是最有操作价值的结论:夏普 2.0 的信号在 20 倍噪声稀释下仍然 p=0.00,意味着 WRC 的保守性并不会误杀强信号——如果你的”最优策略”过不了 WRC,大概率不是检验太苛刻,而是信号本身太弱或根本不存在;
- 与多重检验折扣(Bonferroni/BHY)的分工:Bonferroni 类方法只用各策略的边际 p 值、忽略相关性,在策略高度相关时过度保守;WRC 通过自助法保留完整相关结构,是更精细的工具。实务顺序:日常快筛用 BHY 打折扣,重要决策(上实盘前)用 WRC/SPA 做终审;
- 适用边界:WRC 假设收益序列平稳,跨越重大结构断裂(如 2015 股灾前后、2020 疫情)的样本会让自助分布失真;此时应分段检验或改用允许结构变化的后继方法。它也不能替代样本外验证——WRC 回答”样本内的最优是否超越运气”,样本外回答”它在未见过的数据上是否依然成立”,两道关都要过。