找回密码
立即注册
搜索
发回帖 发新帖

5203

积分

0

好友

675

主题
发表于 2 小时前 | 查看: 9| 回复: 0

回测报告里经常能见到这样一句话:「策略日均超额 0.26%,t 值 2.5,显著。」这个 t 值很可能被高估了。问题并不出在数据本身,而是普通 t 检验默认每天的观测相互独立;量化策略的日收益几乎从不满足这个前提。

本文围绕三件事展开:t 值到底衡量什么;相邻交易日相关为什么会推高 t 值;HAC(Newey–West)如何修正,并一步一步算清楚。所有例子基于模拟数据,核心代码见文末。

一、普通 t 值:平均值是不是真的大于 0

假设一个选股策略每天的超额收益是 $x_1, x_2, \dots, x_n$。我们想知道:它真实的平均超额是不是大于 0?

光看平均值并不够。日均 +0.26% 看起来不错,但如果每日波动是 ±2%,这 0.26% 也有可能纯属运气。

t 值衡量的是“平均值相对它自己的误差有多大”:

t = 平均值 ÷ 标准误

标准误 = 每日波动 ÷ √n

用 338 个交易日举例:

标准误 = 1.92% ÷ √338 ≈ 0.104%

t = 0.265% ÷ 0.104% ≈ 2.53

通常认为 t ≥ 2 时,大约有 95% 的把握认为真实均值不为 0(单边看大于 0 的置信度更高)。

关键就在这个“÷ √n”上。它背后的假设是:338 天就是 338 份独立的信息。

二、相邻日子相关,信息就“缩水”了

量化策略的日收益,相邻几天往往是正相关的:

  • 市场风格会延续:小盘股强势阶段可能持续几周,模型顺风时连续几天走好,逆风时连续几天走差。
  • 持仓有重叠:调仓慢、持股周期长的策略,相邻两天手里的股票很多是同一批。
  • 收益区间重叠:每天计算一次“未来 5 日收益”时,相邻两天的 5 日收益有 4 天是重合的,这是最极端的情形。

相邻日子正相关时,连续几天的好结果,说穿了只是“同一件好事”重复听了好几遍。338 天的有效信息,可能只相当于一两百天。

对于最简单的情形,即每天的结果只跟前一天有关、相关系数为 ρ(统计上叫 AR(1)),有一个近似公式:

有效天数 ≈ n × (1 − ρ) ÷ (1 + ρ)

t 值被高估的倍数 ≈ √( (1 + ρ) ÷ (1 − ρ) )

相邻两天的相关系数 ρ 338 天的有效天数 t 值被高估约
0 338 1.00 倍
0.1 277 1.11 倍
0.3 182 1.36 倍
0.5 113 1.73 倍

ρ = 0.3 并不罕见。此时普通 t 值如果是 2.7,真实大约只有 2.0。

模拟:一个什么都不会的策略,有多大概率“显著”?

生成 5000 个真实平均值为 0 的策略,每个 338 天,相邻两天的相关系数为 ρ。理论上,t ≥ 2 的比例应该接近 2.5%(单边):

ρ 普通 t ≥ 2 的比例 HAC t ≥ 2 的比例
0 2.3% 2.6%
0.1 3.7% 2.8%
0.3 7.2% 3.4%
0.5 12.3% 4.5%

ρ = 0.5 时,用普通 t 检验,每 8 个没有真实能力的策略里就有 1 个会被判为“显著”,差不多是应有比例的 5 倍。HAC 则把比例拉回到接近 2.5%。

更极端的例子:重叠收益

每天计算一次“未来 5 日收益”作为策略表现(例如持有 5 天、每天调仓 1/5),相邻两天的相关系数理论上高达 0.8。同样模拟 5000 次,真实平均值为 0:

方法 t ≥ 2 的比例
普通 t 18.8%
HAC,滞后 5 天 4.5%
HAC,滞后 10 天 3.6%

普通 t 检验在这里几乎失效:将近五分之一的纯噪声会被判为显著。

三、HAC 怎么修正

HAC 是 Heteroskedasticity and Autocorrelation Consistent 的缩写,意思是“对异方差和自相关都稳健”。最常用的版本由 Newey 和 West 在 1987 年提出,所以也常被称为 Newey–West 标准误。

思路

普通标准误只用到每天自己的波动(方差)。HAC 再把“相邻日子之间的协方差”加进来:相邻日子正相关,误差就加大;负相关,误差就减小。

公式

长期方差 = γ₀ + 2 × [ w₁·γ₁ + w₂·γ₂ + … + w_L·γ_L ]

HAC 标准误 = √( 长期方差 ÷ n )

HAC t = 平均值 ÷ HAC 标准误

  • γ₀:日收益的方差
  • γⱼ:相隔 j 天的协方差,即“今天”和“j 天前”一起偏离平均值的程度
  • L:最多看到相隔几天,称为滞后阶数
  • wⱼ = 1 − j ÷ (L + 1):权重,相隔越远的协方差权重越小(也叫 Bartlett 核)。这样处理能保证估计的方差不会是负数,也避免远处噪声干扰

为了理解方便,可以把长期方差写成“普通方差 × 放大倍数”:

