6. 随机波动率模型:Heston模型基础,如何用Heston生成波动率曲面
说到波动率曲面,咱们之前聊的Black-Scholes模型有个硬伤——它假设波动率是常数。但你在市场上待久了就会发现,这玩意儿压根儿就不是常数。我刚开始做期权定价那会儿,用BS模型算出来的价格和实际交易价格总是对不上,心里那个憋屈啊。
后来接触到了Heston模型,才算是找到了正解。说白了,Heston模型就是让波动率自己也有个随机过程。你想想看,波动率会均值回归,会随机波动,这不更符合真实市场吗?
6.1 Heston模型的核心思想
Heston模型的核心就两句话:
- 资产价格本身是随机的
- 波动率也是随机的,而且它会向长期均值回归
模型长这样:
dS = μS dt + √v S dW₁
dv = κ(θ - v) dt + σ√v dW₂
这里:
- S 是资产价格
- v 是方差(波动率的平方)
- κ 是均值回归速度——我习惯叫它"拉回力度"
- θ 是长期方差均值
- σ 是波动率的波动率(听着有点绕,但很重要)
- dW₁, dW₂ 是两个相关的布朗运动
嗯,这里要注意:两个随机过程之间有个相关系数ρ。这个ρ特别关键,它决定了所谓的"杠杆效应"——市场跌的时候波动率往往上升。
关键参数速查表
| 参数 | 含义 | 典型范围 |
|---|---|---|
| v₀ | 初始方差 | 0.01 - 0.09 |
| κ | 均值回归速度 | 1 - 5 |
| θ | 长期方差均值 | 0.04 - 0.09 |
| σ | 波动率的波动率 | 0.1 - 0.5 |
| ρ | 价格与波动率的相关性 | -0.7 到 -0.3 |
6.2 从Heston模型到波动率曲面
有了模型,怎么生成曲面呢?我一般分三步走:
- 参数校准:用市场数据反推模型参数
- 数值求解:用特征函数方法算期权价格
- 反推隐含波动率:把算出来的价格转成波动率
我个人习惯用特征函数法,因为速度快。Heston模型有个漂亮的半解析解,不需要蒙特卡洛模拟那么费劲。
6.3 代码实现:生成波动率曲面
下面是我常用的Python代码片段。说实话,这代码我改过不下十版了。
import numpy as np
from scipy.integrate import quad
def heston_price(S, K, T, r, v0, kappa, theta, sigma, rho):
"""
Heston模型期权定价
用特征函数方法
"""
def characteristic_function(u, j):
# 特征函数实现
# 这里省略了具体推导,直接上代码
a = kappa * theta
b = kappa + (1 if j == 1 else -1) * sigma * rho * 1j * u
d = np.sqrt((rho * sigma * 1j * u - b)**2 -
sigma**2 * (2 * 1j * u + u**2))
g = (b - rho * sigma * 1j * u + d) / \
(b - rho * sigma * 1j * u - d)
C = r * 1j * u * T + (a / sigma**2) * \
((b - rho * sigma * 1j * u + d) * T -
2 * np.log((1 - g * np.exp(d * T)) / (1 - g)))
D = (b - rho * sigma * 1j * u + d) / sigma**2 * \
((1 - np.exp(d * T)) / (1 - g * np.exp(d * T)))
return np.exp(C + D * v0 + 1j * u * np.log(S))
# 用数值积分算价格
# 这里简化处理,实际需要更精细的积分
price = 0.5 * S + 0.5 * K * np.exp(-r * T)
# 实际代码需要做数值积分
return price
# 生成曲面
def generate_vol_surface():
strikes = np.linspace(0.8, 1.2, 5) # 80%到120%的行权价
maturities = np.array([0.1, 0.25, 0.5, 1.0, 2.0]) # 到期时间
params = {
'v0': 0.04,
'kappa': 2.0,
'theta': 0.04,
'sigma': 0.3,
'rho': -0.5
}
surface = np.zeros((len(maturities), len(strikes)))
for i, T in enumerate(maturities):
for j, K in enumerate(strikes):
price = heston_price(100, K, T, 0.05, **params)
# 用BS公式反推隐含波动率
surface[i, j] = implied_vol(price, 100, K, T, 0.05)
return surface
避坑指南
我曾经在特征函数积分时踩过一个坑——积分上限设太小,导致远虚值期权价格不准。后来我把积分上限设到100以上,结果才稳定下来。建议你至少用100个积分点,精度才够用。
6.4 Heston曲面的典型特征
用Heston模型生成的曲面,有几个明显特点:
- 微笑效应:短期限的曲面有明显的"微笑"形状
- 偏斜效应:长期限的曲面呈现"偏斜",低行权价波动率更高
- 期限结构:波动率会随期限变化,通常短期波动更大
为什么会这样?说白了就是均值回归在起作用。短期波动率可以偏离均值很远,但长期来看它会被拉回来。
Heston曲面 vs BS曲面
BS模型只能生成一个平面(常数波动率),而Heston能生成一个带微笑和偏斜的曲面。这就是为什么做期权交易的人更爱用Heston——它更贴近真实市场。
6.5 参数对曲面的影响
我整理了一张表,方便你理解每个参数怎么影响曲面:
| 参数变化 | 对曲面的影响 |
|---|---|
| κ 增大 | 曲面更平坦,均值回归更快 |
| σ 增大 | 微笑更明显,波动更大 |
| ρ 为负且绝对值大 | 偏斜更严重,低行权价波动率高 |
| θ 增大 | 整体波动率水平上移 |
注意:参数校准是个技术活。我见过有人用优化算法硬怼,结果参数物理意义都不对。建议你先固定ρ和κ,只校准v₀、θ和σ,这样更稳定。
6.6 知识体系总览
下面这张图帮你理清Heston模型生成波动率曲面的完整流程:
嗯,整个流程就是这么回事。从市场数据出发,经过参数校准、模型定价、反推隐含波动率,最后得到一张完整的波动率曲面。我每次做这个流程的时候,都会反复检查校准那一步——参数不准,后面全白搭。
个人经验:刚开始学Heston的时候,我总想着把所有参数都校准得特别精确。后来发现,其实κ和ρ对曲面形状影响最大,优先校准这两个参数,其他参数用历史数据估计就行。这样既快又稳。
公众号:蓝海资料掘金营,微信deep3321