Beispiel #1
0
        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)));
        }
Beispiel #2
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);
            }
        }
Beispiel #3
0
        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)));
            }
        }
Beispiel #4
0
        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);
            }
        }