flatVol() public static method

public static flatVol ( Date today, Quote vol, DayCounter dc ) : QLNet.BlackVolTermStructure
today Date
vol QLNet.Quote
dc DayCounter
return QLNet.BlackVolTermStructure
コード例 #1
0
            // setup
            public CommonVars()
            {
                calendar = new TARGET();

                today = calendar.adjust(Date.Today);
                Settings.Instance.setEvaluationDate(today);

                dayCounter     = new Actual360();
                frequency      = Frequency.Annual;
                settlementDays = 3;

                issueDate    = calendar.advance(today, 2, TimeUnit.Days);
                maturityDate = calendar.advance(issueDate, 10, TimeUnit.Years);
                // reset to avoid inconsistencies as the schedule is backwards
                issueDate = calendar.advance(maturityDate, -10, TimeUnit.Years);

                underlying.linkTo(new SimpleQuote(50.0));
                dividendYield.linkTo(Utilities.flatRate(today, 0.02, dayCounter));
                riskFreeRate.linkTo(Utilities.flatRate(today, 0.05, dayCounter));
                volatility.linkTo(Utilities.flatVol(today, 0.15, dayCounter));

                process = new BlackScholesMertonProcess(underlying, dividendYield, riskFreeRate, volatility);

                creditSpread.linkTo(new SimpleQuote(0.005));

                // it fails with 1000000
                // faceAmount = 1000000.0;
                faceAmount      = 100.0;
                redemption      = 100.0;
                conversionRatio = redemption / underlying.link.value();
            }
コード例 #2
0
        public void testBjerksundStenslandValues()
        {
            // ("Testing Bjerksund and Stensland approximation for American options...");

            AmericanOptionData[] values = new AmericanOptionData[] {
                //      type, strike,   spot,    q,    r,    t,  vol,   value, tol
                // from "Option pricing formulas", Haug, McGraw-Hill 1998, pag 27
                new AmericanOptionData(Option.Type.Call, 40.00, 42.00, 0.08, 0.04, 0.75, 0.35, 5.2704),
                // from "Option pricing formulas", Haug, McGraw-Hill 1998, VBA code
                new AmericanOptionData(Option.Type.Put, 40.00, 36.00, 0.00, 0.06, 1.00, 0.20, 4.4531)
            };

            Date               today = Date.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);

            double tolerance = 3.0e-3;

            for (int i = 0; i < values.Length; i++)
            {
                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);
                Date     exDate          = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise        = new AmericanExercise(today, exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine = new BjerksundStenslandApproximationEngine(stochProcess);

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

                double calculated = option.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > tolerance)
                {
                    REPORT_FAILURE("value", payoff, exercise, values[i].s, values[i].q,
                                   values[i].r, today, values[i].v, values[i].result,
                                   calculated, error, tolerance);
                }
            }
        }
コード例 #3
0
        public void testCashOrNothingEuropeanValues()
        {
            // Testing European cash-or-nothing digital option

            DigitalOptionData[] values =
            {
                // "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 - pag 88
                //        type, strike,  spot,    q,    r,    t,  vol,  value, tol
                new DigitalOptionData(Option.Type.Put, 80.00, 100.0, 0.06, 0.06, 0.75, 0.35, 2.6710, 1e-4, true)
            };

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

            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 < values.Length; i++)
            {
                StrikedTypePayoff payoff = new CashOrNothingPayoff(values[i].type, values[i].strike, 10.0);

                Date     exDate   = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine = new AnalyticEuropeanEngine(stochProcess);

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

                double calculated = opt.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("value", payoff, exercise, values[i].s, values[i].q,
                                   values[i].r, today, values[i].v, values[i].result,
                                   calculated, error, values[i].tol, values[i].knockin);
                }
            }
        }
コード例 #4
0
ファイル: T_CliquetOption.cs プロジェクト: scchess/QLNet
        public void testValues()
        {
            // Testing Cliquet option values

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

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

            BlackScholesMertonProcess process = new BlackScholesMertonProcess(
                new Handle <Quote>(spot),
                new Handle <YieldTermStructure>(qTS),
                new Handle <YieldTermStructure>(rTS),
                new Handle <BlackVolTermStructure>(volTS));
            IPricingEngine engine = new AnalyticCliquetEngine(process);

            List <Date> reset = new List <Date>();

            reset.Add(today + 90);
            Date maturity = today + 360;

            Option.Type type      = Option.Type.Call;
            double      moneyness = 1.1;

            PercentageStrikePayoff payoff   = new PercentageStrikePayoff(type, moneyness);
            EuropeanExercise       exercise = new EuropeanExercise(maturity);

            CliquetOption option = new CliquetOption(payoff, exercise, reset);

            option.setPricingEngine(engine);

            double calculated = option.NPV();
            double expected   = 4.4064; // Haug, p.37
            double error      = Math.Abs(calculated - expected);
            double tolerance  = 1e-4;

            if (error > tolerance)
            {
                REPORT_FAILURE("value", payoff, exercise, spot.value(),
                               qRate.value(), rRate.value(), today,
                               vol.value(), expected, calculated,
                               error, tolerance);
            }
        }
コード例 #5
0
        public void testFdValues()
        {
            //("Testing finite-difference engine for American options...");

            Date               today = Date.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);

            double tolerance = 8.0e-2;

            for (int i = 0; i < juValues.Length; i++)
            {
                StrikedTypePayoff payoff = new PlainVanillaPayoff(juValues[i].type, juValues[i].strike);
                Date     exDate          = today + Convert.ToInt32(juValues[i].t * 360 + 0.5);
                Exercise exercise        = new AmericanExercise(today, exDate);

                spot.setValue(juValues[i].s);
                qRate.setValue(juValues[i].q);
                rRate.setValue(juValues[i].r);
                vol.setValue(juValues[i].v);

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

                IPricingEngine engine = new FDAmericanEngine(stochProcess, 100, 100);

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

                double calculated = option.NPV();
                double error      = Math.Abs(calculated - juValues[i].result);
                if (error > tolerance)
                {
                    REPORT_FAILURE("value", payoff, exercise, juValues[i].s, juValues[i].q,
                                   juValues[i].r, today, juValues[i].v, juValues[i].result,
                                   calculated, error, tolerance);
                }
            }
        }
コード例 #6
0
ファイル: T_DividendOption.cs プロジェクト: tzhdingli/qlnet
        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);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #7
0
        public void testCashAtHitOrNothingAmericanValues()
        {
            // Testing American cash-(at-hit)-or-nothing digital option

            DigitalOptionData[] values =
            {
                //        type, strike,   spot,    q,    r,   t,  vol,   value, tol
                // "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 - pag 95, case 1,2
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.00, 0.10, 0.5, 0.20,  9.7264,  1e-4, true),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.00, 0.10, 0.5, 0.20, 11.6553,  1e-4, true),

                // the following cases are not taken from a reference paper or book
                // in the money options (guaranteed immediate payoff)
                new DigitalOptionData(Option.Type.Call, 100.00, 105.00, 0.00, 0.10, 0.5, 0.20, 15.0000, 1e-16, true),
                new DigitalOptionData(Option.Type.Put,  100.00,  95.00, 0.00, 0.10, 0.5, 0.20, 15.0000, 1e-16, true),
                // non null dividend (cross-tested with MC simulation)
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.20, 0.10, 0.5, 0.20, 12.2715,  1e-4, true),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.20, 0.10, 0.5, 0.20,  8.9109,  1e-4, true),
                new DigitalOptionData(Option.Type.Call, 100.00, 105.00, 0.20, 0.10, 0.5, 0.20, 15.0000, 1e-16, true),
                new DigitalOptionData(Option.Type.Put,  100.00,  95.00, 0.20, 0.10, 0.5, 0.20, 15.0000, 1e-16, true)
            };

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

            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 < values.Length; i++)
            {
                StrikedTypePayoff payoff = new CashOrNothingPayoff(values[i].type, values[i].strike, 15.00);

                Date     exDate     = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise amExercise = new AmericanExercise(today, exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine = new AnalyticDigitalAmericanEngine(stochProcess);

                VanillaOption opt = new VanillaOption(payoff, amExercise);
                opt.setPricingEngine(engine);

                double calculated = opt.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("value", payoff, amExercise, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   values[i].result, calculated, error, values[i].tol, values[i].knockin);
                }
            }
        }
