递归乘法的有效方法

时间:2016-05-25 01:09:04

标签: python numpy

我正在创建N_MC个模拟股票价格路径S,每条路径中的n点,不包括初始点。对于给定路径,这样做的算法是对股票价格的先前值递归的。这就是我现在所拥有的:

import numpy as np
import time

N_MC = 1000
n = 10000

S = np.zeros((N_MC, n+1))
S0 = 1.0
S[:, 0] = S0

start_time_normals = time.clock()
Z = np.exp(np.random.normal(size=(N_MC, n)))
print "generate normals time = ", time.clock() - start_time_normals

start_time_prices = time.clock()
for i in xrange(N_MC):
    for j in xrange(1, n+1):
        S[i, j] = S[i, j-1]*Z[i, j-1]

print "pices time = ", time.clock() - start_time_prices

时代是:

generate normals time =  1.07
pices time =  9.98

是否有更有效的方法来生成数组S,也许使用Numpy的例程?如果正常的随机变量Z也可以更快地生成,那将会很好,但我不是那么有希望。

1 个答案:

答案 0 :(得分:4)

没有必要循环“路径”,因为它们彼此独立。因此,您可以移除外部循环for i in xrange(N_MC),只需对SZ的整列进行操作。

为了加速递归计算,我们只考虑一条单一路径'。假设z是包含每个时间步长的随机值的向量(所有已知的提前)。 s是一个向量,应该包含每个时间步的输出。 s0是零时的初始输出。 j是时候了。

您的代码以递归方式定义输出:

s[j] = s[j-1]*z[j-1]

让我们扩展一下:

s[1] = s[0]*z[0]

s[2] = s[1]*z[1]
     = s[0]*z[0]*z[1]

s[3] = s[2]*z[2]
     = s[0]*z[0]*z[1]*z[2]

s[4] = s[3]*z[3]
     = s[0]*z[0]*z[1]*z[2]*z[3]

每个输出s[j]s[0]乘以从0到j-1的随机值的乘积。您可以使用numpy.cumprod()计算这样的累积产品,这应该比循环更有效:

s = np.concatenate(([s0], s0 * np.cumprod(z[0:-1])))

您可以使用axis参数沿矩阵的一个维度进行操作(例如,在'路径'之间并行执行此操作。)