2. 时间序列基础回顾:平稳性、单位根、差分操作、白噪声过程
做量化交易这些年,我踩过最大的坑,就是拿非平稳数据直接跑回归。结果呢?看着R²高达0.95,实盘一跑就亏成狗。说白了,那就是伪回归——两个毫无关系的随机游走,硬是被你算出了“相关性”。
所以,在讲协整之前,咱们必须把时间序列的基础打牢。这一章,我带你回顾四个核心概念:平稳性、单位根、差分操作、白噪声。嗯,都是老朋友了,但咱们得换个角度重新认识它们。
2.1 平稳性:时间序列的“定海神针”
什么叫平稳?我个人的理解很简单:统计性质不随时间变化。具体来说,就是均值、方差、自协方差都是常数,不依赖你观察的时间点。
数学上,严平稳要求联合分布完全不变,太苛刻了。实际中我们常用弱平稳(宽平稳):
- 均值恒定:E(Xt) = μ
- 方差恒定:Var(Xt) = σ²
- 自协方差只与时间间隔有关:Cov(Xt, Xt-k) = γ(k)
我在项目中遇到过最典型的非平稳序列,就是股票价格。你想想看,茅台股价从200块涨到2000块,均值一直在变,怎么可能平稳?但收益率序列往往就平稳了。这就是为什么我们做量化,很少直接拿价格建模。
重要提醒:协整关系研究的是非平稳序列之间的长期均衡关系。所以,别一看到非平稳就急着差分——先看看它能不能跟别的序列“配对”。
2.2 单位根:平稳性的“照妖镜”
怎么判断一个序列是否平稳?最常用的方法就是单位根检验。
考虑一个AR(1)模型:
Xt = φXt-1 + εt
如果|φ| < 1,序列平稳;如果φ = 1,就出现了单位根,序列非平稳。为什么叫“单位根”?因为特征方程1 - φz = 0的根z = 1/φ,当φ=1时根就在单位圆上。
我最常用的单位根检验是ADF检验(Augmented Dickey-Fuller)。它的原假设H₀:序列存在单位根(非平稳)。p值小于0.05,就拒绝原假设,认为序列平稳。
来看个Python示例:
import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import adfuller
# 生成一个随机游走(含单位根)
np.random.seed(42)
n = 200
random_walk = np.cumsum(np.random.randn(n))
# ADF检验
result = adfuller(random_walk)
print(f'ADF统计量: {result[0]:.4f}')
print(f'p值: {result[1]:.4f}')
print(f'临界值(1%): {result[4]["1%"]:.4f}')
# 输出:p值通常大于0.05,无法拒绝单位根假设
我的经验:ADF检验对滞后阶数很敏感。我一般用AIC或BIC自动选择滞后阶数,别手动瞎调。曾经有一次,我手动选了滞后2阶,结果p值0.04,换了自动选择变成0.08——差点犯错误。
2.3 差分操作:把非平稳“掰”成平稳
如果序列有单位根,怎么办?最直接的办法就是差分。
一阶差分:ΔXt = Xt - Xt-1
对于随机游走Xt = Xt-1 + εt,一阶差分后就是白噪声εt,平稳了。
但注意:差分次数不是越多越好。过度差分会丢失信息,甚至引入负的自相关。我见过有人把已经平稳的序列再差分,结果自相关函数变得乱七八糟。
怎么判断差分次数够了?看两个指标:
- ADF检验:差分后p值小于0.05
- 自相关图(ACF):快速衰减到置信区间内
# 对随机游走做一阶差分
diff_series = np.diff(random_walk)
# 再次ADF检验
result_diff = adfuller(diff_series)
print(f'差分后p值: {result_diff[1]:.4f}')
# 输出:p值通常远小于0.05,序列变得平稳
注意:协整分析中,我们通常不直接差分原始价格序列。因为协整研究的是价格之间的长期关系,差分后反而会丢失这个信息。记住:协整是“非平稳序列的线性组合变得平稳”,而不是“把每个序列都差分到平稳”。
2.4 白噪声过程:最“干净”的随机性
白噪声,说白了就是纯随机。每个时间点的值独立同分布,均值为0,方差恒定,没有任何自相关。
数学定义:
- E(εt) = 0
- Var(εt) = σ²
- Cov(εt, εs) = 0,对于t ≠ s
白噪声是时间序列建模的“基准”。如果你的模型残差不是白噪声,说明还有信息没被提取出来,模型需要改进。
怎么检验残差是不是白噪声?我常用Ljung-Box检验:
from statsmodels.stats.diagnostic import acorr_ljungbox
# 生成白噪声
white_noise = np.random.randn(200)
# Ljung-Box检验
lb_result = acorr_ljungbox(white_noise, lags=[10], return_df=True)
print(lb_result)
# p值通常大于0.05,不能拒绝“残差是白噪声”的原假设
一个小技巧:我习惯在建模后,先看残差的ACF图。如果前几个滞后的自相关系数都落在蓝色置信区间内,基本就是白噪声了。Ljung-Box检验只是给个正式的p值确认一下。
2.5 本章知识体系
下面这张图,帮你理清本章的核心逻辑:
这张图把四个概念串起来了。你从平稳性出发,用单位根检验判断是否平稳,如果不平稳就考虑差分,而白噪声则是模型残差的理想状态。协整分析,就是在这个框架下,寻找非平稳序列之间的“稳定关系”。
公众号:蓝海资料掘金营,微信deep3321