「大人の教養・知識・気付き」を伸ばすブログ

一流の大人(ビジネスマン、政治家、リーダー…)として知っておきたい、教養・社会動向を意外なところから取り上げ学ぶことで“気付く力”を伸ばすブログです。目下、データ分析・語学に力点を置いています。今月(2022年10月)からは多忙につき、日々の投稿数を減らします。

MENU

コンピュテーショナル・ファイナンス(その05/X)

 古典的名著

を基に「コンピュテーショナル・ファイナンス」を学んでいきます。

2. ツリーモデルによるオプションの評価

 ツリーモデルを用いたデリバティブ評価の理論的背景と具体的なアルゴリズムを紹介する。

2.6 ツリーモデルの応用

2.6.1 ツリーモデルによるヘッジパラメータの計算

 2項モデルを用いて誤差を少なくデルタやガンマを計算する方法を扱う。

 現時点における通貨の価値をSとすると、オプション価値をC(S)と書ける。このときデルタはh\gt0として


\begin{aligned}
\Delta=\displaystyle{\frac{\partial C}{\partial S}}\approx \displaystyle{\frac{C(S+h)-C(S-h)}{2h}}
\end{aligned}

として計算できる。ガンマは同様に


\begin{aligned}
\Gamma=\displaystyle{\frac{\partial^2 C}{\partial S^2}}&\approx\displaystyle{\frac{\left(\displaystyle{\frac{C(S+h)-C(S)}{h}}-\displaystyle{\frac{C(S)-C(S-h)}{h}}\right)}{h}}\\
&=\displaystyle{\frac{C(S+h)+C(S-h)-2C(S)}{h^2}}
\end{aligned}

で計算できる。すなわち2項モデルによってデルタを計算する場合には2回、ガンマを計算するためには3回オプション評価を行なわなければならない。そこでツリーを時間をさかのぼって計算する方法でオプション評価回数を減らす。
 拡張されたツリーを用いることで


\begin{aligned}
\Delta&=\displaystyle{\frac{C(S_{0,1})-C(S_{0,-1})}{S_{0,1}-S_{0,-1}}},\\
\Gamma&=\displaystyle{\frac{\left(\displaystyle{\frac{C(S_{0,1})-C(S_{0,0})}{S_{0,1}-S_{0,0}}}-\displaystyle{\frac{C(S_{0,0})-C(S_{0,-1})}{S_{0,0}-S_{0,-1}}}\right)}{\displaystyle{\frac{1}{2}}(S_{0,1}-S_{0,-1})}}
\end{aligned}

従来の方法では、ガンマを計算するためには\displaystyle{\frac{(n+1)(n+2)}{2}}個のノードを持つツリーを3回計算する必要があったものの、この方法を用いることで\displaystyle{\frac{(n+3)(n+4)}{2}}個のノードを持つツリーを1回だけ計算すればよいことになる。
 数値微分で計算したデルタは階段状になる一方で拡張ツリー法で計算した場合、Black-Scholesモデルによる計算結果に非常に近い値を取り、かなり精度が向上する。またガンマはより顕著に相違が出る。

2.6.2 2項モデルを用いたバリアオプションの評価

 下方にバリアを持つ停止条件コールオプションノックアウトオプション)を考える。

using System;
using System.Collections.Generic;

