You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Portfolio Optimizer 无法生成有效前沿仅输出散点团问题求助

问题核心原因
  • 代码未计算日度收益率的协方差矩阵cov_matrix,计算组合波动率时调用了未定义的变量,导致散点分布逻辑错误
  • 仅生成了随机权重的组合散点,未通过凸优化求解有效边界上的最优组合,无法生成连续的前沿曲线
  • 循环内重复定义data字典属于无效代码,且weights变量行存在缩进错误
修复步骤与完整代码

首先在计算完单资产年化波动率后,补全协方差矩阵的定义:

# 你原有代码的前面部分保持不变,补全下面两行
log_ret = df.pct_change().apply(lambda x: np.log(1+x)).dropna()
cov_matrix = log_ret.cov() # 之前完全缺失的协方差矩阵计算步骤

修正原有循环的缩进问题和data定义位置:

p_ret = [] 
p_vol = [] 
p_weights = [] 

num_assets = len(df.columns)
num_portfolios = 10000

for portfolio in range(num_portfolios):
    weights = np.random.random(num_assets)
    weights = weights/np.sum(weights) # 修正原代码的缩进错误
    p_weights.append(weights)
    returns = np.dot(weights, ind_er)
    p_ret.append(returns)
    var = cov_matrix.mul(weights, axis=0).mul(weights, axis=1).sum().sum()
    sd = np.sqrt(var)
    ann_sd = sd*np.sqrt(250)
    p_vol.append(ann_sd)

# 把data定义移到循环外面
data = {'Returns':p_ret, 'Volatility':p_vol}
portfolios = pd.DataFrame(data)

新增有效前沿求解代码:

import matplotlib.pyplot as plt
from scipy.optimize import minimize

# 定义组合波动率计算函数
def portfolio_vol(weights):
    return np.sqrt(np.dot(weights.T, np.dot(cov_matrix*250, weights)))

# 定义组合收益计算函数
def portfolio_ret(weights):
    return np.dot(weights, ind_er)

# 约束条件:权重和为1
cons = ({'type':'eq', 'fun':lambda x: np.sum(x) - 1})
# 边界:每个资产权重在0到1之间(不允许做空)
bnds = tuple((0,1) for _ in range(num_assets))

# 遍历不同收益目标,求最小波动率,得到有效前沿点
target_returns = np.linspace(min(p_ret), max(p_ret), 100)
efficient_vols = []

for ret in target_returns:
    cons_new = (cons, {'type':'eq', 'fun':lambda x: portfolio_ret(x) - ret})
    # 初始权重用平均权重
    init_w = np.ones(num_assets)/num_assets
    result = minimize(portfolio_vol, init_w, method='SLSQP', bounds=bnds, constraints=cons_new)
    efficient_vols.append(result['fun'])

新增绘图代码即可同时展示散点和有效前沿:

plt.figure(figsize=(10,6))
plt.scatter(portfolios['Volatility'], portfolios['Returns'], c=portfolios['Returns']/portfolios['Volatility'], cmap='viridis', alpha=0.6)
plt.plot(efficient_vols, target_returns, 'r-', linewidth=3, label='有效前沿')
plt.xlabel('年化波动率')
plt.ylabel('年化收益率')
plt.legend()
plt.colorbar(label='夏普比率')
plt.show()
其他TODO问题说明
  • 对数收益率的使用是合理的,符合复利计算逻辑,无需修改
  • 250是通用的年化交易日系数,A股可调整为252,差异极小,不影响有效前沿形状

内容的提问来源于stack exchange,提问作者Sloane Marshall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 15:36:03