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

基于CVXOPT设置最小交易规模,去除微小权重

处理CVXOPT优化中的微小权重问题:设置最小交易规模约束

这是个很常见的资产配置类优化需求啊!我来给你梳理两种可行的方案,都是在CVXOPT框架下能落地的:

一、迭代修剪法(最实用的CVXOPT原生方案)

你提到的“当权重小于阈值时剔除并迭代优化”的思路完全可行,而且不需要引入额外工具,步骤清晰:

核心逻辑

  1. 先跑一轮原始优化(带sum(w)=1、w≥0这类基础约束),得到初始权重结果
  2. 设定一个你能接受的最小权重阈值ε(比如0.01,对应1%的仓位),把所有低于这个阈值的权重直接标记为“需要置零”
  3. 重新构建优化问题,强制这些标记的权重为0,同时保持剩余权重的总和为1,再次求解
  4. 重复上述过程,直到没有新的权重低于阈值,或者达到预设的迭代次数为止

代码示例(以最小方差组合为例)

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本身只支持凸优化,无法直接处理整数变量。不过你可以做以下变通:

  1. 引入0-1变量z_i,其中z_i=1表示第i个资产被选中(权重非零),z_i=0表示被剔除
  2. 添加约束: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:20