计算投资组合波动率异常:所有结果值均为同一数值
问题分析与解决方案
我一眼就看出问题出在你的循环逻辑上啦!你现在的代码其实只计算了最后一行权重对应的波动率,然后把整个Volatility列都赋值成了这个结果,所以所有行显示的都是同一个值0.022906。
具体来说,你的for循环里每次迭代都会把temp_list替换成当前行的data.tolist(),但你并没有在循环里计算并保存每一行的波动率,而是等循环结束后才执行一次矩阵乘法——这时候用的是最后一次循环的npa,自然整列都是同一个数。
修正后的循环版本代码
我们需要把每一行计算出的波动率收集起来,最后再赋值给DataFrame列:
import numpy as np covariance_matrix = clean_returns.cov() volatility_list = [] # 直接解构iterrows的返回值,写法更简洁 for index, weights_data in temp.iterrows(): # 把当前行的权重转为numpy数组 weights = weights_data.to_numpy() # 计算投资组合方差:权重转置 × 协方差矩阵 × 权重 portfolio_variance = np.dot(weights.T, np.dot(covariance_matrix, weights)) # 波动率是方差的平方根 portfolio_volatility = np.sqrt(portfolio_variance) # 把当前行的波动率加入列表 volatility_list.append(portfolio_volatility) # 把收集到的波动率批量赋值给新列 Portfolio_Returns['Volatility'] = volatility_list
更高效的向量化版本(推荐)
如果你的temp数据量比较大,循环会比较慢,推荐用向量化操作替代循环,效率提升明显:
import numpy as np covariance_matrix = clean_returns.cov() # 把权重表转为二维numpy数组,每一行对应一组权重 weights_array = temp.to_numpy() # 向量化计算每一行的波动率:先算权重与协方差矩阵的乘积,再和原权重逐元素相乘,最后按行求和开根号 Portfolio_Returns['Volatility'] = np.sqrt(np.sum((weights_array @ covariance_matrix) * weights_array, axis=1))
这样修改后,Portfolio_Returns['Volatility']就会显示每一组权重对应的不同波动率啦!
内容的提问来源于stack exchange,提问作者ahrnad
相关产品推荐
相关产品推荐

