8、曲面特征工程:从曲面中提取特征

做期权波动率曲面交易,说白了就是跟曲面上的「形状」打交道。你想想看,曲面本身是个三维结构——行权价、剩余期限、隐含波动率。但我们的模型没法直接吃进去一个曲面,得把它拆成一个个有意义的特征。

我个人习惯把特征工程分成三大块:曲面几何特征滚动窗口统计量市场微观结构特征。这三块缺一不可,就像炒菜得放盐、放油、放火候一样。

8.1 曲面几何特征:期限结构斜率、微笑曲率、偏度

曲面几何特征,说白了就是描述曲面「长什么样」。我刚开始做这个的时候,以为直接把曲面扔进模型就行,结果发现模型根本学不到东西。后来才明白,得把曲面的关键「骨架」抽出来。

8.1.1 期限结构斜率

期限结构斜率,衡量的是「短期波动率 vs 长期波动率」的关系。通常我们用近月合约和远月合约的波动率差值来表示。

举个例子:

# 计算期限结构斜率
short_tenor = 0.1  # 1个月
long_tenor = 0.5   # 6个月

# 取平值附近的波动率
iv_short = get_iv_at_strike(surface, short_tenor, atm_strike)
iv_long = get_iv_at_strike(surface, long_tenor, atm_strike)

term_slope = iv_long - iv_short

嗯,这里要注意:斜率可以是正的(远期波动率更高),也可以是负的(近期波动率更高)。我在2020年3月那波行情里,就见过斜率瞬间从正变负,那感觉就像坐过山车。

8.1.2 微笑曲率

微笑曲率,衡量的是「虚值期权 vs 平值期权」的波动率差异。说白了就是看微笑的「弯度」有多大。

我一般用二次函数去拟合微笑曲线:

# 用二次函数拟合微笑曲线
import numpy as np

def fit_smile_curvature(moneyness, iv):
    # moneyness: 行权价/标的价格
    # iv: 对应行权价的隐含波动率
    coeffs = np.polyfit(moneyness, iv, 2)
    curvature = coeffs[0]  # 二次项系数
    return curvature

曲率越大,说明市场对尾部风险的定价越高。我曾经在某个商品期权上发现曲率突然飙升,结果第二天就出了个大新闻——嗯,市场永远比我们聪明。

8.1.3 偏度

偏度,衡量的是「左侧尾部 vs 右侧尾部」的不对称性。如果虚值看跌期权的波动率远高于虚值看涨期权,说明市场在定价下行风险。

我常用的偏度指标:

# 计算偏度
put_iv = get_iv_at_delta(surface, -0.25)  # 25-delta看跌
call_iv = get_iv_at_delta(surface, 0.25)  # 25-delta看涨

skew = put_iv - call_iv

偏度为正,说明看跌期权更贵;偏度为负,说明看涨期权更贵。我记得在2021年某个事件驱动策略里,偏度连续三天为正,结果第四天市场就崩了——这个信号其实挺灵的。

核心要点: 期限结构斜率、微笑曲率、偏度这三个特征,构成了曲面几何特征的「三驾马车」。它们分别从不同维度描述了曲面的形状,是后续模型的基础输入。

8.2 滚动窗口统计量

光看当前曲面的形状还不够,还得看它「怎么变的」。滚动窗口统计量就是干这个的。

我一般用以下几个统计量:

  • 滚动均值:过去N个交易日的平均斜率/曲率/偏度
  • 滚动标准差:衡量波动率的波动率(有点绕,但很重要)
  • 滚动偏度:特征值本身的偏度,看是否有极端值
  • 滚动峰度:特征值分布的尾部厚度

举个例子:

# 计算滚动窗口统计量
window = 20  # 20个交易日

rolling_mean = term_slope.rolling(window).mean()
rolling_std = term_slope.rolling(window).std()
rolling_skew = term_slope.rolling(window).skew()
rolling_kurt = term_slope.rolling(window).kurt()

你想想看,如果斜率突然偏离滚动均值超过2个标准差,那大概率是个交易信号。我曾经用这个逻辑抓过几次不错的入场点——当然,也有被打脸的时候。

小技巧: 滚动窗口的大小很关键。我个人习惯用20天(约一个月)作为基准,然后同时计算5天、10天、40天的版本,看看不同时间尺度下的信号是否一致。

8.3 市场微观结构特征

这部分容易被忽略,但其实特别重要。市场微观结构特征,说白了就是「交易层面的细节」。

我常用的微观结构特征包括:

  • 买卖价差:隐含波动率的bid-ask spread,越宽说明流动性越差
  • 成交量分布:不同行权价、不同期限的成交量占比
  • 持仓量变化:特别是虚值期权的持仓量变化,往往预示方向
  • 订单簿不平衡:买卖订单的深度差异

举个例子:

# 计算买卖价差
bid_iv = get_iv_from_bid(surface, strike, tenor)
ask_iv = get_iv_from_ask(surface, strike, tenor)

spread = (ask_iv - bid_iv) / ((ask_iv + bid_iv) / 2)

嗯,这里要注意:价差太宽的期权,即使信号再好也别碰。我曾经在某个深度虚值期权上吃过亏,信号看起来完美,但一进去就被价差吃掉了所有利润。

避坑指南: 我曾经在微观结构特征上犯过一个错误——把不同交易所的数据混在一起用。不同交易所的微观结构差异很大,比如CME和ICE的订单簿深度就完全不同。一定要先做数据对齐。

8.4 特征工程的整体框架

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

曲面特征工程框架 波动率曲面 曲面几何特征 滚动窗口统计量 市场微观结构 期限结构斜率 微笑曲率 偏度 曲面局部形状 滚动均值 滚动标准差 滚动偏度 滚动峰度 买卖价差 成交量分布 持仓量变化 订单簿不平衡 特征矩阵 → 模型输入

从这张图可以看得很清楚:波动率曲面经过三大类特征工程的处理,最终变成一个结构化的特征矩阵,然后喂给模型。每一步都很关键,缺了任何一个环节,模型的效果都会打折扣。

8.5 实战中的注意事项

最后,分享几个我在实战中踩过的坑:

  1. 特征之间的相关性:期限结构斜率和偏度有时候高度相关,记得做相关性分析,避免多重共线性
  2. 数据频率对齐:微观结构特征通常是高频数据(分钟级),而曲面几何特征是日频数据,合并时要小心
  3. 异常值处理:波动率曲面偶尔会出现极端值(比如某个行权价的IV突然飙升),我一般用中位数滤波或者截断处理
  4. 特征标准化:不同特征的量纲差异很大,比如斜率可能是0.01量级,而价差可能是0.001量级,记得做标准化
我的习惯: 每次做完特征工程,我都会先跑一个简单的线性回归或者随机森林,看看每个特征的重要性排序。如果某个特征的重要性为0,那大概率是数据有问题或者特征构造错了。

好了,这一章的内容就到这里。特征工程是个细活,急不得。你想想看,模型再牛逼,喂进去的是垃圾,出来的还是垃圾。所以,花时间把特征做好,绝对值得。


公众号:蓝海数据掘金营,微信deep3321