public static double ibachelier(OptionType optType, double F, double K, double T, double premium, bool safe = false) { if (T <= 0.0) { throw FS.FailWith($"T must be postive, got {T}"); } var epsilon = optType.ToEpsilon(); var intrinsic = Math.Max(epsilon * (F - K), 0.0); if (premium <= intrinsic) { if (DoubleUtils.ApproximatelyEqual(premium, intrinsic, DoubleUtils.DoubleEpsilon)) { return(0.0); } if (safe) { return(0.0); } throw FS.FailWith($"premium must be larger than intrinsic. Got premium = {premium}, vs intrinsic = {intrinsic}"); //! } if (F == K) { return(premium * Math.Sqrt(2.0 * Math.PI / T)); } var sqrtT = Math.Sqrt(T); var phiStar = -Math.Abs((premium - intrinsic) / (K - F)); var xBar = 0.0; if (phiStar < -0.001882039271) { var g = 1.0 / (phiStar - 0.5); var g2 = g * g; var zeta = (0.032114372355 - g2 * (0.016969777977 - g2 * (2.6207332461e-3 - 9.6066952861e-5 * g2))) / (1.0 - g2 * (0.6635646938 - g2 * (0.14528712196 - 0.010472855461 * g2))); xBar = g * (1.0 / Math.Sqrt(2.0 * Math.PI) + zeta * g2); } else { var h = Math.Sqrt(-Math.Log(-phiStar)); xBar = (9.4883409779 - h * (9.6320903635 - h * (0.58556997323 + 2.1464093351 * h))) / (1 - h * (0.65174820867 + h * (1.5120247828 + 6.6437847132e-5 * h))); } var xBar2 = xBar * xBar; var nxBar = SpecialFunction.pdf_normal(xBar); var phiTildaXBar = SpecialFunction.cdf_normal(xBar) + nxBar / xBar; var q = (phiTildaXBar - phiStar) / nxBar; var xStar = xBar + (3.0 * q * xBar2 * (2.0 - q * xBar * (2.0 + xBar2))) / (6.0 + q * xBar * (-12.0 + xBar * (6.0 * q + xBar * (-6.0 + q * xBar * (3.0 + xBar2))))); return(Math.Abs((K - F) / (xStar * sqrtT))); }
public static double beta_black(double beta, OptionType optType, double F, double K, double T, double sigma) { 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 stdev = sigma * Math.Sqrt(T); if (stdev == 0.0) { return(Math.Max(optType.ToEpsilon() * (F - K), 0.0)); } var mu = inv_m1_beta_black(beta, F, stdev); var d = (inv_g(beta, K) - mu) / stdev; var t1 = K * SpecialFunction.cdf_normal(d); var t2 = beta_black_trunc(beta, mu, stdev, d); var put = t1 - t2; var intrinsic = Math.Max(optType.ToEpsilon() * (F - K), 0.0); if (optType == OptionType.Put) { return(Math.Max(put, intrinsic)); } else if (optType == OptionType.Call) { return(Math.Max(put + F - K, intrinsic)); } else { throw FS.E_CASE(optType); } }
public static double black76(OptionType optType, double F, double K, double sdev) { var num = optType.ToEpsilon(); if (sdev < 0.0) { throw FS.FailWith($"sdev must be positive. Got {sdev}"); } if (sdev == 0.0 || K <= 0.0) { return(Math.Max(num * (F - K), 0.0)); } else { var num2 = (Math.Log(F / K) + 0.5 * sdev * sdev) / sdev; var num3 = num2 - sdev; return(num * (F * SpecialFunction.cdf_normal(num * num2) - K * SpecialFunction.cdf_normal(num * num3))); } }
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); } }