業務でC#を用いることになったので、最近勉強していなくて朧気になってきた知識をReviseする意味でも、以下の書籍を読みながらC#で実装してみる。今日はP.47-49まで。
3. 確率論の基礎
3.5 二項モデルによるオプション価格モデル
と二項分布に従う確率変数を考える。関数
を
回成功したときに支払われる利得とすると、期待値
はこの試行において期待される利得を表す。二項モデルで株価が表される株式を原資産とするデリバティブの価格は、
をそのペイオフ関数とすれば、満期
で得られる期待利得は
で与えられる(価格を計算したいときは、これを割引けばよい)。
3.6 C#での実装
using System;
using MathNet.Numerics;
private static int nCk(int n, int k)
{
if (n < k) return 0;
if (n == k) return 1;
int x = 1;
for (int i = 0; i < k; i++)
{
x = x * (n - i) / (i + 1);
}
return x;
}
private static double max(double x, double y)
{
double z = x + y;
z += Math.Abs(x - y);
return 0.5 * z;
}
/// <summary>
/// 2項モデルによる株価とその出現確率を計算する。
/// </summary>
/// <param name="S">初期時点の株価。0以上でなければならない。</param>
/// <param name="u">上昇率。0より大きくなければならない。またuが1より大きいならばdは1未満,uが1未満ならばdは1より大きくなければならない。</param>
/// <param name="d">下落率。0より大きくなければならない。またuが1より大きいならばdは1未満,uが1未満ならばdは1より大きくなければならない。</param>
/// <param name="p">上昇する確率。0より大きく1未満でなければならない。</param>
/// <param name="T">時点数。0より大きい整数。</param>
/// <returns>t=Tにおける株価の経路と各確率を返す。</returns>
public static double[] StockPriceByBinModel(double S, double u, double d, double p, int T, int k)
{
// 全過程を計算して返す。
double SP = 0.0;
double Prob = 0.0;
// 株価と確率を計算する。
SP = S * Math.Pow(u, T - k) * Math.Pow(d, k);
Prob = (double)nCk(T, T - k) * Math.Pow(p, T - k) * Math.Pow(1 - p, k);
var ret = new double[] { SP, Prob };
return ret;
}
/// <summary>
/// 二項モデルに従う株式を原資産とするオプションの期待利得を返す
/// </summary>
/// <param name="S0">初期時点における株価</param>
/// <param name="u">上昇率</param>
/// <param name="d">下落率</param>
/// <param name="p">上昇確率</param>
/// <param name="K">行使価格</param>
/// <param name="T">満期</param>
/// <param name="CallPutFlg">コール・プットを表すフラグ。0ならばコール・オプション、1ならばプット・オプションの価格を返す。</param>
/// <returns>二項モデルに従う株式を原資産とするオプションの期待利得</returns>
public static double OptionPayOff(double S0, double u, double d, double p, double K, int T, int CallPutFlg)
{
// エラーハンドリング
if (S0 <= 0)
{
Console.WriteLine("初期時点の原資産価格S0が0以下です。0より大きい値を入力して下さい。");
return -999999;
}
if (u <= 0 | d <= 0)
{
if (u < d)
{
Console.WriteLine("上昇率uまたは下落率dが0以下です。しかもuがdよりも小さいです。0より大きい値を入力して下さい。");
return -999999;
}
else
{
Console.WriteLine("上昇率uまたは下落率dが0以下です。0より大きい値を入力して下さい。");
return -999999;
}
}
if (u < d)
{
Console.WriteLine("上昇率uが下落率dよりも小さいです。uはdよりも大きい値を入力して下さい。");
return -999999;
}
if (K <= 0)
{
Console.WriteLine("行使価格Kが0以下です。Kは0よりも大きい値を入力して下さい。");
return -999999;
}
if (T <= 0)
{
Console.WriteLine("満期Tは0よりも大きい値を入力して下さい。");
return -999999;
}
double ret = 0.0;
if (CallPutFlg == 0 | CallPutFlg == 1)
{
for (int i = 0; i < T; i++)
{
double[] SPs = StockPriceByBinModel(S0, u, d, p, T, i);
int sign = -2 * CallPutFlg + 1;
SPs[0] = max(sign *(SPs[0] - K), 0);
ret += SPs[0] * SPs[1];
}
return ret;
}
else
{
return -999999;
}
}