namespace ComputationalFinance
{
    class Program
    {
        static void Main(string[] args)
        {

            /*
             * パラメータの設定
             */
            int N = 20;
            var dblUlAssetPrices = new double[N + 1, N + 1];
            var dblCallOptionPremia = new double[N + 1, N + 1];

            double dblUlAssetPrice = 100.0; //現在の為替レート
            double dblStrikePrice = 100.0;  //行使価格
            double dblKnockOutRate = 95.0;  //ノックアウト水準

            // 国内・外国金利
            double dblDomesticIR = 0.05;
            double dblForeignIR = 0.02;

            // 原資産価格のボラティリティ
            double dblVolatility = 0.1;

            // 残存期間t
            double dblTime = 1.0;

            // 時点の刻みΔt
            double dblDeltaTime = dblTime / N;

            // 上昇率・下落率
            double dblUp = Math.Exp(dblVolatility * Math.Sqrt(dblDeltaTime));
            double dblDown = Math.Exp(-dblVolatility * Math.Sqrt(dblDeltaTime));

            // リスク中立確率
            double dblRiskNeutProb = (Math.Exp((dblDomesticIR - dblForeignIR) * dblDeltaTime ) - dblDown) / (dblUp - dblDown);

            /*
             * 通貨価値のツリー構築
             */

            for(int i = 0; i <= N; i++)
            {
                for(int j = 0; j <= i; j++)
                {
                    dblUlAssetPrices[i, j] = dblUlAssetPrice * Math.Pow(dblUp, j) * Math.Pow(dblDown, i - j);
                }
            }

            /*
             * 満期時点のコールオプション価値の計算
             */
            for(int j =0; j <= N; j++)
            {
                if (dblUlAssetPrices[N, j] > dblStrikePrice)
                {
                    dblCallOptionPremia[N, j] = dblUlAssetPrices[N, j] - dblStrikePrice;
                }
                else
                {
                    dblCallOptionPremia[N, j] = 0.0;
                }
            }

            /*
             * バックワードに各時点におけるオプション価値を計算
             */
            for(int i = N; i >= 1; i--)
            {
                for (int j = 1; j <= i; j++)
                {
                    dblCallOptionPremia[i - 1, j - 1] = Math.Exp(-dblDomesticIR * dblDeltaTime) * (dblRiskNeutProb * dblCallOptionPremia[i, j - 1] + (1 - dblRiskNeutProb) * dblCallOptionPremia[i, j]);

                    // ノックアウトの判定
                    if (dblUlAssetPrices[i,j]<= dblKnockOutRate)
                    {
                        dblCallOptionPremia[i, j] = 0.0;
                    }
                }
            }

            // 出力
            Console.WriteLine("ノックアウトオプションの価値は{0}です。", dblCallOptionPremia[0, 0]);
        }
    }
}

 通常のオプション計算では、数値解は分割数を増やせば振動しつつも解析解に収束した。しかしノックアウトオプションの評価では、ある分割数を超えると、精度が悪くなり、その後また解析解に振動しながら近づいていくような振る舞いを見せる。
 この精度の悪化はノックアウトレートとツリーにおけるノードの位置に関係している。たとえば2つのノックアウトレートA,\ A^{\prime}, A\neq A^{\prime}を考える。A=S_{1,0},\ S_{2,1}\gt A^{\prime}\gt S_{1,0}とすると、いずれであっても同じオプション価値が計算されてしまう。したがってバリアオプションをより正確に計算するためには、与えられたノックアウトレートとノードの位置が等しくなるようなツリーを構成すればよい。いま通貨がm回下降したときの値がノックアウトレートAに等しくなるためには


\begin{aligned}
Sd^m=A
\end{aligned}

とすればよい。ここでd=e^{-\sigma\sqrt{\Delta t}},\ \Delta t=\displaystyle{\frac{T}{N}}であることから、


\begin{aligned}
\ &\ Se^{-m\sigma\sqrt{\Delta t}}=A\\
\Leftrightarrow &\ e^{m\sigma\sqrt{\Delta t}}=\displaystyle{\frac{S}{A}}\\
\Leftrightarrow &\ \Delta t=\displaystyle{\frac{1}{m^2\sigma^2}}\displaystyle{\log\left(\frac{S}{A}\right)^2}\\
\Leftrightarrow &\ \displaystyle{\frac{T}{N}}=\displaystyle{\frac{1}{m^2\sigma^2}}\displaystyle{\log\left(\frac{S}{A}\right)^2}\\
\therefore &\ N(m)=\displaystyle{\frac{m^2\sigma^2T}{\log\left(\displaystyle{\frac{S}{A}}\right)^2}}
\end{aligned}

一般にこれは非整数なので、実際にはこれを超えないような最大の整数を用いる。

プライバシーポリシー お問い合わせ