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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 05:45:03