一、均值回归策略概述
什么是均值回归
均值回归,说白了就是「涨多了会跌,跌多了会涨」。
我刚开始做量化那会儿,总觉得这个道理太简单了。后来在实盘里摔了几次跟头,才明白——简单的道理,往往最难做好。
举个例子。你盯着某只股票看,它今天跌了5%。你心里想:「明天该反弹了吧?」这种直觉,其实就是均值回归的朴素版本。价格偏离了它的「正常位置」,市场会把它拉回来。
但这里有个坑——「正常位置」到底是什么?
我个人习惯用移动平均线来定义这个位置。比如20日均线,或者60日均线。价格离均线越远,回归的动能就越强。
核心思想: 资产价格会围绕某个均值上下波动,偏离越大,回归概率越高。
均值回归的数学原理
嗯,这里要上点硬货了。
均值回归的数学基础,其实是一个随机过程——Ornstein-Uhlenbeck过程。公式长这样:
dX(t) = θ(μ - X(t))dt + σdW(t)
别被符号吓到。我来拆开讲:
- X(t):当前价格
- μ:长期均值(你猜的那个「正常位置」)
- θ:回归速度(拉回来的力度)
- σ:波动率(市场噪音的大小)
- dW(t):随机扰动(市场的不确定性)
为什么会这样?
你看,当价格X(t)高于均值μ时,公式里的(μ - X(t))是负数,所以dX(t)会往负方向走——价格被拉回来。反过来也一样。
我在项目中遇到过一个问题:θ值怎么选?
θ太小,回归太慢,你等不起。θ太大,回归太快,你抓不住。我建议用历史数据做最大似然估计,代码长这样:
import numpy as np
from statsmodels.tsa.stattools import adfuller
# 计算均值回归的半衰期
def half_life(price_series):
lag = price_series.shift(1).dropna()
ret = price_series.diff().dropna()
# 线性回归求θ
X = np.column_stack([lag, np.ones(len(lag))])
beta = np.linalg.lstsq(X, ret, rcond=None)[0]
theta = -beta[0]
# 半衰期 = ln(2) / θ
hl = np.log(2) / theta
return hl
小技巧: 半衰期在5-20个周期之间,通常是比较舒服的交易区间。太短了是噪音,太长了是趋势。
均值回归的适用市场与品种
不是所有市场都适合做均值回归。你想想看,比特币那种一天涨30%的品种,你敢做回归吗?
我总结了几条经验:
| 市场/品种 | 适用性 | 原因 |
|---|---|---|
| A股大盘股 | ★★★★★ | 流动性好,波动适中,机构主导 |
| 外汇对(EUR/USD) | ★★★★☆ | 长期均衡存在,但需注意央行干预 |
| 商品期货(螺纹钢) | ★★★☆☆ | 有季节性规律,但趋势行情多 |
| 加密货币 | ★★☆☆☆ | 波动太大,回归信号容易被吞没 |
| 个股(小盘妖股) | ★☆☆☆☆ | 容易被操纵,均值不稳定 |
我曾经在螺纹钢上吃过亏。当时看到价格偏离60日均线10%,觉得稳了,直接重仓做回归。结果呢?趋势延续了三天,我爆仓了。
后来我学乖了——先看市场状态。如果是震荡市,均值回归很香。如果是趋势市,别碰。
避坑指南: 我曾经在2015年股灾期间做均值回归,结果被连续跌停板教育了。记住——极端行情下,均值回归会失效。市场恐慌时,什么「均值」都不管用。
怎么判断市场状态?我习惯用ADF检验:
def check_mean_reversion(price_series):
result = adfuller(price_series, autolag='AIC')
p_value = result[1]
if p_value < 0.05:
return "适合均值回归"
else:
return "不适合,可能是趋势行情"
p值小于0.05,说明序列平稳,可以做回归。大于0.05,说明有单位根,别硬来。
总结一下: 均值回归不是万能药。它适合震荡市、高流动性品种、稳定的均值环境。趋势市里硬做回归,就是给市场送钱。
嗯,这一章就到这里。记住——均值回归的核心不是「猜顶底」,而是「赌概率」。你只要在概率有利的时候出手,长期下来就能赚钱。