3. 统计套利入门:均值回归、协整关系与配对交易
统计套利,说白了就是「赌价格会回来」。
我刚开始接触量化的时候,觉得这玩意儿特别玄乎。后来做了几个实盘项目才发现,它背后的数学逻辑其实很扎实。今天我们就来聊聊这个领域的三个核心概念:均值回归、协整关系,还有配对交易。
3.1 均值回归:价格不会永远跑偏
先问一个问题:为什么股价涨多了会跌,跌多了会涨?
嗯,这背后就是均值回归的思想。简单说,一个资产的价格,长期来看会围绕某个均值上下波动。偏离得越远,回归的动力就越强。
核心公式:
均值回归过程可以用 Ornstein-Uhlenbeck 过程来描述:
dXt = θ(μ - Xt)dt + σdWt
其中 θ 是回归速度,μ 是长期均值,σ 是波动率。
我在项目中遇到过一只股票,连续跌了5天。很多人慌了,但我看了它的均值回归半衰期——只有3天。结果第6天就反弹了。这就是均值回归的力量。
避坑指南:
我曾经以为所有股票都会均值回归,结果踩了大坑。有些股票在趋势行情里,越涨越猛,根本不等你。所以均值回归只适用于震荡市,别在单边行情里硬扛。
3.2 协整关系:两个资产的「隐形锁链」
均值回归是针对单个资产的。那如果两个资产之间有关系呢?
比如,茅台和五粮液。它们都是白酒龙头,价格走势长期来看应该差不多。如果茅台涨了10%,五粮液没动,那大概率五粮液会补涨。
这种关系,就是协整。
协整的定义:
- 两个时间序列各自是非平稳的(比如随机游走)
- 但它们的线性组合是平稳的(均值回归)
- 说白了,就是两个醉汉走路,虽然各自东倒西歪,但始终被一根绳子拴着
检验协整的步骤:
- 对两个序列做单位根检验(ADF检验),确认它们都是非平稳的
- 用OLS回归估计协整系数:Y = α + βX + ε
- 对残差ε做ADF检验,如果残差平稳,就说明存在协整关系
我个人习惯用 Engle-Granger 两步法。虽然简单,但够用。你想想看,如果两个资产连协整关系都没有,那配对交易就是空中楼阁。
3.3 配对交易:实战中的「多空组合」
好了,有了均值回归和协整关系这两个武器,我们就可以构建配对交易策略了。
核心逻辑:
- 找到一对协整的资产(比如股票A和股票B)
- 计算价差:spread = price_A - β × price_B
- 当价差偏离均值超过某个阈值(比如2倍标准差),就开仓
- 价差回归到均值时平仓
注意:
配对交易不是简单的「买低卖高」。你需要做多被低估的资产,同时做空被高估的资产。这样才能对冲市场风险,只赚价差回归的钱。
我曾经做过一个石油和天然气的配对。当时价差偏离了3倍标准差,我果断开仓。结果等了2周才回归,中间浮亏了8%。嗯,这里要注意:配对交易的持仓周期可能很长,资金管理一定要做好。
3.4 代码实战:用Python实现配对交易
光说不练假把式。我们直接上代码。
import numpy as np
import pandas as pd
import statsmodels.api as sm
from statsmodels.tsa.stattools import adfuller
# 1. 加载数据
df = pd.read_csv('pair_data.csv', index_col=0, parse_dates=True)
asset_a = df['A']
asset_b = df['B']
# 2. 检验协整关系
def check_cointegration(x, y):
# OLS回归
x = sm.add_constant(x)
model = sm.OLS(y, x).fit()
residuals = model.resid
# ADF检验残差
adf_stat, p_value, _, _, critical_values, _ = adfuller(residuals)
return p_value < 0.05, model.params[1]
is_cointegrated, beta = check_cointegration(asset_a, asset_b)
print(f'协整关系存在: {is_cointegrated}, 对冲比率: {beta:.2f}')
# 3. 计算价差
spread = asset_a - beta * asset_b
spread_mean = spread.mean()
spread_std = spread.std()
# 4. 生成交易信号
z_score = (spread - spread_mean) / spread_std
entry_threshold = 2.0
signals = pd.DataFrame(index=df.index)
signals['z_score'] = z_score
signals['position_a'] = 0
signals['position_b'] = 0
# 当z_score超过阈值时开仓
signals.loc[z_score > entry_threshold, 'position_a'] = -1 # 做空A
signals.loc[z_score > entry_threshold, 'position_b'] = 1 # 做多B
signals.loc[z_score < -entry_threshold, 'position_a'] = 1 # 做多A
signals.loc[z_score < -entry_threshold, 'position_b'] = -1 # 做空B
print('交易信号生成完毕')
个人经验:
阈值设2倍标准差是经典做法,但我在实盘中喜欢动态调整。波动率大的时候用2.5倍,波动率小的时候用1.5倍。你想想看,市场环境变了,参数也得跟着变。
3.5 知识体系总览
下面这张图,是我自己整理的知识框架。每次做配对交易前,我都会过一遍。
3.6 实战中的注意事项
| 环节 | 常见问题 | 我的建议 |
|---|---|---|
| 数据选择 | 用了不同频率的数据 | 统一用日线,别混用 |
| 协整检验 | 样本期太短 | 至少用2年数据 |
| 交易执行 | 滑点太大 | 用限价单,别追涨杀跌 |
| 风险控制 | 不止损 | 设好最大回撤,比如5% |
最后提醒一句:
统计套利不是印钞机。协整关系可能会失效,市场结构可能会变化。我见过太多人把配对交易当成稳赚不赔的策略,结果亏得底裤都不剩。记住,任何策略都有失效的时候,风控永远是第一位的。
公众号:蓝海资料掘金营,微信deep3321