python - 投资组合优化的蒙特卡罗方法

标签 python numpy random montecarlo

我正在尝试根据以下条件创建 n 列长度为 x 的向量:

i) 每个向量(例如,x[i])的第 i 个分量都有一个最小值和一个最大值。最小值和最大值以百分比表示。

ii) 每列之和为1。

iii) 我想确保对整个空间进行均匀采样。

我编写了以下名为“gen_port”的例程,它采用两个向量,其中包含向量的下限和上限,以及要生成的随机向量的数量(例如,N)。

def gen_port (lower_bound, upper_bound, number):
    import random
    # Given vector description of minimum and maximum, return an array of 'number' vectors,  each of which sums to 100%
    # We generate RVs, scale them by upper and lower bounds, then normalize. 
    values = np.random.random((len(lower_bound),number))   # create big array of RVs. 
    for n in range (0,number):
        for i in range (0, len(lower_bound)):
            values[i,n] = np.float(lower_bound[i]+ values[i,n]*(upper_bound[i]-lower_bound[i]))  # scale
    return values

因此,例如,如果我要生成由以下向量描述的 10 列向量:

lower_bound = [0.0,0.0,0.0,0.0]
upper_bound = [0.50,0.50,0.50,0.50] 
gen_ports(lower_bound, upper_bound, 10)

[Out]
array([[ 0.15749895,  0.21279324,  0.35603417,  0.27367365],
   [ 0.2970716 ,  0.48189552,  0.04709743,  0.17393545],
   [ 0.20367186,  0.47925996,  0.21349772,  0.10357047],
   [ 0.29129967,  0.15936119,  0.26925573,  0.28008341],
   [ 0.11058273,  0.2699138 ,  0.39068379,  0.22881968],
   [ 0.21286622,  0.39058314,  0.33895212,  0.05759852],
   [ 0.18726399,  0.37648587,  0.32808714,  0.108163  ],
   [ 0.03839954,  0.24170767,  0.40299362,  0.31689917],
   [ 0.35782691,  0.31928643,  0.24712695,  0.0757597 ],
   [ 0.25595576,  0.08776559,  0.16836131,  0.48791733]])

但是,如果 lower_bound 和 upper_bound 的值不同,我希望能够填充向量。

例如,如果

[In]:
lower_bound = [0.0,0.25,0.25,0.0]
upper_bound = [0.50,0.50,0.75,1.0] 
gen_ports(lower_bound, upper_bound, 100000)

结果总和不为 1(以下仅包含 10 个样本):

[Out]:
array([[ 0.16010701,  0.31426425,  0.38776233,  0.1378664 ],
   [ 0.00360632,  0.37343983,  0.57538205,  0.0475718 ],
   [ 0.28273906,  0.2228893 ,  0.1998151 ,  0.29455654],
   [ 0.06602521,  0.21386937,  0.49896407,  0.22114134],
   [ 0.17785613,  0.33885919,  0.25276605,  0.23051864],
   [ 0.07223014,  0.19988808,  0.16398971,  0.56389207],
   [ 0.14320281,  0.14400242,  0.18276333,  0.53003144],
   [ 0.04962725,  0.2578919 ,  0.19029586,  0.50218499],
   [ 0.01619681,  0.21040566,  0.30615235,  0.46724517],
   [ 0.10905285,  0.23641745,  0.40660215,  0.24792755]])

我想生成 100,000 个场景,以便对下限和上限定义的空间进行均匀采样。但我很难过,因为当前函数在将向量 转换为下限和上限后对其进行归一化。

那么,我有一个明显的第一个问题 - 如何在大多数情况下修改例程?

此外:

i) 这种方法是否正确?例如,我在这个实现中引入了任何偏见吗?

ii) 是否有更快和/或更“pythonic”的方式来做到这一点? n = 1,000,000 和 x = 35 大约需要 15 分钟

最佳答案

如果您不需要允许任何下限/上限(或者,如果下限始终为 0 而上限始终为 1),那么答案就是众所周知的 Dirichlet 分布

https://en.wikipedia.org/wiki/Dirichlet_distribution

链接中有示例 python 代码。对于最简单的\vec{a}=1 的情况,也有非常简单的方法对 Dirichlet 进行采样,如果你需要它,我会挖掘出来。但是界限会带来额外的问题......

更新

我相信你可以使用拒绝,从 Dirichlet 采样并拒绝任何不适合区间的东西,但我猜效率会很低

更新二

在所有 \alpha 都等于 1 的情况下找到了与 Python Dirichlet 采样的链接

Generating N uniform random numbers that sum to M

关于python - 投资组合优化的蒙特卡罗方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33765809/

相关文章:

c - 难以理解 void 数组并在函数调用中使用它们

python - prime_factorize(1) -> ? (Python 错误信号)

python - 如何在 PyQt 的动态 UI 中覆盖小部件的事件(dropEvent)?

python - 计算两个 3D 数组之间的元素级欧氏距离

python - 如何使用 python numpy.savetxt 将字符串和 float 写入 ASCII 文件?

python - 使用 OpenCV 和 Python 获取图像中颜色的百分比

MATLAB:生成相同的随机数序列

sql-server - 从 SQL Server 表中获取随机行数

Python的 `email.message.as_string`将某些部分编码为base64;不清楚为什么

python - 如果传入选项,则将值设置为 argparse 中的变量