使用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)
错误分析
- 目标函数与优化变量无关:原反向代码的目标函数是
cp.Minimize(cp.quad_form(weights, asset_covariance)),这是一个仅由输入参数计算出的常数,和要优化的expected_return变量完全无关。优化器不会对变量做任何调整,因此expected_return.value始终为无效初始值。 - 约束逻辑错误:代码中对已知输入
weights添加权重范围和求和约束,这些约束完全多余——weights是给定的固定值,不需要作为优化约束;同时错误地将组合方差和风险厌恶系数直接比较,两者单位和含义完全不同,原正向问题中风险厌恶系数是权衡收益和风险的系数,不是方差上限。 - 未体现反向优化核心逻辑:反向优化的本质是找到期望收益向量,使得给定的权重是原正向最大化问题的最优解。原正向问题的一阶最优条件为:
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
相关产品推荐
相关产品推荐

