3、市场数据获取与清洗:期权链数据、标的资产数据、数据源选择(如Wind、Tushare)、数据清洗与对齐

做期权回测,最怕什么?

不是策略写错了,是数据有问题。数据错了,再牛的策略也是白搭。我见过太多人,策略跑出来曲线漂亮得不行,结果一查,是数据对齐出了偏差——期权数据和标的物数据差了那么几毫秒,整个回测就失真了。

这一章,咱们就聊聊怎么把数据这关把好。

3.1 数据源选择:Wind vs Tushare,怎么选?

做量化,数据源是第一步。国内主流就两个:Wind(万得)和 Tushare(通联数据)。

我个人习惯是:生产环境用 Wind,研究环境用 Tushare。为什么?

  • Wind:数据全、质量高、实时性好。但贵,一年几万块。适合机构或资金充裕的团队。
  • Tushare:免费(积分制),社区活跃,接口友好。但数据有延迟,历史数据偶尔有缺失。适合个人研究、策略验证。

嗯,这里要注意:千万别混用。我见过有人 Wind 拿期权数据,Tushare 拿标的物数据,结果两个数据源的时间戳格式不一样,对齐时出了大问题。选一个,用到底。

我的建议:如果你刚开始做期权回测,先用 Tushare 跑通流程。等策略稳定了,再换 Wind 做精细化回测。别一上来就砸钱买 Wind,万一策略不行呢?

3.2 期权链数据:你需要哪些字段?

期权链数据,说白了就是一张大表。每一行是一个期权合约,每一列是一个属性。你需要关注的核心字段有这些:

字段 说明 重要性
合约代码 唯一标识,如 "510050C2303M03000" 必选
交易日期 数据日期,格式 YYYY-MM-DD 必选
行权价 期权合约约定的行权价格 必选
到期日 合约到期日期 必选
看涨/看跌 Call 或 Put 必选
收盘价 当日收盘价(或结算价) 必选
成交量 当日成交量 推荐
持仓量 当日持仓量 推荐
隐含波动率 由期权价格反推的波动率 可选

你想想看,做期权做市,核心就是看隐含波动率和实际波动率的差值。所以隐含波动率这个字段,虽然数据源不一定直接给,但你自己得算出来。

3.3 标的资产数据:别小看它

期权是衍生品,它的价格跟标的物高度相关。所以标的资产数据必须同步获取。

对于 50ETF 期权,标的物就是 510050 这只 ETF。你需要的数据包括:

  • 日线数据:开盘价、收盘价、最高价、最低价、成交量
  • 分钟线数据:如果做高频回测,至少需要 1 分钟或 5 分钟线
  • 分红除权信息:ETF 分红会影响期权合约的调整,这个很容易被忽略
我曾经踩过的坑:有一次回测 50ETF 期权策略,发现某一天所有期权合约的价格都跳变了。查了半天,原来是 ETF 分红了,合约乘数做了调整,但我用的标的物数据没做复权处理。从那以后,我每次回测前都会检查分红日历。

3.4 数据清洗:脏数据怎么处理?

数据拿到手,别急着用。先洗一洗。我一般按以下步骤来:

  1. 去重:同一合约同一天出现多条记录,保留第一条或最后一条
  2. 缺失值处理:成交量、持仓量为空的行,直接删除。收盘价为空,用前一日数据填充(但要注意:如果连续多日缺失,说明合约可能已经退市)
  3. 异常值检测:比如某期权收盘价突然涨了 1000%,明显是数据错误。用 3-sigma 或 IQR 方法剔除
  4. 合约状态过滤:只保留正常交易的合约,剔除已到期、暂停交易的合约

说白了,数据清洗就是「去伪存真」。你想想看,如果数据里混了一个错误的价格,回测时可能就会触发一次虚假的套利信号,整个策略评估就偏了。

3.5 数据对齐:期权和标的物必须同步

这是最容易被忽视的一步,也是最重要的一步。

期权数据和标的物数据,时间戳必须严格对齐。比如你用 50ETF 的 1 分钟线,那期权数据也得是 1 分钟线,而且时间点要完全一致。

我遇到过的情况:Tushare 的期权数据是 15:00 收盘,但标的物数据是 15:01 收盘。差了这 1 分钟,计算出来的期权理论价格就完全不对了。

对齐的方法很简单:

  • 以标的物数据的时间轴为基准
  • 将期权数据按时间戳匹配到最近的标的物数据点上
  • 如果某个时间点没有期权数据,用前向填充(forward fill)
核心原则:期权和标的物的数据,必须在同一时间坐标系下。否则,你算出来的 Greeks、隐含波动率,全是错的。

3.6 知识体系总览

下面这张图,是我自己整理的数据获取与清洗流程。你可以照着这个框架来搭建你的数据管道。

市场数据获取与清洗流程 数据源选择 期权链数据 标的资产数据 数据清洗 数据清洗 去重 缺失值处理 异常值检测 合约状态过滤 数据对齐(时间戳匹配)

3.7 代码示例:用 Tushare 获取期权数据

下面是一个简单的示例,展示如何用 Tushare 获取 50ETF 期权链数据:

import tushare as ts
import pandas as pd

# 设置 token(需要先在 tushare 官网注册)
ts.set_token('your_token_here')
pro = ts.pro_api()

# 获取 50ETF 期权合约列表
# 注意:Tushare 的期权数据需要先获取合约列表,再获取行情
opt_basic = pro.opt_basic(exchange='SSE', 
                          fields='ts_code,name,exercise_type,list_date,delist_date')
print(opt_basic.head())

# 获取某合约的历史行情
# 以 50ETF 购 3 月 3000 为例
df = pro.opt_daily(ts_code='510050C2303M03000',
                   start_date='20230101',
                   end_date='20231231',
                   fields='trade_date,open,high,low,close,vol,amount')
print(df.head())
小技巧:Tushare 的期权数据接口有调用频率限制。如果你要批量获取大量合约数据,建议用循环加 sleep 的方式,避免被封 IP。

3.8 数据对齐实战:分钟级对齐

假设你拿到了期权 1 分钟数据和标的物 1 分钟数据,怎么对齐?

# 假设 opt_df 是期权分钟数据,underlying_df 是标的物分钟数据
# 两者都有 'datetime' 列

# 以标的物数据为基准
aligned_df = underlying_df.copy()

# 将期权数据按时间匹配到最近的标的物时间点
# 使用 merge_asof 进行时间对齐
aligned_df = pd.merge_asof(aligned_df, 
                           opt_df, 
                           on='datetime', 
                           direction='nearest', 
                           tolerance=pd.Timedelta('1min'))

# 检查对齐后的数据
print(aligned_df.head())

嗯,这里要注意:merge_asof 要求两个 DataFrame 都按时间排序。如果数据量很大,建议先排序再合并,否则会报错。

好了,数据获取与清洗这块就聊到这儿。记住一句话:数据质量决定回测质量。花 80% 的时间在数据上,剩下的 20% 写策略,这才是做量化该有的态度。


专注资料整理