relativeError() public static method

public static relativeError ( double x1, double x2, double reference ) : double
x1 double
x2 double
reference double
return double
示例#1
0
        public void testATMRate()
        {
            CommonVars vars = new CommonVars();

            int[]    lengths = { 1, 2, 3, 5, 7, 10, 15, 20 };
            double[] strikes = { 0.0, 0.03, 0.04, 0.05, 0.06, 0.07 };
            double[] vols    = { 0.01, 0.05, 0.10, 0.15, 0.20 };

            Date startDate = vars.termStructure.link.referenceDate();

            for (int i = 0; i < lengths.Length; i++)
            {
                List <CashFlow> leg      = vars.makeLeg(startDate, lengths[i]);
                Date            maturity = vars.calendar.advance(startDate, lengths[i], TimeUnit.Years, vars.convention);
                Schedule        schedule = new Schedule(startDate, maturity,
                                                        new Period(vars.frequency), vars.calendar,
                                                        vars.convention, vars.convention,
                                                        DateGeneration.Rule.Forward, false);

                for (int j = 0; j < strikes.Length; j++)
                {
                    for (int k = 0; k < vols.Length; k++)
                    {
                        CapFloor cap          = vars.makeCapFloor(CapFloorType.Cap, leg, strikes[j], vols[k]);
                        CapFloor floor        = vars.makeCapFloor(CapFloorType.Floor, leg, strikes[j], vols[k]);
                        double   capATMRate   = cap.atmRate(vars.termStructure);
                        double   floorATMRate = floor.atmRate(vars.termStructure);

                        if (!checkAbsError(floorATMRate, capATMRate, 1.0e-10))
                        {
                            Assert.Fail(
                                "Cap ATM Rate and floor ATM Rate should be equal :\n"
                                + "   length:        " + lengths[i] + " years\n"
                                + "   volatility:    " + vols[k] + "\n"
                                + "   strike:        " + strikes[j] + "\n"
                                + "   cap ATM rate:  " + capATMRate + "\n"
                                + "   floor ATM rate:" + floorATMRate + "\n"
                                + "   relative Error:"
                                + Utilities.relativeError(capATMRate, floorATMRate, capATMRate) * 100 + "%");
                        }
                        VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, vars.nominals[0],
                                                           schedule, floorATMRate,
                                                           vars.index.dayCounter(),
                                                           schedule, vars.index, 0.0,
                                                           vars.index.dayCounter());
                        swap.setPricingEngine((IPricingEngine)(
                                                  new DiscountingSwapEngine(vars.termStructure)));
                        double swapNPV = swap.NPV();
                        if (!checkAbsError(swapNPV, 0, 1.0e-10))
                        {
                            Assert.Fail(
                                "the NPV of a Swap struck at ATM rate "
                                + "should be equal to 0:\n"
                                + "   length:        " + lengths[i] + " years\n"
                                + "   volatility:    " + vols[k] + "\n"
                                + "   ATM rate:      " + floorATMRate + "\n"
                                + "   swap NPV:      " + swapNPV);
                        }
                    }
                }
            }
        }
示例#2
0
        public void testEuropeanGreeks()
        {
            // Testing dividend European option greeks...

            SavedSettings backup = new SavedSettings();

            Dictionary <string, double> calculated = new Dictionary <string, double>(),
                                        expected   = new Dictionary <string, double>(),
                                        tolerance  = new Dictionary <string, double>();

            tolerance["delta"] = 1.0e-5;
            tolerance["gamma"] = 1.0e-5;
            tolerance["theta"] = 1.0e-5;
            tolerance["rho"]   = 1.0e-5;
            tolerance["vega"]  = 1.0e-5;

            Option.Type[] types       = { Option.Type.Call, Option.Type.Put };
            double[]      strikes     = { 50.0, 99.5, 100.0, 100.5, 150.0 };
            double[]      underlyings = { 100.0 };
            double[]      qRates      = { 0.00, 0.10, 0.30 };
            double[]      rRates      = { 0.01, 0.05, 0.15 };
            int[]         lengths     = { 1, 2 };
            double[]      vols        = { 0.05, 0.20, 0.40 };

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.setEvaluationDate(today);

            SimpleQuote spot  = new SimpleQuote(0.0);
            SimpleQuote qRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc));
            SimpleQuote rRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc));
            SimpleQuote vol = new SimpleQuote(0.0);
            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc));

            for (int i = 0; i < types.Length; i++)
            {
                for (int j = 0; j < strikes.Length; j++)
                {
                    for (int k = 0; k < lengths.Length; k++)
                    {
                        Date     exDate   = today + new Period(lengths[k], TimeUnit.Years);
                        Exercise exercise = new EuropeanExercise(exDate);

                        List <Date>   dividendDates = new List <Date>();
                        List <double> dividends     = new List <double>();
                        for (Date d = today + new Period(3, TimeUnit.Months);
                             d < exercise.lastDate();
                             d += new Period(6, TimeUnit.Months))
                        {
                            dividendDates.Add(d);
                            dividends.Add(5.0);
                        }

                        StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]);

                        BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot),
                                                                                               qTS, rTS, volTS);

                        IPricingEngine engine = new AnalyticDividendEuropeanEngine(stochProcess);

                        DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates,
                                                                                 dividends);
                        option.setPricingEngine(engine);

                        for (int l = 0; l < underlyings.Length; l++)
                        {
                            for (int m = 0; m < qRates.Length; m++)
                            {
                                for (int n = 0; n < rRates.Length; n++)
                                {
                                    for (int p = 0; p < vols.Length; p++)
                                    {
                                        double u = underlyings[l];
                                        double q = qRates[m],
                                               r = rRates[n];
                                        double v = vols[p];
                                        spot.setValue(u);
                                        qRate.setValue(q);
                                        rRate.setValue(r);
                                        vol.setValue(v);

                                        double value = option.NPV();
                                        calculated["delta"] = option.delta();
                                        calculated["gamma"] = option.gamma();
                                        calculated["theta"] = option.theta();
                                        calculated["rho"]   = option.rho();
                                        calculated["vega"]  = option.vega();

                                        if (value > spot.value() * 1.0e-5)
                                        {
                                            // perturb spot and get delta and gamma
                                            double du = u * 1.0e-4;
                                            spot.setValue(u + du);
                                            double value_p = option.NPV(),
                                                   delta_p = option.delta();
                                            spot.setValue(u - du);
                                            double value_m = option.NPV(),
                                                   delta_m = option.delta();
                                            spot.setValue(u);
                                            expected["delta"] = (value_p - value_m) / (2 * du);
                                            expected["gamma"] = (delta_p - delta_m) / (2 * du);

                                            // perturb risk-free rate and get rho
                                            double dr = r * 1.0e-4;
                                            rRate.setValue(r + dr);
                                            value_p = option.NPV();
                                            rRate.setValue(r - dr);
                                            value_m = option.NPV();
                                            rRate.setValue(r);
                                            expected["rho"] = (value_p - value_m) / (2 * dr);

                                            // perturb volatility and get vega
                                            double dv = v * 1.0e-4;
                                            vol.setValue(v + dv);
                                            value_p = option.NPV();
                                            vol.setValue(v - dv);
                                            value_m = option.NPV();
                                            vol.setValue(v);
                                            expected["vega"] = (value_p - value_m) / (2 * dv);

                                            // perturb date and get theta
                                            double dT = dc.yearFraction(today - 1, today + 1);
                                            Settings.setEvaluationDate(today - 1);
                                            value_m = option.NPV();
                                            Settings.setEvaluationDate(today + 1);
                                            value_p = option.NPV();
                                            Settings.setEvaluationDate(today);
                                            expected["theta"] = (value_p - value_m) / dT;

                                            // compare
                                            foreach (KeyValuePair <string, double> it in calculated)
                                            {
                                                string greek = it.Key;
                                                double expct = expected  [greek],
                                                       calcl = calculated[greek],
                                                       tol   = tolerance [greek];
                                                double error = Utilities.relativeError(expct, calcl, u);
                                                if (error > tol)
                                                {
                                                    REPORT_FAILURE(greek, payoff, exercise,
                                                                   u, q, r, today, v,
                                                                   expct, calcl, error, tol);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#3
0
        public void testFdGreeks <Engine>() where Engine : IFDEngine, new()
        {
            //SavedSettings backup;

            Dictionary <string, double> calculated = new Dictionary <string, double>(),
                                        expected   = new Dictionary <string, double>(),
                                        tolerance  = new Dictionary <string, double>();

            tolerance.Add("delta", 7.0e-4);
            tolerance.Add("gamma", 2.0e-4);
            //tolerance["theta"]  = 1.0e-4;

            Option.Type[] types       = new Option.Type[] { Option.Type.Call, Option.Type.Put };
            double[]      strikes     = { 50.0, 99.5, 100.0, 100.5, 150.0 };
            double[]      underlyings = { 100.0 };
            double[]      qRates      = { 0.04, 0.05, 0.06 };
            double[]      rRates      = { 0.01, 0.05, 0.15 };
            int[]         years       = { 1, 2 };
            double[]      vols        = { 0.11, 0.50, 1.20 };

            Date today = Date.Today;

            Settings.setEvaluationDate(today);

            DayCounter         dc    = new Actual360();
            SimpleQuote        spot  = new SimpleQuote(0.0);
            SimpleQuote        qRate = new SimpleQuote(0.0);
            YieldTermStructure qTS   = Utilities.flatRate(today, qRate, dc);

            SimpleQuote           rRate = new SimpleQuote(0.0);
            YieldTermStructure    rTS   = Utilities.flatRate(today, rRate, dc);
            SimpleQuote           vol   = new SimpleQuote(0.0);
            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc);

            for (int i = 0; i < types.Length; i++)
            {
                for (int j = 0; j < strikes.Length; j++)
                {
                    for (int k = 0; k < years.Length; k++)
                    {
                        Date                      exDate       = today + new Period(years[k], TimeUnit.Years);
                        Exercise                  exercise     = new AmericanExercise(today, exDate);
                        StrikedTypePayoff         payoff       = new PlainVanillaPayoff(types[i], strikes[j]);
                        BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot),
                                                                                               new Handle <YieldTermStructure>(qTS),
                                                                                               new Handle <YieldTermStructure>(rTS),
                                                                                               new Handle <BlackVolTermStructure>(volTS));

                        IPricingEngine engine = new Engine().factory(stochProcess);

                        VanillaOption option = new VanillaOption(payoff, exercise);
                        option.setPricingEngine(engine);

                        for (int l = 0; l < underlyings.Length; l++)
                        {
                            for (int m = 0; m < qRates.Length; m++)
                            {
                                for (int n = 0; n < rRates.Length; n++)
                                {
                                    for (int p = 0; p < vols.Length; p++)
                                    {
                                        double u = underlyings[l];
                                        double q = qRates[m],
                                               r = rRates[n];
                                        double v = vols[p];
                                        spot.setValue(u);
                                        qRate.setValue(q);
                                        rRate.setValue(r);
                                        vol.setValue(v);

                                        double value = option.NPV();
                                        calculated.Add("delta", option.delta());
                                        calculated.Add("gamma", option.gamma());
                                        //calculated["theta"]  = option.theta();

                                        if (value > spot.value() * 1.0e-5)
                                        {
                                            // perturb spot and get delta and gamma
                                            double du = u * 1.0e-4;
                                            spot.setValue(u + du);
                                            double value_p = option.NPV(),
                                                   delta_p = option.delta();
                                            spot.setValue(u - du);
                                            double value_m = option.NPV(),
                                                   delta_m = option.delta();
                                            spot.setValue(u);
                                            expected.Add("delta", (value_p - value_m) / (2 * du));
                                            expected.Add("gamma", (delta_p - delta_m) / (2 * du));

                                            /*
                                             * // perturb date and get theta
                                             * Time dT = dc.yearFraction(today-1, today+1);
                                             * Settings::instance().setEvaluationDate(today-1);
                                             * value_m = option.NPV();
                                             * Settings::instance().setEvaluationDate(today+1);
                                             * value_p = option.NPV();
                                             * Settings::instance().setEvaluationDate(today);
                                             * expected["theta"] = (value_p - value_m)/dT;
                                             */

                                            // compare
                                            foreach (string greek in calculated.Keys)
                                            {
                                                double expct      = expected  [greek],
                                                            calcl = calculated[greek],
                                                            tol   = tolerance [greek];
                                                double error      = Utilities.relativeError(expct, calcl, u);
                                                if (error > tol)
                                                {
                                                    REPORT_FAILURE(greek, payoff, exercise,
                                                                   u, q, r, today, v,
                                                                   expct, calcl, error, tol);
                                                }
                                            }
                                        }
                                        calculated.Clear();
                                        expected.Clear();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#4
0
        void testFdGreeks <Engine>(Date today, Exercise exercise) where Engine : IFDEngine, new()
        {
            Dictionary <string, double> calculated = new Dictionary <string, double>(),
                                        expected   = new Dictionary <string, double>(),
                                        tolerance  = new Dictionary <string, double>();

            tolerance.Add("delta", 5.0e-3);
            tolerance.Add("gamma", 7.0e-3);
            // tolerance["theta"] = 1.0e-2;

            Option.Type[] types       = { Option.Type.Call, Option.Type.Put };
            double[]      strikes     = { 50.0, 99.5, 100.0, 100.5, 150.0 };
            double[]      underlyings = { 100.0 };
            double[]      qRates      = { 0.00, 0.10, 0.20 };
            double[]      rRates      = { 0.01, 0.05, 0.15 };
            double[]      vols        = { 0.05, 0.20, 0.50 };

            DayCounter dc = new Actual360();

            SimpleQuote spot  = new SimpleQuote(0.0);
            SimpleQuote qRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc));
            SimpleQuote rRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc));
            SimpleQuote vol = new SimpleQuote(0.0);
            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc));

            for (int i = 0; i < types.Length; i++)
            {
                for (int j = 0; j < strikes.Length; j++)
                {
                    List <Date>   dividendDates = new List <Date>();
                    List <double> dividends     = new List <double>();
                    for (Date d = today + new Period(3, TimeUnit.Months);
                         d < exercise.lastDate();
                         d += new Period(6, TimeUnit.Months))
                    {
                        dividendDates.Add(d);
                        dividends.Add(5.0);
                    }

                    StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]);

                    BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot),
                                                                                           qTS, rTS, volTS);

                    IPricingEngine        engine = new Engine().factory(stochProcess);
                    DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends);
                    option.setPricingEngine(engine);

                    for (int l = 0; l < underlyings.Length; l++)
                    {
                        for (int m = 0; m < qRates.Length; m++)
                        {
                            for (int n = 0; n < rRates.Length; n++)
                            {
                                for (int p = 0; p < vols.Length; p++)
                                {
                                    double u = underlyings[l];
                                    double q = qRates[m],
                                           r = rRates[n];
                                    double v = vols[p];
                                    spot.setValue(u);
                                    qRate.setValue(q);
                                    rRate.setValue(r);
                                    vol.setValue(v);

                                    // FLOATING_POINT_EXCEPTION
                                    double value = option.NPV();
                                    calculated["delta"] = option.delta();
                                    calculated["gamma"] = option.gamma();
                                    // calculated["theta"]  = option.theta();

                                    if (value > spot.value() * 1.0e-5)
                                    {
                                        // perturb spot and get delta and gamma
                                        double du = u * 1.0e-4;
                                        spot.setValue(u + du);
                                        double value_p = option.NPV(),
                                               delta_p = option.delta();
                                        spot.setValue(u - du);
                                        double value_m = option.NPV(),
                                               delta_m = option.delta();
                                        spot.setValue(u);
                                        expected["delta"] = (value_p - value_m) / (2 * du);
                                        expected["gamma"] = (delta_p - delta_m) / (2 * du);

                                        // perturb date and get theta

                                        /*
                                         *      Time dT = dc.yearFraction(today-1, today+1);
                                         *      Settings::instance().evaluationDate() = today-1;
                                         *      value_m = option.NPV();
                                         *      Settings::instance().evaluationDate() = today+1;
                                         *      value_p = option.NPV();
                                         *      Settings::instance().evaluationDate() = today;
                                         *      expected["theta"] = (value_p - value_m)/dT;
                                         */

                                        // compare
                                        foreach (string greek in calculated.Keys)
                                        {
                                            double expct      = expected[greek],
                                                        calcl = calculated[greek],
                                                        tol   = tolerance[greek];
                                            double error      = Utilities.relativeError(expct, calcl, u);
                                            if (error > tol)
                                            {
                                                REPORT_FAILURE(greek, payoff, exercise,
                                                               u, q, r, today, v,
                                                               expct, calcl, error, tol);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#5
0
        //void testEngineConsistency(EngineType engine, int binomialSteps, int samples, Dictionary<string,double> tolerance,
        //                           bool testGreeks = false) {
        void testEngineConsistency(EngineType engine, int binomialSteps, int samples, Dictionary <string, double> tolerance,
                                   bool testGreeks)
        {
            //QL_TEST_START_TIMING

            Dictionary <string, double> calculated = new Dictionary <string, double>(), expected = new Dictionary <string, double>();

            // test options
            Option.Type[] types         = { Option.Type.Call, Option.Type.Put };
            double[]      strikes       = { 75.0, 100.0, 125.0 };
            int[]         lengths       = { 1 };

            // test data
            double[] underlyings        = { 100.0 };
            double[] qRates             = { 0.00, 0.05 };
            double[] rRates             = { 0.01, 0.05, 0.15 };
            double[] vols               = { 0.11, 0.50, 1.20 };

            DayCounter dc               = new Actual360();
            Date       today            = Date.Today;

            SimpleQuote           spot = new SimpleQuote(0.0);
            SimpleQuote           vol   = new SimpleQuote(0.0);
            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc);
            SimpleQuote           qRate = new SimpleQuote(0.0);
            YieldTermStructure    qTS   = Utilities.flatRate(today, qRate, dc);
            SimpleQuote           rRate = new SimpleQuote(0.0);
            YieldTermStructure    rTS   = Utilities.flatRate(today, rRate, dc);

            for (int i = 0; i < types.Length; i++)
            {
                for (int j = 0; j < strikes.Length; j++)
                {
                    for (int k = 0; k < lengths.Length; k++)
                    {
                        Date              exDate   = today + lengths[k] * 360;
                        Exercise          exercise = new EuropeanExercise(exDate);
                        StrikedTypePayoff payoff   = new PlainVanillaPayoff(types[i], strikes[j]);
                        // reference option
                        VanillaOption refOption = makeOption(payoff, exercise, spot, qTS, rTS, volTS,
                                                             EngineType.Analytic, 0, 0);
                        // option to check
                        VanillaOption option = makeOption(payoff, exercise, spot, qTS, rTS, volTS,
                                                          engine, binomialSteps, samples);

                        for (int l = 0; l < underlyings.Length; l++)
                        {
                            for (int m = 0; m < qRates.Length; m++)
                            {
                                for (int n = 0; n < rRates.Length; n++)
                                {
                                    for (int p = 0; p < vols.Length; p++)
                                    {
                                        double u = underlyings[l];
                                        double q = qRates[m],
                                               r = rRates[n];
                                        double v = vols[p];
                                        spot.setValue(u);
                                        qRate.setValue(q);
                                        rRate.setValue(r);
                                        vol.setValue(v);

                                        expected.Clear();
                                        calculated.Clear();

                                        // FLOATING_POINT_EXCEPTION
                                        expected.Add("value", refOption.NPV());
                                        calculated.Add("value", option.NPV());

                                        if (testGreeks && option.NPV() > spot.value() * 1.0e-5)
                                        {
                                            expected.Add("delta", refOption.delta());
                                            expected.Add("gamma", refOption.gamma());
                                            expected.Add("theta", refOption.theta());
                                            calculated.Add("delta", option.delta());
                                            calculated.Add("gamma", option.gamma());
                                            calculated.Add("theta", option.theta());
                                        }
                                        foreach (string greek in calculated.Keys)
                                        {
                                            double expct      = expected[greek],
                                                        calcl = calculated[greek],
                                                        tol   = tolerance[greek];
                                            double error      = Utilities.relativeError(expct, calcl, u);
                                            if (error > tol)
                                            {
                                                REPORT_FAILURE(greek, payoff, exercise,
                                                               u, q, r, today, v,
                                                               expct, calcl, error, tol);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#6
0
        public void testCashAtHitOrNothingAmericanGreeks()
        {
            // Testing American cash-(at-hit)-or-nothing digital option greeks

            using (SavedSettings backup = new SavedSettings())
            {
                SortedDictionary <string, double> calculated = new SortedDictionary <string, double>();
                SortedDictionary <string, double> expected   = new SortedDictionary <string, double>();
                SortedDictionary <string, double> tolerance  = new SortedDictionary <string, double>(); // std::map<std::string,Real> calculated, expected, tolerance;

                tolerance["delta"] = 5.0e-5;
                tolerance["gamma"] = 5.0e-5;
                tolerance["rho"]   = 5.0e-5;

                Option.Type[] types       = { QLNet.Option.Type.Call, QLNet.Option.Type.Put };
                double[]      strikes     = { 50.0, 99.5, 100.5, 150.0 };
                double        cashPayoff  = 100.0;
                double[]      underlyings = { 100 };
                double[]      qRates      = { 0.04, 0.05, 0.06 };
                double[]      rRates      = { 0.01, 0.05, 0.15 };
                double[]      vols        = { 0.11, 0.5, 1.2 };

                DayCounter dc    = new Actual360();
                Date       today = Date.Today;
                Settings.setEvaluationDate(today);

                SimpleQuote spot  = new SimpleQuote(0.0);
                SimpleQuote qRate = new SimpleQuote(0.0);
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc));
                SimpleQuote rRate = new SimpleQuote(0.0);
                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc));
                SimpleQuote vol = new SimpleQuote(0.0);
                Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc));

                // there is no cycling on different residual times
                Date       exDate     = today + 360;
                Exercise   exercise   = new EuropeanExercise(exDate);
                Exercise   amExercise = new AmericanExercise(today, exDate, false);
                Exercise[] exercises  = { exercise, amExercise };

                BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS);

                IPricingEngine euroEngine = new AnalyticEuropeanEngine(stochProcess);

                IPricingEngine amEngine = new AnalyticDigitalAmericanEngine(stochProcess);

                IPricingEngine[] engines = { euroEngine, amEngine };

                bool knockin = true;
                for (int j = 0; j < engines.Length; j++)
                {
                    for (int i1 = 0; i1 < types.Length; i1++)
                    {
                        for (int i6 = 0; i6 < strikes.Length; i6++)
                        {
                            StrikedTypePayoff payoff = new CashOrNothingPayoff(types[i1], strikes[i6], cashPayoff);

                            VanillaOption opt = new VanillaOption(payoff, exercises[j]);
                            opt.setPricingEngine(engines[j]);

                            for (int i2 = 0; i2 < underlyings.Length; i2++)
                            {
                                for (int i4 = 0; i4 < qRates.Length; i4++)
                                {
                                    for (int i3 = 0; i3 < rRates.Length; i3++)
                                    {
                                        for (int i7 = 0; i7 < vols.Length; i7++)
                                        {
                                            // test data
                                            double u = underlyings[i2];
                                            double q = qRates[i4];
                                            double r = rRates[i3];
                                            double v = vols[i7];
                                            spot.setValue(u);
                                            qRate.setValue(q);
                                            rRate.setValue(r);
                                            vol.setValue(v);

                                            // theta, dividend rho and vega are not available for
                                            // digital option with american exercise. Greeks of
                                            // digital options with european payoff are tested
                                            // in the europeanoption.cpp test
                                            double value = opt.NPV();
                                            calculated["delta"] = opt.delta();
                                            calculated["gamma"] = opt.gamma();
                                            calculated["rho"]   = opt.rho();

                                            if (value > 1.0e-6)
                                            {
                                                // perturb spot and get delta and gamma
                                                double du = u * 1.0e-4;
                                                spot.setValue(u + du);
                                                double value_p = opt.NPV(),
                                                       delta_p = opt.delta();
                                                spot.setValue(u - du);
                                                double value_m = opt.NPV(),
                                                       delta_m = opt.delta();
                                                spot.setValue(u);
                                                expected["delta"] = (value_p - value_m) / (2 * du);
                                                expected["gamma"] = (delta_p - delta_m) / (2 * du);

                                                // perturb rates and get rho and dividend rho
                                                double dr = r * 1.0e-4;
                                                rRate.setValue(r + dr);
                                                value_p = opt.NPV();
                                                rRate.setValue(r - dr);
                                                value_m = opt.NPV();
                                                rRate.setValue(r);
                                                expected["rho"] = (value_p - value_m) / (2 * dr);

                                                // check
                                                //std::map<std::string,Real>::iterator it;
                                                foreach (var it in calculated)
                                                {
                                                    string greek = it.Key;
                                                    double expct = expected  [greek],
                                                           calcl = calculated[greek],
                                                           tol   = tolerance [greek];
                                                    double error = Utilities.relativeError(expct, calcl, value);
                                                    if (error > tol)
                                                    {
                                                        REPORT_FAILURE(greek, payoff, exercise,
                                                                       u, q, r, today, v,
                                                                       expct, calcl, error, tol, knockin);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#7
0
        private void testOptionGreeks(ForwardVanillaEngine.GetOriginalEngine getEngine)
        {
            SavedSettings backup = new SavedSettings();

            Dictionary <String, double> calculated = new Dictionary <string, double>(),
                                        expected   = new Dictionary <string, double>(),
                                        tolerance  = new Dictionary <string, double>();

            tolerance["delta"]  = 1.0e-5;
            tolerance["gamma"]  = 1.0e-5;
            tolerance["theta"]  = 1.0e-5;
            tolerance["rho"]    = 1.0e-5;
            tolerance["divRho"] = 1.0e-5;
            tolerance["vega"]   = 1.0e-5;

            Option.Type[] types       = { Option.Type.Call, Option.Type.Put };
            double[]      moneyness   = { 0.9, 1.0, 1.1 };
            double[]      underlyings = { 100.0 };
            double[]      qRates      = { 0.04, 0.05, 0.06 };
            double[]      rRates      = { 0.01, 0.05, 0.15 };
            int[]         lengths     = { 1, 2 };
            Frequency[]   frequencies = { Frequency.Semiannual, Frequency.Quarterly, };
            double[]      vols        = { 0.11, 0.50, 1.20 };

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.setEvaluationDate(today);

            SimpleQuote spot  = new SimpleQuote(0.0);
            SimpleQuote qRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc));
            SimpleQuote rRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc));
            SimpleQuote vol = new SimpleQuote(0.0);
            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc));

            BlackScholesMertonProcess process = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS);

            for (int i = 0; i < types.Length; i++)
            {
                for (int j = 0; j < moneyness.Length; j++)
                {
                    for (int k = 0; k < lengths.Length; k++)
                    {
                        for (int kk = 0; kk < frequencies.Length; kk++)
                        {
                            EuropeanExercise maturity = new EuropeanExercise(today + new Period(lengths[k], TimeUnit.Years));

                            PercentageStrikePayoff payoff = new PercentageStrikePayoff(types[i], moneyness[j]);

                            List <Date> reset = new List <Date>();
                            for (Date d = today + new Period(frequencies[kk]);
                                 d < maturity.lastDate();
                                 d += new Period(frequencies[kk]))
                            {
                                reset.Add(d);
                            }

                            IPricingEngine engine = getEngine(process);

                            CliquetOption option = new CliquetOption(payoff, maturity, reset);
                            option.setPricingEngine(engine);

                            for (int l = 0; l < underlyings.Length; l++)
                            {
                                for (int m = 0; m < qRates.Length; m++)
                                {
                                    for (int n = 0; n < rRates.Length; n++)
                                    {
                                        for (int p = 0; p < vols.Length; p++)
                                        {
                                            double u = underlyings[l];
                                            double q = qRates[m],
                                                   r = rRates[n];
                                            double v = vols[p];
                                            spot.setValue(u);
                                            qRate.setValue(q);
                                            rRate.setValue(r);
                                            vol.setValue(v);

                                            double value = option.NPV();
                                            calculated["delta"]  = option.delta();
                                            calculated["gamma"]  = option.gamma();
                                            calculated["theta"]  = option.theta();
                                            calculated["rho"]    = option.rho();
                                            calculated["divRho"] = option.dividendRho();
                                            calculated["vega"]   = option.vega();

                                            if (value > spot.value() * 1.0e-5)
                                            {
                                                // perturb spot and get delta and gamma
                                                double du = u * 1.0e-4;
                                                spot.setValue(u + du);
                                                double value_p = option.NPV(),
                                                       delta_p = option.delta();
                                                spot.setValue(u - du);
                                                double value_m = option.NPV(),
                                                       delta_m = option.delta();
                                                spot.setValue(u);
                                                expected["delta"] = (value_p - value_m) / (2 * du);
                                                expected["gamma"] = (delta_p - delta_m) / (2 * du);

                                                // perturb rates and get rho and dividend rho
                                                double dr = r * 1.0e-4;
                                                rRate.setValue(r + dr);
                                                value_p = option.NPV();
                                                rRate.setValue(r - dr);
                                                value_m = option.NPV();
                                                rRate.setValue(r);
                                                expected["rho"] = (value_p - value_m) / (2 * dr);

                                                double dq = q * 1.0e-4;
                                                qRate.setValue(q + dq);
                                                value_p = option.NPV();
                                                qRate.setValue(q - dq);
                                                value_m = option.NPV();
                                                qRate.setValue(q);
                                                expected["divRho"] = (value_p - value_m) / (2 * dq);

                                                // perturb volatility and get vega
                                                double dv = v * 1.0e-4;
                                                vol.setValue(v + dv);
                                                value_p = option.NPV();
                                                vol.setValue(v - dv);
                                                value_m = option.NPV();
                                                vol.setValue(v);
                                                expected["vega"] = (value_p - value_m) / (2 * dv);

                                                // perturb date and get theta
                                                double dT = dc.yearFraction(today - 1, today + 1);
                                                Settings.setEvaluationDate(today - 1);
                                                value_m = option.NPV();
                                                Settings.setEvaluationDate(today + 1);
                                                value_p = option.NPV();
                                                Settings.setEvaluationDate(today);
                                                expected["theta"] = (value_p - value_m) / dT;

                                                // compare
                                                foreach (var it in calculated)
                                                {
                                                    String greek = it.Key;
                                                    double expct = expected  [greek],
                                                           calcl = calculated[greek],
                                                           tol   = tolerance [greek];
                                                    double error = Utilities.relativeError(expct, calcl, u);
                                                    if (error > tol)
                                                    {
                                                        REPORT_FAILURE(greek, payoff, maturity,
                                                                       u, q, r, today, v,
                                                                       expct, calcl, error, tol);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#8
0
        private void testForwardGreeks(Type engine_type)
        {
            Dictionary <String, double> calculated = new Dictionary <string, double>(),
                                        expected   = new Dictionary <string, double>(),
                                        tolerance  = new Dictionary <string, double>();

            tolerance["delta"]  = 1.0e-5;
            tolerance["gamma"]  = 1.0e-5;
            tolerance["theta"]  = 1.0e-5;
            tolerance["rho"]    = 1.0e-5;
            tolerance["divRho"] = 1.0e-5;
            tolerance["vega"]   = 1.0e-5;

            Option.Type[] types       = { Option.Type.Call, Option.Type.Put };
            double[]      moneyness   = { 0.9, 1.0, 1.1 };
            double[]      underlyings = { 100.0 };
            double[]      qRates      = { 0.04, 0.05, 0.06 };
            double[]      rRates      = { 0.01, 0.05, 0.15 };
            int[]         lengths     = { 1, 2 };
            int[]         startMonths = { 6, 9 };
            double[]      vols        = { 0.11, 0.50, 1.20 };

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.setEvaluationDate(today);

            SimpleQuote spot  = new SimpleQuote(0.0);
            SimpleQuote qRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc));
            SimpleQuote rRate = new SimpleQuote(0.0);
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc));
            SimpleQuote vol = new SimpleQuote(0.0);
            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc));

            BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS);

            IPricingEngine engine = engine_type == typeof(ForwardVanillaEngine) ? new ForwardVanillaEngine(stochProcess, process => new AnalyticEuropeanEngine(process)) :
                                    new ForwardPerformanceVanillaEngine(stochProcess, process => new AnalyticEuropeanEngine(process));

            for (int i = 0; i < types.Length; i++)
            {
                for (int j = 0; j < moneyness.Length; j++)
                {
                    for (int k = 0; k < lengths.Length; k++)
                    {
                        for (int h = 0; h < startMonths.Length; h++)
                        {
                            Date     exDate   = today + new Period(lengths[k], TimeUnit.Years);
                            Exercise exercise = new EuropeanExercise(exDate);

                            Date reset = today + new Period(startMonths[h], TimeUnit.Months);

                            StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], 0.0);

                            ForwardVanillaOption option = new ForwardVanillaOption(moneyness[j], reset, payoff, exercise);
                            option.setPricingEngine(engine);

                            for (int l = 0; l < underlyings.Length; l++)
                            {
                                for (int m = 0; m < qRates.Length; m++)
                                {
                                    for (int n = 0; n < rRates.Length; n++)
                                    {
                                        for (int p = 0; p < vols.Length; p++)
                                        {
                                            double u = underlyings[l];
                                            double q = qRates[m],
                                                   r = rRates[n];
                                            double v = vols[p];
                                            spot.setValue(u);
                                            qRate.setValue(q);
                                            rRate.setValue(r);
                                            vol.setValue(v);

                                            double value = option.NPV();
                                            calculated["delta"]  = option.delta();
                                            calculated["gamma"]  = option.gamma();
                                            calculated["theta"]  = option.theta();
                                            calculated["rho"]    = option.rho();
                                            calculated["divRho"] = option.dividendRho();
                                            calculated["vega"]   = option.vega();

                                            if (value > spot.value() * 1.0e-5)
                                            {
                                                // perturb spot and get delta and gamma
                                                double du = u * 1.0e-4;
                                                spot.setValue(u + du);
                                                double value_p = option.NPV(),
                                                       delta_p = option.delta();
                                                spot.setValue(u - du);
                                                double value_m = option.NPV(),
                                                       delta_m = option.delta();
                                                spot.setValue(u);
                                                expected["delta"] = (value_p - value_m) / (2 * du);
                                                expected["gamma"] = (delta_p - delta_m) / (2 * du);

                                                // perturb rates and get rho and dividend rho
                                                double dr = r * 1.0e-4;
                                                rRate.setValue(r + dr);
                                                value_p = option.NPV();
                                                rRate.setValue(r - dr);
                                                value_m = option.NPV();
                                                rRate.setValue(r);
                                                expected["rho"] = (value_p - value_m) / (2 * dr);

                                                double dq = q * 1.0e-4;
                                                qRate.setValue(q + dq);
                                                value_p = option.NPV();
                                                qRate.setValue(q - dq);
                                                value_m = option.NPV();
                                                qRate.setValue(q);
                                                expected["divRho"] = (value_p - value_m) / (2 * dq);

                                                // perturb volatility and get vega
                                                double dv = v * 1.0e-4;
                                                vol.setValue(v + dv);
                                                value_p = option.NPV();
                                                vol.setValue(v - dv);
                                                value_m = option.NPV();
                                                vol.setValue(v);
                                                expected["vega"] = (value_p - value_m) / (2 * dv);

                                                // perturb date and get theta
                                                double dT = dc.yearFraction(today - 1, today + 1);
                                                Settings.setEvaluationDate(today - 1);
                                                value_m = option.NPV();
                                                Settings.setEvaluationDate(today + 1);
                                                value_p = option.NPV();
                                                Settings.setEvaluationDate(today);
                                                expected["theta"] = (value_p - value_m) / dT;

                                                // compare
                                                //std::map<std::string,double>::iterator it;
                                                foreach (KeyValuePair <string, double> it in calculated)
                                                {
                                                    String greek = it.Key;
                                                    double expct = expected  [greek],
                                                           calcl = calculated[greek],
                                                           tol   = tolerance [greek];
                                                    double error = Utilities.relativeError(expct, calcl, u);
                                                    if (error > tol)
                                                    {
                                                        REPORT_FAILURE(greek, payoff, exercise,
                                                                       u, q, r, today, v,
                                                                       moneyness[j], reset,
                                                                       expct, calcl, error, tol);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }