第二十八节:基差与回测框架——基差策略的回测设计、数据清洗与绩效评估
做基差交易这么多年,我越来越觉得,策略好不好,回测说了算。但回测这东西,说白了就是个双刃剑。你设计得不好,它骗你;你数据没洗干净,它坑你;你评估指标选错了,它误导你。今天咱们就聊聊,怎么把这个回测框架搭扎实。
一、基差策略的回测设计
回测设计,我个人的习惯是分三步走:定义信号、构建组合、执行模拟。每一步都有坑,咱们一个一个说。
1.1 信号定义:基差怎么变成交易指令?
基差策略的核心信号,无非就是基差的绝对水平、相对变化、或者统计上的异常值。举个例子:
- 绝对基差阈值:当基差大于某个值(比如+200元/吨)时做空基差,小于某个值(比如-200元/吨)时做多基差。
- 基差动量:基差连续N日扩大或收窄,触发入场。
- 统计套利信号:基差偏离历史均值超过2倍标准差,做回归。
我在项目中遇到过一个问题:用绝对阈值做回测,结果发现大部分信号都集中在交割月前两周。为什么?因为那时候基差波动最大。后来我加了时间过滤条件——只交易非交割月的前两个月,信号质量明显提升。
1.2 组合构建:多空腿怎么配?
基差交易通常涉及两个腿:现货(或近月期货)和远月期货。回测时,你得明确:
- 头寸比例:是1:1对冲,还是根据贝塔调整?
- 换月规则:合约到期前多少天换仓?换仓成本怎么算?
- 资金管理:每笔交易用多少保证金?杠杆倍数怎么设?
嗯,这里要注意:很多新手回测时忽略换月成本,结果实盘一跑,收益直接腰斩。我建议在回测中显式记录每次换月的滑点和手续费,哪怕只是估算,也比没有强。
1.3 执行模拟:滑点与流动性
回测里最骗人的就是“理想成交”。你想想看,基差策略往往交易的是非主力合约,流动性差得很。我见过一个策略,回测年化30%,实盘一跑只有5%。原因就是回测时没考虑滑点。
我的做法是:根据合约的日均成交量,动态设置滑点。比如成交量低于5000手的合约,滑点设为1个tick;低于1000手的,设为3个tick。这样回测结果才靠谱。
二、基差数据的清洗与处理
数据清洗,说白了就是“垃圾进,垃圾出”。基差数据尤其脏,因为涉及两个价格序列,任何一个出问题,基差就歪了。
2.1 常见的数据问题
| 问题类型 | 表现 | 原因 |
|---|---|---|
| 缺失值 | 某天基差为NaN | 节假日、数据源中断 |
| 异常跳点 | 基差突然偏离正常范围10倍 | 数据录入错误、涨跌停 |
| 合约换月断层 | 基差在换月日出现跳跃 | 新旧合约价格不连续 |
| 时间戳不对齐 | 现货和期货数据时间不同步 | 数据源采集频率不一致 |
我曾经遇到过一个坑:某品种的现货数据是收盘价,期货数据是15:00的结算价,两者时间戳差了15分钟。结果基差序列里每天都有个“假波动”。后来我强制对齐到同一时间戳,问题才解决。
2.2 清洗流程:我的标准做法
- 去重与排序:按时间升序排列,删除重复行。
- 缺失值处理:连续缺失不超过3天,用线性插值;超过3天,直接删除该段。
- 异常值检测:用3倍标准差或百分位法(比如0.5%~99.5%)过滤。
- 换月调整:在换月日,用“后复权”方法调整基差序列,避免断层。
- 时间对齐:将现货和期货数据统一到同一时间频率(比如日频)。
2.3 代码示例:基差数据清洗
import pandas as pd
import numpy as np
def clean_basis_data(df, price_col='close', basis_col='basis'):
"""
基差数据清洗函数
df: 包含日期、现货价格、期货价格的DataFrame
"""
# 1. 去重排序
df = df.sort_values('date').drop_duplicates(subset='date')
# 2. 计算基差
df[basis_col] = df['spot_price'] - df['futures_price']
# 3. 缺失值处理(线性插值,最多3天)
df[basis_col] = df[basis_col].interpolate(method='linear', limit=3)
# 4. 异常值过滤(3倍标准差)
mean = df[basis_col].mean()
std = df[basis_col].std()
df = df[(df[basis_col] > mean - 3*std) & (df[basis_col] < mean + 3*std)]
# 5. 换月调整(后复权示例)
# 假设换月日为 roll_date,调整因子为 roll_adjust
# df['basis_adj'] = df[basis_col] - roll_adjust
return df
三、基差策略的绩效评估
绩效评估,不能只看年化收益率。我见过太多人拿一个夏普比率2.0的策略当宝贝,结果实盘亏成狗。为什么?因为回测里的夏普比率是“纸面夏普”,没考虑实盘的各种摩擦。
3.1 核心指标:哪些必须看?
| 指标 | 计算公式 | 我的关注点 |
|---|---|---|
| 年化收益率 | (总收益率+1)^(252/N) - 1 | 低于10%的策略,我基本不看 |
| 夏普比率 | (年化收益 - 无风险利率) / 年化波动 | 大于1.5才算及格 |
| 最大回撤 | 峰值到谷值的最大跌幅 | 超过20%的策略,需要谨慎 |
| 卡玛比率 | 年化收益 / 最大回撤 | 大于2.0才算优秀 |
| 胜率 | 盈利交易次数 / 总交易次数 | 基差策略胜率通常在40%-60% |
| 盈亏比 | 平均盈利 / 平均亏损 | 大于1.5才值得做 |
我个人习惯,还会加一个“资金曲线平滑度”的指标——说白了就是看最大回撤的持续时间。如果一个策略回撤了6个月还没回来,那它的逻辑可能已经失效了。
3.2 回测中的“幸存者偏差”陷阱
做基差回测,最容易犯的错误就是只回测活下来的合约。你想想看,如果一个品种的某个合约在交割前被强行平仓了,那它的基差数据就不完整。如果你只保留完整数据的合约,那回测结果就会偏乐观。
我的做法是:回测时包含所有合约,包括那些提前退市的。如果某个合约的数据不完整,就把它当作“亏损交易”计入回测。这样虽然保守,但更接近真实。
3.3 绩效归因:赚钱到底靠什么?
基差策略的收益来源,无非三个:
- 基差回归收益:基差从偏离回归到均值,赚的是价差。
- 展期收益:换月时,由于远近月价差结构带来的收益。
- 方向性收益:现货或期货单边波动带来的意外收益(通常不是策略本意)。
我建议在绩效评估中,把这三部分拆开来看。怎么拆?很简单:
- 基差回归收益 = 基差变化 × 头寸方向
- 展期收益 = 每次换月时的价差变化
- 方向性收益 = 总收益 - 基差回归收益 - 展期收益
如果发现方向性收益占比超过30%,那你的策略其实是个“伪基差策略”,本质是在赌方向。这时候就要小心了。
四、知识体系总览
下面这张图,是我对本章内容的总结。你可以把它当作一个检查清单,做回测时对照着看,能少踩不少坑。
好了,关于基差策略的回测框架,咱们就聊到这儿。数据清洗、回测设计、绩效评估,这三块缺一不可。下次你再跑回测的时候,不妨对照着这张图,一个一个检查过去。相信我,能帮你省下不少冤枉钱。