第四章:数据获取与清洗——套利策略的“地基工程”
做期货跨品种套利,我最深的体会是什么?
数据决定生死。
你策略再牛,模型再复杂,数据是脏的,结果就是垃圾进垃圾出。我见过太多人花几周写策略,却只花半小时拉数据——嗯,最后亏得不明不白。
这一章,咱们就把数据这块硬骨头啃下来。
4.1 数据源选择:Tushare vs JoinQuant
国内做期货量化,主流数据源就两个:Tushare和JoinQuant(聚宽)。
我个人习惯两个都备着,为什么?因为各有各的脾气。
| 对比维度 | Tushare | JoinQuant |
|---|---|---|
| 数据覆盖 | 全品种,历史数据深 | 全品种,实时数据强 |
| 获取方式 | HTTP API + Token | 本地SDK + 在线平台 |
| 免费额度 | 积分制,基础够用 | 每日调用有限制 |
| 适合场景 | 离线研究、回测 | 实盘、策略开发 |
4.2 数据对齐:主力合约与连续合约
跨品种套利最头疼的问题是什么?合约不统一。
螺纹钢和热卷,一个1月、5月、10月主力,另一个可能2月、6月。你直接拿两个不同月份的合约算价差?那叫关公战秦琼。
4.2.1 主力合约的“坑”
主力合约是成交量最大的那个。但问题在于——它会切换。
我曾经在回测螺纹钢和铁矿石的套利时,没处理换月,结果价差图里出现了一个巨大的“断崖”。排查了半天,原来是螺纹钢换月了,铁矿石没换。说白了,数据没对齐。
4.2.2 连续合约的构建逻辑
连续合约就是把不同月份的主力合约“拼接”起来。怎么拼?我常用的方法有两种:
- 价格复权法:在换月日,把新旧合约的价差调整掉。适合做统计套利。
- 持仓量加权法:按持仓量比例合成一个虚拟合约。适合做趋势跟踪。
我个人偏好复权法,因为它保留了价格的真实波动。你想想看,套利策略本质是赌价差回归,复权后的价差序列更干净。
4.3 异常值处理:那些“离谱”的数据点
数据里总有些“怪物”——比如螺纹钢突然涨停10%,或者铁矿石价格瞬间跌停。这些是真实行情吗?不一定。
我遇到过最离谱的一次:某天螺纹钢的收盘价被记录成了0.01元。查了半天,是数据源的一个bug。如果我没做异常值检测,策略就会认为“哇,价差巨大,赶紧开仓”——然后爆仓。
4.3.1 常用的检测方法
- 3σ原则:超过均值±3倍标准差的数据,标记为异常。
- IQR方法:四分位距法,适合非正态分布的数据。
- 百分比截断:直接去掉前后0.5%的极端值。
4.4 缺失值填充:别让数据“断片”
期货数据经常有缺失——节假日、夜盘中断、数据源故障。怎么办?
我常用的填充策略:
- 前向填充:用上一个非缺失值填充。适合分钟级数据,因为价格变化连续。
- 线性插值:用前后两个值做线性拟合。适合日线数据。
- 不填充:直接删除缺失行。适合数据量大的情况。
嗯,这里要注意:千万别用均值填充!期货价格是非平稳的,均值填充会引入巨大偏差。我刚开始做的时候犯过这个错,回测曲线漂亮得不行,实盘一跑就崩。
4.5 实战代码:数据清洗流水线
下面是我常用的数据清洗函数,直接拿去用:
import pandas as pd
import numpy as np
def clean_futures_data(df, method='forward'):
"""
期货数据清洗流水线
df: DataFrame,必须包含'close'列
method: 填充方法,'forward'或'linear'
"""
# 1. 去除停牌日(成交量=0)
df = df[df['volume'] > 0].copy()
# 2. 异常值检测(3σ)
mean = df['close'].mean()
std = df['close'].std()
df = df[(df['close'] > mean - 3*std) &
(df['close'] < mean + 3*std)]
# 3. 缺失值填充
if method == 'forward':
df['close'] = df['close'].ffill()
elif method == 'linear':
df['close'] = df['close'].interpolate()
# 4. 删除剩余NaN
df = df.dropna()
return df
# 使用示例
# raw_data = tushare.get_futures_daily('RB.SHF')
# clean_data = clean_futures_data(raw_data, method='forward')
4.6 知识体系总览
这一章的内容,我用一张图帮你串起来:
这张图就是数据清洗的完整流水线。从数据源到最终可用的价差序列,每一步都有讲究。跳过任何一步,你的策略都可能“翻车”。
- 数据源选Tushare+JoinQuant双保险
- 主力合约必须做换月调整,否则价差失真
- 异常值用3σ或IQR检测,宁可漏杀不可误杀
- 缺失值用前向填充或线性插值,别用均值
- 清洗完一定要可视化检查,肉眼最可靠
数据搞定了,下一步才能谈策略。别急,地基打牢了,楼才能盖得高。