コード例 #8
0
        public void testFdGreeks <Engine>() where Engine : IFDEngine, new()
        {
            using (SavedSettings backup = new SavedSettings())
            {
                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();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #9
0
ファイル: T_CliquetOption.cs プロジェクト: scchess/QLNet
        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);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #10
0
        public void testAssetOrNothingHaugValues()
        {
            // Testing asset-or-nothing barrier options against Haug's values

            BinaryOptionData[] values =
            {
                /* The data below are from
                 * "Option pricing formulas 2nd Ed.", E.G. Haug, McGraw-Hill 2007 pag. 180 - cases 15,16,19,20,23,24,27,28
                 * Note:
                 * q is the dividend rate, while the book gives b, the cost of carry (q=r-b)
                 */
                //    barrierType, barrier,  cash,         type, strike,   spot,    q,    r,   t,  vol,   value, tol
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 0.00, Option.Type.Call, 102.00, 105.00, 0.00, 0.10, 0.5, 0.20, 37.2782, 1e-4),
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 0.00, Option.Type.Call,  98.00, 105.00, 0.00, 0.10, 0.5, 0.20, 45.8530, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 0.00, Option.Type.Call, 102.00,  95.00, 0.00, 0.10, 0.5, 0.20, 44.5294, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 0.00, Option.Type.Call,  98.00,  95.00, 0.00, 0.10, 0.5, 0.20, 54.9262, 1e-4),
                // 19,20
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 0.00, Option.Type.Put,  102.00, 105.00, 0.00, 0.10, 0.5, 0.20, 27.5644, 1e-4),
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 0.00, Option.Type.Put,   98.00, 105.00, 0.00, 0.10, 0.5, 0.20, 18.9896, 1e-4),
                // following value is wrong in book.
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 0.00, Option.Type.Put,  102.00,  95.00, 0.00, 0.10, 0.5, 0.20, 33.1723, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 0.00, Option.Type.Put,   98.00,  95.00, 0.00, 0.10, 0.5, 0.20, 22.7755, 1e-4),
                // 23,24
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 0.00, Option.Type.Call, 102.00, 105.00, 0.00, 0.10, 0.5, 0.20, 39.9391, 1e-4),
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 0.00, Option.Type.Call,  98.00, 105.00, 0.00, 0.10, 0.5, 0.20, 40.1574, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 0.00, Option.Type.Call, 102.00,  95.00, 0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 0.00, Option.Type.Call,  98.00,  95.00, 0.00, 0.10, 0.5, 0.20,  0.2676, 1e-4),
                // 27,28
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 0.00, Option.Type.Put,  102.00, 105.00, 0.00, 0.10, 0.5, 0.20,  0.2183, 1e-4),
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 0.00, Option.Type.Put,   98.00, 105.00, 0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 0.00, Option.Type.Put,  102.00,  95.00, 0.00, 0.10, 0.5, 0.20, 17.2983, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 0.00, Option.Type.Put,   98.00,  95.00, 0.00, 0.10, 0.5, 0.20, 17.0306, 1e-4),
            };

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

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

            for (int i = 0; i < values.Length; i++)
            {
                StrikedTypePayoff payoff = new AssetOrNothingPayoff(values[i].type, values[i].strike);
                Date     exDate          = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise amExercise      = new AmericanExercise(today, exDate, true);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine = new AnalyticBinaryBarrierEngine(stochProcess);

                BarrierOption opt = new BarrierOption(values[i].barrierType, values[i].barrier, 0, payoff, amExercise);

                opt.setPricingEngine(engine);

                double calculated = opt.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("value", payoff, amExercise, values[i].barrierType,
                                   values[i].barrier, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   values[i].result, calculated, error, values[i].tol);
                }
            }
        }
コード例 #11
0
ファイル: T_DividendOption.cs プロジェクト: tzhdingli/qlnet
        public void testFdEuropeanValues()
        {
            // Testing finite-difference dividend European option values...

            SavedSettings backup = new SavedSettings();

            double tolerance  = 1.0e-2;
            int    gridPoints = 300;
            int    timeSteps  = 40;

            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 };
            // Rate qRates[] = { 0.00, 0.10, 0.30 };
            // Analytic dividend may not be handling q correctly
            double[] qRates  = { 0.00 };
            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 FDDividendEuropeanEngine(stochProcess, timeSteps, gridPoints);

                        IPricingEngine ref_engine = new AnalyticDividendEuropeanEngine(stochProcess);

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

                        DividendVanillaOption ref_option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends);
                        ref_option.setPricingEngine(ref_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 calculated = option.NPV();
                                        if (calculated > spot.value() * 1.0e-5)
                                        {
                                            double expected = ref_option.NPV();
                                            double error    = Math.Abs(calculated - expected);
                                            if (error > tolerance)
                                            {
                                                REPORT_FAILURE("value", payoff, exercise,
                                                               u, q, r, today, v,
                                                               expected, calculated,
                                                               error, tolerance);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #12
0
        public void testBSMOperatorConsistency()
        {
            //("Testing consistency of BSM operators...");

            Vector grid   = new Vector(10);
            double price  = 20.0;
            double factor = 1.1;

            for (int i = 0; i < grid.size(); i++)
            {
                grid[i] = price;
                price  *= factor;
            }

            double dx    = Math.Log(factor);
            double r     = 0.05;
            double q     = 0.01;
            double sigma = 0.5;

            BSMOperator refer = new BSMOperator(grid.size(), dx, r, q, sigma);

            DayCounter dc           = new Actual360();
            Date       today        = Date.Today;
            Date       exercise     = today + new Period(2, TimeUnit.Years);
            double     residualTime = dc.yearFraction(today, exercise);

            SimpleQuote                    spot         = new SimpleQuote(0.0);
            YieldTermStructure             qTS          = Utilities.flatRate(today, q, dc);
            YieldTermStructure             rTS          = Utilities.flatRate(today, r, dc);
            BlackVolTermStructure          volTS        = Utilities.flatVol(today, sigma, dc);
            GeneralizedBlackScholesProcess stochProcess = new GeneralizedBlackScholesProcess(
                new Handle <Quote>(spot),
                new Handle <YieldTermStructure>(qTS),
                new Handle <YieldTermStructure>(rTS),
                new Handle <BlackVolTermStructure>(volTS));
            BSMOperator          op1 = new BSMOperator(grid, stochProcess, residualTime);
            PdeOperator <PdeBSM> op2 = new PdeOperator <PdeBSM>(grid, stochProcess, residualTime);

            double tolerance = 1.0e-6;
            Vector lderror   = refer.lowerDiagonal() - op1.lowerDiagonal();
            Vector derror    = refer.diagonal() - op1.diagonal();
            Vector uderror   = refer.upperDiagonal() - op1.upperDiagonal();

            for (int i = 2; i < grid.size() - 2; i++)
            {
                if (Math.Abs(lderror[i]) > tolerance ||
                    Math.Abs(derror[i]) > tolerance ||
                    Math.Abs(uderror[i]) > tolerance)
                {
                    Assert.Fail("inconsistency between BSM operators:\n"
                                + i + " row:\n"
                                + "expected:   "
                                + refer.lowerDiagonal()[i] + ", "
                                + refer.diagonal()[i] + ", "
                                + refer.upperDiagonal()[i] + "\n"
                                + "calculated: "
                                + op1.lowerDiagonal()[i] + ", "
                                + op1.diagonal()[i] + ", "
                                + op1.upperDiagonal()[i]);
                }
            }
            lderror = refer.lowerDiagonal() - op2.lowerDiagonal();
            derror  = refer.diagonal() - op2.diagonal();
            uderror = refer.upperDiagonal() - op2.upperDiagonal();

            for (int i = 2; i < grid.size() - 2; i++)
            {
                if (Math.Abs(lderror[i]) > tolerance ||
                    Math.Abs(derror[i]) > tolerance ||
                    Math.Abs(uderror[i]) > tolerance)
                {
                    Assert.Fail("inconsistency between BSM operators:\n"
                                + i + " row:\n"
                                + "expected:   "
                                + refer.lowerDiagonal()[i] + ", "
                                + refer.diagonal()[i] + ", "
                                + refer.upperDiagonal()[i] + "\n"
                                + "calculated: "
                                + op2.lowerDiagonal()[i] + ", "
                                + op2.diagonal()[i] + ", "
                                + op2.upperDiagonal()[i]);
                }
            }
        }
コード例 #13
0
        public void testCashAtHitOrNothingAmericanGreeks()
        {
            // Testing American cash-(at-hit)-or-nothing digital option greeks

            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);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #14
0
        public void testAnalyticContinuousPartialFixedLookback()
        {
            // Testing analytic continuous fixed-strike lookback options
            LookbackOptionData[] values =
            {
                // data from "Option Pricing Formulas, Second Edition", Haug, 2006, pg.148
                //type,         strike, minmax, s,    q,    r,    t,    v, l,   t1,  result,   tol
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.1, 0, 0.25, 20.2845, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.1, 0,  0.5, 19.6239, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.1, 0, 0.75, 18.6244, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.1, 0, 0.25,  4.0432, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.1, 0,  0.5,   3.958, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.1, 0, 0.75,  3.7015, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.2, 0, 0.25, 27.5385, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.2, 0,  0.5, 25.8126, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.2, 0, 0.75, 23.4957, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.2, 0, 0.25, 11.4895, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.2, 0,  0.5, 10.8995, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.2, 0, 0.75,  9.8244, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.3, 0, 0.25, 35.4578, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.3, 0,  0.5, 32.7172, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  90, 0, 100, 0, 0.06, 1, 0.3, 0, 0.75, 29.1473, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.3, 0, 0.25,  19.725, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.3, 0,  0.5, 18.4025, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 110, 0, 100, 0, 0.06, 1, 0.3, 0, 0.75, 16.2976, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.1, 0, 0.25,  0.4973, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.1, 0,  0.5,  0.4632, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.1, 0, 0.75,  0.3863, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.1, 0, 0.25, 12.6978, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.1, 0,  0.5, 10.9492, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.1, 0, 0.75,  9.1555, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.2, 0, 0.25,  4.5863, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.2, 0,  0.5,  4.1925, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.2, 0, 0.75,  3.5831, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.2, 0, 0.25, 19.0255, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.2, 0,  0.5, 16.9433, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.2, 0, 0.75, 14.6505, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.3, 0, 0.25,  9.9348, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.3, 0,  0.5,  9.1111, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   90, 0, 100, 0, 0.06, 1, 0.3, 0, 0.75,  7.9267, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.3, 0, 0.25, 25.2112, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.3, 0,  0.5, 22.8217, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  110, 0, 100, 0, 0.06, 1, 0.3, 0, 0.75, 20.0566, 1.0e-4)
            };

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

            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 < values.Length; i++)
            {
                Date     exDate   = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);

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

                IPricingEngine engine = new AnalyticContinuousPartialFixedLookbackEngine(stochProcess);

                Date lookbackStart = today + Convert.ToInt32(values[i].t1 * 360 + 0.5);
                ContinuousPartialFixedLookbackOption option = new ContinuousPartialFixedLookbackOption(lookbackStart,
                                                                                                       payoff, exercise);
                option.setPricingEngine(engine);

                double calculated = option.NPV();
                double expected   = values[i].result;
                double error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE_FIXED("value", values[i].minmax, payoff, exercise,
                                         values[i].s, values[i].q, values[i].r, today,
                                         values[i].v, expected, calculated, error,
                                         values[i].tol);
                }
            }
        }
