예제 #1
0
        public void testAnalyticContinuousGeometricAveragePrice()
        {
            //("Testing analytic continuous geometric average-price Asians...");
            // data from "Option Pricing Formulas", Haug, pag.96-97

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

            SimpleQuote spot = new SimpleQuote(80.0);
            SimpleQuote qRate = new SimpleQuote(-0.03);
            YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc);
            SimpleQuote rRate = new SimpleQuote(0.05);
            YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc);
            SimpleQuote vol = new SimpleQuote(0.20);
            BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc);

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

            IPricingEngine engine = new
                AnalyticContinuousGeometricAveragePriceAsianEngine(stochProcess);

            Average.Type averageType = Average.Type.Geometric;
            Option.Type type = Option.Type.Put;
            double strike = 85.0;
            Date exerciseDate = today + 90;

            int pastFixings = 0; //Null<int>();
            double runningAccumulator = 0.0; //Null<Real>();

            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);

            Exercise exercise = new EuropeanExercise(exerciseDate);

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

            double calculated = option.NPV();
            double expected = 4.6922;
            double tolerance = 1.0e-4;
            if (Math.Abs(calculated - expected) > tolerance)
            {
                REPORT_FAILURE("value", averageType, runningAccumulator, pastFixings,
                               new List<Date>(), payoff, exercise, spot.value(),
                               qRate.value(), rRate.value(), today,
                               vol.value(), expected, calculated, tolerance);
            }

            // trying to approximate the continuous version with the discrete version
            runningAccumulator = 1.0;
            pastFixings = 0;
            List<Date> fixingDates = new InitializedList<Date>(exerciseDate - today + 1);
            for (int i = 0; i < fixingDates.Count; i++)
            {
                fixingDates[i] = today + i;
            }
            IPricingEngine engine2 = new
                AnalyticDiscreteGeometricAveragePriceAsianEngine(stochProcess);

            DiscreteAveragingAsianOption option2 =
                new DiscreteAveragingAsianOption(averageType,
                                                 runningAccumulator, pastFixings,
                                                 fixingDates,
                                                 payoff,
                                                 exercise);
            option2.setPricingEngine(engine2);

            calculated = option2.NPV();
            tolerance = 3.0e-3;
            /*if (Math.Abs(calculated - expected) > tolerance)
            {
                REPORT_FAILURE("value", averageType, runningAccumulator, pastFixings,
                               fixingDates, payoff, exercise, spot.value(),
                               qRate.value(), rRate.value(), today,
                               vol.value(), expected, calculated, tolerance);
            }*/
        }
예제 #2
0
        public void testAnalyticContinuousGeometricAveragePriceGreeks()
        {
            //BOOST_MESSAGE("Testing analytic continuous geometric average-price Asian "
            //              "greeks...");

            //std::map<std::string,Real>
            Dictionary<string, double> calculated, expected, tolerance;
            calculated = new Dictionary<string, double>(6);
            expected = new Dictionary<string, double>(6);
            tolerance = new Dictionary<string, double>(6);
            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[] underlyings = { 100.0 };
            double[] strikes = { 90.0, 100.0, 110.0 };
            double[] qRates = { 0.04, 0.05, 0.06 };
            double[] rRates = { 0.01, 0.05, 0.15 };
            int[] lengths = { 1, 2 };
            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 < strikes.Length; j++)
                {
                    for (int k = 0; k < lengths.Length; k++)
                    {

                        EuropeanExercise maturity =
                            //new EuropeanExercise(today + lengths[k]*Years);
                                            new EuropeanExercise(today +
                                                new Period(lengths[k], TimeUnit.Years));
                        PlainVanillaPayoff payoff =
                                            new PlainVanillaPayoff(types[i], strikes[j]);

                        IPricingEngine engine = new
                             AnalyticContinuousGeometricAveragePriceAsianEngine(process);

                        ContinuousAveragingAsianOption option =
                            new ContinuousAveragingAsianOption(Average.Type.Geometric,
                                                                payoff, maturity);
                        option.setPricingEngine(engine);

                        int pastFixings = 0; //Null<Size>();
                        double runningAverage = 0; //Null<Real>();

                        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 (KeyValuePair<string, double> kvp in calculated)
                                            {
                                                string greek = kvp.Key;
                                                double expct = expected[greek],
                                                     calcl = calculated[greek],
                                                     tol = tolerance[greek];
                                                double error = Utilities.relativeError(expct, calcl, u);
                                                if (error > tol)
                                                {
                                                    REPORT_FAILURE(greek, Average.Type.Geometric,
                                                                   runningAverage, pastFixings,
                                                                   new List<Date>(),
                                                                   payoff, maturity,
                                                                   u, q, r, today, v,
                                                                   expct, calcl, tol);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }