如何在CVXPY中添加资产数量≤12的约束以最小化跟踪误差
解决方案
要添加“选中资产总数≤12”的约束,需要引入二进制变量标记资产是否被选中,因为这属于混合整数优化问题。以下是修改后的完整代码:
import pandas as pd import cvxpy as cp import numpy as np import os os.chdir(r'\\Directory') input_file = pd.read_csv('your_input_file.csv') # 补充读取输入文件的代码 base_weights # 17 x 1 msci_na = input_file['MSCI North America Index'].to_numpy() # 转为numpy数组匹配计算维度 funds = input_file.loc[:, input_file.columns != 'MSCI North America Index'] funds_np = funds.to_numpy() n_funds = funds.shape[1] # 定义权重变量 weights = cp.Variable(n_funds) # 定义二进制变量:z[i]=1表示选中第i只资产,0表示未选中 z = cp.Variable(n_funds, boolean=True) # 跟踪误差目标函数(与原逻辑一致) tracking_error = cp.norm(funds_np @ weights - msci_na, 2) / np.sqrt(funds_np.shape[0] - 1) # 更新约束条件 constraints = [ cp.sum(weights) == 1, # 选中资产权重总和为100% # 选中资产权重限制在3%-20%,未选中资产权重强制为0 weights >= 0.03 * z, weights <= 0.20 * z, cp.sum(z) <= 12, # 选中资产总数不超过12只 weights >= 0 # 额外确保权重非负(可选,z=0时已通过约束限制权重为0) ] # 定义问题并求解,需指定支持混合整数规划的求解器 problem = cp.Problem(cp.Minimize(tracking_error), constraints) # ECOS_BB是CVXPY自带的免费整数规划求解器,若需要更高精度可尝试GUROBI/CPLEX(需单独安装) problem.solve(solver=cp.ECOS_BB, verbose=True) # 提取结果 optimal_weights = weights.value selected_assets = np.where(z.value > 0.5)[0] # z值接近1的即为选中资产
关键说明:
- 二进制变量
z的核心作用是区分“选中/未选中”资产,通过与权重变量的联动约束,确保未选中资产权重为0,选中资产落在3%-20%的区间内。 - 混合整数规划需要特定求解器支持,
ECOS_BB是免费且无需额外安装的选项;如果数据规模大或追求更高求解效率,可选择商业求解器如GUROBI。 - 需确保
msci_na与funds_np的维度匹配:funds_np为48行(月份)×17列(资产),msci_na需为48行的数组,保证组合收益与指数收益的差值计算合法。
内容的提问来源于stack exchange,提问作者JungleDiff
相关产品推荐
相关产品推荐

