程式

Python中的幾何布朗運動模擬:奇怪的結果

  • December 17, 2020

我正在嘗試在 Python 中模擬幾何布朗運動,但是我得到的結果看起來很奇怪,在我看來它們不可能是正確的。我的目標是模擬 1 年的每一天。基本上,我使用了兩種略有不同的方法。根據我的研究,應該可以使用每日漂移和波動率,dt = 1或者年化漂移和波動率並使用dt = 1/365. 對於第一種方法,我根據每日曆史數據計算了每日漂移和波動率,並在第二種方法中對其進行了年度化。因此也隨之T改變。以下是我從這個答案(Python 中的幾何布朗運動模擬)中部分獲得的 Python 程式碼:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(1000)

quandl.ApiConfig.api_key = "XXXXXX"


def gen_paths(S0, r, sigma, T, M, I):
   dt = float(T) / M
   paths = np.zeros((M + 1, I), np.float64)
   paths[0] = S0
   for t in range(1, M + 1):
       rand = np.random.standard_normal(I)
       paths[t] = paths[t - 1] * np.exp((r - 0.5 * sigma ** 2) * dt + sigma * np.sqrt(dt) * rand)
   return paths


# Get data
df = quandl.get(...)
value = df['Value']

# Compute returns
returns = value.pct_change(1)


# Daily drift and volatility
S0 = value[-1]              # initial stock price
r = np.mean(returns)        # drift
sigma = np.std(returns)     # volatility
T = 365                     # time
M = 365                     # number of steps
I = 100000                  # number of simulations

paths_1 = gen_paths(S0, r, sigma, T, M, I)
print("Average: " + str(np.average(paths_1[-1])))


# Yearly drift and volatility
r = np.mean(returns) * 365
sigma = np.std(returns) * np.sqrt(365)
T = 1.0

paths_2 = gen_paths(S0, r, sigma, T, M, I)
print("Average: " + str(np.average(paths_2[-1])))

# Visualize 5 simulated paths for each
fig, axs = plt.subplots(2)
axs[0].plot(paths_1[:, :5])
axs[1].plot(paths_2[:, :5])
plt.show() 

這是我得到的結果:

在此處輸入圖像描述

對於我得到117183的具有每日漂移和波動率76145的方法以及具有年度漂移和波動率的方法的平均值。以下是我的問題:

  1. 這些結果是否正確或我的程式碼有什麼問題?
  2. 兩種方法的平均值不應該非常相似嗎?
  3. 哪種方法有利於使用?

好問題!

摘要:您的程式碼和數學是正確的,但是您使用了太高的音量和漂移,以至於無法真實世界。由於高音量和對數正態性,您的模擬衰減為零。


基本上,我使用了兩種略有不同的方法。根據我的研究,應該可以使用 dt = 1 的每日漂移和波動率,或者將漂移和波動率年化並使用 dt = 1/365

使用年數量的解決方案 $ {t, \sigma, r} $ 是 $$ \begin{align} S(t+\Delta t) = S(t) \exp \left((r-\tfrac{1}{2}\sigma^2)\Delta t + \sigma\sqrt{\Delta t}\cdot Z \right). \end{align} $$

創建新的每日數量 $ {d, s, \nu} $ 通過替換 $ \Delta t := d/365 $ , $ ; \sigma := s \sqrt{365} $ , $ ; r:= \nu \cdot 365 $ ,我們得到 $$ \begin{align} S(d+\Delta d) = S(d) \exp \left((\nu-\tfrac{1}{2}s^2)\Delta d + s\sqrt{\Delta d}\cdot Z \right). \end{align} $$

因此,無論您使用年度參數還是每日參數,“公式”看起來都是一樣的。


  1. 這些結果是否正確或我的程式碼有什麼問題?

您的程式碼和結果是正確的。問題是你的參數是巨大的。您假設的每日值應該是年度值。因此,您假設每年的內容是巨大的。每日費率應該是 $ \nu=\tfrac{0.04}{365} $ ; 卷應該是 $ s=\tfrac{0.4}{\sqrt{365}}. $ 然後是年度版本 $ \sigma=0.4 $ 和 $ r=0.04 $ .

儘管可以預料,但令​​人困惑的是,您的所有模擬都向零衰減。這是因為您的 GBM 是對數正態分佈,並且當您的變異數接近無窮大(您的 vol 很大)時,幾乎所有的終端密度都為零。終值很大的機率很小,但是這個機率很小,所以我們看不到這個。您可以通過繪製具有較大變異數的 PDF 和 CDF 來看到這一點。


  1. 兩種方法的平均值不應該非常相似嗎?

您對兩個模擬使用不同的隨機數。*通過刪除頂部的np.random.seed(1000)*來強制隨機數相同,並在每次呼叫函式之前添加一次,如下所示

...
np.random.seed(1000)
paths_1 = gen_paths(S0, r, sigma, T, M, I)
...
np.random.seed(1000)
paths_2 = gen_paths(S0, r, sigma, T, M, I)

這將確保它們使用相同的隨機性,並且您將看到您的兩個圖是相同的。


哪種方法有利於使用?

每年(幾乎)總是,除非您從事日內建模和真正的高解析度工作,並避免出現下溢的數值問題。我從未真正見過有人使用除年度以外的任何東西來進行標準 GBM 建模和定價。


引用自:https://quant.stackexchange.com/questions/60005