コード例 #1
0
ファイル: T_ForwardOption.cs プロジェクト: scchess/QLNet
        public void testPerformanceValues()
        {
            // Testing forward performance option values...

            /* The data below are the performance equivalent of the
             * forward options tested above and taken from
             * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998
             */
            ForwardOptionData[] values =
            {
                //  type, moneyness, spot,  div, rate,start, maturity,  vol,                       result, tol
                new ForwardOptionData(Option.Type.Call, 1.1, 60.0, 0.04, 0.08, 0.25, 1.0, 0.30, 4.4064 / 60 * Math.Exp(-0.04 * 0.25), 1.0e-4),
                new ForwardOptionData(Option.Type.Put,  1.1, 60.0, 0.04, 0.08, 0.25, 1.0, 0.30, 8.2971 / 60 * Math.Exp(-0.04 * 0.25), 1.0e-4)
            };

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

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

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

            IPricingEngine engine = new ForwardPerformanceVanillaEngine(stochProcess, process => new AnalyticEuropeanEngine(process));  // AnalyticEuropeanEngine

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

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

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

                double calculated = option.NPV();
                double error      = Math.Abs(calculated - values[i].result);
                double tolerance  = 1e-4;
                if (error > tolerance)
                {
                    REPORT_FAILURE("value", payoff, exercise, values[i].s,
                                   values[i].q, values[i].r, today,
                                   values[i].v, values[i].moneyness, reset,
                                   values[i].result, calculated,
                                   error, tolerance);
                }
            }
        }
コード例 #2
0
ファイル: T_ForwardOption.cs プロジェクト: scchess/QLNet
        private void testForwardGreeks(Type engine_type)
        {
            Dictionary <String, double> calculated = new Dictionary <string, double>(),
                                        expected   = new Dictionary <string, double>(),
                                        tolerance  = new Dictionary <string, double>();

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

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

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

            Settings.setEvaluationDate(today);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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