Python - 生成一个包含 40 个随机数的列表,总和为 1,具有最小和最大权重

Python - Generate a list of 40 random numbers summing to 1, with min and max weight

我有一个包含 40 只股票的投资组合,我试图计算整个投资组合的标准差,同时每次计算这个标准差时都会更改每只股票的权重。我知道如何创建总和为 1 的随机数列表,但如何添加每只股票的最大和最小权重..

我使用的最大值是 4.5%,最小值是 0.5%。

我用来创建总和为 1 的随机数列表的代码是:

import numpy as np, numpy.random

random = np.random.dirichlet(np.ones(10), size=1)

但是我怎样才能使这个列表只包含 0.005 到 0.045 之间的值呢?

考虑使用以下内容:

import numpy as np
first_half = np.random.random(size=20)*0.04+0.005
second_half = 0.05-first_half

这是正确的范围,均匀分布,全部随机,但是,第二部分与第一部分(反)相关。您可以合并两半:

tot40elems = np.concatenate((first_half,second_half))

也许使用 np.random.normal 会得到更好的结果。您可以使用 80% 的可变比例(高于 0.005)将分布缩小到 0.005-0.045 范围。因为正态分布仍然可能有异常值,所以如果值超出范围,则有必要“重试”计算(但这不应该发生得太频繁,除非你给出一个大的标准偏差):

将 numpy 导入为 np

def randStock(count=40,minR=0.005,maxR=0.045,sd=3):
    iterations = 0
    while True:
        iterations += 1
        r = np.random.normal(1,sd,count) #normal distribution
        r -= min(r) # offset to zero
        r /= max(r) # scale to 0..1
        r = minR + r/sum(r)*(maxR-minR)/(maxR+minR) # scale to range
        if min(r)>=minR and max(r)<=maxR: return r, iterations

输出:

for _ in range(10):
    s,i = randStock()
    print(*map("{:6.4f}".format,(sum(s),min(s),max(s))),i,"iterations")

[sum]  [min]  [max]  [mean] 
1.0000 0.0050 0.0404 0.0250 1 iterations
1.0000 0.0050 0.0409 0.0250 2 iterations
1.0000 0.0050 0.0395 0.0250 1 iterations
1.0000 0.0050 0.0411 0.0250 4 iterations
1.0000 0.0050 0.0410 0.0250 2 iterations
1.0000 0.0050 0.0428 0.0250 1 iterations
1.0000 0.0050 0.0433 0.0250 1 iterations
1.0000 0.0050 0.0424 0.0250 1 iterations
1.0000 0.0050 0.0371 0.0250 1 iterations
1.0000 0.0050 0.0446 0.0250 1 iterations

请注意,这可以改进以随机化下限更多一点,您可以选择不同的标准偏差