7. 局部波动率模型:Dupire公式推导

局部波动率模型,说白了就是解决一个核心问题:我们能不能从市场上看到的期权价格,反推出未来的波动率长什么样?

BS模型假设波动率是常数,这显然不现实。我在2015年做期权做市商系统时,就被这个假设坑过——用BS算出来的理论价格,跟市场实际报价总是对不上。后来我才明白,市场已经把对未来波动率的预期,全部隐含在期权价格里了。

Dupire公式就是干这个的。它告诉我们:给定一个完整的期权价格曲面,我们可以唯一地反解出局部波动率函数

7.1 从BS到局部波动率

先回顾一下BS框架下的期权定价公式。对于欧式看涨期权,价格C满足:

C = C(S, K, T, r, σ)

其中S是标的价格,K是行权价,T是到期时间,r是无风险利率,σ是波动率。

BS模型假设σ是常数。但市场数据告诉我们,隐含波动率随K和T变化。这就产生了所谓的波动率微笑和期限结构。

局部波动率模型的想法很直接:允许波动率是标的价格和时间的函数,即σ(S, t)。这样,标的资产价格过程变为:

dS = μS dt + σ(S, t) S dW

关键问题是:如何从期权价格反推σ(S, t)?

核心思想:Dupire公式给出了从期权价格曲面到局部波动率曲面的显式映射。你不需要做复杂的参数估计,只需要对期权价格求偏导。

7.2 Dupire公式的推导

推导过程其实不复杂。我们从Fokker-Planck方程出发,也叫前向Kolmogorov方程。

假设标的价格S服从:

dS = rS dt + σ(S, t) S dW

那么,在风险中性测度下,S在时间T的概率密度函数p(S, T)满足:

∂p/∂T = -∂(rS p)/∂S + ½ ∂²(σ² S² p)/∂S²

另一方面,欧式看涨期权的价格可以写成:

C(K, T) = e^{-rT} ∫_{K}^{∞} (S - K) p(S, T) dS

这里的关键是:对C关于K和T求偏导,就能把p和σ联系起来

我对C求关于K的一阶偏导:

∂C/∂K = -e^{-rT} ∫_{K}^{∞} p(S, T) dS = -e^{-rT} (1 - P(S ≤ K))

再求二阶偏导:

∂²C/∂K² = e^{-rT} p(K, T)

嗯,这里要注意:二阶偏导给出了风险中性密度。这个关系在量化金融里非常基础,我每次做模型校验都会用到它。

接下来,对C关于T求偏导。利用莱布尼茨法则:

∂C/∂T = -rC + e^{-rT} ∫_{K}^{∞} (S - K) ∂p/∂T dS

把Fokker-Planck方程代入,经过一番整理(这里我省略了中间步骤,感兴趣的同学可以自己推一下),最终得到:

∂C/∂T = -rK ∂C/∂K + ½ σ²(K, T) K² ∂²C/∂K²

解出σ²(K, T):

σ²(K, T) = (∂C/∂T + rK ∂C/∂K) / (½ K² ∂²C/∂K²)

这就是Dupire公式

实用技巧:在实际计算中,∂C/∂T和∂²C/∂K²都需要用数值方法近似。我建议用中心差分法,边界处用前向或后向差分。网格要足够密,否则导数会很不稳定。

7.3 公式的直观理解

Dupire公式看起来有点吓人,但它的含义其实很直观:

  • 分子:∂C/∂T + rK ∂C/∂K,衡量的是期权价格随时间的变化,减去由于利率引起的调整
  • 分母:½ K² ∂²C/∂K²,衡量的是期权价格对行权价的曲率,也就是凸性
  • 比值:局部波动率平方 = 时间变化率 / 凸性

为什么会这样?你想想看:凸性越大,说明市场对未来价格的不确定性越强,对应的局部波动率就应该越高。

我在做波动率曲面构建时,经常用这个公式来校验模型是否合理。如果算出来的局部波动率出现负值,那一定是输入数据有问题——要么是期权价格有套利机会,要么是数值求导精度不够。

7.4 数值实现要点

