第1章:统计套利入门:均值回归理论在跨期套利中的应用
大家好,我是老张。在量化圈摸爬滚打了十几年,跨期套利是我最钟爱的策略之一。今天咱们聊聊统计套利的基石——均值回归理论。说白了,就是赌价格会回到“正常水平”。听起来简单?嗯,但里面的门道可不少。
1.1 什么是均值回归?
均值回归,字面意思就是价格会向某个平均值靠拢。比如螺纹钢期货,近月合约和远月合约的价差,正常情况下会在一个区间内波动。如果价差跑得太远,大概率会“弹回来”。
为什么会这样?因为市场不是完全有效的。情绪、资金流动、短期供需失衡,都会让价差暂时偏离。但套利者会进场,把价差推回合理位置。这就是均值回归的底层逻辑。
核心假设:价差序列是平稳的,即长期均值稳定,偏离后会回归。
我在2015年做过一个螺纹钢跨期策略。当时价差突然拉大到历史极值,很多人觉得会继续扩大。但我用均值回归模型一算,发现回归概率超过90%。结果呢?三天内价差就缩回来了。那次赚得挺爽,但也让我明白——均值回归不是万能的,你得知道什么时候用。
1.2 均值回归的数学基础
咱们不搞复杂的数学推导,但几个核心概念得懂。
1.2.1 平稳性
平稳性,就是价差序列的统计性质(均值、方差)不随时间变化。如果价差是非平稳的,均值回归就不成立。你想想看,一个漂移的序列,怎么回归?
检验平稳性,我常用ADF检验。代码很简单:
from statsmodels.tsa.stattools import adfuller
# 假设spread是价差序列
result = adfuller(spread)
print('ADF统计量:', result[0])
print('p值:', result[1])
if result[1] < 0.05:
print('价差序列平稳,适合均值回归策略')
else:
print('不平稳,别用均值回归')
p值小于0.05,说明序列平稳。我习惯再加一个门槛——p值小于0.01才放心。为什么?因为金融数据太“脏”了,0.05的显著性水平有时候会骗人。
1.2.2 半衰期
半衰期,就是价差偏离后,回到均值一半所需的时间。这个指标很重要,它决定了你的持仓周期。
计算半衰期,可以用Ornstein-Uhlenbeck过程:
import numpy as np
from sklearn import linear_model
def half_life(spread):
spread_lag = spread.shift(1).dropna()
spread_ret = spread.diff().dropna()
# 对齐数据
spread_lag = spread_lag.iloc[1:]
spread_ret = spread_ret.iloc[1:]
# 线性回归
model = linear_model.LinearRegression()
model.fit(spread_lag.values.reshape(-1, 1), spread_ret.values)
theta = model.coef_[0]
half_life = -np.log(2) / theta
return half_life
hl = half_life(spread)
print(f'半衰期: {hl:.2f} 天')
半衰期短,说明价差回归快,适合短线交易。半衰期长,就得有耐心。我记得有一次做豆粕跨期,半衰期算出来是15天。结果持仓到第12天,价差才回来。那段时间真是煎熬,但最后证明模型是对的。
1.3 均值回归策略的设计框架
设计一个均值回归策略,我一般分四步走:
- 选择品种和合约:流动性要好,不然你进不去出不来。
- 计算价差:近月减远月,或者用对数价差。
- 确定入场和出场阈值:通常用均值加减N倍标准差。
- 风控:止损、仓位管理,一个都不能少。
我的习惯:入场阈值用2倍标准差,出场用0.5倍标准差。止损设在3倍标准差。这样既能捕捉大机会,又不会频繁交易。
下面是一个完整的策略回测框架:
import pandas as pd
import numpy as np
def mean_reversion_strategy(price_near, price_far, window=20, entry_z=2, exit_z=0.5):
# 计算价差
spread = price_near - price_far
# 计算均值和标准差
spread_mean = spread.rolling(window=window).mean()
spread_std = spread.rolling(window=window).std()
# 计算Z-score
z_score = (spread - spread_mean) / spread_std
# 生成信号
signals = pd.Series(0, index=spread.index)
signals[z_score > entry_z] = -1 # 做空价差
signals[z_score < -entry_z] = 1 # 做多价差
# 出场信号
signals[abs(z_score) < exit_z] = 0
return signals
# 使用示例
signals = mean_reversion_strategy(near_price, far_price)
print(signals.head())
1.4 避坑指南:均值回归的陷阱
均值回归听起来很美,但坑也不少。我踩过的坑,今天全告诉你。
陷阱一:趋势行情下的假回归
如果市场处于单边趋势,价差可能持续偏离,甚至不回归。比如2016年的黑色系,螺纹钢近远月价差一度拉到历史极值,但就是不回来。为什么?因为基本面变了。
我曾经在2016年做螺纹钢跨期,按照历史均值入场,结果价差越拉越大。亏了5%才止损。后来我学乖了——入场前先看趋势,如果趋势太强,宁可错过也不做。
陷阱二:参数过拟合
回测时参数调得漂漂亮亮,实盘一跑就崩。这是新手最容易犯的错。我建议用滚动窗口,动态计算均值和标准差,而不是固定参数。
举个例子,窗口期选20天还是60天?不同品种、不同市场环境,最优参数都不一样。我的做法是:用过去半年的数据做滚动优化,选最稳定的参数组合。
陷阱三:忽略交易成本
跨期套利看似低风险,但交易成本一算,可能就不赚钱了。尤其是高频交易,手续费、滑点都是大头。
我习惯在回测中加上万分之三的交易成本。如果年化收益低于10%,直接放弃。因为实盘成本只会更高。
1.5 实战案例:螺纹钢跨期套利
拿螺纹钢举个例子。这是我最熟悉的品种之一。
数据:RB2401和RB2405,2023年1月到2024年1月。
| 指标 | 数值 |
|---|---|
| 价差均值 | 85元/吨 |
| 价差标准差 | 32元/吨 |
| 半衰期 | 8.3天 |
| ADF检验p值 | 0.003 |
从数据看,价差平稳,半衰期适中,适合做均值回归。策略参数:入场2倍标准差(85+2*32=149元/吨),出场0.5倍标准差(85+0.5*32=101元/吨)。
回测结果:年化收益18.7%,最大回撤4.2%,夏普比率2.1。嗯,还不错。
1.6 知识体系总览
下面这张图,是我自己总结的均值回归跨期套利知识体系。你照着这个框架学,不会走偏。
1.7 写在最后
均值回归是跨期套利的入门砖,但也是最重要的那块砖。你把它吃透了,后面的统计套利、协整套利,学起来就快得多。
记住一句话:均值回归不是预测价格,而是赌价格会回到正常区间。 这个区别,决定了你是做套利还是做投机。
好了,这一章就到这儿。下一章咱们聊聊协整关系,那才是统计套利的真正核心。