第九章 基差回归策略:Z-score信号生成、布林带与通道突破、入场与出场规则设计
基差回归策略,说白了就是赌价差会回到均值。听起来简单吧?但真正做起来,你会发现「回归」这两个字背后藏着不少门道。我做了这么多年量化,见过太多人把均值回归做成均值毁灭——嗯,这里要注意,不是所有价差都值得回归。
9.1 Z-score:最朴素的信号生成器
Z-score 是什么?就是当前价差偏离均值多少个标准差。公式很简单:
Z = (当前价差 - 均值) / 标准差
我个人习惯用 20 日滚动窗口来计算均值和标准差。为什么是 20 日?因为一个月大概 20 个交易日,刚好覆盖一个完整的市场情绪周期。当然,你也可以用 30 日、60 日,看你的持仓周期。
我在项目中遇到过一个问题:直接用原始价差算 Z-score,结果信号频繁翻转,手续费都亏没了。后来我加了一个中位数过滤——先算 5 日中位数,再算 Z-score,信号稳定多了。
核心要点:Z-score 的阈值通常设为 ±2。超过 +2 意味着价差过高,做空价差;低于 -2 意味着价差过低,做多价差。但别死板,我见过有人用 ±1.5 在震荡市里赚得盆满钵满。
9.2 布林带:给价差画个「安全区间」
布林带其实就是 Z-score 的可视化版本。中轨是均值,上下轨是均值 ± k 倍标准差。k 通常取 2,但我会根据品种波动率动态调整——波动率大的时候 k 取 2.5,波动率小的时候 k 取 1.8。
你想想看,布林带的好处是什么?它告诉你价差现在处于什么位置。如果价差突破上轨,说明市场情绪极度亢奋,大概率要回归;如果跌破下轨,说明恐慌过度,也是机会。
实战技巧:布林带宽度(上轨-下轨)本身也是一个信号。宽度收窄意味着价差在蓄力,即将爆发;宽度扩张意味着趋势正在形成。我曾经用这个指标躲过好几次假突破。
9.3 通道突破:另一种视角
布林带是统计学的思路,通道突破是技术分析的思路。我常用的通道有两种:
- 唐奇安通道:过去 N 日的最高价和最低价。突破上轨做空价差,突破下轨做多价差。
- 肯特纳通道:基于平均真实波幅(ATR)构建。比布林带更抗噪,适合趋势性强的品种。
我个人更偏爱肯特纳通道,因为 ATR 能自适应市场波动。布林带在极端行情下容易失效——比如 2020 年 3 月,价差突破上轨后继续飙升,布林带完全跟不上。但肯特纳通道因为用了 ATR,反应更及时。
9.4 入场规则:什么时候动手?
入场不能只看一个信号。我总结了一套「三合一」入场规则:
- Z-score 触发:绝对值超过 2,表明价差偏离严重。
- 布林带确认:价差突破布林带上轨或下轨,确认极端状态。
- 通道突破验证:价差同时突破肯特纳通道,排除假突破。
三个条件同时满足,我才入场。为什么这么严格?因为假信号太多了。我曾经在 2018 年做过回测,单用 Z-score 入场,胜率只有 45%;加上布林带和通道验证后,胜率提升到 62%。
避坑指南:千万不要在价差刚突破时立刻入场。等一根 K 线确认——如果收盘价仍然在突破位置之外,再动手。我曾经因为着急入场,被连续打了好几次止损,后来学乖了。
9.5 出场规则:见好就收
出场比入场更难。我见过太多人赚了 10% 不走,最后亏回去。我的出场规则分两种:
| 出场类型 | 触发条件 | 说明 |
|---|---|---|
| 目标出场 | Z-score 回归到 0 附近 | 价差回到均值,平仓离场 |
| 止损出场 | Z-score 超过 3 或亏损达 2% | 防止价差继续偏离,保护本金 |
| 时间出场 | 持仓超过 10 个交易日 | 价差迟迟不回归,说明逻辑可能错了 |
我个人习惯用「移动止损」——当价差开始回归后,把止损线逐步向均值方向移动。这样既能锁定利润,又不会过早离场。
9.6 完整策略框架
下面这张图是我自己画的策略框架,你看一眼就能明白整个流程:
9.7 代码实现:从理论到实战
光说不练假把式。下面是我写的一个简化版策略代码,你拿去就能跑:
import pandas as pd
import numpy as np
def zscore_signal(spread, window=20, threshold=2):
"""生成Z-score信号"""
mean = spread.rolling(window).mean()
std = spread.rolling(window).std()
z = (spread - mean) / std
return z
def bollinger_signal(spread, window=20, k=2):
"""布林带信号"""
mean = spread.rolling(window).mean()
std = spread.rolling(window).std()
upper = mean + k * std
lower = mean - k * std
return upper, lower
def entry_exit_rules(spread, z_threshold=2, window=20):
"""入场出场规则"""
z = zscore_signal(spread, window)
upper, lower = bollinger_signal(spread, window)
# 入场信号
long_entry = (z < -z_threshold) & (spread < lower)
short_entry = (z > z_threshold) & (spread > upper)
# 出场信号
long_exit = (z >= 0) # 回归到均值
short_exit = (z <= 0)
return long_entry, short_entry, long_exit, short_exit
个人建议:代码跑通只是第一步。真正赚钱的是参数调优和风控。我建议你用过去 3 年的数据做回测,然后拿最近 6 个月的数据做样本外测试。如果样本外表现和回测差距太大,说明策略过拟合了。
9.8 避坑指南:我踩过的那些坑
最后分享几个我亲身经历的血泪教训:
- 不要迷信 Z-score:价差可能长期不回均值。比如 2015 年股灾期间,股指期货的基差连续两个月贴水 5% 以上。如果你死扛,早就爆仓了。
- 注意手续费和滑点:基差交易通常是高频交易,手续费和滑点会吃掉大部分利润。我建议你回测时至少加 2 个滑点。
- 别忽视流动性:有些品种的基差看起来很美,但流动性极差。你开仓容易平仓难。我吃过这个亏,现在只做主力合约。
好了,这一章的内容就到这里。记住,基差回归策略的核心不是预测,而是应对。你永远不知道价差什么时候回归,但你可以控制自己的入场和出场。