コード例 #15
0
        public void testMonteCarloLookback()
        {
            double tolerance = 0.1;

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

            double strike = 90;
            double t      = 1;
            double t1     = 0.25;

            Date     exDate   = today + Convert.ToInt32(t * 360 + 0.5);
            Exercise exercise = new EuropeanExercise(exDate);

            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);

            spot.setValue(100);
            qRate.setValue(0);
            rRate.setValue(0.06);
            vol.setValue(0.1);

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

            Option.Type[] types = new Option.Type[] { Option.Type.Call, Option.Type.Put };

            for (int i = 0; i < types.Length; i++)
            {
                Option.Type type = types[i];

                StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);

                /**
                 * Partial Fixed
                 * **/

                Date lookbackStart = today + Convert.ToInt32(t1 * 360 + 0.5);
                ContinuousPartialFixedLookbackOption partialFixedLookback
                    = new ContinuousPartialFixedLookbackOption(lookbackStart,
                                                               payoff,
                                                               exercise);
                IPricingEngine engine =
                    new AnalyticContinuousPartialFixedLookbackEngine(stochProcess);

                partialFixedLookback.setPricingEngine(engine);

                double analytical = partialFixedLookback.NPV();

                IPricingEngine mcpartialfixedengine =
                    new MakeMCLookbackEngine <ContinuousPartialFixedLookbackOption.Arguments, ContinuousPartialFixedLookbackOption.Results,
                                              PseudoRandom, Statistics>(stochProcess)
                    .withSteps(2000)
                    .withAntitheticVariate()
                    .withSeed(1)
                    .withAbsoluteTolerance(tolerance)
                    .value();

                partialFixedLookback.setPricingEngine(mcpartialfixedengine);
                double monteCarlo = partialFixedLookback.NPV();

                double diff = Math.Abs(analytical - monteCarlo);

                if (diff > tolerance)
                {
                    REPORT_FAILURE_MC("Partial Fixed", type, analytical, monteCarlo, tolerance);
                }

                /**
                 * Fixed
                 * **/

                double minMax = 100;

                ContinuousFixedLookbackOption fixedLookback
                    = new ContinuousFixedLookbackOption(minMax,
                                                        payoff,
                                                        exercise);
                IPricingEngine analyticalfixedengine =
                    new AnalyticContinuousFixedLookbackEngine(stochProcess);

                fixedLookback.setPricingEngine(analyticalfixedengine);
                analytical = fixedLookback.NPV();

                IPricingEngine mcfixedengine =
                    new MakeMCLookbackEngine <ContinuousFixedLookbackOption.Arguments, ContinuousFixedLookbackOption.Results,
                                              PseudoRandom, Statistics>(stochProcess)
                    .withSteps(2000)
                    .withAntitheticVariate()
                    .withSeed(1)
                    .withAbsoluteTolerance(tolerance)
                    .value();

                fixedLookback.setPricingEngine(mcfixedengine);
                monteCarlo = fixedLookback.NPV();

                diff = Math.Abs(analytical - monteCarlo);

                if (diff > tolerance)
                {
                    REPORT_FAILURE_MC("Fixed", type, analytical, monteCarlo, tolerance);
                }

                /**
                 * Partial Floating
                 * **/

                double lambda      = 1;
                Date   lookbackEnd = today + Convert.ToInt32(t1 * 360 + 0.5);

                FloatingTypePayoff floatingPayoff = new FloatingTypePayoff(type);

                ContinuousPartialFloatingLookbackOption partialFloating
                    = new ContinuousPartialFloatingLookbackOption(minMax,
                                                                  lambda,
                                                                  lookbackEnd,
                                                                  floatingPayoff,
                                                                  exercise);
                IPricingEngine analyticalpartialFloatingengine =
                    new AnalyticContinuousPartialFloatingLookbackEngine(stochProcess);
                partialFloating.setPricingEngine(analyticalpartialFloatingengine);

                analytical = partialFloating.NPV();

                IPricingEngine mcpartialfloatingengine =
                    new MakeMCLookbackEngine <ContinuousPartialFloatingLookbackOption.Arguments, ContinuousPartialFloatingLookbackOption.Results,
                                              PseudoRandom, Statistics>
                        (stochProcess)
                    .withSteps(2000)
                    .withAntitheticVariate()
                    .withSeed(1)
                    .withAbsoluteTolerance(tolerance)
                    .value();

                partialFloating.setPricingEngine(mcpartialfloatingengine);
                monteCarlo = partialFloating.NPV();

                diff = Math.Abs(analytical - monteCarlo);

                if (diff > tolerance)
                {
                    REPORT_FAILURE_MC("Partial Floating", type, analytical, monteCarlo, tolerance);
                }

                /**
                 * Floating
                 * **/

                ContinuousFloatingLookbackOption floating =
                    new ContinuousFloatingLookbackOption(minMax,
                                                         floatingPayoff,
                                                         exercise);
                IPricingEngine analyticalFloatingengine =
                    new AnalyticContinuousFloatingLookbackEngine(stochProcess);
                floating.setPricingEngine(analyticalFloatingengine);

                analytical = floating.NPV();

                IPricingEngine mcfloatingengine =
                    new MakeMCLookbackEngine <ContinuousFloatingLookbackOption.Arguments, ContinuousFloatingLookbackOption.Results,
                                              PseudoRandom, Statistics>
                        (stochProcess)
                    .withSteps(2000)
                    .withAntitheticVariate()
                    .withSeed(1)
                    .withAbsoluteTolerance(tolerance)
                    .value();

                floating.setPricingEngine(mcfloatingengine);
                monteCarlo = floating.NPV();

                diff = Math.Abs(analytical - monteCarlo);

                if (diff > tolerance)
                {
                    REPORT_FAILURE_MC("Floating", type, analytical, monteCarlo, tolerance);
                }
            }
        }
コード例 #16
0
        public void testAnalyticContinuousPartialFloatingLookback()
        {
            // Testing analytic continuous partial floating-strike lookback options...");
            LookbackOptionData[] values =
            {
                // data from "Option Pricing Formulas, Second Edition", Haug, 2006, pg.146

                //type,         strike, minmax, s,    q,    r,    t,    v,    l,  t1,     result,   tol
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.1, 1, 0.25,  8.6524, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.1, 1,  0.5,  9.2128, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.1, 1, 0.75,  9.5567, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.25, 10.5751, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.1, 1,  0.5, 11.2601, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.75, 11.6804, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.2, 1, 0.25, 13.3402, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.2, 1,  0.5, 14.5121, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.2, 1, 0.75,  15.314, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.25, 16.3047, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.2, 1,  0.5,  17.737, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.75, 18.7171, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.3, 1, 0.25, 17.9831, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.3, 1,  0.5, 19.6618, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0,  90,  90, 0, 0.06, 1, 0.3, 1, 0.75, 20.8493, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.25, 21.9793, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.3, 1,  0.5, 24.0311, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.75, 25.4825, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.1, 1, 0.25,  2.7189, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.1, 1,  0.5,  3.4639, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.1, 1, 0.75,  4.1912, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.25,  3.3231, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.1, 1,  0.5,  4.2336, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.1, 1, 0.75,  5.1226, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.2, 1, 0.25,  7.9153, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.2, 1,  0.5,  9.5825, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.2, 1, 0.75, 11.0362, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.25,  9.6743, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.2, 1,  0.5, 11.7119, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.2, 1, 0.75, 13.4887, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.3, 1, 0.25, 13.4719, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.3, 1,  0.5, 16.1495, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0,  90,  90, 0, 0.06, 1, 0.3, 1, 0.75, 18.4071, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.25, 16.4657, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.3, 1,  0.5, 19.7383, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 110, 0, 0.06, 1, 0.3, 1, 0.75, 22.4976, 1.0e-4)
            };

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

            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 < values.Length; i++)
            {
                Date     exDate   = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

                FloatingTypePayoff payoff = new FloatingTypePayoff(values[i].type);

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

                IPricingEngine engine = new AnalyticContinuousPartialFloatingLookbackEngine(stochProcess);

                Date lookbackEnd = today + Convert.ToInt32(values[i].t1 * 360 + 0.5);
                ContinuousPartialFloatingLookbackOption option = new ContinuousPartialFloatingLookbackOption(
                    values[i].minmax, values[i].l, lookbackEnd, payoff, exercise);
                option.setPricingEngine(engine);

                double calculated = option.NPV();
                double expected   = values[i].result;
                double error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE_FLOATING("value", values[i].minmax, payoff,
                                            exercise, values[i].s, values[i].q,
                                            values[i].r, today, values[i].v,
                                            expected, calculated, error,
                                            values[i].tol);
                }
            }
        }
