Python类中最小化目标函数实现投资组合夏普比率优化的正确写法
修正后的夏普比率优化类实现
原有代码核心问题
- 缺失numpy导入,代码中大量使用
np前缀但未声明导入 - 变量名不一致:构造函数
__init__中存储的预期收益属性名为self.expected_return,后续方法中误用为带s的expected_returns - 目标函数
calculate_negative_sharpe未接收优化器迭代传入的权重参数,方法内weights变量未定义 - 实例方法语法错误:第一种写法的
max_sharpe_ratio是实例方法却未加self入参,第二种写法中self/expected_returns是语法错误,应该用.访问属性 sco.minimize调用时没有正确传递目标函数的入参,优化器每次迭代的权重值无法传入目标函数计算
可直接运行的修正代码
import numpy as np import pandas as pd import scipy.optimize as sco class Optimisation: def __init__(self, rf, expected_return, cov, asset_names=None): self.rf = rf self.expected_return = expected_return self.cov = cov # 可选传入资产名,方便后续生成DataFrame时标注 self.asset_names = asset_names if asset_names else [f"资产_{i+1}" for i in range(len(expected_return))] def calculate_negative_sharpe(self, weights): # 接收优化器传入的当前权重weights portfolio_return = np.sum(self.expected_return * weights) * 252 portfolio_std = np.sqrt(np.dot(weights.T, np.dot(self.cov, weights))) * np.sqrt(252) sharpe_ratio = (portfolio_return - self.rf) / portfolio_std return -sharpe_ratio def max_sharpe_ratio(self): num_assets = len(self.expected_return) # 约束:权重和为1 constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) # 边界:单资产权重0到1 bounds = tuple((0.0, 1.0) for _ in range(num_assets)) # 初始权重:平均分配 init_weights = num_assets * [1./num_assets,] # 调用优化器 opt_result = sco.minimize( self.calculate_negative_sharpe, init_weights, method='SLSQP', bounds=bounds, constraints=constraints ) return opt_result def get_result_df(self): # 直接返回你需要的可打印可保存的结果DataFrame opt_result = self.max_sharpe_ratio() # 最优权重 optimal_weights = opt_result.x # 计算最优组合指标 optimal_return = np.sum(self.expected_return * optimal_weights) * 252 optimal_std = np.sqrt(np.dot(optimal_weights.T, np.dot(self.cov, optimal_weights))) * np.sqrt(252) optimal_sharpe = (optimal_return - self.rf) / optimal_std # 构造结果:先存资产权重 result_dict = dict(zip(self.asset_names, optimal_weights.round(4))) # 再加组合整体指标 result_dict.update({ "组合年化收益": round(optimal_return, 4), "组合年化波动": round(optimal_std, 4), "组合夏普比率": round(optimal_sharpe, 4), "优化是否收敛": opt_result.success }) return pd.DataFrame([result_dict]).T.reset_index().rename(columns={"index": "指标/资产", 0: "数值"}) # 调用示例,替换成你自己的rf、er、cov数据即可 if __name__ == "__main__": # 样例输入:3个资产,无风险利率3%,预期年化收益分别5%、8%、12% rf = 0.03 er = np.array([0.05, 0.08, 0.12]) cov = np.array([ [0.04, 0.02, 0.01], [0.02, 0.09, 0.03], [0.01, 0.03, 0.16] ]) asset_names = ["沪深300", "中证500", "创业板指"] opt = Optimisation(rf, er, cov, asset_names) result_df = opt.get_result_df() print(result_df) # 保存到本地直接调用:result_df.to_csv("最大夏普组合优化结果.csv", index=False, encoding="utf_8_sig")
输出说明
运行后直接输出结构化的DataFrame,包含每个资产的最优权重、组合整体收益波动夏普指标、优化收敛状态,可直接打印或调用to_csv/to_excel保存到本地。
内容的提问来源于stack exchange,提问作者anarchy
相关产品推荐
相关产品推荐

