1. 构建基础波动率曲面

任务目标

本案例使用一组有限的期权市场报价(行权价、到期时间、隐含波动率),通过插值构建一个光滑的隐含波动率曲面,并可视化不同到期日与行权价下的波动率结构。输入数据为模拟的期权链快照,输出为可交互的3D曲面图与二维热力图。

环境依赖

需要Python 3.9+,并安装以下库:

numpy, scipy, matplotlib

实现代码

import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# ---------- 1. 模拟市场期权数据(行权价K,到期时间T,隐含波动率IV) ----------
# 真实场景中这些数据来自期权链快照
K = np.array([80, 90, 100, 110, 120, 130, 140])
T = np.array([0.1, 0.3, 0.6, 1.0])
# 构造典型波动率微笑+期限结构:短期微笑更陡,长期更平
K_grid, T_grid = np.meshgrid(K, T)
IV_surface = 0.2 + 0.1 * np.exp(-0.5 * ((K_grid - 100) / 20) ** 2) + 0.05 * T_grid

# 展平为观测点
K_obs = K_grid.ravel()
T_obs = T_grid.ravel()
IV_obs = IV_surface.ravel()

# ---------- 2. 构建稠密插值网格 ----------
K_dense = np.linspace(75, 145, 60)
T_dense = np.linspace(0.05, 1.05, 40)
K_dense_grid, T_dense_grid = np.meshgrid(K_dense, T_dense)

# 三次样条插值(使用scipy的griddata,method='cubic')
IV_interp = griddata(
    (K_obs, T_obs), IV_obs,
    (K_dense_grid, T_dense_grid),
    method='cubic', fill_value=np.nan
)

# ---------- 3. 可视化 ----------
fig = plt.figure(figsize=(14, 5))

# 左图:3D曲面
ax1 = fig.add_subplot(121, projection='3d')
surf = ax1.plot_surface(
    K_dense_grid, T_dense_grid, IV_interp,
    cmap='viridis', edgecolor='none', alpha=0.9
)
ax1.set_xlabel('行权价 K')
ax1.set_ylabel('到期时间 T (年)')
ax1.set_zlabel('隐含波动率')
ax1.set_title('隐含波动率曲面(插值后)')
fig.colorbar(surf, ax=ax1, shrink=0.6, pad=0.1)

# 右图:二维热力图(俯视)
ax2 = fig.add_subplot(122)
c = ax2.contourf(
    K_dense_grid, T_dense_grid, IV_interp,
    levels=20, cmap='viridis'
)
ax2.set_xlabel('行权价 K')
ax2.set_ylabel('到期时间 T (年)')
ax2.set_title('波动率曲面俯视图(热力图)')
fig.colorbar(c, ax=ax2)

plt.tight_layout()
plt.savefig('vol_surface.png', dpi=150)
plt.show()

# ---------- 4. 验证:输出插值后指定点的IV值 ----------
# 选取一个不在原始网格上的点进行验证
test_K, test_T = 105.0, 0.45
test_IV = griddata(
    (K_obs, T_obs), IV_obs,
    (test_K, test_T), method='cubic'
)
print(f"验证点: K={test_K}, T={test_T} -> 插值IV = {test_IV:.4f}")
print("预期范围: 0.20 ~ 0.35(根据微笑+期限结构形态)")

运行方式

python vol_surface.py

验证方法

  • 程序正常结束且无报错,当前目录生成vol_surface.png文件。
  • 图像中曲面呈现“微笑”形态:在行权价100附近IV最低,向两侧升高;且到期时间越长,整体IV水平越高(期限结构向上倾斜)。
  • 控制台输出的验证点插值IV应落在0.20~0.35区间内,且与相邻原始网格点的IV值连续过渡,无跳变。

关键说明

  • 本案例使用scipy.interpolate.griddata的cubic方法进行插值,适用于散点数据;若原始数据本身在规则网格上,也可直接使用RectBivariateSpline获得更平滑的结果。
  • 实际市场中,行权价和到期日的分布往往不规则,griddata能直接处理非均匀采样点,这正是本案例选择它的原因。
  • 插值边界外的点会被填充为NaN,在图中显示为空白区域,这是合理行为——曲面不应外推到超出市场报价范围之外的区域。