提问人:Pavel 提问时间:11/11/2023 最后编辑:Pavel 更新时间:11/12/2023 访问量:49
为什么用于毛坯模拟的几何布朗运动 (GBM) 函数会产生不同的结果?
Why do my Geometric Brownian Motion (GBM) functions for stock simulation produce different results?
问:
我使用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()
我尝试以多种方式修改功能,但没有任何真正改变。理想情况下,我希望看到两种非常手段和图(当然考虑到随机性给出的轻微随机性)
答:
1赞
JustLearning
11/12/2023
#1
为了理解其中的区别,请注意,在以下两个操作之间重置种子会导致完全相同的噪声矩阵:
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
评论
0赞
Pavel
11/12/2023
谢谢你的回答。我刚刚替换了您建议的两行代码。即使它正在工作并且我得到了相同的矩阵,我认为这在 GBM 理论上是不正确的。在绘制结果后,我得到了非常奇怪的绘图,看起来像白噪声。我的理解是,在第一个函数中,需要依赖于 t-1,因为股票路径必须不断前进。同样,出于同样的原因,第二个函数具有 cumsum。但也许应该有cumprod。
0赞
JustLearning
11/12/2023
该问题试图理解为什么这些函数会给出不同的结果。这就是我提供的。虽然我理解你对这个理论的担忧,但我的建议是将这个问题标记为已解决,并提出一个关于如何使用矢量化操作实现你想要的东西的新问题。
评论