我使用 GBM 运行了一些股票模拟。我编写了两个函数,一个使用 for 循环,并且计算成本更高。之后,我又写了另一个,它是矢量化的,因此效率更高。然而,在显示结果后,这些函数似乎显示出一些不同的行为。尽管图看起来非常相似,但它们的平均值不同 - 第一个函数的平均值约为 105,另一个函数的平均值约为 102。我确实这样做不要认为这种差异只是由于随机性造成的(尤其是在运行 1,000 次模拟时)
import numpy as np
import matplotlib.pyplot as plt
import time
np.random.seed(123)
def MC_gbm1(S0, mu, sigma, T, M, n):
start_time2 = time.time()
dt = float(T) / n
paths = np.zeros((n+1,M), np.float64)
paths[0] = S0
for t in range(1, n + 1):
rand = np.random.normal(0,np.sqrt(dt), M)
paths[t] = paths[t-1] * np.exp((mu- 0.5 * sigma ** 2) * dt +
sigma * rand)
comp_time2 = round(time.time() - start_time2,4)
print("Computation time:", comp_time2)
return paths
def MC_gbm2(S0, mu, sigma, T, M, n):
#timesteps = np.linspace(0, T, n+1)[:,None]
dt = T / n
dW = np.random.normal(0, np.sqrt(dt), size=(n, M))
dW_cumsum = np.cumsum(dW, axis=0)
paths = S0 * np.exp((mu - 0.5 * sigma**2) * dt + sigma * dW_cumsum)
result = np.concatenate((np.full((1,M), S0), paths), axis=0)
return result
# Parameters
mu = 0.1
n = 100 # number of steps
T = 1 # time in years
M = 1000 #no of sims
S0 = 100
sigma = 0.3
# GBM Simulation 1
St = MC_gbm1(S0, mu, sigma, T, M, n)
# GBM Simulation 2
St3 = MC_gbm2(S0, mu, sigma, T, M, n)
# Plot the results
sequence = np.linspace(0, T, n+1)
tt = np.full(shape = (M,n+1), fill_value=sequence).T
plt.plot(tt,St)
plt.title("GBM simulation 1")
plt.ylabel("Stock price")
plt.xlabel("Years")
plt.show()
plt.plot(tt,St2)
plt.title("GBM simulation 2")
plt.ylabel("Stock price")
plt.xlabel("Years")
plt.show()
我尝试了多种方式修改功能,但没有真正改变。理想情况下,我希望看到两个非常均值和图(当然考虑到随机性所带来的轻微随机性)
为了理解差异,请注意重置以下两个操作之间的种子会产生完全相同的噪声矩阵:
n = 10
M = 1000
dt = 1 / 10
rands = np.empty((n, M))
# Operation 1
np.random.seed(123)
for i in range(n):
rands[i] = np.random.normal(0, np.sqrt(dt), M)
# Operation 2
np.random.seed(123)
dW = np.random.normal(0, np.sqrt(dt), size=(n, M))
print("Equal matrices?", np.allclose(rands, dW)) # True
所以差异一定来自于每个函数中的操作顺序和数量。事实上,如果你通过这样做关闭每个函数中的随机噪声
paths[t] = paths[t-1] * np.exp((mu- 0.5 * sigma ** 2) * dt + sigma * np.zeros_like(rand))
和
paths = S0 * np.exp((mu - 0.5 * sigma**2) * dt + sigma * np.zeros_like(dW_cumsum))
两个函数产生不同的矩阵:
# GBM Simulation 1
np.random.seed(123)
St = MC_gbm1(S0, mu, sigma, T, M, n)
# GBM Simulation 2
np.random.seed(123)
St2 = MC_gbm2(S0, mu, sigma, T, M, n)
print("Equal matrices?", np.allclose(St, St2)) # False
在这种情况下,差异来自于方法 1 中生成
t
迭代的方式:您使用前一个值来计算下一个值。将相应行更改为
paths[t] = S0 * np.exp((mu- 0.5 * sigma ** 2) * dt + sigma * np.zeros_like(rand))
当噪音关闭时,这两个函数将给出相同的结果。
最后,当您打开噪音时,差异的来源是方法 2 中的额外步骤:
cumsum
破坏了结果。如果你只是这样做
paths = S0 * np.exp((mu - 0.5 * sigma**2) * dt + sigma * dW)
除了已经讨论过的
paths[t] = S0 * np.exp((mu- 0.5 * sigma ** 2) * dt + sigma * rand)
您将得到相同的结果:
# GBM Simulation 1
np.random.seed(123)
St = MC_gbm1(S0, mu, sigma, T, M, n)
# GBM Simulation 2
np.random.seed(123)
St2 = MC_gbm2(S0, mu, sigma, T, M, n)
print("Equal matrices?", np.allclose(St, St2)) # True