7. 均值回归策略设计:布林带策略、Z-score策略、卡尔曼滤波动态基差跟踪
均值回归,说白了就是「涨多了会跌,跌多了会涨」。在基差交易里,这个逻辑特别适用。基差不会无限扩大,也不会无限缩小,它总在某个合理区间内晃悠。我们要做的,就是抓住它偏离均值的那一刻,赌它回来。
今天咱们聊三种主流方法:布林带、Z-score、还有卡尔曼滤波。前两个是经典派,第三个是动态派。我个人习惯是先用布林带做快速扫描,再用卡尔曼滤波做精细入场。嗯,咱们一个一个来。
7.1 布林带策略:最直观的均值回归工具
布林带由三条线组成:中轨是移动平均线,上下轨是标准差通道。当基差触及上轨,说明偏离太大,大概率要回落;触及下轨,则可能反弹。
我在项目中遇到过一个问题:布林带参数怎么选?周期太短,信号太多,假突破频繁;周期太长,反应迟钝,错过行情。我的经验是,对于股指期货基差,20周期、2倍标准差是个不错的起点。
import numpy as np
import pandas as pd
def bollinger_bands_strategy(basis, window=20, num_std=2):
"""
布林带基差交易策略
basis: 基差序列
window: 移动平均窗口
num_std: 标准差倍数
"""
rolling_mean = basis.rolling(window=window).mean()
rolling_std = basis.rolling(window=window).std()
upper_band = rolling_mean + num_std * rolling_std
lower_band = rolling_mean - num_std * rolling_std
# 生成信号
signals = pd.Series(0, index=basis.index)
signals[basis > upper_band] = -1 # 做空基差
signals[basis < lower_band] = 1 # 做多基差
return signals, upper_band, lower_band
7.2 Z-score策略:标准化后的均值回归
Z-score说白了就是把基差变成标准分数。公式很简单:(当前基差 - 均值) / 标准差。Z-score的绝对值越大,回归的概率越高。
你想想看,Z-score=2意味着当前基差偏离均值2个标准差。根据正态分布,这种情况发生的概率只有5%左右。嗯,这时候入场,胜率确实高。
| Z-score 范围 | 偏离程度 | 交易动作 |
|---|---|---|
| Z > 2 | 严重偏高 | 做空基差 |
| Z < -2 | 严重偏低 | 做多基差 |
| |Z| < 0.5 | 正常范围 | 不交易 |
def zscore_strategy(basis, window=20, entry_threshold=2.0, exit_threshold=0.5):
"""
Z-score基差交易策略
"""
rolling_mean = basis.rolling(window=window).mean()
rolling_std = basis.rolling(window=window).std()
zscore = (basis - rolling_mean) / rolling_std
# 入场信号
entry_long = zscore < -entry_threshold
entry_short = zscore > entry_threshold
# 出场信号
exit_long = zscore > -exit_threshold
exit_short = zscore < exit_threshold
return zscore, entry_long, entry_short, exit_long, exit_short
7.3 卡尔曼滤波动态基差跟踪
布林带和Z-score有个共同问题:它们假设均值和标准差是固定的。但市场是动态的,基差的均值会漂移。比如2015年股灾期间,基差均值从-10点漂到了-50点。用固定均值去判断,肯定死得很惨。
卡尔曼滤波就是来解决这个问题的。它能动态估计基差的「真实均值」和「波动率」,实时更新。说白了,它像一个自适应滤波器,跟着市场变。
import pykalman
def kalman_basis_tracker(basis):
"""
卡尔曼滤波动态基差跟踪
"""
# 初始化卡尔曼滤波器
kf = pykalman.KalmanFilter(
transition_matrices=[1],
observation_matrices=[1],
initial_state_mean=basis[0],
initial_state_covariance=1,
observation_covariance=1,
transition_covariance=0.01
)
# 滤波
state_means, state_covs = kf.filter(basis.values)
# 动态均值 = 滤波后的状态
dynamic_mean = pd.Series(state_means.flatten(), index=basis.index)
# 动态标准差 = 观测残差的标准差
residuals = basis - dynamic_mean
dynamic_std = residuals.rolling(window=20).std()
# 生成信号
zscore_dynamic = residuals / dynamic_std
signals = pd.Series(0, index=basis.index)
signals[zscore_dynamic > 2] = -1
signals[zscore_dynamic < -2] = 1
return signals, dynamic_mean, dynamic_std
- 传统方法:均值固定,适合平稳市场
- 卡尔曼滤波:均值动态,适合结构变化的市场
- 代价:卡尔曼滤波需要调参(观测噪声、过程噪声),参数敏感
我记得有一次做原油期货的基差交易,布林带和Z-score都失效了,因为基差均值在持续下移。换成卡尔曼滤波后,信号质量明显提升。嗯,这就是动态跟踪的价值。
7.4 三种策略的对比与选择
没有完美的策略,只有适合的策略。我一般这样选:
- 布林带:适合快速扫描,直观易懂。我用来做初筛,看哪些品种的基差到了极端位置。
- Z-score:适合标准化比较,跨品种对比时特别好用。比如同时看10个品种的基差,Z-score可以统一阈值。
- 卡尔曼滤波:适合精细入场,尤其是市场结构发生变化时。但参数调起来比较麻烦,新手容易过拟合。
最后说一句:均值回归策略最怕的就是「趋势延续」。如果基差突破后不回归,反而继续扩大,那就是亏损的来源。所以一定要设止损,别硬扛。我个人的止损线是基差偏离均值3个标准差,或者亏损达到总资金的1%。
好了,这一章就到这里。记住:没有完美的策略,只有不断优化的交易系统。