コード例 #17
0
        public void testAnalyticContinuousFixedLookback()
        {
            // Testing analytic continuous fixed-strike lookback options
            LookbackOptionData[] values =
            {
                // data from "Option Pricing Formulas", Haug, 1998, pg.63-64
                //type,            strike, minmax,  s,     q,    r,    t,    v,    l, t1, result,  tol
                new LookbackOptionData(Option.Type.Call,  95, 100, 100.0, 0.00, 0.10, 0.50, 0.10, 0, 0, 13.2687, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  95, 100, 100.0, 0.00, 0.10, 0.50, 0.20, 0, 0, 18.9263, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  95, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 24.9857, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 100, 100, 100.0, 0.00, 0.10, 0.50, 0.10, 0, 0,  8.5126, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 100, 100, 100.0, 0.00, 0.10, 0.50, 0.20, 0, 0, 14.1702, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 100, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 20.2296, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 105, 100, 100.0, 0.00, 0.10, 0.50, 0.10, 0, 0,  4.3908, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 105, 100, 100.0, 0.00, 0.10, 0.50, 0.20, 0, 0,  9.8905, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 105, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 15.8512, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  95, 100, 100.0, 0.00, 0.10, 1.00, 0.10, 0, 0, 18.3241, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  95, 100, 100.0, 0.00, 0.10, 1.00, 0.20, 0, 0, 26.0731, 1.0e-4),
                new LookbackOptionData(Option.Type.Call,  95, 100, 100.0, 0.00, 0.10, 1.00, 0.30, 0, 0, 34.7116, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 100, 100, 100.0, 0.00, 0.10, 1.00, 0.10, 0, 0, 13.8000, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 100, 100, 100.0, 0.00, 0.10, 1.00, 0.20, 0, 0, 21.5489, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 100, 100, 100.0, 0.00, 0.10, 1.00, 0.30, 0, 0, 30.1874, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 105, 100, 100.0, 0.00, 0.10, 1.00, 0.10, 0, 0,  9.5445, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 105, 100, 100.0, 0.00, 0.10, 1.00, 0.20, 0, 0, 17.2965, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 105, 100, 100.0, 0.00, 0.10, 1.00, 0.30, 0, 0, 25.9002, 1.0e-4),

                new LookbackOptionData(Option.Type.Put,   95, 100, 100.0, 0.00, 0.10, 0.50, 0.10, 0, 0,  0.6899, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   95, 100, 100.0, 0.00, 0.10, 0.50, 0.20, 0, 0,  4.4448, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   95, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0,  8.9213, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  100, 100, 100.0, 0.00, 0.10, 0.50, 0.10, 0, 0,  3.3917, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  100, 100, 100.0, 0.00, 0.10, 0.50, 0.20, 0, 0,  8.3177, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  100, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 13.1579, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  105, 100, 100.0, 0.00, 0.10, 0.50, 0.10, 0, 0,  8.1478, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  105, 100, 100.0, 0.00, 0.10, 0.50, 0.20, 0, 0, 13.0739, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  105, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 17.9140, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   95, 100, 100.0, 0.00, 0.10, 1.00, 0.10, 0, 0,  1.0534, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   95, 100, 100.0, 0.00, 0.10, 1.00, 0.20, 0, 0,  6.2813, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,   95, 100, 100.0, 0.00, 0.10, 1.00, 0.30, 0, 0, 12.2376, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  100, 100, 100.0, 0.00, 0.10, 1.00, 0.10, 0, 0,  3.8079, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  100, 100, 100.0, 0.00, 0.10, 1.00, 0.20, 0, 0, 10.1294, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  100, 100, 100.0, 0.00, 0.10, 1.00, 0.30, 0, 0, 16.3889, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  105, 100, 100.0, 0.00, 0.10, 1.00, 0.10, 0, 0,  8.3321, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  105, 100, 100.0, 0.00, 0.10, 1.00, 0.20, 0, 0, 14.6536, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  105, 100, 100.0, 0.00, 0.10, 1.00, 0.30, 0, 0, 20.9130, 1.0e-4)
            };

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

            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 < values.Length; i++)
            {
                Date     exDate   = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);

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

                IPricingEngine engine = new AnalyticContinuousFixedLookbackEngine(stochProcess);

                ContinuousFixedLookbackOption option = new ContinuousFixedLookbackOption(values[i].minmax,
                                                                                         payoff, exercise);
                option.setPricingEngine(engine);

                double calculated = option.NPV();
                double expected   = values[i].result;
                double error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE_FIXED("value", values[i].minmax, payoff, exercise,
                                         values[i].s, values[i].q, values[i].r, today,
                                         values[i].v, expected, calculated, error,
                                         values[i].tol);
                }
            }
        }
コード例 #18
0
        public void testAnalyticContinuousFloatingLookback()
        {
            // Testing analytic continuous floating-strike lookback options
            LookbackOptionData[] values =
            {
                // data from "Option Pricing Formulas", Haug, 1998, pg.61-62
                new LookbackOptionData(Option.Type.Call, 0, 100, 120.0, 0.06, 0.10, 0.50, 0.30, 0, 0, 25.3533, 1.0e-4),
                // data from "Connecting discrete and continuous path-dependent options",
                // Broadie, Glasserman & Kou, 1999, pg.70-74
                new LookbackOptionData(Option.Type.Call, 0, 100, 100.0, 0.00, 0.05, 1.00, 0.30, 0, 0, 23.7884, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 100, 100.0, 0.00, 0.05, 0.20, 0.30, 0, 0, 10.7190, 1.0e-4),
                new LookbackOptionData(Option.Type.Call, 0, 100, 110.0, 0.00, 0.05, 0.20, 0.30, 0, 0, 14.4597, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 100, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 15.3526, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 110, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 16.8468, 1.0e-4),
                new LookbackOptionData(Option.Type.Put,  0, 120, 100.0, 0.00, 0.10, 0.50, 0.30, 0, 0, 21.0645, 1.0e-4),
            };

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

            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 < values.Length; i++)
            {
                Date     exDate   = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

                FloatingTypePayoff payoff = new FloatingTypePayoff(values[i].type);

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

                IPricingEngine engine = new AnalyticContinuousFloatingLookbackEngine(stochProcess);

                ContinuousFloatingLookbackOption option = new ContinuousFloatingLookbackOption(values[i].minmax,
                                                                                               payoff,
                                                                                               exercise);
                option.setPricingEngine(engine);

                double calculated = option.NPV();
                double expected   = values[i].result;
                double error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE_FLOATING("value", values[i].minmax, payoff,
                                            exercise, values[i].s, values[i].q,
                                            values[i].r, today, values[i].v,
                                            expected, calculated, error,
                                            values[i].tol);
                }
            }
        }
コード例 #19
0
        public void testCashAtExpiryOrNothingAmericanValues()
        {
            // Testing American cash-(at-expiry)-or-nothing digital option

            DigitalOptionData[] values =
            {
                //        type, strike,   spot,    q,    r,   t,  vol,   value, tol
                // "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 - pag 95, case 5,6,9,10
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.00, 0.10,  0.5,  0.20,                    9.3604,  1e-4, true),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.00, 0.10,  0.5,  0.20,                   11.2223,  1e-4, true),
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.00, 0.10,  0.5,  0.20,                    4.9081,  1e-4, false),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.00, 0.10,  0.5,  0.20,                    3.0461,  1e-4, false),
                // in the money options (guaranteed discounted payoff)
                new DigitalOptionData(Option.Type.Call, 100.00, 105.00, 0.00, 0.10,  0.5,  0.20, 15.0000 * Math.Exp(-0.05), 1e-12, true),
                new DigitalOptionData(Option.Type.Put,  100.00,  95.00, 0.00, 0.10,  0.5,  0.20, 15.0000 * Math.Exp(-0.05), 1e-12, true),
                // out of bonds case
                new DigitalOptionData(Option.Type.Call,   2.37,   2.33, 0.07, 0.43, 0.19, 0.005,                    0.0000,  1e-4, false),
            };

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

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

            for (int i = 0; i < values.Length; i++)
            {
                StrikedTypePayoff payoff = new CashOrNothingPayoff(values[i].type, values[i].strike, 15.0);

                Date     exDate     = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise amExercise = new AmericanExercise(today, exDate, true);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine;
                if (values[i].knockin)
                {
                    engine = new AnalyticDigitalAmericanEngine(stochProcess);
                }
                else
                {
                    engine = new AnalyticDigitalAmericanKOEngine(stochProcess);
                }

                VanillaOption opt = new VanillaOption(payoff, amExercise);
                opt.setPricingEngine(engine);

                double calculated = opt.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("value", payoff, amExercise, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   values[i].result, calculated, error, values[i].tol, values[i].knockin);
                }
            }
        }
