下面是一些代碼重新寫一個可能的使S
的符號更直觀,並允許您檢查您的答案的合理性。
初始點:
- 在你的代碼,第二
deltat
應由np.sqrt(deltat)
取代。來源here(是的,我知道這不是最官方的,但下面的結果應該是令人放心的)。
- 關於將您的短期利率和西格瑪價值未年化的評論可能不正確。這與你所看到的向下漂移無關。你需要保持這些年率。這些將始終是複合(恆定)費率。
首先,這裏是一個GBM路徑從伊夫Hilpisch生成功能 - Python的財務,chapter 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
更高的值應該引起更接近收斂。
乾杯,謝謝你的深入迴應。我已經upvoted你:) – tgood