VBAでブラックショールズ #2

oryzaeです。
前回、VBAでオプションの価格を求める関数を書いてみました。
今回はその関数を使って、インプライドボラティリティを求める関数を作っていきます。
今回の操作は、オプションの仕組みという問題ではなく、色々なボラティリティを当て嵌めながら、現在のオプション価格と等しくなるようなボラティリティを見つけ出して、それをインプライドボラティリティとして返すだけというかなりシンプルなものになります。

前回のオプション価格を求める関数では下記の7つの引数を使ってオプション価格を求めました。
1. 原資産価格(日経平均の現在価格)
2. 行使価格
3. インプライドボラティリティ
4. 無リスク金利(ここもいずれ議論する必要がありそうですね)
5. 配当利回り(これもいずれ議論させて頂きます)
6. 残存年数
7. プット・コールの別

インプライドボラティリティを求める場合には、既知のオプション価格を満たすような上記の#3を求めるだけです(上記引数の#3インプライドボラティリティ以外は固定します)。
次の回で改めて関数は作っていきますが、オプション価格は、プット・コールに限らず、ボラティリティが高いほど、高くなります。数学的には単調増加関数です。もっと言うならば、オプション価格の式をボラティリティで偏微分したもの(これがベガとかヴェガとか呼ばれるものです)は必ず正の値になります。インプライドボラティリティの計算にはこれを利用します。
具体的には、インプライドボラティリティ=30%で計算したオプション価格が、実際のオプション価格より高ければ、求めるべきインプライドボラティリティは30%未満ということがわかります。
そこで次に15%で試してみる。結果として計算されたオプション価格が実際のオプション価格よりまだ高ければ、7.5%で試し、安ければ15%-30%の間の22.5%で試すような反復計算を行い、最終的に実際のオプション価格と計算されたオプション価格が一致したインプライドボラティリティをもって現在のインプライドボラティリティとするということになります。
私は面倒なので、あるX%という値を入れて計算した結果が小さすぎるならば2倍、大きすぎるならば0.5倍のような反復計算をしますが、ここはお好みで色々なやり方でよいと思います。

ということで下記がVBA上のインプライドボラティリティを求める関数の一例です。
引数は前記の#1-#7のうち、#3をオプション価格に置き換えたものになります。

Function bsIV(ByVal S As Double, ByVal K As Double, ByVal prem As Double, ByVal r As Double, ByVal d As Double, ByVal t As Double, ByVal CorP As Integer)
‘ S: 原資産価格 – 例えば日経平均指数
‘ K: オプション行使価格 – 27500とか
‘ prem: 実際のオプション価格
‘ r: 無リスク金利 – %ではなく、小数点で
‘ d: 配当利回り – %ではなく、小数点で
‘ t: 残存年数 – 残存日数/365
‘ CorP: Call or Put, コール=1, プット=2の整数

Dim sigma, maxSigma, minSigma As Double
Dim calcPrem As Double
' 試したボラティリティで高すぎる場合にはそのボラティリティの値をボラティリティの上限とする
' 試したボラティリティで低すぎる場合にはそのボラティリティの値をボラティリティの下限とする
' 上記の上限と下限の幅を狭めていくことで、最終的に正しいボラティリティを求めていく

' ボラティリティは正の値なので、
    minSigma = 0
' ボラティリティの最大値は100%を超えることもないと思うが、超えてしまう可能性も考えてmaxSigmaは決めない
' 残存年数がプラスの場合(SQ日より前)
    If t > 0 Then
     ' とりあえずボラティリティ20%で試してみる
        sigma = 0.2
        calcPrem = bsPrem(S, K, sigma, r, d, t, CorP)
    ' 計算されたオプション価格と実際の価格の誤差が0.01円未満になるまで反復
        Do While (Abs(prem - calcPrem) >= 0.01)
    ' もしも計算されたオプション価格が実際のオプション価格より高ければ
            If calcPrem > prem Then
                maxSigma = sigma ' 現在使っているボラティリティの値をボラティリティ上限とする
                If maxSigma = 0 Then
                        maxSigma = sigma * 2 ' もしまだボラティリティの上限が決まっていなかった場合
                    Else
                        sigma = (maxSigma + minSigma) / 2 ' 次の反復計算に使うボラティリティを現在の上限と下限の平均値に設定
                    End If
                calcPrem = bsPrem(S, K, sigma, r, d, t, CorP)

    ' もしも計算されたオプション価格が実際のオプション価格より低ければ
            Else
                minSigma = sigma ' 現在使っているボラティリティの値をボラティリティ上限とする
                sigma = (maxSigma + minSigma) / 2 ' 次の反復計算に使うボラティリティを現在の上限と下限の平均値に設定
                calcPrem = bsPrem(S, K, sigma, r, d, t, CorP)
            End If
        Loop
' 残存年数が0(SQ日)かマイナスの場合は適宜エラー処理
    Else
        'エラー処理省略
    End If
' 上記計算の結果最終的に残ったsigmaが求めたいインプライドボラティリティ
    bsIV = sigma

End Function

様々な答え合わせは次回、デルタ、ベガ等々の計算をしたのちにやってみましょう。
今やれよですよね・・・どうやら15:00を回るとRSSの示すインプライドボラティリティが一体何なのか不思議な事象があって、現在時刻17:00、うまく検証ができないので、、、まとめて後日やらせていただきます。

コメント

タイトルとURLをコピーしました