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

基于Dirichlet分布的带权重边界的随机投资组合模拟问题求助

随机投资组合模拟约束问题的原因与解决方案

问题原因

你的代码生成的new_weights为空,核心原因是约束条件的可行域极小,随机抽样几乎不可能命中:

  • 38个资产要求每个权重在[0.02, 0.04]之间,同时总和必须为1。计算可得:
    • 所有资产的最小总权重:38 * 0.02 = 0.76
    • 所有资产的最大总权重:38 * 0.04 = 1.52
  • 虽然1落在这个区间内,但要让38个权重同时卡在[0.02, 0.04]且总和为1,相当于要把剩余的0.24(1 - 0.76)精准分配到38个资产,每个最多加0.02。这种情况的概率极低,百万级别的随机样本完全抽不到符合条件的组合。

可行解决方案

不要用「随机抽样后筛选」的方式,直接生成满足约束的权重,步骤如下:

  1. 先给每个资产分配最小权重0.02,此时总权重为0.76,剩余可分配额度为0.24;
  2. 生成38个非负数,满足「总和为0.24」且「每个数≤0.02」(因为单个资产权重上限是0.04,0.04-0.02=0.02);
  3. 将生成的额外额度加到每个资产的最小权重上,得到最终符合约束的权重。

实现代码

import numpy as np

n, width = 1000000, 38
min_weight = 0.02
max_weight = 0.04
remaining = 1 - width * min_weight  # 剩余可分配额度:0.24
max_add = max_weight - min_weight   # 单个资产最多可追加的额度:0.02

np.random.seed(5)
# 先生成Dirichlet分布样本(天然满足总和为1),缩放后得到初始额外分配额度
dirichlet_samples = np.random.dirichlet(np.ones(width), size=n)
extra = dirichlet_samples * remaining

# 迭代调整,确保所有额外额度不超过max_add,同时总和保持为remaining
while np.any(extra > max_add):
    # 计算每个样本中超过上限的部分
    excess = extra - max_add
    excess[excess < 0] = 0
    total_excess = excess.sum(axis=1, keepdims=True)
    
    # 找到未达上限的资产,计算可分配比例
    mask = extra < max_add
    available = max_add - extra
    available[~mask] = 0
    available_ratio = available / available.sum(axis=1, keepdims=True)
    
    # 把超额部分重新分配给未达上限的资产
    extra[mask] += total_excess * available_ratio[mask]
    # 超过上限的部分直接设为max_add
    extra[extra > max_add] = max_add

# 最终生成符合约束的权重
new_weights = min_weight + extra

# 验证约束是否满足
assert np.all(new_weights >= min_weight)
assert np.all(new_weights <= max_weight)
assert np.allclose(new_weights.sum(axis=1), 1, atol=1e-6)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:15:38