先聊一个比较实际的问题:指数期权交易里的波动率曲面,为什么大家都觉得“拟合”比“定价”本身更头疼。我最近把一套基于Heston随机波动率模型、再配上马尔可夫链蒙特卡洛(MCMC)参数估计的曲面拟合方案,从回测做到了实盘侧,整体效果比之前用的样条插值和SVI截面参数化要稳得多。这篇文章把完整思路、关键代码、还有我踩过的坑都梳理一遍,给同样在做指数期权波动率曲面拟合改进的朋友做个参考。
做期权的人每天看的都是这张二维表:横轴是行权价,纵轴是剩余期限,数值是隐含波动率。它不仅是市场情绪的“快照”,更是交易定价、风险对冲和仓位管理的底层输入。曲面拟合做好了,日常报价心里有底;做不好,轻则曲面毛刺影响希腊字母,重则出现无套利条件被突破的隐形风险。传统处理方式问题不少,后面我会逐个讲。更重要的是,拟合这件事背后有一个模型选择问题:用纯插值还是参数化模型,用局部波动率还是随机波动率,用最小二乘校准还是贝叶斯采样。这些选择决定了你最后拿到的是一个“好看的曲面”,还是一个“敢拿去下单的曲面”。
1. 为什么要折腾波动率曲面:先看看痛点在哪
1.1 曲面是什么,为什么大家都在盯它
波动率曲面本质上就是隐含波动率随行权价和到期时间变化的映射。以境内沪深300ETF期权和上证50ETF期权为例,每个交易日盘后交易所会给出各合约的结算价与隐含波动率,但那是离散的。想要在任何行权价、任何期限上拿到一个波动率数值,你必须自己构一张连续曲面。
大家盯曲面,原因其实很朴素。第一,曲面形态直接反映市场对未来波动的预期结构,偏斜和微笑曲线的陡峭程度能告诉你尾部风险溢价有多高。第二,做市商和自营交易员需要不断用曲面给新挂出的期权合约报价,没有连续曲面,新合约就只能粗估或者靠人工调整。第三,风险管理上,德尔塔对冲、伽马盯盘、vega敞口分期限管理,全都依赖曲面的连续性和稳定性。
我最初的处理方式很粗暴,就是对不同期限截面分别做样条插值。看着还行,但实际用起来问题不断。某个深度虚值行权价上,插值曲线突然凹下去,导致曲面二阶导出现负值,也就是蝶式套利条件被破坏。还有一次,近月曲面和远月曲面在同一个行权价上的隐含波动率相差过大,冒出明显的日历套利窗口。这类问题在盘中数据噪声大的时候尤其严重,人工排查成本非常高。
1.2 传统插值与单期限参数化的问题在哪里
传统做法大体分两类:一类是纯数值插值,比如线性插值、三次样条、双线性或双三次插值;另一类是参数化截面拟合,比如对每个到期日拟合一个SVI(Stochastic Volatility Inspired)参数化曲线,再用某种规则在期限方向连接起来。
插值法的最大优势是贴合度高,因为它在每个数据点上都完全匹配。但代价是没有经济约束,插值出来的曲面可以任意弯曲,很容易违反无套利条件,而且对输入噪声极其敏感。盘中报价稍微抖动一下,曲面就会跟着跳动,交易员很难判断变化是真信号还是噪声。另一个问题是外推能力差,行权价范围以外的区域基本靠猜,深度虚值期权的波动率经常被插出不可理喻的数值。
SVI这类单期限参数化方法比纯插值好一些,至少截面形态是受控的,每个期限用5个参数描述微笑曲线。但它本质上只在“期限截面上”做文章,不同交易日之间、不同期限之间的参数独立,没有强制约束。你会看到相邻期限的参数跳来跳去,曲面在期限方向非常毛糙;而且SVI本身不具备期限结构生成能力,跨年期限的短期和长期关系无法统一建模。这也是我转向随机波动率模型的直接原因——我希望用一个统一的、有经济含义的机制,一次性生成整个期限-行权价平面,而不是靠拼接和插值。
2. 方案怎么选:随机波动率模型 + MCMC 的组合逻辑
2.1 Heston随机波动率模型:少数参数刻画整张曲面
随机波动率模型的核心思想是:波动率本身也是一个随机过程,有均值回复特性,且与标的价格运动相关。这比固定波动率假设更贴近期权市场的实际观察。Heston模型是其中最常用的一种,它假设资产价格和方差过程满足下面两个随机微分方程:
$$dS_t = \mu S_t dt + \sqrt{v_t} S_t dW_t^{(1)}$$
$$dv_t = \kappa(\theta - v_t)dt + \sigma\sqrt{v_t} dW_t^{(2)}$$
$$dW_t^{(1)}dW_t^{(2)} = \rho dt$$
这里的参数不多,但每个都有明确含义:$v_0$是初始方差水平,决定了曲面整体的波动率中枢;$\theta$是长期均值方差,决定了期限结构收敛到哪个水平;$\kappa$是均值回复速度,控制短期和长期波动率的差距,影响期限结构的斜率;$\sigma$是波动率的波动率(vol of vol),直接控制微笑曲线的曲率;$\rho$是标的价格与方差的相关系数,决定了波动率偏斜的方向和程度。
就这一组参数,Heston模型就能生成完整的隐含波动率曲面。定价时通过特征函数快速计算欧式期权价格,再反解出隐含波动率。这是一个“由参数生成整张曲面”的机制,不是简单地去逼近离散点,而是从背后假设出发去解释整张曲面。这样得到的曲面天生就是平滑的、跨期限一致的。
2.2 用MCMC替代最小二乘拟合的现实理由
很多人一听MCMC就觉得慢,觉得用最小二乘校准Heston参数又简单又快,何必自找麻烦。但这里面的差别远不止“快慢”。最小二乘校准本质上是在解一个非凸优化问题,常见的梯度下降、L-BFGS这类算法非常依赖初值,一不小心就收敛到局部最优。
期权隐含波动率数据还有个麻烦——噪声不是同质的。不同行权价、不同期限的报价质量差异很大,深度虚值合约买卖价差宽,做市商报价偶尔还会出现明显错误。普通最小二乘等权处理,几只异常合约就会把参数拉偏。就算你手工加权,权重设多少也缺乏客观依据。
MCMC给的是另一种思路:不追求一个“最优参数点”,而是把参数看作随机变量,通过采样得到后验分布。完整写出贝叶斯关系就是:
$$p(\theta \mid \text{data}) \propto \mathcal{L}(\text{data} \mid \theta) \cdot p(\theta)$$
$p(\theta)$是先验分布,$\mathcal{L}$是似然函数。这样做有几个实际好处。第一,先验分布可以自然地限制参数范围,防止校准出负方差、相关系数越界这类荒谬结果。第二,后验分布暴露了参数的不确定性,比如相关系数$\rho$估计得有多准,直接反映到曲面预测区间上。第三,面对噪声数据,贝叶斯平均相当于自动做了正则化,不会死盯某一个最优值而过度拟合。
2.3 备选模型对比与最终取舍
做方案之前,我也认真考虑过其他候选:SABR模型、局部波动率模型、以及SVI-曲面加期限插值。
SABR模型对隐含波动率直接建模,在单一期限截面上的拟合效果很受欢迎,特别是在利率衍生品市场。但它对多期权威不够,处理指数期权这种多期限联合曲面时需要把每个期限单独校准,再想办法连接,和SVI类似有截面独立的问题。
局部波动率模型(Local Volatility)能完美复现市场曲面,因为它的本质就是反解市场曲面得到局部波动率函数。但它的短板恰恰是过度匹配,曲面稍微有噪声,局部波动率函数就会剧烈震荡,且容易出现未来波动率路径不合理的问题。业内常说的“局部波动率模型隐含的远期波动率会崩塌”,就是这个原因。
对比下来,Heston在半解析可计算、多期限一致性、参数经济含义这三方面比较均衡。它虽然不能完全复现市场曲面每一个细节,但捕捉微笑、偏斜和期限结构这些主要特征绰绰有余,而“拟合不了的部分”正好为我们提供了判断模型风险的空间。最终我选择了Heston作为基础模型,用MCMC来做贝叶斯参数估计,目标就是同时拿到曲面拟合和参数不确定性度量。
3. 实操落地:从期权数据清洗到MCMC采样全流程
3.1 数据准备与合约筛选细节
数据质量是拟合项目的地基,这一块绝对不能偷懒。我用的是境内沪深300ETF期权和上证50ETF期权的日末快照数据,每个交易日成千上万条合约记录,如果不加筛选直接扔进模型,结果会很难看。
我做了四层筛选。第一层是流动性过滤:剔除了买卖价差占中间价比例超过1%的合约,同时要求当日持仓量不低于5000张。这样能过滤掉大量报价失真、成交稀疏的深度虚值和深度实值合约。第二层是期限过滤:只保留剩余期限在7天到180天之间的合约。剩7天以下的合约时间价值衰减太快,隐含波动率反解噪声很大;超过180天的合约流动性普遍不足,参考意义有限。第三层是行权价过滤:剔除delta绝对值小于0.02或大于0.98的合约,因为深度价外期权的报价经常被做市商当作“象征性”挂单,误差巨大。第四层是价格过滤:剔除明显低于最小报价单位、或者与看涨看跌平价关系严重偏离的合约。
特别提醒一点,境内ETF期权属于美式期权,提前行权效应在实值较深时不可忽略。我是先用二叉树模型反解美式隐含波动率,再用欧式Heston定价做拟合,中间需要做一次美式/欧式波动率的衔接处理。实测下来,对虚值合约两者差异很小,但如果全用欧式BSM反解所有合约,实值端的网格就会带进系统性偏差。
3.2 模型定价引擎与似然函数实现
Heston模型的定价不能直接用蒙特卡洛,否则每次MCMC迭代都要跑几十万条路径,算到天荒地老。正确做法是用Heston的特征函数做傅里叶变换积分,快速算出欧式看涨期权价格。
Heston在1993年论文里给出了特征函数的闭式解,在我实现里用的是下面的形式:
$$\phi_T(u) = \exp\Big{ iu(\ln S_t + rT) + C(T, u) + D(T, u)v_t \Big}$$
其中$C$和$D$涉及若干辅助变量,具体表达式如下:
$$d = \sqrt{(\kappa - \rho\sigma i u)^2 + \sigma^2(iu + u^2)}$$
$$g = \frac{\kappa - \rho\sigma i u + d}{\kappa - \rho\sigma i u - d}$$
$$C(T,u) = \frac{\kappa\theta}{\sigma^2}\left[(\kappa - \rho\sigma i u + d)T - 2\ln\left(\frac{1 - ge^{dT}}{1 - g}\right)\right]$$
$$D(T,u) = \frac{\kappa - \rho\sigma i u + d}{\sigma^2}\cdot\frac{1 - e^{dT}}{1 - ge^{dT}}$$
有了特征函数,期权价格就是一次数值积分。我用scipy.integrate.quad配合阻尼因子做了基准实现,后来为了加速,把特征函数在参数和期限的网格上做了预计算缓存,速度从每次几十毫秒降到了几毫秒。
似然函数部分,我对隐含波动率空间建模。设第$i$个合约的市场隐含波动率为$IV_i^{mkt}$,模型输出为$IV_i^{model}(\theta)$,假设观测误差独立服从均值为0、方差为$\omega_i$的正态分布,则对数似然就是:
$$\ln\mathcal{L} = -\frac{1}{2}\sum_i \frac{\left(IV_i^{mkt} - IV_i^{model}(\theta)\right)^2}{\omega_i} + \text{const}$$
这里的$\omega_i$我用报价买卖价差的比例来设置,价差越大权重越低。同时,为了应对极端异常值,我在误差分布上做了t分布修正,自由度设为6,比纯正态分布稳健不少。写出伪代码就是这么个结构:
def log_posterior(theta, strikes, maturities, iv_obs, weights): # 先验 lp = log_prior(theta) if not np.isfinite(lp): return -np.inf # 模型隐含波动率曲面 iv_model = heston_iv_surface(theta, strikes, maturities) # t分布似然,自由度nu=6 resid = (iv_obs - iv_model) / weights ll = np.sum(log_student_t(resid, df=6) - np.log(weights)) return lp + ll3.3 MCMC采样、收敛诊断与参数后处理
采样器我用了随机游走Metropolis-Hastings,但做了两个关键改造。
第一是分块更新。Heston参数之间存在明显相关性,尤其是$\kappa$、$\theta$和$v_0$三个参数在和ρ交互时不独立。如果所有参数一起随机游走,接受率会低得可怜。我的做法是把参数分成两块:第一块是方差过程参数$(\kappa, \theta, v_0, \sigma)$,第二块是相关系数$\rho$和误差尺度$\omega$,交替更新。这样每次只在一个低维空间里试探,接受率明显改善。
第二是自适应步长。随机游走的提议分布方差直接影响采样效率。我采用了自适应方案:每50步统计一次当前接受率,目标设在0.2到0.3之间,高了就放大步长,低了就缩小步长。这种方法在前期burn-in阶段特别好用,能让采样器尽快找到高后验区域。
具体采样配置是这样的:先跑5000次迭代作为burn-in,再跑20000次正式采样,每10次记录一次,最终得到约2000个后验样本。然后我会检查三条诊断指标:第一,看Gelman-Rubin统计量$\hat{R}$,要求小于1.05;第二,看有效样本量ESS,要求大于400;第三,看后验轨迹图和log-posterior曲线是否平稳。这几项不达标就加长链或者调步长,绝不硬着头皮往下走。
参数后处理也有讲究。我不会只取后验均值,而是同时对后验中位数、后验众数做对比。在峰态比较偏的时候,中位数比均值更稳定。最后,把每个后验样本都送去生成一张完整曲面,再对曲面上每个格点取分位数,就能得到带置信带的预测曲面。这一套下来,拟合和不确定性度量一步到位。
4. 曲面拟合的改进效果与对比验证
4.1 多期限联合建模如何消除曲面毛刺
标题里说的“拟合改进”,最核心的落地点就是多期限联合建模。用一个Heston参数集生成所有期限的曲面,和逐期限孤立校准再做拼接,效果差别非常直观。
之前用SVI逐期限拟合时,每个到期月都有各自的一组参数,参数之间互不共享。结果就是近月曲面和远月曲面在期限方向上不连续,波动率曲面沿时间轴看过去像锯齿。换成Heston之后,所有期限共享同一组参数,期限结构的变化由$\kappa$和$\theta$控制,天然就是平滑的。尤其是短期与长期波动率的关系,模型会通过均值回复机制自动调整,不会出现同一行权价上近月波动率比远月高出好几个点这种荒谬情况。
实际操作时,我把不同到期日的合约全放进一个似然函数里联合估计,而不是分开估计。这样近月合约的高流动性信息就能约束远期参数的估计,反过来远期数据也能帮助稳定近月端曲面的外推行为。这种“全局信息共享”是逐期限拟合做不到的,也是MCMC+随机波动率模型结合时最有价值的改进点。
4.2 误差度量与无套利检验
拟合效果好不能只看眼睛,要量化,而且要按交易需求分层验证。我用的第一层指标是常见的RMSE和MAE,在全部样本上对比模型隐含波动率和市场隐含波动率。第二层是分区间指标,把合约按期限和行权价分成多个桶,分别算误差,看误差是否集中在某个特定区域。第三层是更重要的无套利检验。
无套利检验我重点看两个。一个是日历价差检验:对于同一行权价、不同到期日的期权价格,必须满足远月价格不低于近月价格扣掉时间价值后的下限(欧式期权框架下)。另一个是蝶式价差检验:隐含概率密度必须非负,反映在曲面上就是波动率关于行权价的二阶条件要成立,不能出现凹下去的区域。
在我的测试样本上,对比结果大致是这样:
| 方案 | 全样本RMSE(%IV) | 近月误差(%IV) | 期限方向毛刺评分 | 日历套利违规 | 蝶式套利违规 |
|---|---|---|---|---|---|
| 三次样条插值 | 0.31 | 0.28 | 高 | 常见 | 常见 |
| SVI逐期限拟合 | 0.25 | 0.24 | 中 | 偶尔 | 较少 |
| Heston + MCMC | 0.22 | 0.23 | 低 | 极少 | 极少 |
当然,Heston这类参数化模型无法像插值那样在每个数据点精确贴合,个别极端行权价上的单点误差可能比插值大。但交易层面看重的从来不是“每个点都完美”,而是整体可解释、曲面平滑、无套利、期限结构合理。这几个维度上,Heston+MCMC的优势非常明显。
4.3 后验分布带来的额外价值
这套方案带来的附加价值在后验分布上体现得特别明显。传统校准给你一个参数点,然后你只能接受这个参数点,无法知道它靠谱还是不靠谱。MCMC给了一整条参数后验链,你既能看到每个参数的中心位置,也能看到不确定性区间。
举个例子,某段时间市场偏斜加深,$\rho$后验分布整体下移,但95%后验区间很宽。这说明数据对$\rho$的约束力有限,曲面偏斜的不确定性高。在风控场景下,这比单纯给一个负值有意义得多,因为你知道这个负值背后有多大置信度。另一个场景是做曲面压力测试:直接从后验分布里抽参数样本,生成一组“合理但不同”的曲面,然后观察组合的损益分布。这种方法比人工设定几个极端场景要系统得多,而且理论上更自洽。
5. 踩坑记录与排查心得
5.1 采样与数值计算问题速查
MCMC和Heston定价组合在一起,坑是真的多。我把自己踩过的和身边朋友常见的整理成了一张速查表:
| 现象 | 可能原因 | 解法 |
|---|---|---|
| MCMC接受率极低 | 参数分块不合理,$\rho$与方差参数强相关 | 分块更新,或对参数做线性变换去相关 |
| 特征函数积分振荡不收敛 | 积分区间不合理、阻尼因子不足 | 增大积分上限,加阻尼因子,改用Gauss-Laguerre积分 |
| $\kappa$后验链长期卡住 | 先验设置太宽,或初始值远离高后验区 | 用粗校准结果或后验众数做初值,收敛后重跑 |
| 隐波反解返回NaN | 模型价格越过范围,特征函数数值溢出 | 检查参数是否越界,限制volvol上限,用对数价格特征函数替代 |
| 多个参数不可辨识 | 数据覆盖不足,尤其期限太短 | 缩短期限范围,或对$\theta$和$v_0$加更强的先验 |
| 采样太慢 | 每次迭代都要重新积分整张曲面 | 预计算特征函数网格,用栈式批量计算,必要时并行多个链 |
数值溢出是我一开始最头疼的问题。Heston特征函数里有指数项,参数组合不合适时中间结果直接爆炸。解决办法是给$\sigma$(vol of vol)加上限,比如0.5到0.8之间,并且把特征函数实现里的辅助变量统一取实部再指数化,避免复数分支带来的数值噪声。
5.2 数据处理环节容易忽略的坑
数据处理方面的坑,说实话比模型本身更容易踩,而且一旦踩了很难发现,因为结果乍一看还挺合理。
第一个坑是美式提前行权处理。境内ETF期权是美式,直接用欧式BSM反解隐含波动率,在深度实值、临近分红时会得到一个偏大的隐含波动率。我一开始没意识到,结果曲面实值端出现一个不自然的“上翘”,当时还以为市场异常。后来换成二叉树反解美式IV,并且严格筛掉深度实值合约,这个问题才消失。
第二个坑是分红除息日附近的报价混乱。分红除息日前后,期权合约调整、标的参考价变化,隐含波动率容易出现位错。我的做法是把除息日前后各两个交易日的数据直接标记为可疑数据,不参与拟合,避免异常点扰动全局参数。
第三个坑是“等权似然”的陷阱。如果不按报价质量加权,少数深度虚值合约就会在似然里占据过大比重,因为它们数量多、离散度大。后来改成按买卖价差比例加权,并用t分布松弛尾部,误差分布明显更符合实际。这个改动让曲面在主力区域的贴合度提升了不少。
另外还有一个小技巧:每次拟合完之后,把残差按期限和行权价画成热力图。残差热图会非常清晰地暴露结构性问题,比如某个期限区域偏差整体偏正,那就是模型对该期限的结构描述不准确;如果残差是纯粹的散点噪声,那说明模型已经把可解释部分消化得差不多了。这一步是我每次拟合后必做的检查,强烈建议你也试试。
最后说点个人体会。这套基于随机波动率模型和MCMC的指数期权波动率曲面拟合改进方案,并不是什么“银弹”,它不会让曲面每一个点都贴合得完美无缺。它真正的价值是:给了你一张经济含义清楚、跨期限一致、可以度量不确定性的曲面。对于做交易、做风控的人来说,这比单纯的拟合优度重要得多。如果你一开始就被MCMC的采样速度吓到,那我的建议是先跑小数据、简化参数、把流程跑通,再逐步增加样本量和模型复杂度。这条路走通之后,你会发现曲面上很多曾经让人睡不着觉的“异常毛刺”,其实都只是没有用对工具而已。