第三章:数据准备与清洗——数据源选择、频率、缺失值、异常值、对齐

做基差交易,数据就是你的弹药。弹药有问题,枪法再准也白搭。

我见过太多交易员,策略逻辑写得漂漂亮亮,回测曲线美如画,一上实盘就崩。为什么?十有八九是数据没处理好。今天咱们就把这块硬骨头啃下来。

3.1 数据源选择:期货、现货、指数,到底用哪个?

基差交易的核心,就是盯着期货和现货之间的价差。但「现货」这个词,其实挺模糊的。

期货数据:这个最直接。主力合约、连续合约、指数合约,你得想清楚用哪个。我个人习惯用主力合约做交易信号,因为流动性最好,滑点小。但回测时用主力合约有个坑——换月跳空。你想想看,每个月合约切换那几天,价格可能直接跳几十个点,基差也跟着乱跳。

现货数据:这才是真正的难点。比如做螺纹钢基差,现货价格去哪找?我的经验是:找权威现货价格指数,比如我的钢铁网、生意社这些。别自己去市场上问,你问到的价格可能只是某个贸易商的报价,不具备代表性。

指数数据:比如南华商品指数、文华商品指数。这些适合做宏观对冲,不适合做具体品种的基差交易。指数是加权平均,跟实际交割品有差距。

核心原则:基差交易的数据源,必须保证「可复制、可验证、可交易」。你用的数据,别人也能拿到,而且你能按这个价格实际成交。

3.2 数据频率:日线还是分钟线?

这个问题没有标准答案,取决于你的交易周期。

日线数据:适合中长线基差交易。比如做季节性回归、跨期套利,日线足够了。我早期做豆粕基差,用的就是日线,效果不错。日线的优点是数据干净,噪声少,处理起来省心。

分钟线数据:适合高频基差交易,或者做日内回归。比如股指期货的期现套利,你得用1分钟甚至tick数据。为什么?因为价差可能在几秒内就消失了。

我个人建议:先用日线跑通逻辑,再考虑降频到分钟线。别一上来就搞分钟线,数据量太大,处理起来费时费力,而且容易过拟合。

数据频率 适用场景 优点 缺点
日线 中长线基差回归、季节性套利 噪声少、处理简单 信号延迟、无法捕捉日内机会
分钟线 高频套利、日内回归 信号及时、捕捉微观结构 噪声多、数据量大、易过拟合
Tick级 极高频做市、期现套利 最精确、无延迟 数据量巨大、处理复杂

3.3 缺失值处理:别让空值毁了你的策略

数据缺失是家常便饭。节假日、交易所故障、数据源断更,都会导致缺失。

我遇到过最坑的一次:某个品种的现货数据,周末和节假日都不更新,但期货还在交易。结果周一开盘,基差直接跳空,策略信号全乱套了。

处理缺失值,常见方法有几种:

  • 向前填充:用上一个有效值填充。适合现货数据,因为现货价格变化慢,用昨天的价格也说得过去。
  • 线性插值:用前后两个值取平均。适合期货数据,尤其是分钟线。
  • 直接删除:如果缺失比例很低(比如<1%),直接删掉那几行。简单粗暴,但要注意别把关键信号删了。

我的习惯:先检查缺失比例。如果超过5%,就得怀疑数据源是不是有问题。别盲目填充,先搞清楚为什么缺失。

# 缺失值处理示例(Python伪代码)
import pandas as pd

# 加载数据
df = pd.read_csv('basis_data.csv')

# 检查缺失比例
missing_ratio = df.isnull().sum() / len(df)
print(missing_ratio)

# 向前填充现货数据
df['spot_price'] = df['spot_price'].fillna(method='ffill')

# 线性插值期货数据
df['futures_price'] = df['futures_price'].interpolate(method='linear')

# 如果还有缺失,直接删除
df = df.dropna()

3.4 异常值检测:把「妖孽」揪出来

异常值,说白了就是那些明显不合理的数据。比如螺纹钢现货价格突然跳到10000元/吨,或者基差突然变成-2000。这些多半是数据录入错误,或者交易所的乌龙指。

我常用的检测方法:

  • 3σ原则:超过均值±3倍标准差的数据,视为异常。适合正态分布的数据。
  • IQR方法:用四分位距。超过Q1-1.5*IQR或Q3+1.5*IQR的数据,视为异常。这个方法更稳健,不受极端值影响。
  • 业务规则:比如基差不可能超过某个范围。这个需要你对品种有深刻理解。

注意:别把「极端行情」当成异常值。比如2020年原油期货跌到负值,那不是数据错误,是真实发生的。异常值检测要结合业务背景,不能机械地套用统计方法。

# 异常值检测示例
import numpy as np

# 计算基差
df['basis'] = df['spot_price'] - df['futures_price']

# 使用IQR方法
Q1 = df['basis'].quantile(0.25)
Q3 = df['basis'].quantile(0.75)
IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

# 标记异常值
df['is_outlier'] = (df['basis'] < lower_bound) | (df['basis'] > upper_bound)

# 查看异常值
print(df[df['is_outlier']])

3.5 数据对齐:让期货和现货「对上眼」

这是最容易被忽视的一步。期货和现货的交易时间不一样,交割日期不一样,甚至节假日都不一样。如果不做对齐,你算出来的基差就是错的。

举个例子:期货夜盘交易到晚上11点,但现货市场下午3点就收盘了。你用晚上11点的期货价格,跟下午3点的现货价格算基差,这合理吗?显然不合理。

对齐的核心原则:时间戳对齐。确保期货和现货的价格是在同一时刻采集的。

  • 日线对齐:用同一交易日的收盘价。注意节假日差异,比如国内期货市场休市,但外盘还在交易。
  • 分钟线对齐:用同一分钟的时间戳。如果现货没有分钟数据,可以用插值法对齐。
  • 交割日对齐:临近交割时,期货价格会向现货收敛。这时候基差会自然缩小,别把它当成交易信号。

避坑指南:我曾经因为没对齐节假日,导致基差数据出现系统性偏差。回测时赚得盆满钵满,实盘一跑就亏。后来发现,原来节假日期间现货不更新,但期货还在波动,基差被「人为」拉大了。

3.6 知识体系总览

下面这张图,把数据准备与清洗的核心逻辑串起来了。你可以把它当成一个检查清单,每次做数据前先过一遍。

数据准备与清洗核心流程 数据源选择 数据频率 缺失值处理 异常值检测 数据对齐 数据合并与清洗 干净、对齐、可用的基差数据 期货/现货/指数 日线/分钟线/Tick 填充/插值/删除 3σ/IQR/业务规则 时间戳/交割日/节假日 合并后检查一致性

数据准备这件事,说白了就是「脏活累活」。但正是这些脏活累活,决定了你的策略能不能赚钱。别嫌麻烦,把每一步做扎实了,后面回测和实盘才能省心。

嗯,今天就聊到这儿。数据准备好了,下一章咱们就可以开始构建基差交易策略了。


蓝海数据掘金营,专注资料整理