コード例 #20
0
        public void testEuropeanHaugValues()
        {
            // Testing double barrier european options against Haug's values

            Exercise.Type          european = Exercise.Type.European;
            NewBarrierOptionData[] values   =
            {
                /* The data below are from
                 * "The complete guide to option pricing formulas 2nd Ed",E.G. Haug, McGraw-Hill, p.156 and following.
                 *
                 * Note:
                 * The book uses b instead of q (q=r-b)
                 */
                //           BarrierType, barr.lo,  barr.hi,         type, exercise,strk,     s,   q,   r,    t,    v,  result, tol
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  4.3515, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  6.1644, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  7.0373, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  6.9853, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  7.9336, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  6.5088, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  4.3505, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  5.8500, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  5.7726, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  6.8082, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  6.3383, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  4.3841, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  4.3139, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  4.8293, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  3.7765, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  5.9697, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  4.0004, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  2.2563, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  3.7516, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  2.6387, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  1.4903, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  3.5805, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  1.5098, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  0.5635, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  1.2055, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  0.3098, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  0.0477, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  0.5537, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  0.0441, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  0.0011, 1.0e-4),

                //           BarrierType, barr.lo,  barr.hi,         type, exercise,strk,     s,   q,   r,    t,    v,  result, tol
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  1.8825, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  3.7855, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  5.7191, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  2.1374, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  4.7033, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 50.0, 150.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  7.1683, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  1.8825, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  3.7845, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  5.6060, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  2.1374, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  4.6236, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 60.0, 140.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  6.1062, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  1.8825, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  3.7014, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  4.6472, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  2.1325, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  3.8944, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 70.0, 130.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  3.5868, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  1.8600, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  2.6866, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  2.0719, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  1.8883, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  1.7851, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 80.0, 120.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  0.8244, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  0.9473, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  0.3449, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  0.0578, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  0.4555, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  0.0491, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockOut, 90.0, 110.0, Option.Type.Put,  european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  0.0013, 1.0e-4),

                //           BarrierType, barr.lo,  barr.hi,         type,  strk,     s,   q,   r,    t,    v,  result, tol
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  0.0000, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  0.0900, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  1.1537, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  0.0292, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  1.6487, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  50.0, 150.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  5.7321, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  0.0010, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  0.4045, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  2.4184, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  0.2062, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  3.2439, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  60.0, 140.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  7.8569, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  0.0376, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  1.4252, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  4.4145, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  1.0447, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  5.5818, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  70.0, 130.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35,  9.9846, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  0.5999, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  3.6158, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  6.7007, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  3.4340, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  8.0724, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  80.0, 120.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35, 11.6774, 1.0e-4),

                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.15,  3.1460, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.25,  5.9447, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.25, 0.35,  8.1432, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.15,  6.4608, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.25,  9.5382, 1.0e-4),
                new NewBarrierOptionData(DoubleBarrier.Type.KnockIn,  90.0, 110.0, Option.Type.Call, european, 100, 100.0, 0.0, 0.1, 0.50, 0.35, 12.2398, 1.0e-4),
            };

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

            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 < values.Length; i++)
            {
                Date     exDate   = today + (int)(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);

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

                DoubleBarrierOption opt = new DoubleBarrierOption(values[i].barrierType, values[i].barrierlo,
                                                                  values[i].barrierhi, 0, // no rebate
                                                                  payoff, exercise);

                // Ikeda/Kunitomo engine
                IPricingEngine engine = new AnalyticDoubleBarrierEngine(stochProcess);
                opt.setPricingEngine(engine);

                double calculated = opt.NPV();
                double expected   = values[i].result;
                double error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("Ikeda/Kunitomo value", values[i].barrierType, values[i].barrierlo,
                                   values[i].barrierhi, payoff, exercise, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   expected, calculated, error, values[i].tol);
                }

                // Wulin Suo/Yong Wang engine
                engine = new WulinYongDoubleBarrierEngine(stochProcess);
                opt.setPricingEngine(engine);

                calculated = opt.NPV();
                expected   = values[i].result;
                error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("Wulin/Yong value", values[i].barrierType, values[i].barrierlo,
                                   values[i].barrierhi, payoff, exercise, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   expected, calculated, error, values[i].tol);
                }
            }
        }
コード例 #21
0
        public void testAssetAtExpiryOrNothingAmericanValues()
        {
            // Testing American asset-(at-expiry)-or-nothing digital option

            DigitalOptionData[] values =
            {
                //        type, strike,   spot,    q,    r,   t,  vol,   value, tol
                // "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 - pag 95, case 7,8,11,12
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.00, 0.10, 0.5, 0.20,                     64.8426, 1e-04, true),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.00, 0.10, 0.5, 0.20,                     77.7017, 1e-04, true),
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.00, 0.10, 0.5, 0.20,                     40.1574, 1e-04, false),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.00, 0.10, 0.5, 0.20,                     17.2983, 1e-04, false),
                // data from Haug VBA code results
                new DigitalOptionData(Option.Type.Put,  100.00, 105.00, 0.01, 0.10, 0.5, 0.20,                     65.5291, 1e-04, true),
                new DigitalOptionData(Option.Type.Call, 100.00,  95.00, 0.01, 0.10, 0.5, 0.20,                     76.5951, 1e-04, true),
                // in the money options (guaranteed discounted payoff = forward * riskFreeDiscount
                //                                                    = spot * dividendDiscount)
                new DigitalOptionData(Option.Type.Call, 100.00, 105.00, 0.00, 0.10, 0.5, 0.20,                    105.0000, 1e-12, true),
                new DigitalOptionData(Option.Type.Put,  100.00,  95.00, 0.00, 0.10, 0.5, 0.20,                     95.0000, 1e-12, true),
                new DigitalOptionData(Option.Type.Call, 100.00, 105.00, 0.01, 0.10, 0.5, 0.20, 105.0000 * Math.Exp(-0.005), 1e-12, true),
                new DigitalOptionData(Option.Type.Put,  100.00,  95.00, 0.01, 0.10, 0.5, 0.20,  95.0000 * Math.Exp(-0.005), 1e-12, true)
            };

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

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

            for (int i = 0; i < values.Length; i++)
            {
                StrikedTypePayoff payoff = new AssetOrNothingPayoff(values[i].type, values[i].strike);

                Date     exDate     = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise amExercise = new AmericanExercise(today, exDate, true);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine;
                if (values[i].knockin)
                {
                    engine = new AnalyticDigitalAmericanEngine(stochProcess);
                }
                else
                {
                    engine = new AnalyticDigitalAmericanKOEngine(stochProcess);
                }

                VanillaOption opt = new VanillaOption(payoff, amExercise);
                opt.setPricingEngine(engine);

                double calculated = opt.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("value", payoff, amExercise, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   values[i].result, calculated, error, values[i].tol, values[i].knockin);
                }
            }
        }
コード例 #22
0
        public void testPathGenerator()
        {
            //"Testing 1-D path generation against cached values...");

            //SavedSettings backup;

            Settings.setEvaluationDate(new Date(26, 4, 2005));

            Handle <Quote> x0 = new Handle <Quote> (new SimpleQuote(100.0));
            Handle <YieldTermStructure>    r     = new Handle <YieldTermStructure> (Utilities.flatRate(0.05, new Actual360()));
            Handle <YieldTermStructure>    q     = new Handle <YieldTermStructure> (Utilities.flatRate(0.02, new Actual360()));
            Handle <BlackVolTermStructure> sigma = new Handle <BlackVolTermStructure>(Utilities.flatVol(0.20, new Actual360()));

            // commented values must be used when Halley's correction is enabled
            testSingle(new BlackScholesMertonProcess(x0, q, r, sigma),
                       "Black-Scholes", false, 26.13784357783, 467.2928561411);
            // 26.13784357783, 467.2928562519);
            //Error make the borwnian bridge test first
            testSingle(new BlackScholesMertonProcess(x0, q, r, sigma),
                       "Black-Scholes", true, 60.28215549393, 202.6143139999);
            // 60.28215551021, 202.6143139437);

            testSingle(new GeometricBrownianMotionProcess(100.0, 0.03, 0.20),
                       "geometric Brownian", false, 27.62223714065, 483.6026514084);
            // 27.62223714065, 483.602651493);

            testSingle(new OrnsteinUhlenbeckProcess(0.1, 0.20),
                       "Ornstein-Uhlenbeck", false, -0.8372003433557, 0.8372003433557);

            testSingle(new SquareRootProcess(0.1, 0.1, 0.20, 10.0),
                       "square-root", false, 1.70608664108, 6.024200546031);
        }
コード例 #23
0
ファイル: T_DividendOption.cs プロジェクト: tzhdingli/qlnet
        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);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #24
