如何从随机波动率-收益对中筛选有效前沿并绘制连线?
筛选有效前沿点并绘制曲线
首先修正你代码里的数组维度问题:你初始化eR、eV、sR时用了(nPort,11),但每个投资组合只有一个预期收益和波动率,改成一维数组(nPort,)才对,否则会出现不必要的维度错误。
接下来是筛选有效前沿的核心逻辑:有效前沿要求相同波动率下收益最高,换个角度看,就是把所有组合按波动率从小到大排序后,只保留收益不低于之前所有点的组合——因为如果一个组合的波动率比之前的高,但收益却更低,那它肯定不在有效前沿上。
下面是修正+添加筛选逻辑后的完整代码:
import numpy as np import pandas as pd import matplotlib.pyplot as plt # 假设ff是你的日收益率DataFrame Mean = ff.mean() * 252 # 乘以252转换成年化收益,和波动率匹配 Vol = ff.cov() * 252 # 协方差矩阵同步年化 nPort = 10000 weight = np.zeros((nPort, 11)) # 修正数组维度为一维 eR = np.zeros(nPort) eV = np.zeros(nPort) sR = np.zeros(nPort) for k in range(nPort): # 生成随机权重并归一化 w = np.array(np.random.random(11)) w = w / np.sum(w) weight[k, :] = w # 计算预期收益 eR[k] = np.sum(Mean * w) # 计算预期波动率 eV[k] = np.sqrt(np.dot(w.T, np.dot(Vol, w))) # 计算夏普比率 sR[k] = eR[k] / eV[k] # 开始筛选有效前沿点 # 1. 把波动率和收益配对,按波动率从小到大排序 portfolios = np.array([eV, eR]).T portfolios = portfolios[portfolios[:, 0].argsort()] # 2. 筛选有效点:只保留收益不低于之前最大收益的点 frontier_vol = [] frontier_ret = [] max_ret = -np.inf for vol, ret in portfolios: if ret >= max_ret: max_ret = ret frontier_vol.append(vol) frontier_ret.append(ret) # 绘图 plt.figure(figsize=(12, 5)) # 绘制所有随机组合的散点图 plt.scatter(eV, eR, c=sR, alpha=0.5) # 绘制有效前沿曲线 plt.plot(frontier_vol, frontier_ret, 'r-', linewidth=2, label='有效前沿') plt.colorbar(label='夏普比率(sR)') plt.xlabel('波动率(Volatility)') plt.ylabel('预期收益(Expected Returns)') plt.legend() plt.show()
几点说明:
- 把日收益和协方差矩阵年化(乘以252,美股年交易日数量),让收益和波动率单位统一,更符合实际分析习惯
- 筛选有效点时,按波动率排序后只保留收益持续上升的点,确保每个波动率区间对应最高收益的组合
- 给散点图加
alpha=0.5的半透明效果,避免遮挡有效前沿曲线
内容的提问来源于stack exchange,提问作者BenGekko
相关产品推荐
相关产品推荐

