第4章 波动率曲面构建:从期权报价到波动率曲面的插值方法
做期权交易的朋友都知道,光看几个行权价的隐含波动率是远远不够的。你想想看,市场上每天交易的期权合约成百上千,每个到期日、每个行权价都有自己的报价。但真正做策略的时候,我们需要的是一个连续、光滑的波动率曲面。
说白了,就是从离散的报价点,推算出任意行权价、任意到期日的波动率数值。这活儿,就叫波动率曲面构建。
我个人习惯把这件事分成两步走:
第一步,处理单一到期日的波动率偏斜曲线。
第二步,把不同到期日的曲线拼接成一个完整的曲面。
今天咱们就重点聊聊第一步——单期波动率曲线的插值方法。我重点讲三种:SVI、SSVI、样条插值。
4.1 为什么不能直接用线性插值?
先泼一盆冷水。很多新手上来就用线性插值,结果做出来的曲面惨不忍睹。
为什么会这样?
因为隐含波动率随行权价的变化,不是线性的。它呈现出明显的偏斜(skew)和微笑(smile)特征。线性插值会把这些特征抹平,导致定价偏差。
我记得有一次做套利策略回测,用线性插值算出来的波动率,跟实际市场报价差了将近2个vol点。那笔回测结果看起来很美,实盘一跑就亏钱。嗯,从那以后我再也不敢用线性插值了。
4.2 SVI模型:业界最流行的参数化方法
SVI(Stochastic Volatility Inspired)模型,是Gatheral在2004年提出的。它用一个5参数公式,就能拟合出漂亮的波动率偏斜曲线。
公式长这样:
w(k) = a + b * ( ρ * (k - m) + sqrt( (k - m)^2 + σ^2 ) )
其中:
- w(k) 是总方差(隐含波动率的平方 × 到期时间)
- k 是行权价的对数(ln(K/S))
- a, b, ρ, m, σ 是待拟合的参数
这5个参数各有各的脾气:
| 参数 | 作用 | 取值范围 |
|---|---|---|
| a | 控制曲线的整体水平 | 任意实数 |
| b | 控制曲线的倾斜程度 | ≥ 0 |
| ρ | 控制偏斜的方向(左偏/右偏) | [-1, 1] |
| m | 控制曲线的最低点位置 | 任意实数 |
| σ | 控制曲线的曲率(微笑程度) | > 0 |
我个人习惯用最小二乘法来拟合这5个参数。代码实现也不复杂:
import numpy as np
from scipy.optimize import minimize
def svi(k, a, b, rho, m, sigma):
"""SVI模型公式"""
return a + b * (rho * (k - m) + np.sqrt((k - m)**2 + sigma**2))
def fit_svi(k_values, w_values):
"""拟合SVI参数"""
def objective(params):
a, b, rho, m, sigma = params
# 参数约束
if b < 0 or sigma <= 0 or abs(rho) > 1:
return 1e10
w_fit = svi(k_values, a, b, rho, m, sigma)
return np.sum((w_values - w_fit)**2)
# 初始值猜测
init_params = [0.1, 0.1, -0.5, 0.0, 0.1]
result = minimize(objective, init_params, method='Nelder-Mead')
return result.x
4.3 SSVI:SVI的升级版
SVI虽然好用,但它有个硬伤——只适用于单一到期日。不同到期日的SVI参数之间没有约束,拼出来的曲面容易出现日历套利机会。
SSVI(Surface SVI)就是来解决这个问题的。它给SVI加了一个时间结构,让不同到期日的曲线之间保持一致性。
SSVI的核心思想是:
- 把SVI的参数b和ρ,写成到期时间T的函数
- 引入一个倾斜函数 φ(T),控制偏斜随时间的变化
公式变成:
w(k, T) = a(T) + b(T) * ( ρ(T) * (k - m(T)) + sqrt( (k - m(T))^2 + σ(T)^2 ) )
其中:
- a(T) 通常用ATM波动率的时间结构来拟合
- b(T) = b0 * φ(T)
- ρ(T) = ρ0 * (1 - exp(-κ * T))
这样做的好处是:
1. 保证了无日历套利条件
2. 曲面更光滑,不会出现奇怪的褶皱
3. 参数更少,拟合更稳定
我在做跨期价差策略时,SSVI帮了大忙。以前用SVI拼出来的曲面,经常出现近月波动率比远月还高的情况,明显不合理。换成SSVI后,这种问题基本消失了。
4.4 样条插值:另一种思路
参数化方法(SVI/SSVI)虽然好,但有时候我们不想假设一个固定的函数形式。这时候,样条插值就派上用场了。
样条插值的核心思想是:
用分段低次多项式,把离散点连成一条光滑曲线。
最常用的是三次样条。它在每个区间内用三次多项式,在节点处保证一阶、二阶导数连续。
代码实现也很直接:
from scipy.interpolate import CubicSpline
# 假设我们有5个行权价的波动率数据
strikes = np.array([0.95, 0.98, 1.00, 1.02, 1.05])
vols = np.array([0.25, 0.22, 0.20, 0.21, 0.24])
# 创建三次样条插值器
cs = CubicSpline(strikes, vols, bc_type='natural')
# 在任意点求值
new_strikes = np.linspace(0.94, 1.06, 100)
smooth_vols = cs(new_strikes)
样条插值的优点:
- 不需要假设函数形式
- 计算速度快
- 局部调整不影响全局
缺点也很明显:
- 外推能力差(超出数据范围就乱来)
- 不能保证无套利条件
- 对异常值敏感
4.5 三种方法的对比与选择
说了这么多,到底该用哪种?我根据自己的经验,给个参考:
| 场景 | 推荐方法 | 理由 |
|---|---|---|
| 数据点充足(>10个) | SVI | 拟合稳定,参数有经济含义 |
| 需要跨期一致性 | SSVI | 避免日历套利 |
| 数据点少(<6个) | 样条插值 | 灵活,不需要太多参数 |
| 实时交易系统 | SVI | 计算速度快,参数少 |
| 研究分析 | 样条插值 | 可视化效果好,便于观察细节 |
我个人在实际项目中,通常是混合使用:
- 先用SVI拟合每个到期日,得到一组参数
- 再用SSVI对参数做时间维度上的平滑
- 最后用样条插值做微调,处理个别异常点
这样既能保证曲面的整体合理性,又能捕捉到局部的市场特征。
4.6 本章小结
波动率曲面构建,说白了就是从离散到连续的过程。SVI、SSVI、样条插值,各有各的适用场景。
我最后想强调一点:没有完美的模型,只有合适的模型。你用的方法再漂亮,如果跟市场实际脱节,那就是纸上谈兵。
嗯,本章的内容就到这里。记住,做波动率曲面,数据质量比模型复杂度更重要。先把数据清洗干净,再谈用什么插值方法。
公众号:蓝海资料掘金营,微信deep3321