0
ファイル: T_DividendOption.cs プロジェクト: tzhdingli/qlnet
        public void testEuropeanStartLimit()
        {
            // Testing dividend European option with a dividend on today's date...

            SavedSettings backup = new SavedSettings();

            double tolerance     = 1.0e-5;
            double dividendValue = 10.0;

            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.70 };

            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>();
                        dividendDates.Add(today);
                        dividends.Add(dividendValue);

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

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

                        IPricingEngine engine = new AnalyticDividendEuropeanEngine(stochProcess);

                        IPricingEngine ref_engine = new AnalyticEuropeanEngine(stochProcess);

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

                        VanillaOption ref_option = new VanillaOption(payoff, exercise);
                        ref_option.setPricingEngine(ref_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 calculated = option.NPV();
                                        spot.setValue(u - dividendValue);
                                        double expected = ref_option.NPV();
                                        double error    = Math.Abs(calculated - expected);
                                        if (error > tolerance)
                                        {
                                            REPORT_FAILURE("value", payoff, exercise,
                                                           u, q, r, today, v,
                                                           expected, calculated,
                                                           error, tolerance);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #25
0
        public void testCashOrNothingHaugValues()
        {
            // Testing cash-or-nothing barrier options against Haug's values

            BinaryOptionData[] values =
            {
                /* The data below are from
                 * "Option pricing formulas 2nd Ed.", E.G. Haug, McGraw-Hill 2007 pag. 180 - cases 13,14,17,18,21,22,25,26
                 * Note:
                 * q is the dividend rate, while the book gives b, the cost of carry (q=r-b)
                 */
                //    barrierType, barrier,  cash,         type, strike,   spot,    q,    r,   t,  vol,   value, tol
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 15.00, Option.Type.Call, 102.00, 105.00,  0.00, 0.10, 0.5, 0.20,  4.9289, 1e-4),
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 15.00, Option.Type.Call,  98.00, 105.00,  0.00, 0.10, 0.5, 0.20,  6.2150, 1e-4),
                // following value is wrong in book.
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Call, 102.00,  95.00,  0.00, 0.10, 0.5, 0.20,  5.8926, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Call,  98.00,  95.00,  0.00, 0.10, 0.5, 0.20,  7.4519, 1e-4),
                // 17,18
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 15.00, Option.Type.Put,  102.00, 105.00,  0.00, 0.10, 0.5, 0.20,  4.4314, 1e-4),
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 15.00, Option.Type.Put,   98.00, 105.00,  0.00, 0.10, 0.5, 0.20,  3.1454, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Put,  102.00,  95.00,  0.00, 0.10, 0.5, 0.20,  5.3297, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Put,   98.00,  95.00,  0.00, 0.10, 0.5, 0.20,  3.7704, 1e-4),
                // 21,22
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 15.00, Option.Type.Call, 102.00, 105.00,  0.00, 0.10, 0.5, 0.20,  4.8758, 1e-4),
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 15.00, Option.Type.Call,  98.00, 105.00,  0.00, 0.10, 0.5, 0.20,  4.9081, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 15.00, Option.Type.Call, 102.00,  95.00,  0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 15.00, Option.Type.Call,  98.00,  95.00,  0.00, 0.10, 0.5, 0.20,  0.0407, 1e-4),
                // 25,26
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 15.00, Option.Type.Put,  102.00, 105.00,  0.00, 0.10, 0.5, 0.20,  0.0323, 1e-4),
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 15.00, Option.Type.Put,   98.00, 105.00,  0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 15.00, Option.Type.Put,  102.00,  95.00,  0.00, 0.10, 0.5, 0.20,  3.0461, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 15.00, Option.Type.Put,   98.00,  95.00,  0.00, 0.10, 0.5, 0.20,  3.0054, 1e-4),

                // other values calculated with book vba
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Call, 102.00,  95.00, -0.14, 0.10, 0.5, 0.20,  8.6806, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Call, 102.00,  95.00,  0.03, 0.10, 0.5, 0.20,  5.3112, 1e-4),
                // degenerate conditions (barrier touched)
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 15.00, Option.Type.Call,  98.00,  95.00,  0.00, 0.10, 0.5, 0.20,  7.4926, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Call,  98.00, 105.00,  0.00, 0.10, 0.5, 0.20, 11.1231, 1e-4),
                // 17,18
                new BinaryOptionData(Barrier.Type.DownIn,  100.00, 15.00, Option.Type.Put,  102.00,  98.00,  0.00, 0.10, 0.5, 0.20,  7.1344, 1e-4),
                new BinaryOptionData(Barrier.Type.UpIn,    100.00, 15.00, Option.Type.Put,  102.00, 101.00,  0.00, 0.10, 0.5, 0.20,  5.9299, 1e-4),
                // 21,22
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 15.00, Option.Type.Call,  98.00,  99.00,  0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 15.00, Option.Type.Call,  98.00, 101.00,  0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                // 25,26
                new BinaryOptionData(Barrier.Type.DownOut, 100.00, 15.00, Option.Type.Put,   98.00,  99.00,  0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
                new BinaryOptionData(Barrier.Type.UpOut,   100.00, 15.00, Option.Type.Put,   98.00, 101.00,  0.00, 0.10, 0.5, 0.20,  0.0000, 1e-4),
            };

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

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

            for (int i = 0; i < values.Length; i++)
            {
                StrikedTypePayoff payoff = new CashOrNothingPayoff(values[i].type, values[i].strike, values[i].cash);

                Date     exDate     = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise amExercise = new AmericanExercise(today, exDate, true);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine = new AnalyticBinaryBarrierEngine(stochProcess);

                BarrierOption opt = new BarrierOption(values[i].barrierType, values[i].barrier, 0, payoff, amExercise);

                opt.setPricingEngine(engine);

                double calculated = opt.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE("value", payoff, amExercise, values[i].barrierType,
                                   values[i].barrier, values[i].s,
                                   values[i].q, values[i].r, today, values[i].v,
                                   values[i].result, calculated, error, values[i].tol);
                }
            }
        }
