11. 曲面平滑技术:核回归、局部多项式、正则化方法
做波动率曲面的人,早晚会遇到一个头疼的问题——你从市场上扒下来的隐含波动率数据,它不干净。
我刚开始做期权做市的时候,每天收盘后第一件事就是看曲面。嗯,那叫一个丑。有的点高得像山峰,有的低得像盆地。你要是直接用这些点去插值定价,隔壁交易员能拿着风控报告来找你打架。
所以,我们需要平滑。说白了,就是把那些噪声滤掉,保留曲面的真实形状。今天咱们就聊聊三种主流方法:核回归、局部多项式、正则化。
为什么需要平滑?
先想一个问题:你从市场上拿到的隐含波动率,真的是「真实」波动率吗?
不是。那是做市商报价、大单成交、流动性溢价、甚至交易员手滑的综合产物。我见过一个极端案例——某天下午3点29分,某个深度虚值期权突然冒出一个波动率80%的成交。你信吗?反正我不信。那是某个倒霉蛋敲错了单。
所以,平滑的本质是:在拟合优度和光滑度之间找一个平衡。你拟合得太紧,噪声全进来了;你拟合得太松,真实结构又丢了。
方法一:核回归(Nadaraya-Watson 估计)
核回归的思路很直观:对于曲面上任意一点 (K, T),用它周围的数据点加权平均来估计波动率。权重由核函数决定,距离越近权重越大。
公式长这样:
σ̂(K, T) = Σ wᵢ · σᵢ / Σ wᵢ
其中 wᵢ = K( (K - Kᵢ)/h_K ) · K( (T - Tᵢ)/h_T )
这里 K(·) 是核函数,h 是带宽。带宽越大,平滑程度越高。
我个人习惯用高斯核,因为它的数学性质好,而且在实际中表现稳定。但要注意——带宽的选择比核函数本身重要得多。
核回归的优点是简单、直观、容易实现。缺点呢?在数据稀疏的区域,估计值会偏向零——说白了就是边缘效应严重。你想想看,在期限很长的远端,数据点本来就少,核回归估计出来的波动率往往偏低。
方法二:局部多项式回归
核回归本质上是在每个点做一个常数拟合。那如果我们用局部线性甚至局部二次拟合呢?这就是局部多项式回归。
它的思路是:在每个估计点附近,用一个低阶多项式去拟合局部数据。权重还是由核函数给出。
局部线性回归的优化问题:
min Σ wᵢ · (σᵢ - β₀ - β₁(Kᵢ - K) - β₂(Tᵢ - T))²
解出 β₀ 就是该点的估计值。
为什么局部多项式比核回归好?因为它能更好地捕捉曲面的局部趋势。核回归在边界处会有偏差,而局部线性回归可以自动修正这个偏差。我做过对比测试,在同样的带宽下,局部多项式的均方误差通常比核回归低 15%-20%。
实际应用中,我推荐用 locpoly 或者自己写一个加权最小二乘。Python 里用 numpy 配合 scipy.spatial 就能搞定。
方法三:正则化方法(惩罚样条)
前面两种方法都是「局部」的。那有没有「全局」的方法?有,正则化方法就是。
正则化的核心是:用一个基函数展开来表示曲面,然后对展开系数的「粗糙度」进行惩罚。最常用的是惩罚样条(P-spline)。
目标函数:
min Σ (σᵢ - f(Kᵢ, Tᵢ))² + λ · ∫ (f'')² dK dT
第一项是拟合误差,第二项是惩罚项。λ 越大,曲面越光滑。
我特别喜欢惩罚样条的一点是:你可以显式控制光滑程度。不像核回归,你得靠调带宽来间接控制。惩罚样条直接告诉你:λ=0 就是插值,λ=∞ 就是平面。
在实际项目中,我用 B-spline 基函数配合二阶差分惩罚。效果很稳定。而且计算效率高——一旦基函数选好,求解就是一个线性系统。
三种方法的对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 核回归 | 简单、直观、计算快 | 边缘偏差、带宽敏感 | 数据密集、快速原型 |
| 局部多项式 | 偏差小、精度高 | 稀疏区不稳定 | 数据质量好、需要高精度 |
| 惩罚样条 | 全局控制、灵活 | 基函数选择有技巧 | 生产环境、需要稳定输出 |
实战代码片段
下面是一个用惩罚样条平滑波动率曲面的简单示例。我用的是 scipy.interpolate 的 LSQBivariateSpline,配合手动调 λ。
import numpy as np
from scipy.interpolate import LSQBivariateSpline
# 假设我们有数据:K, T, sigma
K = np.array([...]) # 行权价
T = np.array([...]) # 期限
sigma = np.array([...]) # 隐含波动率
# 定义样条节点
kx = np.linspace(K.min(), K.max(), 10)
ky = np.linspace(T.min(), T.max(), 8)
# 拟合惩罚样条,lambda 控制光滑度
spline = LSQBivariateSpline(K, T, sigma, kx, ky, lambda_=0.01)
# 在网格上评估
K_grid = np.linspace(K.min(), K.max(), 50)
T_grid = np.linspace(T.min(), T.max(), 30)
sigma_smooth = spline(K_grid, T_grid)
嗯,这里要注意:lambda_ 的取值很关键。我一般先试 0.001、0.01、0.1 三个数量级,然后看哪个在验证集上表现最好。
知识体系图
下面这张图总结了三种平滑方法的核心逻辑和关系:
我的建议
如果你刚开始做曲面平滑,我建议从核回归入手。代码简单,效果直观,能让你快速理解「平滑」到底在干什么。
等你对数据有了感觉,再切换到局部多项式或者惩罚样条。我个人在实盘系统中用的是惩罚样条,因为它的稳定性最好,而且方便做压力测试——我可以直接调 λ 来模拟不同光滑程度下的定价差异。
最后说一句:没有万能的方法。不同的市场、不同的数据质量、不同的业务需求,适合的方法都不一样。多试、多看、多对比,才是正道。
公众号:蓝海资料掘金营,微信deep3321