股票

使用基於“正常”或連續複利的 mu 和 signa 的幾何布朗運動模擬股票價格?

  • June 25, 2020

我編寫了一個簡單的腳本,用於使用幾何布朗運動對股票價格進行建模。我下載的時間序列是每日調整後的收盤價。我的目標是能夠改變預測期和所有其他變數。

但是,我試圖了解使用線性或標準方法與使用對方法計算 mu(平均回報)和 sigma(變異數)之間的價格預測差異。對數方法始終會產生更高的預測股票價格。我的程式碼如下。

我搜尋了網際網路並閱讀了我能找到的任何內容。這個論壇上也有幾篇有用的文章,例如這里這裡。但沒有什麼能真正涵蓋我的問題。

我的問題是,哪種方法最合適?

(我正在使用 Python 3。)

from math import log, e
import matplotlib.pyplot as plt
from pandas_datareader import data
from datetime import date, timedelta
import datetime

stock = 'AAPL' # Enter the name of the stock
start = '2015/1/1'
apple = data.DataReader(stock, 'yahoo', start)

# This is the 'normal' way of calculating mu and sigma
close = apple[:]['Adj Close']
mu = (close[-1]/close[1])** (252.0/len(close)) - 1
sigma = (close/close.shift(1)-1)[1:].std()*np.sqrt(252)

# This is the 'log' way of calculating mu and sigma
apple['log_price'] = np.log(apple['Adj Close'])
apple['log_return'] = apple['log_price'].diff()
mu = apple.log_return.sum() -1
sigma = np.std(apple.log_price)

s0 = close[-1]
T = 18/12
delta_t = 0.001
num_reps = 1000
steps = T/delta_t
plt.figure(figsize=(15,10))
closing_prices = []
for j in range(num_reps):
   price_path = [s0]
   st = s0
   for i in range(int(steps)):
       drift = (mu - 0.5 * sigma**2) * delta_t
       diffusion = sigma * np.sqrt(delta_t) * np.random.normal(0, 1)
       st = st*e**(drift + diffusion)
       price_path.append(st)
       closing_prices.append(price_path[-1])
   plt.plot(price_path)
plt.ylabel('stock price',fontsize=15)
plt.xlabel('steps',fontsize=15)
plt.axhline(y = s0, color = 'r', linestyle = '-') # print latest price TW
plt.show()

mean_end_price = round(np.mean(closing_prices),2)
print("Expected price in 12 months: $", str(mean_end_price))

您的程式碼中的漂移是:

drift = (mu - 0.5 * sigma**2) * delta_t

所以我假設你正在使用幾何布朗運動來模擬你的股票價格,而不僅僅是簡單的布朗運動。因此,您的模型是對數正態,而不是正態。另外,我假設您下載的時間序列是每日收盤價。

GBM模型的解法如下(下 $ \delta t:=(t_i)-(t_{i-1}) $ & $ Z\sim~N(0,1) $ ):

$$ ln(S_{t_i}) - ln(S_{t_{i-1}}) = (\mu - 0.5\sigma^2)\delta t+\sigma\sqrt{\delta t}Z $$

請注意,上面的日誌返回是正常分佈的:

$$ ln(S_{t_i}) - ln(S_{t_{i-1}}) \sim N\left(\tilde{\mu} := (\mu - 0.5\sigma^2)\delta t;\tilde{\sigma}:=\sqrt{\delta t}\sigma\right) $$

如果我們使用每日時間序列,那麼 $ \delta t = \frac{1}{260} $ .

如果您想根據歷史每日數據校准上述模型,您的任務是校準 $ \tilde{\mu} $ 和 $ \tilde{\sigma} $ :

$$ (i): \tilde{\mu}=\frac{1}{n}\sum_{i=1}^{n} ln\left( \frac{S_{t_i}}{S_{t_{i-1}}}\right) $$

$$ (ii): \tilde{\sigma}^2 = \frac{1}{n-1} \sum_{i=1}^{n} \left( \left[ ln\left( \frac{S_{t_i}}{S_{t_{i-1}}}\right) - \tilde{\mu} \right]^2\right) $$

請注意,在上面的 (i) 中,您計算了 $ \tilde{\mu} $ 並不是 $ \mu $ . 在您的模擬中,您需要 $ \mu $ ,所以首先執行以下操作:

$$ \sigma = \tilde{\sigma}\frac{1}{\sqrt{\delta t}}=\tilde{\sigma}\sqrt{260} $$

$$ \mu = \frac{1}{\delta t}\tilde{\mu}+0.5{\sigma}^2=260\tilde{\mu}+0.5{\sigma}^2 $$

那就是 $ \mu $ 你應該在你的模擬中使用。

下一點是:為什麼您的程式碼中有以下行?

mu = apple.log_return.sum() -1

為什麼要減去 1?如果你的日誌返回是每天的,得到 $ \mu $ ,您的程式碼應為:

mu = apple.log_return.sum()/apple.log_return.count()
mu = mu*260 + 0.5*apple.log_return.var()*sqrt(260)

要獲得 $ \mu $ 符合我上面描述的公式。

如果您使用 GBM 來模擬您的股票價格,那麼您不應該使用正常收益來校準您的模型:所以您所謂的“正常”方式是校準模型的錯誤方式。

ps:如果你有每天的時間序列,如果你想以每天的粒度進行模擬,你可以選擇一天作為你的時間單位。這將使您的任務變得更加容易,因為您可以使用 $ \tilde{\sigma} $ 和 $ \tilde{\mu} $ 直接,而不是必須年化它們:即將它們轉換成 $ \sigma $ 和 $ \mu $ .

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