3. 数据获取与清洗:多合约数据源、主力合约拼接、异常值处理

做跨品种价差分析,最头疼的其实不是策略本身。

是数据。

我见过太多人,策略逻辑写得漂漂亮亮,一回测就崩。为什么?数据源没对齐,主力合约跳空,或者某个交易日突然冒出一个天价成交。说白了,数据不干净,后面全是白搭。

这一章,我就把数据获取和清洗的坑,一个一个给你指出来。

3.1 多合约数据源:你从哪里拿数据?

国内期货市场,数据源就那么几个。我个人习惯用这三类:

  • 交易所官方数据:最权威,但获取麻烦。适合做深度研究。
  • 第三方数据商:比如万得、聚宽、米筐。接口稳定,字段齐全。我团队主力用这个。
  • 开源数据包:比如 tushare、akshare。免费,但偶尔断更。适合个人研究。

你可能会问:「哪个最好?」

其实没有标准答案。我建议你至少准备两个数据源。一个做主数据,一个做校验。我在项目中遇到过,某数据商把螺纹钢的夜盘数据漏了整整一周。要不是我交叉验证,回测结果能骗死你。

核心原则:数据源可以不同,但字段定义必须统一。比如「收盘价」是结算价还是最后一笔成交价?这个必须提前定死。

3.2 主力合约拼接:别让换月吃掉你的利润

期货合约有到期日。你不能一直拿着同一个合约做回测。所以需要「主力合约拼接」。

什么叫主力合约?就是当前持仓量最大、成交量最活跃的那个合约。

拼接方式,我常用两种:

  1. 连续主力合约:每天取持仓量最大的合约。换月时直接跳转。
  2. 加权主力合约:按持仓量加权,平滑过渡。适合做价差分析。

嗯,这里要注意。直接跳转会有「跳空缺口」。比如螺纹钢从 RB2401 换到 RB2405,两个合约价格可能差几十点。如果你不做处理,回测里就会出现莫名其妙的盈亏。

我曾经犯过这个错。回测一个螺纹钢和热卷的价差策略,年化收益高得离谱。后来发现,全是主力合约跳空带来的假信号。白高兴一场。

怎么处理?我一般用「后复权」方法:

# 主力合约拼接 + 后复权示例
import pandas as pd

def splice_main_contract(df, method='volume'):
    """
    df: 包含所有合约的日线数据,字段:date, symbol, close, volume
    method: 'volume' 按持仓量选主力,'oi' 按持仓量
    """
    # 选出每日主力合约
    main_idx = df.groupby('date')[method].idxmax()
    main_df = df.loc[main_idx].copy()
    
    # 后复权处理:以第一个主力合约为基准
    main_df['adj_close'] = main_df['close']
    cum_shift = 0
    for i in range(1, len(main_df)):
        if main_df.iloc[i]['symbol'] != main_df.iloc[i-1]['symbol']:
            # 换月日,计算价差
            shift = main_df.iloc[i-1]['close'] - main_df.iloc[i]['close']
            cum_shift += shift
        main_df.iloc[i, main_df.columns.get_loc('adj_close')] += cum_shift
    
    return main_df[['date', 'adj_close']]
小技巧:换月日前后三天,价差数据波动会异常。我一般会在这几天设置「观察期」,不产生交易信号。

3.3 异常值处理:那些让你亏钱的「黑天鹅」

数据里总有一些「怪物」。比如某天螺纹钢价格突然跌停,但成交量只有几手。这种数据,你信还是不信?

我的经验是:先怀疑,再验证

常见的异常值分三类:

异常类型 典型表现 处理方法
价格异常 单日涨跌幅超过 10% 用前一日价格填充,或剔除
成交量异常 成交量突然放大 100 倍 检查是否为交割日或数据错误
缺失值 某天没有数据 向前填充,或插值

你想想看,如果价差数据里混了一个异常点,你的协整检验结果可能完全相反。我见过有人因为一个异常值,把两个本来没有关系的品种硬生生做成了「伪套利对」。

我的清洗流程是这样的:

  1. 基础过滤:剔除涨跌停日、交割日数据。
  2. 统计过滤:用 3 倍标准差或 IQR 方法,标记极端值。
  3. 人工复核:标记出来的异常点,手动查一下当天新闻。如果是真实事件(比如政策突变),保留;如果是数据错误,剔除。
警告:不要自动剔除所有异常值。有些「异常」其实是市场真实波动。比如 2015 年股指期货的极端行情,如果你剔除了,策略就永远学不会应对极端情况。

3.4 知识体系总览

下面这张图,是我做数据清洗时的完整流程。你可以把它贴在工位上。

数据获取与清洗全流程 多合约数据源 主力合约拼接 异常值处理 交易所 / 第三方 / 开源 交叉验证,统一字段 连续主力 / 加权主力 后复权处理跳空 统计过滤 + 人工复核 保留真实波动 干净、连续、可回溯的价差数据 协整检验 / 价差策略回测

这张图的核心逻辑很简单:数据源决定下限,清洗决定上限。你拿到的原始数据再好,清洗不到位,策略照样翻车。

我的习惯:每次拿到新数据,先画一张这样的流程图。把每个环节的输入、输出、处理方法写清楚。这样团队协作时,不会出现「你用的数据和我用的不一样」的尴尬。

好了,数据清洗这块,我就讲这么多。记住一句话:花 80% 的时间处理数据,花 20% 的时间写策略。这个比例,是我亏出来的经验。

专注资料整理