12、曲面可视化:使用Matplotlib/Plotly绘制3D曲面图,热力图,动态曲面动画
曲面可视化,说白了就是把波动率曲面从一堆数字变成一张图。
我刚开始做期权交易那会儿,每天对着Excel表格里的隐含波动率矩阵,眼睛都快看瞎了。后来发现,曲面一画出来,很多问题就一目了然了。比如某个期限的波动率突然凸起,或者曲面出现奇怪的褶皱——这些在数字里很难发现,但图上一眼就能看出来。
12.1 为什么需要可视化?
你想想看,波动率曲面本质上是一个三维结构:
- X轴:行权价(或Delta)
- Y轴:剩余期限
- Z轴:隐含波动率
我们做Gamma交易时,最关心的就是曲面形态的变化。曲面变陡了?还是变平了?某个区域出现异常凸起?这些信息,用3D图一看就懂。
核心观点:可视化不是花架子,它是你判断曲面是否合理、是否存在套利机会的第一道防线。
12.2 用Matplotlib绘制静态3D曲面
Matplotlib是Python最基础的绘图库。虽然它做3D图有点慢,但胜在稳定、可控。
我个人习惯先用Matplotlib做快速验证,确认数据没问题了,再用Plotly做交互式展示。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 模拟波动率曲面数据
strikes = np.linspace(0.8, 1.2, 10) # 行权价比例
tenors = np.linspace(0.1, 2.0, 8) # 剩余期限(年)
X, Y = np.meshgrid(strikes, tenors)
# 构造一个典型的波动率微笑曲面
Z = 0.2 + 0.1 * (X - 1.0)**2 + 0.05 * np.sqrt(Y)
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection='3d')
# 绘制曲面
surf = ax.plot_surface(X, Y, Z, cmap='viridis',
alpha=0.8, edgecolor='none')
# 添加标签
ax.set_xlabel('行权价 (K/S)')
ax.set_ylabel('剩余期限 (年)')
ax.set_zlabel('隐含波动率')
ax.set_title('波动率曲面 - Matplotlib 3D')
# 添加颜色条
fig.colorbar(surf, ax=ax, shrink=0.5, aspect=10)
plt.show()
小技巧:设置 alpha=0.8 可以让曲面半透明,方便看到背后的结构。我一般还会把网格线调淡一点,避免视觉干扰。
12.3 用Plotly做交互式曲面
Matplotlib的图是静态的,不能旋转、缩放。而Plotly可以让你用鼠标拖拽,从任意角度观察曲面。
我记得有一次做策略回测,需要反复查看曲面在不同时间点的形态。用Matplotlib得一张张生成图片,用Plotly直接一个滑块就搞定了。
import plotly.graph_objects as go
import numpy as np
# 同样的数据
strikes = np.linspace(0.8, 1.2, 20)
tenors = np.linspace(0.1, 2.0, 15)
X, Y = np.meshgrid(strikes, tenors)
Z = 0.2 + 0.1 * (X - 1.0)**2 + 0.05 * np.sqrt(Y)
fig = go.Figure(data=[
go.Surface(z=Z, x=X, y=Y,
colorscale='Viridis',
opacity=0.85,
contours={
'z': {'show': True, 'usecolormap': True,
'highlightcolor': 'limegreen', 'project': {'z': True}}
})
])
fig.update_layout(
title='波动率曲面 - Plotly 交互式',
scene=dict(
xaxis_title='行权价 (K/S)',
yaxis_title='剩余期限 (年)',
zaxis_title='隐含波动率',
camera=dict(eye=dict(x=1.5, y=1.5, z=1.2))
),
width=900,
height=700
)
fig.show()
注意:Plotly的曲面在数据点较多时(比如50x50以上),渲染会变慢。我建议在交互式探索时用20x15的网格,够用了。
12.4 热力图:从另一个角度看曲面
3D图虽然直观,但有时候热力图更实用。特别是你想快速定位波动率异常区域时。
热力图把Z轴的值用颜色表示,X和Y轴保持不变。说白了就是俯视图。
import matplotlib.pyplot as plt
import numpy as np
strikes = np.linspace(0.8, 1.2, 20)
tenors = np.linspace(0.1, 2.0, 15)
X, Y = np.meshgrid(strikes, tenors)
Z = 0.2 + 0.1 * (X - 1.0)**2 + 0.05 * np.sqrt(Y)
plt.figure(figsize=(10, 6))
heatmap = plt.contourf(X, Y, Z, levels=20, cmap='RdYlBu_r')
plt.colorbar(heatmap, label='隐含波动率')
# 添加等高线
contours = plt.contour(X, Y, Z, levels=8, colors='black', linewidths=0.5)
plt.clabel(contours, inline=True, fontsize=8)
plt.xlabel('行权价 (K/S)')
plt.ylabel('剩余期限 (年)')
plt.title('波动率曲面热力图 + 等高线')
plt.show()
实战用法:我在做Gamma Scalping时,会盯着热力图的颜色变化。如果某个区域突然变红(波动率上升),说明市场情绪变了,可能需要调整头寸。
12.5 动态曲面动画:捕捉时间变化
静态图只能看一个时间点。但波动率曲面是随时间演变的。动态动画可以展示曲面在几天或几周内的变化过程。
我曾经用这个功能来复盘一次市场波动事件。曲面动画清晰地展示了波动率从平缓到陡峭再到恢复的全过程,比看数字表格直观太多了。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from mpl_toolkits.mplot3d import Axes3D
# 生成多时间步的曲面数据
strikes = np.linspace(0.8, 1.2, 15)
tenors = np.linspace(0.1, 2.0, 10)
X, Y = np.meshgrid(strikes, tenors)
# 模拟曲面随时间变化
def generate_surface(t):
# t 从0到1,模拟曲面形态变化
return (0.2 + 0.1 * (X - 1.0)**2 + 0.05 * np.sqrt(Y)) * (1 + 0.3 * np.sin(2 * np.pi * t))
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection='3d')
def update(frame):
ax.clear()
Z = generate_surface(frame / 50)
surf = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
ax.set_xlabel('行权价')
ax.set_ylabel('期限')
ax.set_zlabel('波动率')
ax.set_title(f'曲面动画 - 时间步 {frame}')
ax.set_zlim(0.15, 0.45)
return surf,
ani = FuncAnimation(fig, update, frames=50, interval=100, blit=False)
plt.show()
避坑指南:动画在Jupyter Notebook里可能不显示。我建议用 ani.save('surface_animation.gif', writer='pillow') 保存成GIF,这样在任何地方都能看。
12.6 可视化在Gamma交易中的实战应用
说了这么多画图的方法,到底怎么用?我总结几个实战场景:
| 场景 | 可视化方式 | 关注点 |
|---|---|---|
| 曲面形态检查 | 3D曲面图 | 是否有异常凸起或凹陷 |
| 波动率期限结构 | 热力图 | 短期 vs 长期波动率差异 |
| 曲面演变跟踪 | 动态动画 | 曲面形态随时间的变化趋势 |
| 套利机会识别 | 等高线叠加 | 是否存在明显的波动率价差 |
嗯,这里要注意一点:可视化只是辅助工具,不能替代量化分析。曲面看起来再漂亮,也得用数据验证。
我的经验:每次做Gamma交易前,我都会先看一眼3D曲面图。如果曲面形态和昨天差别很大,我会重新评估风险敞口。这个习惯帮我躲过好几次大坑。
12.7 本章小结
曲面可视化,说白了就是把抽象的数据变成直观的图形。Matplotlib适合做静态分析和论文插图,Plotly适合做交互式探索,热力图适合快速定位异常,动画适合观察时间演变。
我个人建议:先用Matplotlib快速验证数据,再用Plotly做深入分析。别一上来就搞动画,先把静态图看明白了再说。
记住一句话:画图不是为了好看,是为了发现数字里看不到的东西。
公众号:蓝海资料掘金营,微信deep3321