放大倍数 = 1 + 2 × [ w₁·ρ₁ + w₂·ρ₂ + … + w_L·ρ_L ]

ρⱼ 是相隔 j 天的自相关系数。HAC 标准误 = 普通标准误 × √放大倍数。

滞后阶数 L 取多少

常用经验公式(Newey–West 1994):

L = floor( 4 × (n / 100)^(2/9) )

n = 338 时,L = 5;n = 1000 时,L = 6。

经验上:

  • 收益区间有重叠时,L 至少要等于重叠的天数。持有 5 天就至少取 5,否则修正不够。
  • L 取大一点通常更保守,但样本少时,估计本身会变得不稳定。

四、一步一步算一遍

模拟一个策略:真实日均超额 0.3%,每日波动 2%,相邻两天的相关系数 0.3,共 338 天。

第 1 步:基本统计

项目 数值
实际日均超额 0.265%
每日波动 1.92%
普通标准误 1.92% ÷ √338 = 0.104%
普通 t 2.53

第 2 步:滞后阶数:n = 338,L = floor(4 × 3.38^0.222) = 5

第 3 步:自相关系数和权重

相隔天数 j 自相关 ρⱼ 权重 wⱼ wⱼ × ρⱼ
1 0.360 0.833 0.300
2 0.050 0.667 0.033
3 −0.077 0.500 −0.039
4 −0.042 0.333 −0.014
5 −0.069 0.167 −0.012
合计 0.269

第 4 步:放大倍数 = 1 + 2 × 0.269 = 1.54

第 5 步:HAC 标准误和 t 值

HAC 标准误 = 0.104% × √1.54 ≈ 0.129%

HAC t = 0.265% ÷ 0.129% ≈ 2.05

同一组数据,普通 t 是 2.53,HAC t 只有 2.05,刚好压在 2 的门槛上。如果门槛设在 2.5,用普通 t 就会得到错误结论。

五、几点注意

  1. HAC 不一定让 t 值变小。 相邻日子负相关时(比如反转型策略),HAC 的标准误反而更小。模拟一个相邻相关为 −0.2 的策略:普通 t 2.09,HAC t 2.44。HAC 不是“打折工具”,而是“更准的工具”。

  2. HAC 只修正自相关,不修正多重测试。 试了 100 个策略、挑出 HAC t 最高的那个,它的 t 值照样会被选择偏差抬高,需要另外的方法处理,比如 DSR、SPA 等。

  3. HAC 不修正厚尾。 少数几天的极端收益撑起来的平均值,HAC t 照样可能很好看。要另外看“去掉最好的几天还剩多少”。

  4. 样本少时,HAC 本身也不太准。 几十天的数据,自相关都估不稳,HAC t 只能作参考。

  5. 回归里也一样。 用 α 的 t 值判断“超额是否显著”、用斜率判断“超额是否衰减”时,同样应该用 Newey–West 标准误。主流统计软件都支持:Python 的 statsmodels 里设 cov_type="HAC" 即可。

六、一句话总结

普通 t 检验假设每天都是独立的新信息;量化策略的日收益往往前后相关,信息比天数少,普通 t 值因此虚高。HAC(Newey–West)把相邻日子的协方差算进标准误,给出更诚实的 t 值。

报告 t 值时,顺手写一句“Newey–West,滞后 5 天”,读者就知道这个数是可信的。

参考文献

  1. Newey, W. K., & West, K. D. (1987). A Simple, Positive Semi-Definite, Heteroskedasticity and Autocorrelation Consistent Covariance Matrix. Econometrica, 55(3), 703–708.
  2. Newey, W. K., & West, K. D. (1994). Automatic Lag Selection in Covariance Matrix Estimation. Review of Economic Studies, 61(4), 631–653.
  3. Andrews, D. W. K. (1991). Heteroskedasticity and Autocorrelation Consistent Covariance Matrix Estimation. Econometrica, 59(3), 817–858.

附:核心代码

import math
import numpy as np

def hac_t(x, lags=None):
    """日序列 x 的平均值是否显著不为 0:Newey–West t 值(Bartlett 核)。"""
    x = np.asarray(x, dtype=float)
    n = len(x)
    L = int(4 * (n / 100) ** (2 / 9)) if lags is None else lags
    e = x - x.mean()
    lrv = e @ e / n
    for j in range(1, L + 1):
        lrv += 2 * (1 - j / (L + 1)) * (e[j:] @ e[:-j] / n)
    return x.mean() / math.sqrt(lrv / n)

用 statsmodels 的话,对常数项做回归即可。关掉小样本修正,结果与上面的函数一致;开着的话,t 值会略小一点:

import statsmodels.api as sm

fit = sm.OLS(x, np.ones(len(x))).fit(cov_type="HAC",
                                     cov_kwds={"maxlags": 5, "use_correction": False})
print(fit.tvalues[0])



上一篇:HTTP2Shell 漏洞根源在 Brotli 解码器?波及 .NET、ClickHouse 等多组件
下一篇:MOS管和IGBT到底有什么区别?从结构到选型一次讲透
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-28 08:18 , Processed in 0.072155 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表