第二章:协整理论入门
各位同学,欢迎来到统计套利的核心地带。今天我们要聊的,是整套策略的基石——协整理论。
说实话,我刚入行那会儿,听到「协整」这个词,第一反应是:这又是什么高大上的数学概念?后来在实盘里摔了几次跟头,才真正明白它的价值。你想想看,两只股票,价格走势看起来很像,但直接做配对交易,往往亏得莫名其妙。为什么?因为它们可能只是「伪相关」。
协整,就是用来解决这个问题的。
一、协整的定义与直观理解
先给个官方定义:如果两个或多个非平稳时间序列的线性组合是平稳的,那么它们之间存在协整关系。
听着有点绕?我换个说法。
想象你牵着一条狗散步。你往前走,狗可能跑到左边闻闻,又跑到右边看看。但不管它怎么跑,绳子牵着,它总会回到你身边。你和狗的位置,各自都是非平稳的(一直在移动),但你们之间的距离——也就是绳子的长度——是平稳的,会在一个均值附近波动。
这就是协整的直观画面。
在金融市场里,两只股票的价格就像你和狗的位置。它们各自随机游走,但彼此之间有一种「牵引力」,让它们的价差不会跑太远。一旦价差过大,市场力量就会把它拉回来。
核心要点:协整 ≠ 相关性。两只高度相关的股票,可能根本没有协整关系。我在项目中就遇到过,两只银行股相关系数0.95,但价差越走越远,做配对交易直接亏了3%。
二、平稳性与单位根检验(ADF检验)
要理解协整,必须先搞懂平稳性。
什么是平稳性?简单说,就是一个时间序列的统计性质(均值、方差)不随时间变化。白噪声就是最典型的平稳序列——它没有趋势,没有季节性,就在零轴附近随机波动。
而非平稳序列呢?比如股票价格,它有趋势,有漂移,均值一直在变。你没法预测它下一秒会跑到哪里去。
怎么判断一个序列是否平稳?最常用的方法就是单位根检验,其中ADF检验是标配。
ADF检验的原假设是:序列存在单位根(即非平稳)。如果p值小于0.05,我们就拒绝原假设,认为序列是平稳的。
来,看代码:
import pandas as pd
import numpy as np
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'临界值: {result[4]}')
# 输出示例:
# ADF统计量: -1.2345
# p值: 0.6543
# 临界值: {'1%': -3.46, '5%': -2.87, '10%': -2.57}
p值0.65,远大于0.05,说明我们不能拒绝原假设——这个序列是非平稳的。
我的习惯:做ADF检验时,我一般会同时看统计量和临界值。如果统计量比1%的临界值还小,那基本稳了。p值虽然方便,但有时候样本量小的时候会不准。
三、Engle-Granger两步法
好了,现在我们知道什么是平稳性了。那怎么找协整关系呢?最经典的方法就是Engle-Granger两步法。
名字听着吓人,其实逻辑很简单:
- 第一步:用OLS回归估计两个序列的线性关系,得到残差。
- 第二步:对残差做ADF检验,看它是否平稳。
如果残差是平稳的,就说明这两个序列存在协整关系。
举个例子:
import statsmodels.api as sm
# 模拟两个协整序列
np.random.seed(42)
n = 200
x = np.cumsum(np.random.randn(n)) # 非平稳
y = 0.8 * x + np.random.randn(n) # 与x协整
# 第一步:OLS回归
x_const = sm.add_constant(x)
model = sm.OLS(y, x_const).fit()
residuals = model.resid
# 第二步:对残差做ADF检验
result = adfuller(residuals)
print(f'残差ADF p值: {result[1]:.4f}')
# 输出:p值通常小于0.05,说明残差平稳
p值小于0.05,说明残差平稳,x和y存在协整关系。这时候,我们就可以放心地做配对交易了。
我曾经踩过的坑:用Engle-Granger两步法时,一定要注意第一步的回归方向。如果你把x和y搞反了,结果可能完全不同。我的建议是:先做经济直觉判断,哪个是驱动因素,哪个是被驱动因素。实在拿不准,就两个方向都试一下。
四、Johansen检验简介
Engle-Granger两步法虽然好用,但它有个硬伤——只能处理两个序列。如果你有三只、四只甚至更多股票想一起分析,它就无能为力了。
这时候,Johansen检验就派上用场了。
Johansen检验的核心思想是:通过向量自回归模型(VAR),同时检验多个序列之间是否存在协整关系,并且能告诉你存在几个协整向量。
用Python实现也很简单:
from statsmodels.tsa.vector_ar.vecm import coint_johansen
# 模拟三个协整序列
np.random.seed(42)
n = 200
x1 = np.cumsum(np.random.randn(n))
x2 = 0.7 * x1 + np.random.randn(n)
x3 = 0.5 * x1 + 0.3 * x2 + np.random.randn(n)
data = np.column_stack([x1, x2, x3])
# Johansen检验
result = coint_johansen(data, det_order=0, k_ar_diff=1)
print(f'迹统计量: {result.lr1}')
print(f'5%临界值: {result.cvt[:, 1]}')
print(f'最大特征值统计量: {result.lr2}')
print(f'5%临界值: {result.cvtm[:, 1]}')
输出结果里,迹统计量和最大特征值统计量会分别跟临界值比较。如果统计量大于临界值,就拒绝原假设,认为存在对应数量的协整关系。
实用建议:Johansen检验的结果解读,我一般先看迹统计量。如果第一个统计量(r=0)大于临界值,说明至少存在一个协整关系。然后再看第二个(r≤1),以此类推。实际应用中,找到1-2个协整向量就够用了,太多反而容易过拟合。
五、本章知识体系
为了让你更直观地理解本章的逻辑,我画了一张图:
这张图把本章的核心内容串起来了。从协整的定义出发,到平稳性检验,再到两种具体的检验方法,最后落到实际应用。你学完这一章,应该能回答三个问题:什么是协整?怎么检验协整?用哪种方法更合适?
嗯,今天就到这里。下一章我们会用真实数据,手把手带你跑一遍完整的协整检验流程。到时候你会发现,理论懂了,代码写起来其实很快。