24. 多资产曲面构建:相关性曲面、多资产波动率曲面、协方差矩阵估计
好,咱们进入多资产的部分了。
说实话,单标的的隐含波动率曲面已经够复杂了。但现实交易中,你很少只盯着一个品种。期权组合、价差策略、波动率套利,哪个都离不开多资产之间的联动关系。今天我们就聊聊怎么把单标的的曲面思维,扩展到多资产维度。
24.1 为什么需要多资产曲面?
先问个问题:你手里拿着沪深300的期权和上证50的期权,它们的隐含波动率都在涨。你能说这是独立事件吗?
不能。因为这两个指数高度相关。如果只盯着各自的曲面,你会错过一个关键信息——相关性本身也在变。
我在做跨品种套利时遇到过这种情况:两个品种的隐含波动率都正常,但相关性突然飙升,导致组合风险完全失控。嗯,从那以后,我再也不敢忽略相关性曲面了。
核心观点:多资产波动率建模,本质上是在构建一个动态的协方差矩阵。而相关性曲面,就是把这个矩阵的每个元素,都变成随行权价和到期时间变化的曲面。
24.2 相关性曲面:不只是个数字
很多人以为相关性就是一个常数,比如0.6。但实际市场里,相关性是动态的,而且有结构。
24.2.1 相关性微笑
你想想看,两个资产在极端行情下,相关性往往会上升。这就是所谓的“相关性微笑”。
- 虚值看跌期权:市场大跌时,相关性飙升,所有资产一起跌。
- 虚值看涨期权:市场大涨时,相关性也会上升,但幅度通常小于下跌时。
- 平值附近:相关性相对平稳,但也不是常数。
我个人习惯用双变量SABR模型来拟合相关性曲面。简单说,就是把两个资产的SABR参数联合估计,同时拟合出它们之间的相关性参数。
# 伪代码:双变量SABR相关性曲面拟合
def fit_correlation_surface(price1, price2, strikes, expiries):
# 步骤1:分别拟合两个资产的SABR参数
params1 = fit_sabr(price1, strikes, expiries)
params2 = fit_sabr(price2, strikes, expiries)
# 步骤2:估计残差相关性
residuals1 = compute_residuals(price1, params1)
residuals2 = compute_residuals(price2, params2)
# 步骤3:对每个到期日,估计不同行权价下的相关性
corr_surface = {}
for T in expiries:
for K in strikes:
corr_surface[(T, K)] = estimate_corr(residuals1[T][K], residuals2[T][K])
return corr_surface
我的经验:相关性曲面通常比波动率曲面更“脏”。数据噪声大,拟合时建议用更稳健的估计方法,比如中位数回归,而不是普通最小二乘。
24.3 多资产波动率曲面:联合建模
有了相关性曲面,下一步就是把多个资产的波动率曲面联合起来。这不仅仅是拼凑,而是要考虑它们之间的相互作用。
24.3.1 主成分分析(PCA)降维
多资产曲面维度太高,直接建模不现实。我常用的方法是PCA降维。
- 第一步:把所有资产的波动率曲面展平成一个高维向量。
- 第二步:计算协方差矩阵,提取前几个主成分。
- 第三步:用主成分重构曲面,保留主要结构,去掉噪声。
# 伪代码:PCA降维多资产波动率曲面
def pca_multi_asset_surface(surfaces, n_components=3):
# surfaces: 字典,key为资产名,value为波动率曲面矩阵
# 步骤1:展平所有曲面
flat_surfaces = []
for asset, surface in surfaces.items():
flat_surfaces.append(surface.flatten())
# 步骤2:PCA分解
from sklearn.decomposition import PCA
pca = PCA(n_components=n_components)
pca.fit(flat_surfaces)
# 步骤3:重构曲面
reconstructed = pca.inverse_transform(pca.transform(flat_surfaces))
return reconstructed
注意:PCA假设数据是线性的。如果市场出现非线性联动(比如尾部风险),PCA会失效。我建议在极端行情下,改用t-SNE或自编码器这类非线性方法。
24.4 协方差矩阵估计:从曲面到风险
最后一步,也是最实际的一步:把相关性曲面和波动率曲面,合成一个动态的协方差矩阵。
24.4.1 构建方法
协方差矩阵的每个元素,都可以写成:
cov(i, j, T, K_i, K_j) = vol_i(T, K_i) * vol_j(T, K_j) * corr(i, j, T, K_i, K_j)
其中:
vol_i(T, K_i)是资产i在到期日T、行权价K_i的隐含波动率corr(i, j, T, K_i, K_j)是资产i和j在对应点的相关性
说白了,就是把两个曲面和一个相关性曲面,乘在一起。
24.4.2 正定性保证
这里有个坑:直接乘出来的协方差矩阵,很可能不是正定的。正定性是风险计算的基础,否则VaR、ES这些指标都会出问题。
我曾经在这个问题上栽过跟头。当时算出来的协方差矩阵有负特征值,导致组合风险被低估了30%。后来我用了收缩估计(Shrinkage)方法,才把问题解决。
# 伪代码:收缩估计保证正定性
def shrinkage_covariance(sample_cov, target_cov, shrinkage_factor=0.2):
# sample_cov: 样本协方差矩阵
# target_cov: 目标协方差矩阵(比如常数相关模型)
# shrinkage_factor: 收缩系数,通常通过交叉验证选择
shrunk_cov = (1 - shrinkage_factor) * sample_cov + shrinkage_factor * target_cov
# 检查正定性
eigenvalues = np.linalg.eigvalsh(shrunk_cov)
if np.min(eigenvalues) <= 0:
# 如果还不是正定,做近邻正定修正
shrunk_cov = nearest_positive_definite(shrunk_cov)
return shrunk_cov
我的建议:收缩因子不要固定。我一般用Ledoit-Wolf方法,根据数据质量动态调整。数据质量高时,收缩因子小;数据噪声大时,收缩因子大。
24.5 实战中的注意事项
最后聊几个实际项目中容易踩的坑。
- 数据频率不一致:不同资产的期权数据,到期日可能不同。我习惯用插值法统一到标准期限上。
- 极端行情下的相关性突变:2008年、2020年,相关性都出现过瞬间飙升。建议在模型中加入跳跃项。
- 计算效率:多资产曲面的维度很高,实时计算协方差矩阵很耗资源。我一般用滚动窗口+增量更新的方式。
总结一下:多资产曲面构建,本质上是在做三件事——相关性曲面建模、多资产波动率联合降维、协方差矩阵的正定化。每一步都有坑,但每一步也都有成熟的解决方案。
好了,多资产曲面这块就聊到这儿。内容不少,但核心逻辑其实很清晰:从单资产出发,通过相关性连接,最终合成一个完整的协方差结构。下次你遇到跨品种期权组合时,记得先看看相关性曲面——它往往比波动率本身更能说明问题。