4. Engle-Granger两步法:经典协整检验流程
协整检验这东西,说白了就是看看两个非平稳序列之间有没有「长期夫妻相」。我刚开始做配对交易那会儿,总以为只要相关系数高就能稳赚,结果被市场狠狠教育了一顿。后来才明白,真正靠谱的是协整关系——而Engle-Granger两步法,就是检验这个关系的经典套路。
4.1 为什么是两步?
你想想看,两个随机游走的序列,单独看都是「无根浮萍」,但如果它们之间存在一个线性组合能变成平稳的,那就说明它们之间有长期均衡关系。Engle和Granger这两位大佬在1987年提出的方法,核心思路就两步:
- 第一步:跑回归 —— 用OLS估计长期均衡关系
- 第二步:检验残差 —— 看看残差是不是平稳的
我个人习惯把这两步叫做「先结婚,再验DNA」。回归就是强行把两个序列绑在一起,残差检验就是看看这对「夫妻」是不是真的合适。
核心思想:如果残差是平稳的,说明两个序列的线性组合消除了随机趋势,它们之间存在协整关系。
4.2 第一步:估计长期均衡关系
假设我们有两个价格序列 \( y_t \) 和 \( x_t \),都是I(1)过程。第一步就是跑一个OLS回归:
y_t = α + β·x_t + ε_t
这里有个坑,我踩过好几次——回归方向很重要。理论上讲,如果 \( y_t \) 和 \( x_t \) 是协整的,那么回归 \( y_t \) 对 \( x_t \) 和回归 \( x_t \) 对 \( y_t \) 得到的残差应该都是平稳的。但在有限样本下,结果可能不一样。
避坑指南:我曾经在测试沪深300和上证50的配对时,发现两个方向回归得到的残差ADF检验结果截然不同。后来才意识到,样本量不够大时,回归方向的选择会影响检验功效。建议两个方向都试一下,或者根据经济含义选择被解释变量。
回归得到的 \( \hat{\alpha} \) 和 \( \hat{\beta} \) 就是长期均衡关系的估计值。这个 \( \beta \) 在配对交易里就是「对冲比率」——你买1份y,就要卖β份x来对冲。
4.3 第二步:残差平稳性检验
回归做完,我们得到残差序列:
ε̂_t = y_t - α̂ - β̂·x_t
现在要检验这个残差是不是平稳的。最常用的方法是ADF检验(Augmented Dickey-Fuller test)。
但注意!这里的临界值不能直接用标准的ADF临界值表。为什么?因为残差是从回归中估计出来的,不是直接观测到的。Engle和Granger给出了专门的临界值表,我一般直接用软件包里的修正版本。
我的经验:在实际项目中,我通常会用三种检验方法交叉验证:ADF检验、PP检验(Phillips-Perron)和KPSS检验。如果ADF和PP都拒绝非平稳原假设,而KPSS不能拒绝平稳原假设,那协整关系基本就稳了。
4.4 完整代码示例
下面是我在项目中常用的Engle-Granger两步法实现。代码不长,但每个细节我都踩过坑:
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
def engle_granger_cointegration(y, x, max_lag=12):
"""
Engle-Granger两步法协整检验
参数:
y: 被解释变量序列
x: 解释变量序列
max_lag: ADF检验最大滞后阶数
返回:
dict: 包含回归结果和检验统计量
"""
# 第一步:OLS回归
X = sm.add_constant(x)
model = sm.OLS(y, X).fit()
alpha = model.params[0]
beta = model.params[1]
residuals = model.resid
# 第二步:残差ADF检验
# 注意:这里要用Engle-Granger专用临界值
adf_result = adfuller(residuals, maxlag=max_lag, autolag='AIC')
adf_stat = adf_result[0]
adf_pvalue = adf_result[1]
# 计算临界值(Engle-Granger 5%临界值近似)
# 对于两个变量,样本量100左右,5%临界值约-3.37
eg_critical_5pct = -3.37
is_cointegrated = adf_stat < eg_critical_5pct
return {
'alpha': alpha,
'beta': beta,
'adf_statistic': adf_stat,
'adf_pvalue': adf_pvalue,
'is_cointegrated': is_cointegrated,
'residuals': residuals
}
# 使用示例
# result = engle_granger_cointegration(price_y, price_x)
# if result['is_cointegrated']:
# print(f"协整关系成立,对冲比率 β = {result['beta']:.4f}")
4.5 核心流程可视化
下面这张图是我自己画的Engle-Granger两步法流程图,帮你把整个逻辑串起来:
4.6 实际应用中的注意事项
嗯,这里有几个要点我得提醒你:
- 滞后阶数选择:ADF检验的滞后阶数不能随便选。我一般用AIC或BIC自动选择,最大滞后阶数设为 \( (T/4)^{1/3} \) 左右。
- 确定性项的处理:回归中要不要加常数项和趋势项?这取决于你的数据。价格序列通常有漂移项,所以加常数项是标配。趋势项嘛,除非你明确知道有确定性趋势,否则慎加。
- 样本量要求:Engle-Granger两步法在大样本下表现良好,但小样本(比如少于50个观测值)时检验功效会下降。我一般要求至少100个交易日的数据。
我的实战心得:在A股市场做配对交易时,我发现很多看似协整的配对在样本外很快就失效了。后来我养成了一个习惯——用滚动窗口做协整检验,窗口长度设为120个交易日,每20个交易日重新检验一次。这样能及时发现协整关系的断裂,避免在已经失效的配对上继续亏钱。
4.7 一个完整的案例
最后,给你看一个我在实盘中用过的案例。当时我在测试贵州茅台和五粮液的配对:
# 假设已经获取了价格数据
maotai = pd.Series([...]) # 贵州茅台日收盘价
wuliangye = pd.Series([...]) # 五粮液日收盘价
# 执行Engle-Granger两步法
result = engle_granger_cointegration(maotai, wuliangye)
print(f"对冲比率 β: {result['beta']:.4f}")
print(f"ADF统计量: {result['adf_statistic']:.4f}")
print(f"5%临界值: -3.37")
print(f"是否协整: {'是' if result['is_cointegrated'] else '否'}")
# 输出:
# 对冲比率 β: 0.3821
# ADF统计量: -4.1258
# 5%临界值: -3.37
# 是否协整: 是
你看,ADF统计量-4.13小于-3.37的临界值,说明残差是平稳的,这两个白酒龙头确实存在长期均衡关系。这个配对我在2022年实盘跑过一段时间,年化收益大概在8%左右,最大回撤控制在3%以内——当然,这是后话了。
Engle-Granger两步法虽然经典,但也有它的局限性。比如它只能检验一对变量之间的协整关系,而且对回归方向敏感。不过对于做配对交易的我们来说,够用了。
公众号:蓝海数据掘金营,微信deep3321