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_strike_to_quick_delta(double beta, double F, double T, double sigma, double strike) { var qd = SpecialFunction.cdf_normal((inv_g(beta, F) - inv_g(beta, strike)) / (sigma * Math.Sqrt(T))); if (qd <= -0.5) { return(1.0 + qd); } if (qd > 0.5) { return(qd - 1.0); } return(qd); }
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 m1_beta_black(double beta, double mu, double sigma) { 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 group1 = -SpecialFunction.exp_x_N_y(-beta * mu / betaMinusOneSq + (sigma2 + 2.0 * mu) * one_over_two_betaMinusOneSq, a1); var a2 = sigma - t; var group2 = SpecialFunction.exp_x_N_y(mu + 0.5 * sigma2, a2); var f0 = -1.0 / (2.0 * sqrtPi); return(f0 * sqrt2 * e4 * beta * sigma - betaMinusOneSq * group1 + group2 - beta * (mu - beta + 2) * (SpecialFunction.cdf_normal(-t) - 1.0)); }
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 beta_black_trunc(double beta, double mu, double sigma, double x) { 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); if (x < t) { var x2 = x * x; var e2 = Math.Exp(-0.5 * x2); var a4 = x + sigma / betaMinusOne; var group4 = SpecialFunction.exp_x_N_y(-beta * mu / betaMinusOneSq + (sigma2 + 2.0 * mu) * one_over_two_betaMinusOneSq, a4); return(f0 * sqrt2 * e2 * beta * sigma + +betaMinusOneSq * group4 + beta * SpecialFunction.cdf_normal(x) * (mu - beta + 2.0)); } else { var t2 = t * t; var e4 = Math.Exp(-0.5 * t2); var a1 = t + sigma / betaMinusOne; var group1 = -SpecialFunction.exp_x_N_y(-beta * mu / betaMinusOneSq + (sigma2 + 2.0 * mu) * one_over_two_betaMinusOneSq, a1); var a2 = sigma - t; var a3 = x - sigma; var group2 = -SpecialFunction.exp_x_N_y(mu + 0.5 * sigma2, -a2); var group3 = SpecialFunction.exp_x_N_y(mu + 0.5 * sigma2, a3); return(f0 * sqrt2 * e4 * beta * sigma - betaMinusOneSq * group1 + (group2 + group3) - beta * (mu - beta + 2) * (SpecialFunction.cdf_normal(-t) - 1.0)); } }
public static double beta_black_cdf(double beta, double mu, double sigma, double x) { return(SpecialFunction.cdf_normal((inv_g(beta, x) - mu) / sigma)); }