モンテカルロシミュレーションを通じてヨーロピアンコールオプションの価格を設定するために、Pythonで幾何ブラウン運動をシミュレートしようとしています。私はPythonに比較的慣れていませんが、BSの価格に収斂するどころではなく、何らかの理由で反復がマイナスの傾向にあるように見えるため、間違っていると思われる回答を受け取っています。どんな助けでもいただければ幸いです。
import numpy as np
from matplotlib import pyplot as plt
S0 = 100 #initial stock price
K = 100 #strike price
r = 0.05 #risk-free interest rate
sigma = 0.50 #volatility in market
T = 1 #time in years
N = 100 #number of steps within each simulation
deltat = T/N #time step
i = 1000 #number of simulations
discount_factor = np.exp(-r*T) #discount factor
S = np.zeros([i,N])
t = range(0,N,1)
for y in range(0,i-1):
S[y,0]=S0
for x in range(0,N-1):
S[y,x+1] = S[y,x]*(np.exp((r-(sigma**2)/2)*deltat + sigma*deltat*np.random.normal(0,1)))
plt.plot(t,S[y])
plt.title('Simulations %d Steps %d Sigma %.2f r %.2f S0 %.2f' % (i, N, sigma, r, S0))
plt.xlabel('Steps')
plt.ylabel('Stock Price')
plt.show()
C = np.zeros((i-1,1), dtype=np.float16)
for y in range(0,i-1):
C[y]=np.maximum(S[y,N-1]-K,0)
CallPayoffAverage = np.average(C)
CallPayoff = discount_factor*CallPayoffAverage
print(CallPayoff)
モンテカルロシミュレーションの例(株価シミュレーション)
私は現在Python 3.6.1を使用しています。
よろしくお願いします。
S
の表記をより直感的にし、答えが妥当かどうかを調べることができるように、コードを少し書き直します。
最初のポイント:
deltat
をnp.sqrt(deltat)
に置き換える必要があります。出典 ここ (はい、それが最も公式ではないことは知っていますが、以下の結果は心強いはずです)。まず、Yves HilpischのGBMパス生成関数です-Python for Finance、 第11章 。パラメータはリンクで説明されていますが、セットアップはあなたのものと非常に似ています。
_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
_
初期値の設定(ただし、時間増分の数として_N=252
_、1年間の取引日数を使用):
_S0 = 100.
K = 100.
r = 0.05
sigma = 0.50
T = 1
N = 252
deltat = T / N
i = 1000
discount_factor = np.exp(-r * T)
_
次に、パスを生成します。
_np.random.seed(123)
paths = gen_paths(S0, r, sigma, T, N, i)
_
次に、検査します。_paths[-1]
_は、有効期限が切れたときに、終了St
値を取得します。
_np.average(paths[-1])
Out[44]: 104.47389541107971
_
あなたが今持っているように、見返りは(_St - K, 0
_)の最大になります:
_CallPayoffAverage = np.average(np.maximum(0, paths[-1] - K))
CallPayoff = discount_factor * CallPayoffAverage
print(CallPayoff)
20.9973601515
_
これらのパスをプロットすると(pd.DataFrame(paths).plot()
を使用するのは簡単ですが、それらはもはや下降傾向ではありませんが、St
sはほぼ対数正規分布していることがわかります。
最後に、BSMによるサニティチェックを次に示します。
_class Option(object):
"""Compute European option value, greeks, and implied volatility.
Parameters
==========
S0 : int or float
initial asset value
K : int or float
strike
T : int or float
time to expiration as a fraction of one year
r : int or float
continuously compounded risk free rate, annualized
sigma : int or float
continuously compounded standard deviation of returns
kind : str, {'call', 'put'}, default 'call'
type of option
Resources
=========
http://www.thomasho.com/mainpages/?download=&act=model&file=256
"""
def __init__(self, S0, K, T, r, sigma, kind='call'):
if kind.istitle():
kind = kind.lower()
if kind not in ['call', 'put']:
raise ValueError('Option type must be \'call\' or \'put\'')
self.kind = kind
self.S0 = S0
self.K = K
self.T = T
self.r = r
self.sigma = sigma
self.d1 = ((np.log(self.S0 / self.K)
+ (self.r + 0.5 * self.sigma ** 2) * self.T)
/ (self.sigma * np.sqrt(self.T)))
self.d2 = ((np.log(self.S0 / self.K)
+ (self.r - 0.5 * self.sigma ** 2) * self.T)
/ (self.sigma * np.sqrt(self.T)))
# Several greeks use negated terms dependent on option type
# For example, delta of call is N(d1) and delta put is N(d1) - 1
self.sub = {'call' : [0, 1, -1], 'put' : [-1, -1, 1]}
def value(self):
"""Compute option value."""
return (self.sub[self.kind][1] * self.S0
* norm.cdf(self.sub[self.kind][1] * self.d1, 0.0, 1.0)
+ self.sub[self.kind][2] * self.K * np.exp(-self.r * self.T)
* norm.cdf(self.sub[self.kind][1] * self.d2, 0.0, 1.0))
option.value()
Out[58]: 21.792604212866848
_
GBMセットアップでi
に高い値を使用すると、収束が近くなります。