在 python 中生成价格情景

generate price scenarios in python

我有一个变量列表 price 更改:

price = 1000
changes = [0, -0.5, +0.5, -1, 1]
# change means new_price = old_price * (1 + change)

我需要一个列表,显示 price 将如何因多次连续更改而发生变化;例如,这是 2 次连续更改的样子:

[1000, 1000, 1000]
[1000, 1000, 500]
[1000, 1000, 1500]
[1000, 1000, 0]
[1000, 1000, 2000]

[1000, 500, 500]
[1000, 500, 250]
[1000, 500, 750]
[1000, 500, 0]
[1000, 500, 1000]

[1000, 1500, 1500]
[1000, 1500, 750]
[1000, 1500, 2250]
[1000, 1500, 0]
[1000, 1500, 3000]

[1000, 0, 0]
[1000, 0, 0]
[1000, 0, 0]
[1000, 0, 0]
[1000, 0, 0]

[1000, 2000, 2000]
[1000, 2000, 1000]
[1000, 2000, 3000]
[1000, 2000, 0]
[1000, 2000, 4000]

允许使用numpy库。

看起来很复杂,但矩阵很容易解决。为了解决问题,有几个关键要理解。

让我们采用以下矩阵:

[1000, 1000, 1000] <- list_of_changes
[1000, 1000, 500]  <- list_of_changes
[1000, 1000, 1500] <- list_of_changes
[1000, 1000, 0]    <- list_of_changes
[1000, 1000, 2000] <- list_of_changes

每个更改列表可以分为 3 个部分:index0index1rest_of_indexes

  1. 最终矩阵总是有 3 个轴
  2. index0 永远等于 price
  3. index1 将始终是 price 的变化 axis0changes
  4. 的索引
  5. rest_of_indexes可以像下面的例子一样计算buy迭代过程

change_mat[0, :, 2] =

[1000]   [0]
[1000]   [-0.5]
[1000] * [+0.5]
[1000]   [-1]
[1000]   [1]

change_mat[1, :, 2] =

[500]   [0]
[500]   [-0.5]
[500] * [+0.5]
[500]   [-1]
[500]   [1]

这应该可以解决问题:

import numpy as np


price = 1000
changes = np.array([0, -0.5, 0.5, -1, 1])

combinations = 2

change_mat = np.zeros((len(changes), len(changes), combinations + 1))

change_mat[:, :, 0] = price

for axis0 in range(len(changes)):
    change_mat[axis0, :, 1] = change_mat[axis0, :, 0] * (1 + changes[axis0])

for combination in range(combinations-1):
    change_mat[:, :, combination+2] = change_mat[:, :, combination+1] * (1 + changes)

重复广播计算,然后互相广播结果,最后移动坐标轴:

>>> changes = np.array([0, -0.5, +0.5, -1, 1])
>>> price = np.array(1000)
>>> prices = [price]
>>> times = 2
>>> for _ in range(times):
...     prices.append(prices[-1][..., None] * (changes + 1))
...
>>> shape = prices[-1].shape
>>> ar = np.array([np.broadcast_to(a[(...,) + (None,) * (times - i)], shape) for i, a in enumerate(prices)])
>>> np.moveaxis(ar, 0, -1)
array([[[1000., 1000., 1000.],
        [1000., 1000.,  500.],
        [1000., 1000., 1500.],
        [1000., 1000.,    0.],
        [1000., 1000., 2000.]],

       [[1000.,  500.,  500.],
        [1000.,  500.,  250.],
        [1000.,  500.,  750.],
        [1000.,  500.,    0.],
        [1000.,  500., 1000.]],

       [[1000., 1500., 1500.],
        [1000., 1500.,  750.],
        [1000., 1500., 2250.],
        [1000., 1500.,    0.],
        [1000., 1500., 3000.]],

       [[1000.,    0.,    0.],
        [1000.,    0.,    0.],
        [1000.,    0.,    0.],
        [1000.,    0.,    0.],
        [1000.,    0.,    0.]],

       [[1000., 2000., 2000.],
        [1000., 2000., 1000.],
        [1000., 2000., 3000.],
        [1000., 2000.,    0.],
        [1000., 2000., 4000.]]])