public static double m1_beta_black_b(double beta, double mu, double sigma, ref double beta_b, ref double mu_b, ref double sigma_b, double res_b) { var betaMinusOne = beta - 1.0; var betaMinusOneSq = betaMinusOne * betaMinusOne; var sigma2 = sigma * sigma; var sqrt2 = Math.Sqrt(2.0); var sqrtPi = Math.Sqrt(Math.PI); var t = -mu / sigma; var t2 = t * t; var one_over_two_betaMinusOneSq = 0.5 / betaMinusOneSq; var e4 = Math.Exp(-0.5 * t2); var a1 = t + sigma / betaMinusOne; var b1 = -beta * mu / betaMinusOneSq + (sigma2 + 2.0 * mu) * one_over_two_betaMinusOneSq; var dmgroup1_db1 = 0.0; var dmgroup1_da1 = 0.0; var group1 = -SpecialFunction.exp_x_N_y_b(b1, a1, ref dmgroup1_db1, ref dmgroup1_da1, 1.0); var a2 = sigma - t; var muOneHalfS2 = mu + 0.5 * sigma2; var dgroup2_dmuOneHalfS2 = 0.0; var dgroup2_da2 = 0.0; var group2 = SpecialFunction.exp_x_N_y_b(muOneHalfS2, a2, ref dgroup2_dmuOneHalfS2, ref dgroup2_da2, 1.0); var f0 = -1.0 / (2.0 * sqrtPi); var dnmt_dmt = 0.0; var nmt = SpecialFunction.cdf_normal_b(-t, ref dnmt_dmt, 1.0); var res = f0 * sqrt2 * e4 * beta * sigma - betaMinusOneSq * group1 + group2 - beta * (mu - beta + 2) * (nmt - 1.0); var e4_b = res_b * f0 * sqrt2 * beta * sigma; beta_b += res_b * f0 * sqrt2 * e4 * sigma; beta_b += -res_b * (mu - 2.0 * beta + 2.0) * (nmt - 1.0); sigma_b += res_b * f0 * sqrt2 * e4 * beta; var betaMinusOneSq_b = -res_b * group1; var group1_b = -res_b * betaMinusOneSq; var group2_b = res_b; mu_b += -res_b * beta * (nmt - 1.0); var nmt_b = -res_b * beta * (mu - beta + 2); var t_b = -nmt_b * dnmt_dmt; var a2_b = group2_b * dgroup2_da2; var muOneHalfS2_b = group2_b * dgroup2_dmuOneHalfS2; mu_b += muOneHalfS2_b; sigma_b += muOneHalfS2_b * sigma; sigma_b += a2_b; t_b += -a2_b; var b1_b = -group1_b * dmgroup1_db1; var a1_b = -group1_b * dmgroup1_da1; beta_b += -b1_b * mu / betaMinusOneSq; mu_b += b1_b * (-beta / betaMinusOneSq + 2.0 * one_over_two_betaMinusOneSq); sigma_b += b1_b * 2.0 * sigma * one_over_two_betaMinusOneSq; betaMinusOneSq_b += b1_b * beta * mu / betaMinusOneSq / betaMinusOneSq; var one_over_two_betaMinusOneSq_b = b1_b * (sigma2 + 2.0 * mu); t_b += a1_b; var betaMinusOne_b = -a1_b * sigma / betaMinusOne / betaMinusOne; sigma_b += a1_b / betaMinusOne; var t2_b = -0.5 * e4_b * e4; betaMinusOneSq_b += -one_over_two_betaMinusOneSq_b * 0.5 / betaMinusOneSq / betaMinusOneSq; t_b += t2_b * 2.0 * t; mu_b += -t_b / sigma; sigma_b += t_b * mu / sigma / sigma; betaMinusOne_b += betaMinusOneSq_b * 2.0 * betaMinusOne; beta_b += betaMinusOne_b; return(res); }
public static double beta_black_b(double beta, OptionType optType, double F, double K, double T, double sigma , ref double beta_b, ref double F_b, ref double K_b, ref double T_b, ref double sigma_b, double res_b) { if (T < 0.0) { throw FS.FailWith($"T < 0 not allowed, {T}"); } if (sigma < 0.0) { throw FS.FailWith($"sigma < 0 not allowed {sigma}"); } var sqrtT = Math.Sqrt(T); var stdev = sigma * sqrtT; if (stdev == 0.0) { return(Math.Max(optType.ToEpsilon() * (F - K), 0.0)); } var dmu_dbeta = 0.0; var dmu_dF = 0.0; var dmu_dstdev = 0.0; var mu = inv_m1_beta_black_b(beta, F, stdev, ref dmu_dbeta, ref dmu_dF, ref dmu_dstdev, 1.0); var digb_dbeta = 0.0; var digb_dK = 0.0; var igb = inv_g_b(beta, K, ref digb_dbeta, ref digb_dK, 1.0); var d = (igb - mu) / stdev; var dNd_dd = 0.0; var Nd = SpecialFunction.cdf_normal_b(d, ref dNd_dd, 1.0); var t1 = K * Nd; var dt2_dbeta = 0.0; var dt2_dmu = 0.0; var dt2_dstdev = 0.0; var dt2_dd = 0.0; var t2 = beta_black_trunc_b(beta, mu, stdev, d, ref dt2_dbeta, ref dt2_dmu, ref dt2_dstdev, ref dt2_dd, 1.0); var res = t1 - t2; // now rewind var t1_b = res_b; var t2_b = -res_b; beta_b += t2_b * dt2_dbeta; var mu_b = t2_b * dt2_dmu; var stdev_b = t2_b * dt2_dstdev; var d_b = t2_b * dt2_dd; K_b += t1_b * Nd; var Nd_b = t1_b * K; d_b += Nd_b * dNd_dd; var igb_b = d_b / stdev; mu_b += -d_b / stdev; stdev_b += -d_b * (igb - mu) / stdev / stdev; beta_b += igb_b * digb_dbeta; K_b += igb_b * digb_dK; beta_b += mu_b * dmu_dbeta; F_b += mu_b * dmu_dF; stdev_b += mu_b * dmu_dstdev; sigma_b += stdev_b * sqrtT; T_b += stdev_b * sigma / (2.0 * sqrtT); if (optType == OptionType.Put) { return(res); } else if (optType == OptionType.Call) { F_b += res_b; K_b += -res_b; return(res + F - K); } else { throw FS.E_CASE(optType); } }
public static double beta_black_trunc_b(double beta, double mu, double sigma, double x, ref double beta_b, ref double mu_b, ref double sigma_b, ref double x_b, double res_b) { var betaMinusOne = beta - 1.0; var betaMinusOneSq = betaMinusOne * betaMinusOne; var sigma2 = sigma * sigma; var sqrt2 = Math.Sqrt(2.0); var sqrtPi = Math.Sqrt(Math.PI); var t = -mu / sigma; var one_over_two_betaMinusOneSq = 0.5 / betaMinusOneSq; var f0 = -1.0 / (2.0 * sqrtPi); var res = 0.0; var betaMinusOne_b = 0.0; var betaMinusOneSq_b = 0.0; var one_over_two_betaMinusOneSq_b = 0.0; var x2_b = 0.0; var t_b = 0.0; if (x < t) { var x2 = x * x; var ar2 = -0.5 * x2; var e2 = Math.Exp(ar2); var a4 = x + sigma / betaMinusOne; var ar4 = -beta * mu / betaMinusOneSq + (sigma2 + 2.0 * mu) * one_over_two_betaMinusOneSq; var dgroup4_dar4 = 0.0; var dgroup4_da4 = 0.0; var group4 = SpecialFunction.exp_x_N_y_b(ar4, a4, ref dgroup4_dar4, ref dgroup4_da4, 1.0); var dNx_dx = 0.0; var Nx = SpecialFunction.cdf_normal_b(x, ref dNx_dx, 1.0); res = f0 * sqrt2 * e2 * beta * sigma + betaMinusOneSq * group4 + beta * Nx * (mu - beta + 2.0); var e2_b = res_b * f0 * sqrt2 * beta * sigma; beta_b += res_b * (f0 * sqrt2 * e2 * sigma + Nx * (mu - 2.0 * beta + 2.0)); sigma_b += res_b * f0 * sqrt2 * e2 * beta; betaMinusOneSq_b += res_b * group4; var group4_b = res_b * betaMinusOneSq; var Nx_b = res_b * beta * (mu - beta + 2.0); mu_b += res_b * beta * Nx; x_b += Nx_b * dNx_dx; var ar4_b = group4_b * dgroup4_dar4; var a4_b = group4_b * dgroup4_da4; beta_b += ar4_b * (-mu / betaMinusOneSq); mu_b += ar4_b * (-beta / betaMinusOneSq + 2.0 * one_over_two_betaMinusOneSq); betaMinusOneSq_b += ar4_b * (beta * mu / betaMinusOneSq / betaMinusOneSq); sigma_b += ar4_b * 2.0 * sigma * one_over_two_betaMinusOneSq; one_over_two_betaMinusOneSq_b += ar4_b * (sigma2 + 2.0 * mu); x_b += a4_b; sigma_b += a4_b / betaMinusOne; betaMinusOne_b += a4_b * (-sigma / betaMinusOne / betaMinusOne); var ar2_b = e2_b * e2; x2_b += -0.5 * ar2_b; x_b += x2_b * 2.0 * x; } else { var t2 = t * t; var ar4 = -0.5 * t2; var e4 = Math.Exp(ar4); var a1 = t + sigma / betaMinusOne; var ar1 = -beta * mu / betaMinusOneSq + (sigma2 + 2.0 * mu) * one_over_two_betaMinusOneSq; var dmgroup1_dar1 = 0.0; var dmgroup1_da1 = 0.0; var group1 = -SpecialFunction.exp_x_N_y_b(ar1, a1, ref dmgroup1_dar1, ref dmgroup1_da1, 1.0); var a2 = t - sigma; var a3 = x - sigma; var ar2 = mu + 0.5 * sigma2; var dmgroup2_dar2 = 0.0; var dmgroup2_da2 = 0.0; var group2 = -SpecialFunction.exp_x_N_y_b(ar2, a2, ref dmgroup2_dar2, ref dmgroup2_da2, 1.0); var dgroup3_dar2 = 0.0; var dgroup3_da3 = 0.0; var group3 = SpecialFunction.exp_x_N_y_b(ar2, a3, ref dgroup3_dar2, ref dgroup3_da3, 1.0); var dnmt_dmt = 0.0; var nmt = SpecialFunction.cdf_normal_b(-t, ref dnmt_dmt, 1.0); res = f0 * sqrt2 * e4 * beta * sigma - betaMinusOneSq * group1 + group2 + group3 - beta * (mu - beta + 2) * (nmt - 1.0); var e4_b = res_b * f0 * sqrt2 * beta * sigma; beta_b += res_b * (f0 * sqrt2 * e4 * sigma - (mu - 2.0 * beta + 2.0) * (nmt - 1.0)); sigma_b += res_b * f0 * sqrt2 * e4 * beta; betaMinusOneSq_b += -res_b * group1; var group1_b = -res_b * betaMinusOneSq; var group2_b = res_b; var group3_b = res_b; mu_b += -res_b * beta * (nmt - 1.0); var nmt_b = res_b * -beta * (mu - beta + 2); t_b += -nmt_b * dnmt_dmt; var ar2_b = group3_b * dgroup3_dar2; var a3_b = group3_b * dgroup3_da3; var a2_b = -group2_b * dmgroup2_da2; ar2_b += -group2_b * dmgroup2_dar2; mu_b += ar2_b; sigma_b += ar2_b * sigma; x_b += a3_b; sigma_b += -a3_b; sigma_b += -a2_b; t_b += a2_b; var ar1_b = -group1_b * dmgroup1_dar1; var a1_b = -group1_b * dmgroup1_da1; beta_b += ar1_b * (-mu / betaMinusOneSq); mu_b += ar1_b * (-beta / betaMinusOneSq + 2.0 * one_over_two_betaMinusOneSq); betaMinusOneSq_b += ar1_b * (beta * mu / betaMinusOneSq / betaMinusOneSq); sigma_b += ar1_b * 2.0 * sigma * one_over_two_betaMinusOneSq; one_over_two_betaMinusOneSq_b += ar1_b * (sigma2 + 2.0 * mu); t_b += a1_b; sigma_b += a1_b / betaMinusOne; betaMinusOne_b += -a1_b * sigma / betaMinusOne / betaMinusOne; var ar4_b = e4_b * e4; var t2_b = -0.5 * ar4_b; t_b += t2_b * 2.0 * t; } betaMinusOneSq_b += -one_over_two_betaMinusOneSq_b * 0.5 / betaMinusOneSq / betaMinusOneSq; mu_b += -t_b / sigma; sigma_b += t_b * mu / sigma / sigma; betaMinusOne_b += betaMinusOneSq_b * 2.0 * betaMinusOne; beta_b += betaMinusOne_b; return(res); }