4. 平稳性与单位根检验
做跨期套利,说白了就是赌价差会回归。
但有个前提——价差得是平稳的。
如果价差不平稳,你看到的回归可能只是幻觉。我早年就吃过这个亏,回测曲线漂亮得不行,实盘一跑直接崩了。后来才发现,价差序列压根不平稳,所谓的回归只是随机游走里的假象。
4.1 平稳时间序列的定义
什么叫平稳?我个人的理解很简单:
统计性质不随时间变化。
具体来说,一个时间序列如果满足以下三个条件,我们就说它是弱平稳的:
- 均值恒定:E(X_t) = μ,不依赖时间 t
- 方差恒定:Var(X_t) = σ²,也是常数
- 协方差只与时间间隔有关:Cov(X_t, X_{t-k}) = γ_k,跟起点 t 无关
你想想看,如果价差的均值一直在漂移,你怎么做回归?今天觉得偏离了2个标准差,明天均值变了,这个偏离就毫无意义了。
核心要点:平稳性是统计套利的基石。不平稳的价差,套利逻辑不成立。
4.2 ADF检验原理与实现
ADF检验,全称是Augmented Dickey-Fuller检验。名字挺唬人,其实原理不复杂。
它检验的原假设是:序列存在单位根,即非平稳。
备择假设是:序列平稳。
怎么判断?看p值。
- p值 < 0.05:拒绝原假设,序列平稳
- p值 ≥ 0.05:不能拒绝,序列非平稳
我在项目中遇到过好几次这样的情况:p值刚好0.051,你说它平稳吧,差一点;说不平稳吧,又很接近。这时候我一般会结合KPSS检验交叉验证,后面会讲。
下面是我常用的ADF检验代码:
from statsmodels.tsa.stattools import adfuller
def check_adf(series, name='价差'):
result = adfuller(series, autolag='AIC')
p_value = result[1]
print(f'{name} ADF检验 p值: {p_value:.6f}')
if p_value < 0.05:
print(f'→ {name} 平稳,可以用于套利')
else:
print(f'→ {name} 非平稳,需要进一步处理')
return p_value
嗯,这里要注意autolag='AIC'这个参数。它让模型自动选择最优滞后阶数,省得你手动调。我个人习惯一直开着这个选项。
4.3 KPSS检验
KPSS检验跟ADF正好反过来。
它的原假设是:序列是平稳的。
备择假设是:存在单位根。
为什么要两个检验一起用?
因为单独一个检验可能误判。我举个例子:
| ADF结果 | KPSS结果 | 结论 |
|---|---|---|
| 平稳 | 平稳 | 序列平稳 ✅ |
| 非平稳 | 非平稳 | 序列非平稳 ❌ |
| 平稳 | 非平稳 | 可能存在趋势平稳,需差分 |
| 非平稳 | 平稳 | 可能存在单位根,需差分 |
我曾经遇到过一个价差序列,ADF说平稳,KPSS也说平稳。我当时还挺高兴,结果实盘跑了一个月,价差突然漂了3个标准差不回来。后来复盘发现,样本期内刚好有一段趋势没被捕捉到。
所以我的建议是:两个检验都做,结论一致才放心。
KPSS的代码也很简单:
from statsmodels.tsa.stattools import kpss
def check_kpss(series, name='价差'):
result = kpss(series, regression='c')
p_value = result[1]
print(f'{name} KPSS检验 p值: {p_value:.6f}')
if p_value < 0.05:
print(f'→ {name} 非平稳')
else:
print(f'→ {name} 平稳')
return p_value
4.4 如何判断价差序列是否平稳
实战中,我一般按这个流程走:
- 肉眼观察:先画个图,看看有没有明显趋势或季节性
- ADF检验:快速判断,p值小于0.05算初步通过
- KPSS检验:交叉验证,避免误判
- 自相关图:看ACF是否快速衰减到0
说白了,就是多角度验证。单一指标我是不敢信的。
小技巧:如果价差序列不平稳,可以试试一阶差分。差分后的序列如果平稳了,说明原序列是I(1)过程,套利时需要用协整关系来处理。
⚠️ 注意:千万不要在非平稳序列上直接做统计套利。你看到的回归可能是伪回归,实盘会让你亏到怀疑人生。
4.5 本章知识体系
下面这张图总结了我对平稳性检验的理解框架:
这张图我画了好几次才满意。核心就一句话:ADF和KPSS一起用,结论一致再动手。
好了,平稳性检验就讲到这里。记住,这是统计套利的第一道门槛,跨过去才能谈后面的策略设计。
公众号:蓝海资料掘金营,微信deep3321