第二章 价差计算与数据获取:主力合约识别、近远月价差计算、数据源选择(Wind/天勤)、数据清洗

做跨期套利,说白了就是吃两个合约之间的价差波动。但有个前提——你得先把价差算对,把数据搞干净。这一步要是糊弄过去,后面策略再牛也是白搭。我见过太多人,策略回测曲线漂亮得像假的一样,一上实盘就崩,十有八九是数据源或者价差计算出了问题。

2.1 主力合约识别——别搞错交易对象

跨期套利的第一步,是搞清楚哪个合约是主力。你想想看,如果拿一个流动性枯竭的合约去跟主力合约配对,滑点都能把你吃破产。

主力合约的定义:通常我们取持仓量最大的那个合约。成交量也可以,但我个人习惯用持仓量——它更能反映资金沉淀的深度。

核心逻辑:每天收盘后扫描所有同品种合约,找出持仓量最大的那个,标记为主力。次主力同理。

我在项目中遇到过一个问题:换月期间,主力合约会从近月跳到远月。如果你不做平滑处理,价差序列会出现一个巨大的跳空缺口。嗯,这里要注意——换月日前后,价差数据要特别处理,要么对齐到同一个合约对,要么做滚动调整。

# 伪代码:主力合约识别逻辑
def find_main_contract(data):
    # data 是某品种所有合约的持仓量DataFrame
    main = data.loc[data.groupby('date')['open_interest'].idxmax()]
    return main[['date', 'contract', 'close']]

2.2 近远月价差计算——公式很简单,坑不少

价差 = 近月合约价格 - 远月合约价格。就这么简单?嗯,表面上是这样。但实际做的时候,有几个细节你绕不开。

价差类型 计算公式 适用场景
简单价差 P_near - P_far 同品种、同交易所
比例价差 (P_near - P_far) / P_near 价格水平差异大时
对数价差 ln(P_near) - ln(P_far) 统计建模时常用

我个人习惯用简单价差,直观好理解。但如果你做的是股指期货或者国债期货,比例价差可能更合适——因为价格本身会随时间漂移。

避坑指南:我曾经在计算螺纹钢的价差时,没注意近月合约和远月合约的乘数不同(10吨/手 vs 10吨/手,其实一样),但有些品种比如焦炭,不同合约的乘数可能不同。一定要确认合约单位一致!

2.3 数据源选择——Wind还是天勤?

做量化交易,数据源就是你的弹药库。选错了,后面全白干。

  • Wind:老牌金融终端,数据全、质量高。但贵,一年几万块。适合机构用户。
  • 天勤:新兴的量化数据平台,API友好,Python直接调。免费版够用,付费版也不贵。适合个人和中小团队。

我自己的经验是:如果做高频或者日内套利,Wind的Tick数据更靠谱。如果做日线级别的跨期套利,天勤完全够用,而且代码写起来舒服很多。

# 天勤获取主力合约数据示例
from tqsdk import TqApi

api = TqApi()
# 获取螺纹钢主力连续合约
klines = api.get_kline_serial("SHFE.rb0000", 86400, data_length=500)
print(klines[['close', 'open_interest']])

小技巧:天勤的"rb0000"就是螺纹钢主力连续合约,它会自动帮你做换月处理。但注意——这个连续合约的价格是拼接出来的,不能直接用于计算真实价差。真实价差必须用具体合约(比如rb2401和rb2405)来算。

2.4 数据清洗——脏数据是策略的隐形杀手

数据清洗听着枯燥,但它是整个策略的基石。我见过有人用没清洗的数据跑回测,年化收益30%,实盘直接亏到怀疑人生。为什么?因为数据里有跳空、有缺失、有异常值,回测时这些都被当成了交易机会。

清洗步骤

  1. 缺失值处理:如果某天某个合约没有交易,用前一天的收盘价填充,或者直接删除该天的价差数据。
  2. 异常值检测:价差突然偏离3个标准差以上,大概率是数据错误。我习惯用滚动窗口的Z-score来检测。
  3. 换月跳空处理:主力合约切换时,价差会有一个不自然的跳变。需要做后复权或者直接分段处理。
# 数据清洗示例:滚动Z-score检测异常价差
import pandas as pd
import numpy as np

def clean_spread(spread_series, window=20, threshold=3):
    rolling_mean = spread_series.rolling(window).mean()
    rolling_std = spread_series.rolling(window).std()
    z_scores = (spread_series - rolling_mean) / rolling_std
    # 标记异常值
    spread_series[z_scores.abs() > threshold] = np.nan
    # 向前填充
    spread_series.fillna(method='ffill', inplace=True)
    return spread_series

我曾经踩过的坑:有一次做豆粕的跨期套利,数据里突然出现一个-500的价差,我以为是交易机会,结果发现是数据源把近月和远月的价格搞反了。从那以后,我每次拿到数据都会先画个价差曲线图,肉眼扫一遍——这比任何算法都管用。

2.5 知识体系总览

下面这张图,是我做跨期套利数据准备阶段的核心流程。你照着这个走,基本不会漏掉关键步骤。

跨期套利数据准备流程 数据源选择 Wind / 天勤 主力合约识别 持仓量最大 → 主力 价差计算 近月 - 远月 数据清洗 缺失值 / 异常值 / 换月处理 干净价差序列 选择靠谱的数据源 每天动态识别主力 计算真实价差 清洗掉脏数据

数据准备这一步,说白了就是打地基。地基不稳,楼盖得再高也得塌。我建议你每次拿到新数据,先花10分钟做一遍可视化检查——画个价差曲线,看看有没有异常跳点,有没有缺失区间。这10分钟,能帮你省下后面10小时的debug时间。

我的习惯:我会把清洗后的价差数据存成两个版本——一个是原始未清洗的(留作审计用),一个是清洗后的(用于策略计算)。这样万一策略出问题,我可以回头对比,看看是不是数据清洗环节出了岔子。

专注资料整理