Multi-Index波动率与相关性DataFrame相乘生成协方差矩阵问题
波动率数据与相关性数据计算协方差矩阵实现方案
核心计算逻辑
单日期维度下,协方差矩阵满足计算公式:协方差矩阵Σ = 对角波动率矩阵Dσ * 相关系数矩阵R * 对角波动率矩阵Dσ
其中Dσ为方阵,对角元素为对应资产的日度波动率,非对角元素为0。
现有实现的报错根源
- 逐组计算方案的
ValueError: matrices are not aligned报错原因:
原代码矩阵运算顺序错误、维度匹配逻辑偏差。逐组取数时未显式校验当前日期下rvm对角矩阵与相关系数矩阵的行/列维度一致性,嵌套的dot运算未严格遵循Dσ * R * Dσ的乘法顺序,导致矩阵维度无法对齐。 - 张量方案的广播报错原因:
- 维度计算偏差:将5790行的二维rvm对角值直接传入einsum时,未将其重塑为和相关系数张量(形状为(日期数, 资产数, 资产数))匹配的结构,导致出现(579,10,10)与(5790,10)的形状不匹配
- einsum方程写法错误:未显式对应三维张量的逐天运算维度,直接复用二维数组的运算逻辑,触发广播规则校验失败。
可正常运行的实现代码
方案1:分组逐组计算(易调试,适合小数据量)
# 先对齐两个数据集的索引排序,避免日期、资产标签错位 rvm = rvm.sort_index() omega_tilde = omega_tilde.sort_index() def calculate_daily_corr(date_group, rvm_dataset): # 提取当前日期的对角波动率矩阵 sigma_diag = rvm_dataset.loc[date_group.name].values # 提取当前日期的相关系数矩阵 corr_mat = date_group.values # 严格按乘法顺序计算协方差矩阵 daily_cov = sigma_diag @ corr_mat @ sigma_diag # 返回保留原有索引结构的DataFrame return pd.DataFrame(daily_cov, index=date_group.index, columns=date_group.columns) # 按日期分组计算,不保留分组键,保持原索引结构 sigma_tilde = omega_tilde.groupby(level='Date', group_keys=False).apply( lambda g: calculate_daily_corr(g, rvm) )
方案2:张量批量计算(高吞吐量,适合大日期量级)
import numpy as np import pandas as pd # 提取结构参数 n_dates = omega_tilde.index.get_level_values('Date').nunique() n_assets = omega_tilde.shape[-1] # 重塑波动率数据为 日期数×资产数 的二维数组 sigma_vector = rvm.values.reshape(n_dates, n_assets) # 重塑相关性数据为 日期数×资产数×资产数 的三维张量 corr_tensor = omega_tilde.values.reshape(n_dates, n_assets, n_assets) # 批量执行Dσ * R * Dσ运算 cov_tensor = np.einsum('ti,tij,tj->tij', sigma_vector, corr_tensor, sigma_vector) # 还原为和omega_tilde完全一致的MultiIndex结构 sigma_tilde = pd.DataFrame( cov_tensor.reshape(n_dates * n_assets, n_assets), index=omega_tilde.index, columns=omega_tilde.columns )
结果校验提示
- 输出的
sigma_tilde需完全继承omega_tilde的MultiIndex层级顺序、标签值,无索引错位 - 可随机抽取单日期样本验证:资产i与资产j的协方差值 = 当日资产i波动率 * 当日i-j相关系数 * 当日资产j波动率
内容的提问来源于stack exchange,提问作者Bjarne Timm
相关产品推荐
相关产品推荐

