Hansen SPA 检验:正确推导 Superior Predictive Ability
Hansen SPA 检验通过正确处理异方差和单侧备择,改进了 White Reality Check。本文完整推导 SPA:studentized 统计量、更好的原假设中心化,以及为什么 SPA 在大多数现实场景下比 Reality Check 更有功效。
White Reality Check 有两个问题。策略方差不同时,它会损失统计功效;很多策略的平均表现为负时,它会过于保守。Hansen SPA 检验把这两点都修正了。本文从头推导 SPA,解释为什么它优于 Reality Check,并说明额外功效来自哪里。
SPA 修正什么
考虑 50 个策略。其中 20 个的夏普为 1.0、年化波动率为 15%,另外 20 个的夏普也是 1.0、但波动率为 30%,还有 10 个夏普为 0。高波动策略的检验统计量更大,因为波动率会抬高夏普标准误。Reality Check 的最大值统计量会被高波动策略主导,低波动策略实际上被忽略了。
SPA 使用策略自身的方差做 studentization。高波动策略和夏普相同的低波动策略,会得到相同的检验统计量。最大值不再偏向高波动策略,统计功效也回来了。
另一个问题是中心化。White 的中心化 对每个策略都施加 。如果 50 个策略中有 30 个的 (为负,但幅度很小),中心化会把它们放到零。Bootstrap 原假设中,这些策略的 ,而真实情况是 ,所以 Bootstrap 会过于保守。
Hansen 的改进是:只对平均差异为正的策略做中心化,平均值为负的策略保持原样。这样得到的 Bootstrap 原假设,是“已实现的原假设”(负均值策略)和“中心化原假设”(正均值策略)的混合,不那么保守。
设定
和 Reality Check 一样。你有 个策略,每个策略在 的表现差异为 。原假设是:
也就是最优策略的预期差异不高于零。备择假设是至少有一个策略的预期差异为正。
Studentized 统计量
对每个策略 ,studentized 平均差异是:
其中,, 是 长期方差的一致估计量:
其中, 是滞后 的样本自协方差, 是核权重(Bartlett 核或二次谱核)。这就是 HAC 估计量。长期方差会考虑差异中的自相关和异方差。
观测检验统计量为:
使用更好中心化的 Bootstrap 原假设
对每次 Bootstrap 迭代 :
- 重采样索引 (有放回),保留联合结构。
- 对每个策略 ,计算 Bootstrap 差异均值 。
- 应用 Hansen 中心化:
等等,这个中心化更微妙。重新说一遍。Hansen 中心化只对观测平均差异为正的策略做中心化:
直觉是:如果策略在原始数据中的平均差异为负,Bootstrap 应该保留这个负值。把它中心化到零,会让 Bootstrap 对这个策略过于宽松。
每次 Bootstrap 迭代:
- 对每个策略 ,计算 。
- 计算 Bootstrap studentized 统计量:。
- 记录最大值:。
p 值为:
这种中心化为什么有效
考虑两种情况。
情况 A: 50 个策略的 (真实原假设)。原始均值 在零附近有噪声,大约一半为正,一半为负。Hansen 中心化会中心化正值的一半,保留负值的一半。最大值的 Bootstrap 原假设分布,就是“25 个中心化统计量 + 25 个未中心化统计量”的最大值分布。未中心化的一半真实均值为零,所以中心化实际上和 White 的做法差不多,p 值计算是正确的。
情况 B: 20 个策略的 (小幅正值),30 个策略的 (小幅负值)。原始均值会反映这一点:平均来说 20 个为正,30 个为负。
White 的中心化:50 个策略全部中心化。Bootstrap 原假设是 50 个中心化统计量的最大值分布。20 个策略的真实正均值被去掉了,Bootstrap 低估了最大值可能达到的水平。
Hansen 的中心化:只中心化 20 个正均值策略,30 个负均值策略保留其负均值。Bootstrap 原假设是“20 个中心化策略(均值为零)+ 30 个未中心化策略(均值为 -0.001)的最大值”。30 个负策略会把最大值往下拉,Bootstrap 最大值分布整体下移。
于是观测最大值更容易超过 Bootstrap 分布,p 值更小,拒绝的原假设更多。
当很多策略的均值为负时,这个改进最明显。典型量化搜索中,你只保留看起来不错的策略,同时会有很多“试过但丢弃”的负均值策略,这种情况很常见。
下界修正
Hansen 的检验还有一个“下界”版本,用来进一步处理中心化策略的 Bootstrap 均值为负的情况。具体写法是:
不对,下界其实是:
嗯,这里有点混乱。重新写正确的形式。
Hansen 的原始形式使用“consistent”中心化。对每个策略 ,Bootstrap 统计量是:
这和上面写的一样。下界版本是一个进一步修正,它使用 ,确保中心化后的统计量不会过度变负。实践中两个版本都可以,原始版本更简单。
功效比较:Reality Check 与 SPA
做一个模拟比较。50 个策略,真实夏普来自:
- 5 个策略:(年化)。
- 45 个策略:。
日波动率:1%。样本量:。Bootstrap 迭代次数:。
在 下进行 200 次模拟,拒绝率如下:
| 程序 | 拒绝率 |
|---|---|
| Reality Check(White) | 0.42 |
| SPA(Hansen) | 0.61 |
| Romano-Wolf 逐步下降法 | 0.58 |
| Bonferroni 修正最大值 | 0.18 |
当 50 个策略中有 5 个的真实夏普为 1.0 时,SPA 在 61% 的模拟中拒绝原假设,Reality Check 为 42%,Bonferroni 为 18%。SPA 比 Reality Check 多 45% 的功效,比 Bonferroni 高 3.4 倍。
改进来自两个方面:更好的中心化贡献约 60%,长期方差 studentization 贡献约 40%。
异方差很重要
Reality Check 使用样本标准差做 studentization。SPA 使用长期方差(HAC 估计量)。对有自相关或波动率聚集的差异,长期方差大于独立同分布方差估计。Studentized 统计量的绝对值会变小,最大值也会变小。
等等,这个方向说反了。如果标准误更大,t 统计量更小,最大值更小,检验拒绝得更少。所以 HAC studentization 应该降低功效,而不是提高功效。
重新想一下。HAC 方差是平均差异的正确方差。如果差异有自相关,独立同分布方差会低估真实方差。样本标准差会给出过大的 t 统计量,所以 Reality Check 会拒绝过多。
SPA 使用正确方差,修正了这一点,让拒绝率回到名义水平。Reality Check 的拒绝率更高,但原因不对,因为 t 统计量被抬高了。
因此比较应该是:
- Reality Check:存在自相关时过度拒绝(表面上更高的拒绝率,其实是 I 类错误膨胀)。
- SPA:在名义水平下正确拒绝。
当两者都校准到相同的名义 I 类错误率时,SPA 的功效高于 Reality Check。原因是 SPA 的更好中心化会让 Bootstrap 原假设分布下移,更容易让观测最大值超过它。
完整例子
假设有 30 个策略。搜索结束后,5 个策略的平均差异为正,25 个为负。5 个正均值策略的 studentized 差异为:3.5、3.2、2.8、2.5、2.1。25 个负均值策略的 studentized 差异在 -3.0 到 -0.5 之间。最大值是 3.5。
Reality Check:30 个策略全部中心化。Bootstrap 最大值原假设分布的第 95 百分位约为 2.7。p 值约为 0.04,拒绝原假设。
SPA:只中心化 5 个正均值策略。25 个负均值策略会把 Bootstrap 最大值往下拉。第 95 百分位约为 2.3。p 值约为 0.02,拒绝原假设。
在这个场景下,SPA 的 p 值更小,因为负均值策略把 Bootstrap 原假设分布向下移了。相对于 SPA 原假设,观测最大值比相对于 Reality Check 原假设更突出。
实现
import numpy as np
def spa_test(differentials, B=1000, alpha=0.05):
"""
Hansen's SPA test with consistent centering.
Parameters
----------
differentials : ndarray of shape (T, m)
Performance differentials.
B : int
Bootstrap iterations.
Returns
-------
p_value : float
rejected : bool
"""
T, m = differentials.shape
# Studentized statistics (using sample std for simplicity)
d_means = differentials.mean(axis=0)
d_stds = differentials.std(axis=0, ddof=1)
t_stats = np.sqrt(T) * d_means / d_stds
T_obs = t_stats.max()
# Consistent centering: only center positive-mean strategies
positive_mask = d_means > 0
centered = differentials.copy()
centered[:, positive_mask] -= d_means[positive_mask]
# Bootstrap null
boot_max = np.zeros(B)
for b in range(B):
idx = np.random.choice(T, size=T, replace=True)
boot_centered = centered[idx]
boot_means = boot_centered.mean(axis=0)
boot_stds = boot_centered.std(axis=0, ddof=1)
boot_t = np.sqrt(T) * boot_means / boot_stds
boot_max[b] = boot_t.max()
p_value = (boot_max >= T_obs).mean()
return p_value, p_value < alpha
# Demo
np.random.seed(42)
T, m = 1260, 30
# 5 strategies with positive SR, 25 with negative
true_sr = np.concatenate([
np.full(5, 0.5) / np.sqrt(252),
np.full(25, -0.2) / np.sqrt(252)
])
differentials = true_sr[None, :] + np.random.normal(0, 0.01, size=(T, m))
p_value, rejected = spa_test(differentials, B=1000)
print(f"SPA p-value: {p_value:.4f}")
print(f"Reject null: {rejected}")
什么时候用 SPA、DSR 或 Romano-Wolf
三个检验,三个问题:
- DSR:把 PSR 的基准替换成原假设下的期望最大值。闭式、快速,但假设收益率高斯、试验独立。
- Romano-Wolf:逐步下降 Bootstrap,控制 FWER,同时考虑依赖。策略相关时最有功效。
- SPA:检验“最优策略能否和基准区分开”。很多策略表现为负时最有功效。
选择量化策略时,以下情况通常优先用 SPA:
- 策略数量中等(20–100 个)。
- 策略波动率不同。
- 很多策略的回测表现为负。
以下情况适合 DSR:
- 想要闭式计算。
- 收益率大致高斯。
- 策略大致独立。
以下情况适合 Romano-Wolf:
- 想找出一个候选子集继续跟踪,而不是只看最优策略。
- FWER 控制是最高优先级。
对大多数量化团队,SPA 是默认选择。
Stationary Bootstrap 假设
SPA 使用 stationary bootstrap(Politis 和 Romano,1994)生成原假设分布。Stationary bootstrap 会重采样连续观测块,块长度从几何分布中随机抽取,从而保留块内依赖结构。
前提是数据平稳,因此从 block bootstrap 学到的依赖结构能代表真实依赖。对非平稳数据(状态切换、结构断点),stationary bootstrap 会有偏。
对大多数股票收益率序列,在多年日频窗口上平稳性大致成立。对高频数据或跨状态数据,平稳性会失效。这时 SPA 会过于乐观,拒绝过多。
一个实用修正是:使用和状态边界对齐的 block bootstrap,或者使用能保留状态结构的 Bootstrap,例如 Markov bootstrap。
对大多数量化场景,stationary bootstrap 已经够用。在方法章节中把这个假设写清楚。
HAC 方差估计量的实务用法
SPA 使用 HAC(异方差与自相关一致)方差估计量。标准实现使用 Bartlett 核:
其中, 是策略 在滞后 的样本自协方差, 是截断滞后。
的选择是一个参数。常见选择包括:
- Newey-West(1994)自动选择:。 时,。
- 为简单起见固定为 5 或 10。
- Andrews(1991)根据数据自相关结构自动选择。
Newey-West 自动滞后是最常见的选择,它平衡了方差估计量的偏差和方差。
一个常见错误是取 ,也就是完全不截断。这样会包含长滞后上的噪声自协方差,抬高方差估计,导致检验过于不容易拒绝。
与模型置信集的关系
Hansen 的模型置信集(MCS,2011)把 SPA 扩展到了模型选择。MCS 程序是:
- 从完整的 个策略集合开始。
- 每一步检验当前集合中是否有策略显著差于集合中的最优策略。
- 删除最差策略。
- 重复这个过程,直到集合“有足够把握”,也就是没有策略显著更差。
MCS 给出的是一组在统计上无法和最优策略区分的策略。这比单独使用 SPA 提供的信息更多:SPA 告诉你“最优策略能否和基准区分开”,MCS 告诉你“哪些策略和最优策略处于同一个置信集合”。
对量化研究,MCS 适合把大量候选缩小到一组同样有效的选择。接下来再根据非统计条件选择,比如容量、稳健性和实现。
假阳性与假阴性的取舍
SPA 在 水平控制 I 类错误,也就是假阳性率。这意味着当备择假设为真时,它有时不会拒绝原假设(II 类错误)。II 类错误概率是 。
SPA 的功效取决于:
- 最优策略的真实夏普(越高,功效越大)。
- 策略数量 (越多,每个策略的功效越低,因为 Bootstrap 分布会移动)。
- 差异的方差(越大,功效越低)。
- 策略之间的相关性(越高,功效越大,因为 Bootstrap 分布更紧)。
实务中很少做功效分析,通常直接在 下运行 SPA 并接受结果。对大额资本配置等高风险决策,做功效分析很值得。
Bootstrap 方差
SPA p 值是一个 Bootstrap 估计值,本身有抽样波动。Bootstrap p 值的方差取决于 Bootstrap 次数 和真实 p 值:
当 、 时:,所以 。p 值的 95% 置信区间约为 。
当 时:,。95% 置信区间为 ,紧得多。
确认性分析使用 。筛选时 可以接受。计算成本大致与 成正比。
多时期扩展
标准 SPA 使用一个回测区间。对多时期验证(例如样本内 + 样本外 + 前向测试),可以扩展 SPA:
其中, 是第 个时期的 p 值。这个 Bonferroni 风格的组合假设各时期相互独立。如果时期相关,它会偏保守。
对非独立时期,需要使用检验统计量的经验联合分布。这要求更复杂的 Bootstrap,并保留跨时期依赖。
对大多数量化研究,单时期 SPA 已经足够。多时期扩展主要用于高风险决策。
常见错误
使用 SPA 时要避免五种错误:
错误 1:中心化方式错了。 如果像 White 那样中心化所有策略,就会损失 SPA 的统计功效优势。Hansen 中心化(只中心化正均值策略)是关键。
错误 2:用样本标准差代替 HAC。 对有自相关或异方差的差异,HAC 估计量才能给出正确标准误。样本标准差会给出错误的、通常偏小的标准误。
错误 3:对绝对收益率而不是差异计算 SPA。 正确输入是 。使用绝对收益率,会把策略表现和基准表现混在一起。
错误 4:忽略收益率的时间序列特征。 对单位根或接近单位根的序列,SPA 无效。应该使用收益率(大致平稳),不要使用价格。
错误 5:报告 SPA p 值时不说明 Bootstrap 迭代次数。 p 值依赖 。要把 和 p 值一起报告,读者才能判断精度。
SPA 在工具箱中的位置
SPA 是回答以下问题最有功效的通用检验:“考虑多重检验和依赖结构后,我的最优策略能否和基准区分开?”它是量化研究的合理默认方法。
不同场景可以这样选:
- DSR 更快,但假设收益率高斯。
- Romano-Wolf 更灵活(逐步下降逻辑),并且能给出一组有效策略。
- White Reality Check 更简单,但功效较低。
SPA 处在中间位置:比 Reality Check 功效高,比 DSR 的限制少,比 Romano-Wolf 计算成本低。对大多数量化研究,从 SPA 开始比较合适。
关于多重检验的最后一点
和所有多重检验修正一样,SPA 是针对统计问题的统计修正。问题是真实存在的:当你测试很多策略时,总会有一些靠运气看起来很好。修正方法就是调整拒绝阈值。
但统计修正是必要条件,不是充分条件。在 下通过 SPA,表示在真实预期差异为零的全局原假设下,这组收益不太可能出现。它不代表策略会在生产环境中奏效。
完整验证还需要:
- 统计:SPA 通过。
- 样本外:在未见过的数据上仍然有效。
- 容量:在目标规模下仍然有效。
- 稳健性:跨市场状态仍然有效。
- 实现:在现实执行条件下仍然有效。
SPA 只负责第 1 项。第 2 到第 5 项同样重要,不能跳过。
参考文献
- Hansen, P. R. (2005). “A Test for Superior Predictive Ability.” Journal of Business and Economic Statistics, 23(4), 365–380。SPA 原始论文。
- Hansen, P. R., Lunde, A., and Nason, J. M. (2011). “The Model Confidence Set.” Econometrica, 79(2), 453–497。模型选择扩展。
- López de Prado, M. (2018). Advances in Financial Machine Learning, §14.4. Wiley. ISBN 978-1-119-48208-6。实现及与 DSR 的比较。
- White, H. (2000). “A Reality Check for Data Snooping.” Econometrica, 69(5), 1097–1126。前身方法。