コード例 #26
0
ファイル: T_BasketOption.cs プロジェクト: tzhdingli/qlnet
        public void testEuroTwoValues()
        {
            // Testing two-asset European basket options...

            /*
             * Data from:
             * Excel spreadsheet www.maths.ox.ac.uk/~firth/computing/excel.shtml
             * and
             * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 56-58
             * European two asset max basket options
             */
            BasketOptionTwoData[] values =
            {
                // basketType,   optionType, strike,    s1,    s2,   q1,   q2,    r,    t,   v1,   v2,  rho, result, tol
                // data from http://www.maths.ox.ac.uk/~firth/computing/excel.shtml
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90,  10.898, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70,   8.483, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50,   6.844, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,   5.531, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10,   4.413, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.70, 0.00,   4.981, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.30, 0.00,   4.159, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.10, 0.00,   2.597, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.50, 0.10, 0.50,   4.030, 1.0e-3),

                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90,  17.565, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70,  19.980, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50,  21.619, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,  22.932, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10,  24.049, 1.1e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0,  80.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,  16.508, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0,  80.0,  80.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,   8.049, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0,  80.0, 120.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,  30.141, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call, 100.0, 120.0, 120.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,  42.889, 1.0e-3),

                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90,  11.369, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70,  12.856, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50,  13.890, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,  14.741, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10,  15.485, 1.0e-3),

                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 0.50, 0.30, 0.30, 0.10,  11.893, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 0.25, 0.30, 0.30, 0.10,   8.881, 1.0e-3),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 2.00, 0.30, 0.30, 0.10,  19.268, 1.0e-3),

                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.90,   7.339, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.70,   5.853, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.50,   4.818, 1.0e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.30,   3.967, 1.1e-3),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,  100.0, 100.0, 100.0, 0.00, 0.00, 0.05, 1.00, 0.30, 0.30, 0.10,   3.223, 1.0e-3),

                //      basketType,   optionType, strike,    s1,    s2,   q1,   q2,    r,    t,   v1,   v2,  rho,  result, tol
                // data from "Option pricing formulas" VB code + spreadsheet
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call,  98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63,  4.8177, 1.0e-4),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call,  98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63, 11.6323, 1.0e-4),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,   98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63,  2.0376, 1.0e-4),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,   98.0, 100.0, 105.0, 0.00, 0.00, 0.05, 0.50, 0.11, 0.16, 0.63,  0.5731, 1.0e-4),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Call,  98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63,  2.9340, 1.0e-4),
                new BasketOptionTwoData(BasketType.MinBasket,    Option.Type.Put,   98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63,  3.5224, 1.0e-4),
                // data from "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 58
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Call,  98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63,  8.0701, 1.0e-4),
                new BasketOptionTwoData(BasketType.MaxBasket,    Option.Type.Put,   98.0, 100.0, 105.0, 0.06, 0.09, 0.05, 0.50, 0.11, 0.16, 0.63,  1.2181, 1.0e-4),

                /* "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 59-60
                 * Kirk approx. for a european spread option on two futures*/

                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.20, 0.20, -0.5,  4.7530, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.20, 0.20,  0.0,  3.7970, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.20, 0.20,  0.5,  2.5537, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.25, 0.20, -0.5,  5.4275, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.25, 0.20,  0.0,  4.3712, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.25, 0.20,  0.5,  3.0086, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.20, 0.25, -0.5,  5.4061, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.20, 0.25,  0.0,  4.3451, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.1, 0.20, 0.25,  0.5,  2.9723, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.20, 0.20, -0.5, 10.7517, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.20, 0.20,  0.0,  8.7020, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.20, 0.20,  0.5,  6.0257, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.25, 0.20, -0.5, 12.1941, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.25, 0.20,  0.0,  9.9340, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.25, 0.20,  0.5,  7.0067, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.20, 0.25, -0.5, 12.1483, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.20, 0.25,  0.0,  9.8780, 1.0e-3),
                new BasketOptionTwoData(BasketType.SpreadBasket, Option.Type.Call,   3.0, 122.0, 120.0,  0.0,  0.0, 0.10,  0.5, 0.20, 0.25,  0.5,  6.9284, 1.0e-3)
            };

            DayCounter dc = new Actual360();


            Date today = Date.Today;

            SimpleQuote spot1 = new SimpleQuote(0.0);
            SimpleQuote spot2 = new SimpleQuote(0.0);

            SimpleQuote        qRate1 = new SimpleQuote(0.0);
            YieldTermStructure qTS1   = Utilities.flatRate(today, qRate1, dc);
            SimpleQuote        qRate2 = new SimpleQuote(0.0);
            YieldTermStructure qTS2   = Utilities.flatRate(today, qRate2, dc);

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

            SimpleQuote           vol1   = new SimpleQuote(0.0);
            BlackVolTermStructure volTS1 = Utilities.flatVol(today, vol1, dc);
            SimpleQuote           vol2   = new SimpleQuote(0.0);
            BlackVolTermStructure volTS2 = Utilities.flatVol(today, vol2, dc);

            //double mcRelativeErrorTolerance = 0.01;
            //double fdRelativeErrorTolerance = 0.01;

            for (int i = 0; i < values.Length; i++)
            {
                PlainVanillaPayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);

                Date     exDate   = today + (int)(values[i].t * 360 + 0.5);
                Exercise exercise = new EuropeanExercise(exDate);

                spot1.setValue(values[i].s1);
                spot2.setValue(values[i].s2);
                qRate1.setValue(values[i].q1);
                qRate2.setValue(values[i].q2);
                rRate.setValue(values[i].r);
                vol1.setValue(values[i].v1);
                vol2.setValue(values[i].v2);


                IPricingEngine analyticEngine = null;
                GeneralizedBlackScholesProcess p1 = null, p2 = null;

                switch (values[i].basketType)
                {
                case BasketType.MaxBasket:
                case BasketType.MinBasket:
                    p1 = new BlackScholesMertonProcess(new Handle <Quote>(spot1),
                                                       new Handle <YieldTermStructure>(qTS1),
                                                       new Handle <YieldTermStructure>(rTS),
                                                       new Handle <BlackVolTermStructure>(volTS1));
                    p2 = new BlackScholesMertonProcess(new Handle <Quote>(spot2),
                                                       new Handle <YieldTermStructure>(qTS2),
                                                       new Handle <YieldTermStructure>(rTS),
                                                       new Handle <BlackVolTermStructure>(volTS2));
                    analyticEngine = new StulzEngine(p1, p2, values[i].rho);
                    break;

                case BasketType.SpreadBasket:
                    p1 = new BlackProcess(new Handle <Quote>(spot1),
                                          new Handle <YieldTermStructure>(rTS),
                                          new Handle <BlackVolTermStructure>(volTS1));
                    p2 = new BlackProcess(new Handle <Quote>(spot2),
                                          new Handle <YieldTermStructure>(rTS),
                                          new Handle <BlackVolTermStructure>(volTS2));

                    analyticEngine = new KirkEngine((BlackProcess)p1, (BlackProcess)p2, values[i].rho);
                    break;

                default:
                    Utils.QL_FAIL("unknown basket type");
                    break;
                }


                List <StochasticProcess1D> procs = new List <StochasticProcess1D> {
                    p1, p2
                };

                Matrix correlationMatrix = new Matrix(2, 2, values[i].rho);
                for (int j = 0; j < 2; j++)
                {
                    correlationMatrix[j, j] = 1.0;
                }

                StochasticProcessArray process = new StochasticProcessArray(procs, correlationMatrix);

                //IPricingEngine mcEngine = MakeMCEuropeanBasketEngine<PseudoRandom, Statistics>(process)
                //                           .withStepsPerYear(1)
                //                           .withSamples(10000)
                //                           .withSeed(42);



                //IPricingEngine fdEngine = new Fd2dBlackScholesVanillaEngine(p1, p2, values[i].rho, 50, 50, 15);

                BasketOption basketOption = new BasketOption(basketTypeToPayoff(values[i].basketType, payoff), exercise);

                // analytic engine
                basketOption.setPricingEngine(analyticEngine);
                double calculated = basketOption.NPV();
                double expected   = values[i].result;
                double error      = Math.Abs(calculated - expected);
                if (error > values[i].tol)
                {
                    REPORT_FAILURE_2("value", values[i].basketType, payoff, exercise,
                                     values[i].s1, values[i].s2, values[i].q1,
                                     values[i].q2, values[i].r, today, values[i].v1,
                                     values[i].v2, values[i].rho, values[i].result,
                                     calculated, error, values[i].tol);
                }

                // // fd engine
                // basketOption.setPricingEngine(fdEngine);
                // calculated = basketOption.NPV();
                // double relError = relativeError(calculated, expected, expected);
                // if (relError > mcRelativeErrorTolerance )
                // {
                //    REPORT_FAILURE_2("FD value", values[i].basketType, payoff,
                //                      exercise, values[i].s1, values[i].s2,
                //                      values[i].q1, values[i].q2, values[i].r,
                //                      today, values[i].v1, values[i].v2, values[i].rho,
                //                      values[i].result, calculated, relError,
                //                      fdRelativeErrorTolerance);
                // }

                //// mc engine
                //basketOption.setPricingEngine(mcEngine);
                //calculated = basketOption.NPV();
                //relError = relativeError(calculated, expected, values[i].s1);
                //if (relError > mcRelativeErrorTolerance )
                //{
                //    REPORT_FAILURE_2("MC value", values[i].basketType, payoff,
                //                     exercise, values[i].s1, values[i].s2,
                //                     values[i].q1, values[i].q2, values[i].r,
                //                     today, values[i].v1, values[i].v2, values[i].rho,
                //                     values[i].result, calculated, relError,
                //                     mcRelativeErrorTolerance);
                //}
            }
        }
コード例 #27
0
        public void testCrankNicolsonWithDamping()
        {
            SavedSettings backup = new SavedSettings();

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

            SimpleQuote           spot  = new SimpleQuote(100.0);
            YieldTermStructure    qTS   = Utilities.flatRate(today, 0.06, dc);
            YieldTermStructure    rTS   = Utilities.flatRate(today, 0.06, dc);
            BlackVolTermStructure volTS = Utilities.flatVol(today, 0.35, dc);

            StrikedTypePayoff payoff =
                new CashOrNothingPayoff(Option.Type.Put, 100, 10.0);

            double   maturity = 0.75;
            Date     exDate   = today + Convert.ToInt32(maturity * 360 + 0.5);
            Exercise exercise = new EuropeanExercise(exDate);

            BlackScholesMertonProcess process = new
                                                BlackScholesMertonProcess(new Handle <Quote>(spot),
                                                                          new Handle <YieldTermStructure>(qTS),
                                                                          new Handle <YieldTermStructure>(rTS),
                                                                          new Handle <BlackVolTermStructure>(volTS));
            IPricingEngine engine =
                new AnalyticEuropeanEngine(process);

            VanillaOption opt = new VanillaOption(payoff, exercise);

            opt.setPricingEngine(engine);
            double expectedPV    = opt.NPV();
            double expectedGamma = opt.gamma();

            // fd pricing using implicit damping steps and Crank Nicolson
            int        csSteps = 25, dampingSteps = 3, xGrid = 400;
            List <int> dim = new InitializedList <int>(1, xGrid);

            FdmLinearOpLayout layout       = new FdmLinearOpLayout(dim);
            Fdm1dMesher       equityMesher =
                new FdmBlackScholesMesher(
                    dim[0], process, maturity, payoff.strike(),
                    null, null, 0.0001, 1.5,
                    new Pair <double?, double?>(payoff.strike(), 0.01));

            FdmMesher mesher =
                new FdmMesherComposite(equityMesher);

            FdmBlackScholesOp map =
                new FdmBlackScholesOp(mesher, process, payoff.strike());

            FdmInnerValueCalculator calculator =
                new FdmLogInnerValue(payoff, mesher, 0);

            object rhs = new Vector(layout.size());
            Vector x   = new Vector(layout.size());
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter;
                 ++iter)
            {
                (rhs as Vector)[iter.index()] = calculator.avgInnerValue(iter, maturity);
                x[iter.index()] = mesher.location(iter, 0);
            }

            FdmBackwardSolver solver = new FdmBackwardSolver(map, new FdmBoundaryConditionSet(),
                                                             new FdmStepConditionComposite(),
                                                             new FdmSchemeDesc().Douglas());

            solver.rollback(ref rhs, maturity, 0.0, csSteps, dampingSteps);

            MonotonicCubicNaturalSpline spline = new MonotonicCubicNaturalSpline(x, x.Count, rhs as Vector);

            double s               = spot.value();
            double calculatedPV    = spline.value(Math.Log(s));
            double calculatedGamma = (spline.secondDerivative(Math.Log(s))
                                      - spline.derivative(Math.Log(s))) / (s * s);

            double relTol = 2e-3;

            if (Math.Abs(calculatedPV - expectedPV) > relTol * expectedPV)
            {
                QAssert.Fail("Error calculating the PV of the digital option" +
                             "\n rel. tolerance:  " + relTol +
                             "\n expected:        " + expectedPV +
                             "\n calculated:      " + calculatedPV);
            }
            if (Math.Abs(calculatedGamma - expectedGamma) > relTol * expectedGamma)
            {
                QAssert.Fail("Error calculating the Gamma of the digital option" +
                             "\n rel. tolerance:  " + relTol +
                             "\n expected:        " + expectedGamma +
                             "\n calculated:      " + calculatedGamma);
            }
        }
