6. 期权筛选与预处理:筛选标准、剔除套利、构建标准期限

好,咱们继续。数据拿到手了,但别急着往模型里塞。我见过太多人,把一堆乱七八糟的期权数据直接扔进拟合器,结果出来的曲面跟鬼画符一样。为什么?因为原始数据里充满了噪音——流动性差的合约、临近到期的废纸、还有那些明显的套利机会。不把这些清理干净,你的隐含波动率曲面就是空中楼阁。

这一章,咱们就聊聊怎么给期权数据「洗澡」。说白了,就是三个步骤:筛选剔除标准化

6.1 筛选标准:流动性、到期日、价内/价外

筛选是第一道关卡。我个人习惯,先过三关:

6.1.1 流动性筛选

流动性差的期权,报价就是摆设。你想想看,一个合约一天就成交几手,它的买卖价差可能比波动率本身还大。这种数据进去,除了添乱没别的用。

我常用的流动性指标:

  • 成交量:当日成交量低于某个阈值(比如100张)的,直接扔掉。
  • 持仓量:持仓量太低的合约,市场关注度不够,报价容易失真。
  • 买卖价差:这个很关键。价差占中间价的百分比超过一定比例(比如5%),说明市场深度不够。
我的经验: 在A股期权市场,我一般要求近月合约成交量至少500张,远月可以放宽到100张。但别死守数字,得看具体品种的活跃度。

6.1.2 到期日筛选

快到期的期权,时间价值衰减得厉害,Gamma也大得吓人。这种合约的隐含波动率容易「抽风」——稍微有点动静就上蹿下跳。

我一般会:

  • 剔除到期日小于7天的合约。太近了,噪音太大。
  • 剔除到期日大于1年的合约。太远了,流动性通常不好,而且模型对长期限的假设也不太靠谱。

嗯,这里要注意:如果你做的是事件驱动策略(比如财报前后),可以适当保留近月合约,但一定要单独处理。

6.1.3 价内/价外筛选

深度价内的期权,Delta接近1或-1,时间价值几乎为零。这种合约的隐含波动率对模型参数极其敏感,稍微改一下无风险利率或股息率,结果就天差地别。

我建议只保留:

  • 价外(OTM)看涨期权:行权价高于当前价格。
  • 价外(OTM)看跌期权:行权价低于当前价格。
  • 或者,保留平价附近(ATM)的合约,Delta在0.2到0.8之间。
避坑指南: 我曾经在构建波动率曲面时,不小心混入了深度价内的看涨期权。结果曲面在低行权价区域出现了一个诡异的「凹陷」,排查了半天才发现是那几笔深度价内合约搞的鬼。从那以后,我筛选价内/价外时格外小心。

6.2 剔除套利机会:无套利原则

筛选完数据,下一步就是检查有没有套利机会。你可能会问:「有套利不是好事吗?我正好可以赚一笔。」理论上没错,但现实中,套利机会转瞬即逝,而且你的数据里如果存在套利空间,说明数据本身有问题——要么是报价错误,要么是市场暂时失衡。

我们做波动率曲面,要的是「干净」的数据,而不是「赚钱」的机会。所以,必须剔除那些违反无套利原则的合约。

6.2.1 垂直价差套利

看涨期权:行权价越低,价格应该越高。如果出现K1 < K2但C(K1) < C(K2),那就是套利。

看跌期权:行权价越低,价格应该越低。如果出现K1 < K2但P(K1) > P(K2),那也是套利。

检查方法很简单:

# 伪代码示例
for each expiration:
    for i in range(len(strikes)-1):
        if call_prices[i] < call_prices[i+1]:
            mark_as_arbitrage(i, i+1)
        if put_prices[i] > put_prices[i+1]:
            mark_as_arbitrage(i, i+1)

6.2.2 蝶式价差套利

这个稍微复杂一点。蝶式价差由三个行权价组成:K1 < K2 < K3。理论上,蝶式组合的成本不能为负。如果出现C(K1) - 2*C(K2) + C(K3) < 0,那就是套利。

我个人习惯,在筛选完垂直价差后,再跑一遍蝶式检查。虽然计算量大了点,但能剔除掉很多「看起来正常、实际上有问题」的数据。

6.2.3 看涨-看跌平价

这个是最基本的。对于同一行权价、同一到期日的看涨和看跌,应该满足:

C - P = S - K * exp(-rT)

如果偏差超过某个阈值(比如0.5%),我就认为数据有问题,直接剔除这对合约。

核心原则: 宁可漏掉一些「可能正常」的数据,也不要保留任何「明显套利」的数据。一个套利点,就能毁掉整个波动率曲面。

6.3 构建标准期限

筛选和剔除都做完了,但数据还是乱的——不同合约的到期日五花八门。有的剩23天,有的剩37天,有的剩182天。我们没法直接拿这些乱七八糟的期限去拟合曲面。

所以,需要构建标准期限。说白了,就是把所有期权映射到几个固定的时间点上,比如:7天、14天、30天、60天、90天、180天、365天。

6.3.1 如何选择标准期限?

这个没有标准答案。我一般根据市场惯例来:

  • 短期:7天、14天、30天。用于捕捉短期事件。
  • 中期:60天、90天。最常用的期限,流动性最好。
  • 长期:180天、365天。用于结构性产品和长期对冲。

6.3.2 如何映射?

映射方法有两种:

  1. 最近邻法:直接把期权分配到离它最近的标准期限上。简单粗暴,但会损失精度。
  2. 插值法:用线性插值或样条插值,把期权的隐含波动率「挪」到标准期限上。精度更高,但计算复杂。

我个人更推荐插值法。虽然麻烦一点,但能保留更多信息。具体做法是:

# 对每个行权价,在不同到期日之间做插值
from scipy.interpolate import interp1d

# 假设我们有三个到期日:30天、60天、90天
# 对应的隐含波动率:0.25, 0.28, 0.30
days = [30, 60, 90]
iv = [0.25, 0.28, 0.30]

# 想得到45天的隐含波动率
f = interp1d(days, iv, kind='linear')
iv_45 = f(45)  # 结果是0.265
我的经验: 插值时别用太复杂的函数。线性插值就够用了,样条插值容易过拟合,尤其是在期限结构不平滑的时候。

6.4 本章知识体系

说了这么多,咱们用一张图来总结一下整个流程:

期权筛选与预处理流程 原始期权数据 筛选标准 流动性 | 到期日 | 价内/价外 剔除套利机会 垂直价差 | 蝶式价差 | 看涨-看跌平价 构建标准期限 最近邻法 | 插值法

这张图把咱们这章的核心逻辑串起来了。从原始数据开始,经过筛选、剔除、标准化,最后得到干净、可用的标准期限数据。每一步都不能省,每一步都有坑。

好了,数据准备好了。下一章,咱们就要开始真正的「手艺活」——用这些数据去拟合波动率曲面。到时候你会发现,前面这些预处理工作做得越扎实,后面的拟合就越顺利。