把Dupire公式用到实际数据上,有几个坑要避开:

  1. 数据插值:市场给的期权价格通常是离散的,需要先插值成光滑曲面。我习惯用三次样条,但要注意避免过拟合
  2. 边界处理:在K很小或很大时,∂²C/∂K²可能接近零,导致局部波动率发散。需要加一些正则化
  3. 时间导数:∂C/∂T需要小心处理,尤其是近月合约。我建议用对数时间网格

避坑指南:我曾经在计算∂²C/∂K²时用了太粗糙的网格,结果局部波动率曲面出现了明显的锯齿。后来改用自适应网格,并在每个点用5点差分公式,问题才解决。记住:数值稳定性比精度更重要

7.5 代码示例:Dupire公式实现

下面是一个Python实现的核心部分。假设我们已经有了插值后的期权价格曲面C(K, T):

import numpy as np
from scipy.interpolate import RectBivariateSpline

def dupire_local_vol(K_grid, T_grid, C_surface, r):
    """
    从期权价格曲面计算局部波动率
    
    参数:
        K_grid: 行权价网格 (1D array)
        T_grid: 到期时间网格 (1D array)
        C_surface: 期权价格曲面 (2D array, shape=[len(T), len(K)])
        r: 无风险利率
    
    返回:
        local_vol: 局部波动率曲面 (2D array)
    """
    # 对价格曲面做样条插值
    spline = RectBivariateSpline(T_grid, K_grid, C_surface)
    
    # 计算偏导数
    dC_dT = spline(T_grid, K_grid, dx=1, dy=0)  # ∂C/∂T
    dC_dK = spline(T_grid, K_grid, dx=0, dy=1)  # ∂C/∂K
    d2C_dK2 = spline(T_grid, K_grid, dx=0, dy=2)  # ∂²C/∂K²
    
    # 构造网格
    K_mesh, T_mesh = np.meshgrid(K_grid, T_grid)
    
    # Dupire公式
    numerator = dC_dT + r * K_mesh * dC_dK
    denominator = 0.5 * K_mesh**2 * d2C_dK2
    
    # 防止除零和负值
    denominator = np.maximum(denominator, 1e-10)
    local_var = numerator / denominator
    local_var = np.maximum(local_var, 0)  # 方差不能为负
    
    return np.sqrt(local_var)

个人经验:这段代码在实际使用时,我建议加上一个平滑步骤。比如对算出来的局部波动率再做一次二维高斯滤波,能有效去除数值噪声。另外,永远不要直接用原始市场报价,一定要先做插值和去噪。

7.6 局部波动率曲面的可视化

下面我用SVG画一个典型的局部波动率曲面结构图,展示从期权价格到局部波动率的映射关系:

Dupire公式:从期权价格到局部波动率 期权价格曲面 C(K,T) K (行权价) T (时间) C (价格) Dupire 公式 局部波动率 σ(K,T) K (行权价) T (时间) σ (波动率) 输入:市场期权报价 → 插值光滑曲面 → 数值求导 → 输出:局部波动率曲面 σ²(K,T) = (∂C/∂T + rK·∂C/∂K) / (½·K²·∂²C/∂K²)

7.7 实际应用中的注意事项

Dupire公式在理论上很完美,但实际应用中会遇到几个问题:

问题 原因 解决方案
局部波动率出现负值 期权价格存在套利机会 先做无套利校准,再计算
曲面不平滑 数值求导放大噪声 用正则化样条插值
近月合约不稳定 时间导数对短期数据敏感 增加时间网格密度
深度虚值/实值区域发散 二阶导接近零 加截断或先验约束

核心要点:Dupire公式是连接期权市场和局部波动率的桥梁。它告诉我们,只要市场是完整的、无套利的,局部波动率就唯一存在。这个结论在衍生品定价和风险管理中有着根本性的意义。

我个人习惯在构建波动率曲面时,先用Dupire公式算一个初始的局部波动率,然后用它作为后续随机波动率模型的校准起点。这样既能保证与市场一致,又能引入更丰富的动态特征。

好了,Dupire公式的推导就讲到这里。记住:公式本身不难,难的是数值实现和数据处理。多动手写代码,多跟市场数据打交道,你自然就能掌握其中的门道。

公众号:蓝海资料掘金营,微信deep3321