コード例 #28
0
        public void testBaroneAdesiWhaleyValues()
        {
            // ("Testing Barone-Adesi and Whaley approximation for American options...");

            /* The data below are from
             * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag 24
             *
             * The following values were replicated only up to the second digit
             * by the VB code provided by Haug, which was used as base for the
             * C++ implementation
             *
             */
            AmericanOptionData[] values =
            {
                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.15,  0.0206),
                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8771),
                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.15, 10.0089),
                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.25,  0.3159),
                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1280),
                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.25, 10.3919),
                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.10, 0.35,  0.9495),
                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3777),
                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.10, 0.35, 11.1679),
                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.15,  0.8208),
                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0842),
                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.15, 10.8087),
                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.25,  2.7437),
                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.8015),
                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.25, 13.0170),
                new AmericanOptionData(Option.Type.Call, 100.00,  90.00, 0.10, 0.10, 0.50, 0.35,  5.0063),
                new AmericanOptionData(Option.Type.Call, 100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.5106),
                new AmericanOptionData(Option.Type.Call, 100.00, 110.00, 0.10, 0.10, 0.50, 0.35, 15.5689),
                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.15, 10.0000),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.15,  1.8770),
                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.15,  0.0410),
                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.25, 10.2533),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.25,  3.1277),
                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.25,  0.4562),
                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.10, 0.35, 10.8787),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.10, 0.35,  4.3777),
                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.10, 0.35,  1.2402),
                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.15, 10.5595),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.15,  4.0842),
                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.15,  1.0822),
                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.25, 12.4419),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.25,  6.8014),
                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.25,  3.3226),
                new AmericanOptionData(Option.Type.Put,  100.00,  90.00, 0.10, 0.10, 0.50, 0.35, 14.6945),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.10, 0.10, 0.50, 0.35,  9.5104),
                new AmericanOptionData(Option.Type.Put,  100.00, 110.00, 0.10, 0.10, 0.50, 0.35,  5.8823),
                new AmericanOptionData(Option.Type.Put,  100.00, 100.00, 0.00, 0.00, 0.50, 0.15, 4.22949)
            };

            Date               today = Date.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);

            double tolerance = 3.0e-3;

            for (int i = 0; i < values.Length; i++)
            {
                StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);
                Date     exDate          = today + Convert.ToInt32(values[i].t * 360 + 0.5);
                Exercise exercise        = new AmericanExercise(today, exDate);

                spot.setValue(values[i].s);
                qRate.setValue(values[i].q);
                rRate.setValue(values[i].r);
                vol.setValue(values[i].v);

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

                IPricingEngine engine = new BaroneAdesiWhaleyApproximationEngine(stochProcess);

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

                double calculated = option.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                if (error > tolerance)
                {
                    REPORT_FAILURE("value", payoff, exercise, values[i].s, values[i].q,
                                   values[i].r, today, values[i].v, values[i].result,
                                   calculated, error, tolerance);
                }
            }
        }
コード例 #29
0
        public void testMultiPathGenerator()
        {
            //("Testing n-D path generation against cached values...");

            //SavedSettings backup;

            Settings.setEvaluationDate(new Date(26, 4, 2005));

            Handle <Quote> x0 = new Handle <Quote> (new SimpleQuote(100.0));
            Handle <YieldTermStructure>    r     = new Handle <YieldTermStructure> (Utilities.flatRate(0.05, new Actual360()));
            Handle <YieldTermStructure>    q     = new Handle <YieldTermStructure> (Utilities.flatRate(0.02, new Actual360()));
            Handle <BlackVolTermStructure> sigma = new Handle <BlackVolTermStructure> (Utilities.flatVol(0.20, new Actual360()));

            Matrix correlation = new Matrix(3, 3);

            correlation[0, 0] = 1.0; correlation[0, 1] = 0.9; correlation[0, 2] = 0.7;
            correlation[1, 0] = 0.9; correlation[1, 1] = 1.0; correlation[1, 2] = 0.4;
            correlation[2, 0] = 0.7; correlation[2, 1] = 0.4; correlation[2, 2] = 1.0;

            List <StochasticProcess1D> processes = new List <StochasticProcess1D>(3);
            StochasticProcess          process;

            processes.Add(new BlackScholesMertonProcess(x0, q, r, sigma));
            processes.Add(new BlackScholesMertonProcess(x0, q, r, sigma));
            processes.Add(new BlackScholesMertonProcess(x0, q, r, sigma));
            process = new StochasticProcessArray(processes, correlation);
            // commented values must be used when Halley's correction is enabled
            double[] result1 =
            {
                188.2235868185,
                270.6713069569,
                113.0431145652
            };
            // Real result1[] = {
            //     188.2235869273,
            //     270.6713071508,
            //     113.0431145652 };
            double[] result1a =
            {
                64.89105742957,
                45.12494404804,
                108.0475146914
            };
            // Real result1a[] = {
            //     64.89105739157,
            //     45.12494401537,
            //     108.0475146914 };
            testMultiple(process, "Black-Scholes", result1, result1a);

            processes[0] = new GeometricBrownianMotionProcess(100.0, 0.03, 0.20);
            processes[1] = new GeometricBrownianMotionProcess(100.0, 0.03, 0.20);
            processes[2] = new GeometricBrownianMotionProcess(100.0, 0.03, 0.20);
            process      = new StochasticProcessArray(processes, correlation);
            double[] result2 =
            {
                174.8266131680,
                237.2692443633,
                119.1168555440
            };
            // Real result2[] = {
            //     174.8266132344,
            //     237.2692444869,
            //     119.1168555605 };
            double[] result2a =
            {
                57.69082393020,
                38.50016862915,
                116.4056510107
            };
            // Real result2a[] = {
            //     57.69082387657,
            //     38.50016858691,
            //     116.4056510107 };
            testMultiple(process, "geometric Brownian", result2, result2a);

            processes[0] = new OrnsteinUhlenbeckProcess(0.1, 0.20);
            processes[1] = new OrnsteinUhlenbeckProcess(0.1, 0.20);
            processes[2] = new OrnsteinUhlenbeckProcess(0.1, 0.20);
            process      = new StochasticProcessArray(processes, correlation);
            double[] result3 =
            {
                0.2942058437284,
                0.5525006418386,
                0.02650931054575
            };
            double[] result3a =
            {
                -0.2942058437284,
                -0.5525006418386,
                -0.02650931054575
            };
            testMultiple(process, "Ornstein-Uhlenbeck", result3, result3a);

            processes[0] = new SquareRootProcess(0.1, 0.1, 0.20, 10.0);
            processes[1] = new SquareRootProcess(0.1, 0.1, 0.20, 10.0);
            processes[2] = new SquareRootProcess(0.1, 0.1, 0.20, 10.0);
            process      = new StochasticProcessArray(processes, correlation);
            double[] result4 =
            {
                4.279510844897,
                4.943783503533,
                3.590930385958
            };
            double[] result4a =
            {
                2.763967737724,
                2.226487196647,
                3.503859264341
            };
            testMultiple(process, "square-root", result4, result4a);
        }
コード例 #30
0
ファイル: T_DividendOption.cs プロジェクト: tzhdingli/qlnet
        // Reference pg. 253 - Hull - Options, Futures, and Other Derivatives 5th ed
        // Exercise 12.8
        // Doesn't quite work.  Need to deal with date conventions
        void testEuropeanKnownValue()
        {
            // Testing dividend European option values with known value...

            SavedSettings backup = new SavedSettings();

            double tolerance = 1.0e-2;
            double expected  = 3.67;

            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));

            Date     exDate   = today + new Period(6, TimeUnit.Months);
            Exercise exercise = new EuropeanExercise(exDate);

            List <Date>   dividendDates = new List <Date>();
            List <double> dividends     = new List <double>();

            dividendDates.Add(today + new Period(2, TimeUnit.Months));
            dividends.Add(0.50);
            dividendDates.Add(today + new Period(5, TimeUnit.Months));
            dividends.Add(0.50);

            StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Call, 40.0);

            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);

            double u = 40.0;
            double q = 0.0, r = 0.09;
            double v = 0.30;

            spot.setValue(u);
            qRate.setValue(q);
            rRate.setValue(r);
            vol.setValue(v);

            double calculated = option.NPV();
            double error      = Math.Abs(calculated - expected);

            if (error > tolerance)
            {
                REPORT_FAILURE("value start limit",
                               payoff, exercise,
                               u, q, r, today, v,
                               expected, calculated,
                               error, tolerance);
            }
        }