4. 数据获取与预处理:获取期权链数据、计算隐含波动率、清洗异常数据
做事件驱动交易,说白了就是赌事件发生前后的波动率变化。但有个前提——你得先拿到干净的数据。我见过太多人,策略逻辑写得天花乱坠,结果数据源一塌糊涂,最后亏得莫名其妙。
这一章,咱们就聊聊怎么把期权链数据搞到手,怎么算隐含波动率,以及怎么把那些坑爹的异常数据清洗掉。嗯,这里要注意,数据预处理花的时间,往往比写策略本身还多。
4.1 获取期权链数据
期权链数据,说白了就是一张大表。每一行代表一个期权合约,列包含行权价、到期日、合约代码、最新价、买卖价、成交量、持仓量等等。我个人习惯,先拿到这张表,再做后续处理。
数据来源嘛,国内常用的是万得、聚宽、Tushare,国外就是彭博、路透、IB。我建议你至少准备两个数据源,做交叉验证。为什么?因为单一数据源偶尔会抽风,我曾经遇到过某平台某天的数据全部偏移了一个Tick,差点把策略带沟里去。
获取数据时,有几个关键字段必须拿到:
- 合约代码:唯一标识,用于后续匹配
- 行权价:K值,计算价内外状态用
- 到期日:计算剩余期限,单位年
- 最新价/收盘价:期权价格,用于反推隐含波动率
- 标的资产价格:当前标的价格,S值
- 无风险利率:通常用SHIBOR或国债收益率
你想想看,如果缺少了标的资产价格,隐含波动率根本算不出来。所以数据获取阶段,就要把标的行情一起拉下来。
4.2 计算隐含波动率
隐含波动率,是市场对未来的预期。它不是直接能看到的,得从期权价格反推。怎么反推?用BS模型。
BS公式长这样:
C = S * N(d1) - K * e^(-rT) * N(d2)
其中:
d1 = [ln(S/K) + (r + σ²/2) * T] / (σ * √T)
d2 = d1 - σ * √T
但这里有个问题——公式里有个σ,就是我们要求的隐含波动率。而公式左边C是已知的(市场价格)。所以这是个反问题:已知C,求σ。
解法很简单,用牛顿迭代法或者二分法。我习惯用二分法,稳定,不容易发散。代码实现大概这样:
def implied_volatility(price, S, K, r, T, option_type='call'):
"""
使用二分法计算隐含波动率
price: 期权市场价格
S: 标的资产价格
K: 行权价
r: 无风险利率
T: 剩余期限(年)
option_type: 'call' 或 'put'
"""
sigma_low = 0.001
sigma_high = 5.0
tolerance = 1e-6
for i in range(100):
sigma_mid = (sigma_low + sigma_high) / 2
bs_price = black_scholes(S, K, r, T, sigma_mid, option_type)
if bs_price > price:
sigma_high = sigma_mid
else:
sigma_low = sigma_mid
if abs(bs_price - price) < tolerance:
return sigma_mid
return sigma_mid
这里有个坑——深度虚值期权的价格非常低,可能只有0.01元。这种价格算出来的隐含波动率往往不稳定,甚至出现负值。我建议你设置一个价格阈值,比如低于0.05元的期权,直接跳过不计算。
4.3 清洗异常数据
数据清洗,是这章里最磨人的环节。我做过一个统计,原始期权数据里,大约有3%-5%的数据是有问题的。如果不处理,这些脏数据会直接污染你的波动率曲面。
常见的异常情况有:
- 价格倒挂:看涨期权价格低于内在价值,或者看跌期权价格低于内在价值。这明显不合理,直接剔除。
- 波动率异常:算出来的隐含波动率超过100%或者低于5%。这种要么是数据错误,要么是极端行情。我建议先标记,再人工复核。
- 流动性不足:成交量小于10手,或者买卖价差超过价格的20%。这种数据没有参考意义。
- 到期日太近:剩余期限小于3天的期权,时间价值衰减极快,隐含波动率容易失真。我一般会过滤掉。
我曾经遇到过一件事:某只股票在财报公布前,深度虚值期权的隐含波动率突然飙到300%。乍一看像是机会,但仔细检查发现,是数据源把行权价搞错了,少了一个零。嗯,从那以后,我每次拿到数据都会先做一轮行权价合理性检查。
清洗流程我总结成三步:
- 格式检查:确保所有字段都是数值型,没有空值或NaN
- 逻辑检查:价格是否在合理范围内,是否满足无套利条件
- 统计检查:用3σ原则或IQR方法,剔除离群值
4.4 知识体系总览
下面这张图,把整个数据获取与预处理的流程串起来了。你可以把它当作一个检查清单,每次做数据准备时对照着走一遍。
4.5 实战中的几个坑
最后,分享几个我踩过的坑,希望能帮你省点时间:
- 分红除权:股票分红后,期权合约的行权价和合约乘数会调整。如果你没做复权处理,算出来的隐含波动率会莫名其妙地跳变。我建议用调整后的行权价来计算。
- 非交易日:到期日计算要用交易日历。我曾经直接用自然日算,结果在春节前后数据全乱了。嗯,后来我专门写了个交易日历函数。
- 数据对齐:期权数据和标的行情数据的时间戳要对齐。如果期权是15:00收盘,标的也是15:00收盘,但数据源可能一个用15:00,一个用15:00:01,差一秒就可能差出几个点。
数据准备这一步,确实枯燥,但它是整个波动率曲面交易的地基。地基不稳,楼盖得再高也得塌。我个人觉得,花在数据清洗上的时间,永远不亏。