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

モンテカルロ法によるオプション価格の算出。オプションの詳しい内容については専門書に譲るが、ざっくりとした解説。

オプションとは、将来のある時点に、ある金融商品を、あらかじめ決められた価格で、購入または売却する権利。ここで、「日経平均株価のオプション」を例にとって説明する。今日の日経平均終値は大体9000円。これを、1年後に購入する状況を考える。1年後は1万円かもしれないし8000円かもしれない。そこで、9500円以上だったら買う、それ以下だったら買わないとしたい。このような場合にオプションを用いる。例えば10000円になっていたら500円もらえるし、9000円になっていたら、「権利」なのでそのまま権利を放棄すればよい。この場合0円。

これを一般化して、日経平均の値を「原資産」、9500円と決めた値を「行使価格、またはストライク」という。原資産をS、行使価格をKで表すと、ペイオフはmax(S-K,0)となる。もう少し丁寧に、現在の原資産価格をS(t)、満期の原資産価格をS(T)とする。(tが現在、Tが満期)

これらを用いてプライシングを行う。そのために必要となるのは、S(T)とKの値。Kは今決められるが、S(T)は今すぐはわからない。そこで、ボラティリティという概念を導入する。ボラティリティは日本語だと「分散」で株価の変動具合・ばらつき具合を表す。ボラティリティを導入することにより、S(t)とボラティリティを用いてS(T)を表現する。ボラティリティに、正規乱数(正規分布に従う乱数)を掛け合わせることで、不確実性を表す。これらを用いるとS(T)=S(t)*exp(-0.5σ^2*(T-t)+ランダム項*σ*sqrt(T-t))として表素ことができる。

ということで、ここまででS(T)とKがわかる。このS(T)を出すために、ボラティリティと正規乱数が必要だとわかる。つまり、
・S(t):初期の株価
・K:ストライク
ボラティリティ:変動具合
・正規乱数
を与えてやれば良い。

初期株価、ストライク、ボラティリティは現在マーケットで見えている値及び契約条件から決まる。正規乱数は、pythonではnormalvariate(0,1)で表せる。が、一様乱数(ある範囲に同確率で散らばった乱数)から正規乱数を作り出すアルゴリズムもいろいろある。その前に一様乱数をうまく発生させる方法、そうでない方法もある(メルセンヌツイスターetc)。でもめんどいのでとりあえずnormalvariateを使うと、満期の株価は下記のように表せる。

S(T)=S(t)*exp(-0.5*σ^2*(T-t)+normalvariate(0,1)*σ*sqrt(T-t)

で、モンテカルロ法というのはこのnormalvariateという不確実性な部分を何度も繰り返すことによって期待値に相当するものを算出するという方法なので、コールオプションだったら、これがKを上回ったらS(T)-Kを足し合わせ、下回ったら0を足し合わせ、最終的にpath数で割ればよい。

ということで実際のプログラム例は下記。

#flag=1ならコール
def MCE(S,K,sigma,T,flag):
 import random
 import math
 d=[]
 kabuka=[]
 sum=0
 #正規乱数を記憶
 for i in range(0,10001):
  d.append(random.normalvariate(0,1))
 #正規乱数をベースに、満期の株価を記憶
 for i in range(0,10001):
  kabuka.append(math.exp(-0.5*sigma**2*T+d[i]*sigma*math.sqrt(T))*S)
 #コールオプションなら、S(T)-Kなら足し、プットならK-S(T)の時足し合わせていく
 if flag==1:
  for i in range(0,10001):
   if kabuka[i] > K:
    sum = sum + kabuka[i] - K
 else:
  for i in range(0,10001):
   if kabuka[i]<K:
    sum = sum + K - kabuka[i]
 #path数で割ることでオプション価格とする
 print sum/10000

ということでオプション価格を算出できる。
例えば、S=100,K=95,sigma=0.1,T=1のコールオプションについて、このプログラムだと6.83、Wolframだと6.89。大体よさそうな感じか。

今日はこれまで。。次回は上記を利用してグリークスを算出する。(コードミス、ベターな方法あったらご指摘ください)