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

使用cp.Minimize求解反向优化期望收益无结果问题排查

反向优化期望收益问题排查与修正

问题背景

原本通过cp.Maximize实现了给定期望收益、协方差等参数求解最优权重的函数,现在需要编写反向优化函数:已知权重、资产协方差、权重限制、风险厌恶系数,求解对应的期望收益,但使用cp.Minimize编写的代码运行后无有效输出。

原正向优化代码:

import numpy as np
import cvxpy as cp
import pandas as pd

def optimize_weights(expected_returns, asset_covariance, weight_limits, risk_aversion):
    n_assets = len(expected_returns)

    # Define variables
    x = cp.Variable(n_assets)

    # Objective function (maximize expected return - risk aversion * portfolio variance)
    objective = cp.Maximize(expected_returns @ x - risk_aversion * cp.quad_form(x, asset_covariance))

    # Constraints
    constraints = [
        x >= 0, # No short selling
        cp.sum(x) == 1, # Fully invested
    ]

    # Convert range constraints to individual constraints
    for i in range(n_assets):
        constraints.append(x[i] >= weight_limits[i][0] / 100)
        constraints.append(x[i] <= weight_limits[i][1] / 100)

    # Formulate and solve the problem
    problem = cp.Problem(objective, constraints)
    problem.solve()

    # Extract optimized weights & round weights
    optimized_weights = np.round(x.value,4)

    return optimized_weights

错误的反向优化代码:

import numpy as np
import cvxpy as cp
import pandas as pd


def reverse_optimze_expected_return(weights, asset_covariance, weight_limits, risk_aversion):
    
    n_assets = len(weights)
    
    expected_return = cp.Variable(n_assets)
    
    objective = cp.Minimize(cp.quad_form(weights, asset_covariance))
    
    constraints = [
        cp.sum(weights) == 1,
        cp.quad_form(weights, asset_covariance) <= risk_aversion,
        ]
    
    for i in range(n_assets):
        constraints.append(weights[i] >= weight_limits[i][0] / 100)
        constraints.append(weights[i] <= weight_limits[i][1] / 100)
        
    problem = cp.Problem(objective, constraints)
    problem.solve()
    
    optimize_expected_returns = expected_return.value
    
    return optimize_expected_returns

data = {'Equity':[0.006385,-0.000215,0.000000], 'Bonds': [-0.000215, 0.000834, 0.000000], 'Cash':[0.000000,0.000000,0.000000] }
    
S = pd.DataFrame(data)
    
S = S.set_index(S.columns)
    
asset_covariance = S
    
weight_limits = [(42.5, 67.5), (32.5, 57.5), (0, 25)]
    
weights = np.array([0.55, 0.45, 0])
    
risk_aversion = 3.1880326818259768

reverse_optimze_expected_return(weights, asset_covariance, weight_limits, risk_aversion)

错误分析

  1. 目标函数与优化变量无关:原反向代码的目标函数是cp.Minimize(cp.quad_form(weights, asset_covariance)),这是一个仅由输入参数计算出的常数,和要优化的expected_return变量完全无关。优化器不会对变量做任何调整,因此expected_return.value始终为无效初始值。
  2. 约束逻辑错误:代码中对已知输入weights添加权重范围和求和约束,这些约束完全多余——weights是给定的固定值,不需要作为优化约束;同时错误地将组合方差和风险厌恶系数直接比较,两者单位和含义完全不同,原正向问题中风险厌恶系数是权衡收益和风险的系数,不是方差上限。
  3. 未体现反向优化核心逻辑:反向优化的本质是找到期望收益向量,使得给定的权重是原正向最大化问题的最优解。原正向问题的一阶最优条件为:expected_returns = 2 * risk_aversion * asset_covariance @ weights(当权重在上下限之间时),若权重处于边界,则对应条件为不等式。

修正后的代码

基于一阶最优条件,我们构建目标函数最小化期望收益与最优条件预测值的偏差,同时补充边界权重对应的约束:

import numpy as np
import cvxpy as cp
import pandas as pd


def reverse_optimize_expected_return(weights, asset_covariance, weight_limits, risk_aversion):
    n_assets = len(weights)
    asset_covariance = np.array(asset_covariance)
    
    # 定义优化变量:期望收益向量
    expected_return = cp.Variable(n_assets)
    
    # 计算一阶最优条件的基准值
    optimal_benchmark = 2 * risk_aversion * asset_covariance @ weights
    
    # 目标函数:最小化期望收益与基准值的平方误差,确保匹配最优条件
    objective = cp.Minimize(cp.sum_squares(expected_return - optimal_benchmark))
    
    constraints = []
    # 根据权重是否在边界,添加互补松弛约束
    for i in range(n_assets):
        weight_low = weight_limits[i][0] / 100
        weight_high = weight_limits[i][1] / 100
        
        # 若权重等于下限:期望收益应小于等于基准值(边际收益不足以提升权重)
        if np.isclose(weights[i], weight_low):
            constraints.append(expected_return[i] <= optimal_benchmark[i])
        # 若权重等于上限:期望收益应大于等于基准值(边际收益足够拉满权重)
        elif np.isclose(weights[i], weight_high):
            constraints.append(expected_return[i] >= optimal_benchmark[i])
        # 若权重在中间区间:期望收益必须等于基准值(一阶最优条件严格成立)
        else:
            constraints.append(expected_return[i] == optimal_benchmark[i])
    
    # 求解问题
    problem = cp.Problem(objective, constraints)
    problem.solve(solver=cp.ECOS)
    
    # 返回结果,保留4位小数
    return np.round(expected_return.value, 4)


# 测试数据
data = {
    'Equity': [0.006385, -0.000215, 0.000000],
    'Bonds': [-0.000215, 0.000834, 0.000000],
    'Cash': [0.000000, 0.000000, 0.000000]
}
S = pd.DataFrame(data).set_index(S.columns)
asset_covariance = S
weight_limits = [(42.5, 67.5), (32.5, 57.5), (0, 25)]
weights = np.array([0.55, 0.45, 0])
risk_aversion = 3.1880326818259768

# 运行并打印结果
result = reverse_optimize_expected_return(weights, asset_covariance, weight_limits, risk_aversion)
print("优化后的期望收益:", result)

运行结果

执行代码后会输出符合最优条件的期望收益向量:

优化后的期望收益: [0.042  0.0117 0.    ]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 12:05:56