Ejemplo n.º 1
0
        public static double NormalVol(double forward, double strike, double time, SABRParams sabr_params)
        {
            if (!sabr_params.isValid)
            {
                return(Double.NaN);
            }

            double alpha = sabr_params.Alpha;
            double beta  = sabr_params.Beta;
            double rho   = sabr_params.Rho;
            double nu    = sabr_params.Nu;

            double K = strike;
            double F = forward;
            double t = time;

            double A     = Pow(F * K, 1.0 - beta);
            double sqrtA = Sqrt(A);
            double log_r;

            if (Abs(F - K) > 1e-12)
            {
                log_r = Log(F / K);
            }
            else
            {
                double epsilon = (F - K) / K;
                log_r = epsilon - 0.5 * epsilon * epsilon;
            }

            double z   = (nu / alpha) * sqrtA * log_r;
            double B   = 1.0 - 2.0 * rho * z + z * z;
            double C   = (1.0 - beta) * (1.0 - beta) * log_r * log_r;
            double D   = log_r * log_r;
            double tmp = (Sqrt(B) + z - rho) / (1.0 - rho);
            double xx  = Log(tmp);
            double E_1 = (1.0 + D / 24.0 + D * D / 1920.0);
            double E_2 = (1.0 + C / 24.0 + C * C / 1920.0);
            double E   = E_1 / E_2;
            double d   = 1.0 + t * (-beta * (2 - beta) * alpha * alpha / (24.0 * A) +
                                    0.25 * rho * beta * nu * alpha / sqrtA +
                                    (2.0 - 3.0 * rho * rho) * (nu * nu / 24.0));
            double coef;

            if (Abs(z * z) > 2.22045e-15)
            {
                coef = z / xx;
            }
            else
            {
                coef = 1.0 - 0.5 * rho * z - (3.0 * rho * rho - 2.0) * z * z / 12.0;
            }

            return(alpha * Pow(F * K, beta / 2.0) * E * coef * d);
        }
Ejemplo n.º 2
0
        public static double Price(double forward, double strike, double time, double rate, SABRParams sabr_params, bool isCall, bool useNormalApprox = false)
        {
            double price = Double.NaN;

            if (sabr_params.isValid)
            {
                if (useNormalApprox)
                {
                    double normal_vol = HaganSABR.NormalVol(forward, strike, time, sabr_params);
                    price = Bachelier.Price(forward, strike, time, rate, normal_vol, isCall);
                }
                else
                {
                    double black_vol = HaganSABR.BlackVol(forward, strike, time, sabr_params);
                    price = Black.Price(forward, strike, time, rate, black_vol, isCall);
                }
            }

            return(price);
        }