pythonで学ぶ金融工学(Treeによるオプションプライサー)

前回の記事モンテカルロによるオプション価格の算出を行ったが、その他にツリーで行う方法もある。ツリーとは、ある株価が次の期に上昇または下降すると仮定して、次の期の株価を記録し、それを満期まで繰り返すことによって満期の株価を得た上で、満期の株価に対してオプションバリューを算出し、それを現在の時点まで割り戻す、という方法である。

金融大学のこのページあたりが参考。

これを行うのに必要なのは、オプションの変数に加えて、期間を何期に分割するか(Nとする)ということ。これが決まれば、一度の上昇幅・下降幅も一意に定まる→exp(sigma*sqrt(T/N))となる。

ここで、ルートには精緻な値を使うために新たな関数nrootを設定している。ある方程式f(x)=0の解を求める、ニュートン法を用いて、ルートの近似を行っている。解きたい方程式の接戦を用いて、予め設定した範囲内に誤差が収まるまで試行を繰り返すのだけれども、こちらを利用させていただいた。

ということでコード例は下記。wolframと比較。
(S,K,sigma,T)=(100,100,0.1,1)のコールは、ツール3.98585に対しwolfram3.99
(S,K,sigma,T)=(100,98,0.1,1)のプットは、ツール3.024に対しwolfram3.03
という感じで大体OKか。

当然分割数Nを増やすと値はより近く、安定したものになるが、その分計算時間が増えるのは言うまでもなし。

次回こそグリークスの説明を。。

#European Pricer by Tree: Term is devided by 500. Call:Flag=1, Put:Flag=0
def TreeE(S,K,sigma,T,r,flag):
 import math
 #Defining nroot
 def nroot(a, n, x=1.0, eps=1e-7):
  while abs(a-x**n) > eps:
   x=((n-1)*x+a/(x**(n-1)))/n
	return x
 #Generating Stock Price until T
 stock = []
 for i in range(0,500+1):
  stock.append([])
   for j in range(0,500+1):
	stock[i].append([])
 for i in range(0,500+1):
  for j in range(0,i+1):
   stock[i][j] = S*math.exp(j*sigma*nroot(T/500,2))*math.exp((i-j)*(-1)*sigma*nroot(T/500,2))
 #Payoff Matrix preparation
 payoff = []
 for i in range(0,500+1):
  payoff.append([])
   for j in range(0,500+1):
	payoff[i].append([])
 #payoff at Maturity
 if flag==1:
  for j in range(0,500+1):
   if stock[500][j]>K:
	payoff[500][j]=stock[500][j]-K
   else:
	payoff[500][j]=0
 else:
  for j in range(0,500+1):
   if stock[500][j]<K:
	payoff[500][j]=K-stock[500][j]
   else:
	payoff[500][j]=0
 #Getting back
 u=math.exp(sigma*nroot(T/500,2))
 d=1/u
 p=(math.exp(r*T/500)-d)/(u-d)
 discount=math.exp(-r*T/500)
 for i in range(0,500):
  for j in range(0,500-i):
   payoff[500-1-i][j]=discount*(p*payoff[500-i][j+1]+(1-p)*payoff[500-i][j])
 print payoff[0][0]