基于CVXOPT设置最小交易规模,去除微小权重
处理CVXOPT优化中的微小权重问题:设置最小交易规模约束
这是个很常见的资产配置类优化需求啊!我来给你梳理两种可行的方案,都是在CVXOPT框架下能落地的:
一、迭代修剪法(最实用的CVXOPT原生方案)
你提到的“当权重小于阈值时剔除并迭代优化”的思路完全可行,而且不需要引入额外工具,步骤清晰:
核心逻辑
- 先跑一轮原始优化(带
sum(w)=1、w≥0这类基础约束),得到初始权重结果 - 设定一个你能接受的最小权重阈值
ε(比如0.01,对应1%的仓位),把所有低于这个阈值的权重直接标记为“需要置零” - 重新构建优化问题,强制这些标记的权重为0,同时保持剩余权重的总和为1,再次求解
- 重复上述过程,直到没有新的权重低于阈值,或者达到预设的迭代次数为止
代码示例(以最小方差组合为例)
from cvxopt import matrix, solvers import numpy as np # 模拟资产数据(替换成你的真实数据) n_assets = 10 cov_matrix = np.random.randn(n_assets, n_assets) cov_matrix = cov_matrix.T @ cov_matrix # 构造正定协方差矩阵 cov_matrix = matrix(cov_matrix) ones = matrix(np.ones(n_assets)) zeros = matrix(np.zeros(n_assets)) # 1. 初始优化:求解无修剪的最小方差组合 solvers.options['show_progress'] = False initial_result = solvers.qp( cov_matrix, matrix(np.zeros(n_assets)), -np.eye(n_assets), zeros, # w ≥ 0 的约束 ones, matrix(1.0) # sum(w) = 1 的约束 ) current_weights = np.array(initial_result['x']).flatten() # 2. 迭代修剪流程 epsilon = 0.01 # 自定义最小权重阈值 max_iterations = 5 previous_weights = current_weights.copy() for _ in range(max_iterations): # 筛选出需要保留的资产(权重≥阈值) keep_mask = current_weights >= epsilon if np.all(keep_mask): break # 没有需要修剪的权重了,提前终止 # 构建新的约束:强制被剔除的资产权重为0,同时保持总和为1 eq_constraints_A = [] eq_constraints_b = [] # 总和约束 eq_constraints_A.append(ones.T) eq_constraints_b.append(1.0) # 置零约束:给每个被剔除的资产添加w_i=0的等式约束 for idx in range(n_assets): if not keep_mask[idx]: zero_row = np.zeros(n_assets) zero_row[idx] = 1.0 eq_constraints_A.append(zero_row) eq_constraints_b.append(0.0) # 转换为CVXOPT需要的矩阵格式 eq_A = matrix(np.vstack(eq_constraints_A)) eq_b = matrix(np.array(eq_constraints_b)) # 重新求解优化问题 updated_result = solvers.qp( cov_matrix, matrix(np.zeros(n_assets)), -np.eye(n_assets), zeros, eq_A, eq_b ) current_weights = np.array(updated_result['x']).flatten() # 检查权重是否收敛,避免无意义迭代 if np.max(np.abs(current_weights - previous_weights)) < 1e-6: break previous_weights = current_weights.copy() print("修剪后的最终权重:") print(current_weights)
注意事项
- 阈值
ε的选择要结合你的业务场景:太小可能还是会残留微小权重,太大则可能过度剔除资产,影响优化效果 - 迭代次数不用设太高,3-5次足够,避免陷入循环
二、混合整数规划(精确实现“非零则≥y”的约束)
如果你想严格实现“若x≠0则x≥y”的规则,这本质是个**混合整数非线性规划(MINLP)**问题,但CVXOPT本身只支持凸优化,无法直接处理整数变量。不过你可以做以下变通:
- 引入0-1变量
z_i,其中z_i=1表示第i个资产被选中(权重非零),z_i=0表示被剔除 - 添加约束:
w_i ≥ y * z_i(确保选中的资产权重不低于y)、sum(w)=1、w≥0、z_i∈{0,1}
但要实现这个,你需要搭配支持整数规划的求解器,比如用CVXPY(更易用的凸优化接口)结合GLPK_MI、Gurobi这类MIP求解器。不过如果必须用CVXOPT的话,还是迭代修剪法更直接。
内容的提问来源于stack exchange,提问作者Marco_sbt
相关产品推荐
相关产品推荐

