Пример #1
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            ////////////////  DATES  //////////////////////////////////////////////

            Calendar calendar       = new TARGET();
            Date     todaysDate     = new Date(15, Month.January, 2017);
            Date     settlementDate = new Date(todaysDate);

            Settings.setEvaluationDate(todaysDate);
            DayCounter dayCounter = new Actual365Fixed();


            ////////////////  MARKET  //////////////////////////////////////////////

            // Spot
            double         underlying  = 4468.17;
            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // riskfree
            double riskFreeRate = 0.035;
            Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));

            // dividend
            double dividendYield = 0.0;
            double fixedDiv      = 5.0;

            Handle <YieldTermStructure> flatDividendTS        = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            Handle <YieldTermStructure> FixedDivTermStructure = new Handle <YieldTermStructure>(new FixedForward(settlementDate, fixedDiv, underlying, dayCounter));

            // vol surface

            Date StartDateVol = settlementDate + new Period(1, TimeUnit.Months);


            List <int> maturityInDays = new InitializedList <int>()
            {
                0, 13, 41, 90, 165, 256, 345, 524, 703
            };
            List <Date> datesVol = new InitializedList <Date>();

            for (int d = 1; d < maturityInDays.Count; d++)
            {
                datesVol.Add(calendar.advance(settlementDate, new Period(maturityInDays[d], TimeUnit.Days)));
            }

            List <double> strikes = new InitializedList <double>()
            {
                3400, 3600, 3800, 4000, 4200, 4400, 4500, 4600, 4800, 5000, 5200, 5400, 5600
            };

            Matrix blackVolMatrix = new Matrix(maturityInDays.Count - 1, strikes.Count, 0.2);
            var    vols           = new InitializedList <double>()
            {
                0.6625, 0.4875, 0.4204, 0.3667, 0.3431, 0.3267, 0.3121, 0.3121,
                0.6007, 0.4543, 0.3967, 0.3511, 0.3279, 0.3154, 0.2984, 0.2921,
                0.5084, 0.4221, 0.3718, 0.3327, 0.3155, 0.3027, 0.2919, 0.2889,
                0.4541, 0.3869, 0.3492, 0.3149, 0.2963, 0.2926, 0.2819, 0.2800,
                0.4060, 0.3607, 0.3330, 0.2999, 0.2887, 0.2811, 0.2751, 0.2775,
                0.3726, 0.3396, 0.3108, 0.2781, 0.2788, 0.2722, 0.2661, 0.2686,
                0.3550, 0.3277, 0.3012, 0.2781, 0.2781, 0.2661, 0.2661, 0.2681,
                0.3428, 0.3209, 0.2958, 0.2740, 0.2688, 0.2627, 0.2580, 0.2620,
                0.3302, 0.3062, 0.2799, 0.2631, 0.2573, 0.2533, 0.2504, 0.2544,
                0.3343, 0.2959, 0.2705, 0.2540, 0.2504, 0.2464, 0.2448, 0.2462,
                0.3460, 0.2845, 0.2624, 0.2463, 0.2425, 0.2385, 0.2373, 0.2422,
                0.3857, 0.2860, 0.2578, 0.2399, 0.2357, 0.2327, 0.2312, 0.2351,
                0.3976, 0.2860, 0.2607, 0.2356, 0.2297, 0.2268, 0.2241, 0.2320
            };


            for (int i = 0; i < vols.Count; i++)
            {
                int testraw = (int)(i % (datesVol.Count));
                int testcol = (int)(i / (datesVol.Count));

                blackVolMatrix[testraw, testcol] = vols[i];
            }



            BlackVarianceSurface mySurface = new BlackVarianceSurface(settlementDate, calendar, datesVol,
                                                                      strikes, Matrix.transpose(blackVolMatrix), dayCounter);

            Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(mySurface);


            ////////////////  CALIBRATION  //////////////////////////////////////////////

            Period helperPeriod = new Period();

            //helpers
            List <CalibrationHelper> calibrationHelpers = new List <CalibrationHelper>();

            for (int k = 0; k < strikes.Count; k++)
            {
                for (int d = 0; d < datesVol.Count; d++)
                {
                    helperPeriod = new Period(datesVol[d] - settlementDate, TimeUnit.Days);
                    calibrationHelpers.Add(new HestonModelHelper(helperPeriod,
                                                                 calendar,
                                                                 underlying,
                                                                 strikes[k],
                                                                 new Handle <Quote>(new SimpleQuote(blackVolMatrix[d, k])),
                                                                 flatTermStructure,
                                                                 flatDividendTS,
                                                                 CalibrationHelper.CalibrationErrorType.ImpliedVolError));
                }
            }


            // starting data
            double v0    = 0.1;
            double kappa = 1.0;
            double theta = 0.1;
            double sigma = 0.5;
            double rho   = -0.5;

            // model
            HestonProcess hestonProcess = new HestonProcess(flatTermStructure,
                                                            flatDividendTS,
                                                            underlyingH,
                                                            v0, kappa, theta, sigma, rho);

            HestonModel hestonmodel = new HestonModel(hestonProcess);

            AnalyticHestonEngine analyticHestonEngine = new AnalyticHestonEngine(hestonmodel);


            foreach (HestonModelHelper hmh in calibrationHelpers)
            {
                hmh.setPricingEngine(analyticHestonEngine);
            }


            // optimization
            double             tolerance          = 1.0e-8;
            LevenbergMarquardt optimizationmethod = new LevenbergMarquardt(tolerance, tolerance, tolerance);

            hestonmodel.calibrate(calibrationHelpers, optimizationmethod, new EndCriteria(400, 40, tolerance, tolerance, tolerance));

            double        error     = 0.0;
            List <double> errorList = new InitializedList <double>();


            ////////////////  CALIBRATION RESULTS  //////////////////////////////////////////////
            Console.WriteLine("Calbration :");
            Console.WriteLine("-----------");

            foreach (HestonModelHelper hmh in calibrationHelpers)
            {
                error += Math.Abs(hmh.calibrationError());
                errorList.Add(Math.Abs(hmh.calibrationError()));
            }

            Vector hestonParameters = hestonmodel.parameters();

            Console.WriteLine("v0    = {0:0.00%}", hestonParameters[4]);
            Console.WriteLine("kappa = {0:0.00%}", hestonParameters[1]);
            Console.WriteLine("theta = {0:0.00%}", hestonParameters[0]);
            Console.WriteLine("sigma = {0:0.00%}", hestonParameters[2]);
            Console.WriteLine("rho   = {0:0.00%}", hestonParameters[3]);
            Console.WriteLine();
            Console.WriteLine("Total error = {0:0.0000}", error);
            Console.WriteLine("Mean error  = {0:0.0000%}", error / (errorList.Count - 1));
            Console.WriteLine();

            int    StepsPerYear      = 52;
            double absoluteTolerance = 80.0;
            ulong  mcSeed            = 42;

            // MC Heston process
            HestonProcess calibratedHestonProcess = new HestonProcess(flatTermStructure,
                                                                      flatDividendTS,
                                                                      underlyingH,
                                                                      hestonParameters[4],
                                                                      hestonParameters[1],
                                                                      hestonParameters[0],
                                                                      hestonParameters[2],
                                                                      hestonParameters[3]);

            // BS process
            GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, FixedDivTermStructure, flatTermStructure, mySurfaceH);

            ////////////////  ENGINES  /////////////////////////////////////////////////


            IPricingEngine mcHestonEngine = new MakeMCEuropeanHestonEngine <PseudoRandom, Statistics>(calibratedHestonProcess)
                                            .withStepsPerYear(StepsPerYear)
                                            .withAbsoluteTolerance(absoluteTolerance)
                                            .withSeed(mcSeed)
                                            .getAsPricingEngine();

            double         absoluteTolerance2      = 1.0;
            IPricingEngine mcGenHestonEngineTestbs = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess)
                                                     .withStepsPerYear(StepsPerYear)
                                                     .withAbsoluteTolerance(absoluteTolerance2)
                                                     .withSeed(mcSeed)
                                                     .value();

            IPricingEngine mcGenHestonEngineTestbs2 = new MakeMCGenericScriptInstrument <PseudoRandom>(calibratedHestonProcess)
                                                      .withStepsPerYear(StepsPerYear)
                                                      .withAbsoluteTolerance(absoluteTolerance2)
                                                      .withSeed(mcSeed)
                                                      .value();


            ////////////////  PRICING  //////////////////////////////////////////////
            Console.WriteLine("Pricing Vanilla:");
            Console.WriteLine("---------------");


            Date     maturity         = new Date(17, Month.May, 2019);
            Exercise europeanExercise = new EuropeanExercise(maturity);

            Option.Type       type           = Option.Type.Call;
            double            strike         = underlying;
            StrikedTypePayoff payoff         = new PlainVanillaPayoff(type, strike);
            VanillaOption     europeanOption = new VanillaOption(payoff, europeanExercise);

            // heston
            europeanOption.setPricingEngine(analyticHestonEngine);
            Console.Write("Heston pricing = {0:0.0000}", europeanOption.NPV());
            Console.WriteLine("  ->   {0:0.0000%}", europeanOption.NPV() / underlying);

            // Mc heston
            europeanOption.setPricingEngine(mcHestonEngine);
            Console.Write("HestMC pricing = {0:0.0000}", europeanOption.NPV());
            Console.Write("  ->   {0:0.0000%}", europeanOption.NPV() / underlying);
            Console.WriteLine("  tolerance   {0:0.0} / {1:0.00%}", absoluteTolerance, absoluteTolerance / underlying);

            // analytic bs
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));
            Console.Write("BS pricing     = {0:0.0000}", europeanOption.NPV());
            Console.WriteLine("  ->   {0:0.0000%}", europeanOption.NPV() / underlying);


            Console.WriteLine();
            ////////////////  AUTOCALL HESTON //////////////////////////////////////////////

            List <Date> fixingdates = new InitializedList <Date>();
            double      coupon      = 0.05;
            double      barrierlvl  = 0.6;

            for (int i = 1; i <= 4; i++)
            {
                fixingdates.Add(settlementDate + new Period(i, TimeUnit.Years));
            }

            ScriptGenericAutocall myGenericAutocallHTTEst = new ScriptGenericAutocall(fixingdates, coupon, barrierlvl, underlying);

            myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs);

            Console.WriteLine("Pricing Autocall BS :");
            Console.WriteLine("---------------------");
            Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples());
            Console.Write("\n");

            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1);
            }
            Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid"));
            Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.Write("\n");


            myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs2);

            Console.WriteLine("Pricing Autocall Heston:");
            Console.WriteLine("------------------------");
            Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples());
            Console.Write("\n");

            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1);
            }
            Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid"));
            Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.Write("\n");


            ////////////////  END TEST  //////////////////////////////////////////////
            Console.WriteLine();
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #2
0
        static void Main(string[] args)
        {
            DateTime startTime = DateTime.Now;

            Option.Type optionType      = Option.Type.Put;
            double      underlyingPrice = 36;
            double      strikePrice     = 40;
            double      dividendYield   = 0.0;
            double      riskFreeRate    = 0.06;
            double      volatility      = 0.2;

            Date todaysDate = new Date(15, Month.May, 1998);

            Settings.instance().setEvaluationDate(todaysDate);

            Date settlementDate = new Date(17, Month.May, 1998);
            Date maturityDate   = new Date(17, Month.May, 1999);

            Calendar calendar = new TARGET();

            DateVector exerciseDates = new DateVector(4);

            for (int i = 1; i <= 4; i++)
            {
                Period forwardPeriod = new Period(3 * i, TimeUnit.Months);
                Date   forwardDate   = settlementDate.Add(forwardPeriod);
                exerciseDates.Add(forwardDate);
            }

            EuropeanExercise europeanExercise =
                new EuropeanExercise(maturityDate);
            BermudanExercise bermudanExercise =
                new BermudanExercise(exerciseDates);
            AmericanExercise americanExercise =
                new AmericanExercise(settlementDate, maturityDate);

            // bootstrap the yield/dividend/vol curves and create a
            // BlackScholesMerton stochastic process
            DayCounter dayCounter = new Actual365Fixed();
            YieldTermStructureHandle flatRateTSH =
                new YieldTermStructureHandle(
                    new FlatForward(settlementDate, riskFreeRate,
                                    dayCounter));
            YieldTermStructureHandle flatDividendTSH =
                new YieldTermStructureHandle(
                    new FlatForward(settlementDate, dividendYield,
                                    dayCounter));
            BlackVolTermStructureHandle flatVolTSH =
                new BlackVolTermStructureHandle(
                    new BlackConstantVol(settlementDate, calendar,
                                         volatility, dayCounter));

            QuoteHandle underlyingQuoteH =
                new QuoteHandle(new SimpleQuote(underlyingPrice));
            BlackScholesMertonProcess stochasticProcess =
                new BlackScholesMertonProcess(underlyingQuoteH,
                                              flatDividendTSH,
                                              flatRateTSH,
                                              flatVolTSH);

            PlainVanillaPayoff payoff =
                new PlainVanillaPayoff(optionType, strikePrice);

            // options
            VanillaOption europeanOption =
                new VanillaOption(payoff, europeanExercise);
            VanillaOption bermudanOption =
                new VanillaOption(payoff, bermudanExercise);
            VanillaOption americanOption =
                new VanillaOption(payoff, americanExercise);

            // report the parameters we are using
            ReportParameters(optionType, underlyingPrice, strikePrice,
                             dividendYield, riskFreeRate,
                             volatility, maturityDate);

            // write out the column headings
            ReportHeadings();

            #region Analytic Formulas

            // Black-Scholes for European
            try {
                europeanOption.setPricingEngine(
                    new AnalyticEuropeanEngine(stochasticProcess));
                ReportResults("Black-Scholes",
                              europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Barone-Adesi and Whaley approximation for American
            try {
                americanOption.setPricingEngine(
                    new BaroneAdesiWhaleyEngine(stochasticProcess));
                ReportResults("Barone-Adesi/Whaley",
                              null, null, americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Bjerksund and Stensland approximation for American
            try {
                americanOption.setPricingEngine(
                    new BjerksundStenslandEngine(stochasticProcess));
                ReportResults("Bjerksund/Stensland",
                              null, null, americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Integral
            try {
                europeanOption.setPricingEngine(
                    new IntegralEngine(stochasticProcess));
                ReportResults("Integral",
                              europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            uint timeSteps = 801;

            // Finite differences
            try {
                europeanOption.setPricingEngine(
                    new FDEuropeanEngine(stochasticProcess,
                                         timeSteps, timeSteps - 1));
                bermudanOption.setPricingEngine(
                    new FDBermudanEngine(stochasticProcess,
                                         timeSteps, timeSteps - 1));
                americanOption.setPricingEngine(
                    new FDAmericanEngine(stochasticProcess,
                                         timeSteps, timeSteps - 1));
                ReportResults("Finite differences",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            //Variance Gamma
            try
            {
                VarianceGammaProcess vgProcess = new VarianceGammaProcess(underlyingQuoteH,
                                                                          flatDividendTSH,
                                                                          flatRateTSH,
                                                                          volatility, 0.01, 0.0
                                                                          );
                europeanOption.setPricingEngine(
                    new VarianceGammaEngine(vgProcess));
                ReportResults("Variance-Gamma",
                              europeanOption.NPV(), null, null);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            #endregion Analytic Formulas

            #region Binomial Methods

            // Binomial Jarrow-Rudd
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "jarrowrudd", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "jarrowrudd", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "jarrowrudd", timeSteps));
                ReportResults("Binomial Jarrow-Rudd",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Cox-Ross-Rubinstein
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "coxrossrubinstein", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "coxrossrubinstein", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "coxrossrubinstein", timeSteps));
                ReportResults("Binomial Cox-Ross-Rubinstein",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Additive Equiprobabilities
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "eqp", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "eqp", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "eqp", timeSteps));
                ReportResults("Additive Equiprobabilities",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Trigeorgis
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "trigeorgis", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "trigeorgis", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "trigeorgis", timeSteps));
                ReportResults("Binomial Trigeorgis",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Tian
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "tian", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "tian", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "tian", timeSteps));
                ReportResults("Binomial Tian",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Leisen-Reimer
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "leisenreimer", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "leisenreimer", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "leisenreimer", timeSteps));
                ReportResults("Binomial Leisen-Reimer",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // Binomial Joshi
            try {
                europeanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "joshi4", timeSteps));
                bermudanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "joshi4", timeSteps));
                americanOption.setPricingEngine(
                    new BinomialVanillaEngine(stochasticProcess,
                                              "joshi4", timeSteps));
                ReportResults("Binomial Joshi",
                              europeanOption.NPV(),
                              bermudanOption.NPV(),
                              americanOption.NPV());
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            #endregion Binomial Methods

            #region Monte Carlo Methods

            // quantlib appears to use max numeric (int and real) values to test for 'null' (or rather 'default') values

            // MC (crude)
            try {
                string traits            = "pseudorandom";
                int    mcTimeSteps       = 1;
                int    timeStepsPerYear  = int.MaxValue;
                bool   brownianBridge    = false;
                bool   antitheticVariate = false;
                int    requiredSamples   = int.MaxValue;
                double requiredTolerance = 0.02;
                int    maxSamples        = int.MaxValue;
                int    seed = 42;
                europeanOption.setPricingEngine(
                    new MCEuropeanEngine(stochasticProcess,
                                         traits, mcTimeSteps,
                                         timeStepsPerYear,
                                         brownianBridge,
                                         antitheticVariate,
                                         requiredSamples,
                                         requiredTolerance,
                                         maxSamples, seed));
                ReportResults("MC (crude)", europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // MC (Sobol)
            try {
                string traits            = "lowdiscrepancy";
                int    mcTimeSteps       = 1;
                int    timeStepsPerYear  = int.MaxValue;
                bool   brownianBridge    = false;
                bool   antitheticVariate = false;
                int    requiredSamples   = 32768; // 2^15
                double requiredTolerance = double.MaxValue;
                int    maxSamples        = int.MaxValue;
                int    seed = 0;
                europeanOption.setPricingEngine(
                    new MCEuropeanEngine(stochasticProcess,
                                         traits, mcTimeSteps,
                                         timeStepsPerYear,
                                         brownianBridge,
                                         antitheticVariate,
                                         requiredSamples,
                                         requiredTolerance, maxSamples, seed));
                ReportResults("MC (Sobol)", europeanOption.NPV(), null, null);
            }
            catch (Exception e) {
                Console.WriteLine(e.ToString());
            }

            // MC (Longstaff Schwartz)

            /*
             * try {
             *  // MCAmericanEngine is not currently exposed in SWIG
             *  //americanOption.setPricingEngine(new MCAmericanEngine());
             *  ReportResults("MC (Longstaff Schwartz)", null, null, null);
             * }
             * catch (Exception e) {
             *  Console.WriteLine(e.ToString());
             * }
             */

            #endregion Monte Carlo Methods

            DateTime endTime = DateTime.Now;
            TimeSpan delta   = endTime - startTime;
            Console.WriteLine();
            Console.WriteLine("Run completed in {0} s", delta.TotalSeconds);
            Console.WriteLine();
        }
Пример #3
0
        public void testMethodOfLinesAndCN()
        {
            //Testing method of lines to solve Heston PDEs...

            using (SavedSettings backup = new SavedSettings())
            {
                DayCounter dc    = new Actual365Fixed();
                Date       today = new Date(21, 2, 2018);

                Settings.Instance.setEvaluationDate(today);

                Handle <Quote> spot             = new Handle <Quote>(new SimpleQuote(100.0));
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc));
                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc));

                double v0    = 0.09;
                double kappa = 1.0;
                double theta = v0;
                double sigma = 0.4;
                double rho   = -0.75;

                Date maturity = today + new Period(3, TimeUnit.Months);

                HestonModel model =
                    new HestonModel(
                        new HestonProcess(rTS, qTS, spot, v0, kappa, theta, sigma, rho));

                int xGrid = 21;
                int vGrid = 7;

                IPricingEngine fdmDefault =
                    new FdHestonVanillaEngine(model, 10, xGrid, vGrid, 0);

                IPricingEngine fdmMol =
                    new FdHestonVanillaEngine(
                        model, 10, xGrid, vGrid, 0, new FdmSchemeDesc().MethodOfLines());

                PlainVanillaPayoff payoff =
                    new PlainVanillaPayoff(Option.Type.Put, spot.currentLink().value());

                VanillaOption option = new VanillaOption(payoff, new AmericanExercise(maturity));

                option.setPricingEngine(fdmMol);
                double calculatedMoL = option.NPV();

                option.setPricingEngine(fdmDefault);
                double expected = option.NPV();

                double tol     = 0.005;
                double diffMoL = Math.Abs(expected - calculatedMoL);

                if (diffMoL > tol)
                {
                    QAssert.Fail("Failed to reproduce european option values with MOL"
                                 + "\n    calculated: " + calculatedMoL
                                 + "\n    expected:   " + expected
                                 + "\n    difference: " + diffMoL
                                 + "\n    tolerance:  " + tol);
                }

                IPricingEngine fdmCN =
                    new FdHestonVanillaEngine(model, 10, xGrid, vGrid, 0, new FdmSchemeDesc().CrankNicolson());
                option.setPricingEngine(fdmCN);

                double calculatedCN = option.NPV();
                double diffCN       = Math.Abs(expected - calculatedCN);

                if (diffCN > tol)
                {
                    QAssert.Fail("Failed to reproduce european option values with Crank-Nicolson"
                                 + "\n    calculated: " + calculatedCN
                                 + "\n    expected:   " + expected
                                 + "\n    difference: " + diffCN
                                 + "\n    tolerance:  " + tol);
                }

                BarrierOption barrierOption =
                    new BarrierOption(Barrier.Type.DownOut, 85.0, 10.0,
                                      payoff, new EuropeanExercise(maturity));

                barrierOption.setPricingEngine(new FdHestonBarrierEngine(model, 100, 31, 11));

                double expectedBarrier = barrierOption.NPV();

                barrierOption.setPricingEngine(new FdHestonBarrierEngine(model, 100, 31, 11, 0, new FdmSchemeDesc().MethodOfLines()));

                double calculatedBarrierMoL = barrierOption.NPV();

                double barrierTol     = 0.01;
                double barrierDiffMoL = Math.Abs(expectedBarrier - calculatedBarrierMoL);

                if (barrierDiffMoL > barrierTol)
                {
                    QAssert.Fail("Failed to reproduce barrier option values with MOL"
                                 + "\n    calculated: " + calculatedBarrierMoL
                                 + "\n    expected:   " + expectedBarrier
                                 + "\n    difference: " + barrierDiffMoL
                                 + "\n    tolerance:  " + barrierTol);
                }

                barrierOption.setPricingEngine(new FdHestonBarrierEngine(model, 100, 31, 11, 0, new FdmSchemeDesc().CrankNicolson()));

                double calculatedBarrierCN = barrierOption.NPV();
                double barrierDiffCN       = Math.Abs(expectedBarrier - calculatedBarrierCN);

                if (barrierDiffCN > barrierTol)
                {
                    QAssert.Fail("Failed to reproduce barrier option values with Crank-Nicolson"
                                 + "\n    calculated: " + calculatedBarrierCN
                                 + "\n    expected:   " + expectedBarrier
                                 + "\n    difference: " + barrierDiffCN
                                 + "\n    tolerance:  " + barrierTol);
                }
            }
        }
Пример #4
0
        public void testSpuriousOscillations()
        {
            //Testing for spurious oscillations when solving the Heston PDEs...
            using (SavedSettings backup = new SavedSettings())
            {
                DayCounter dc    = new Actual365Fixed();
                Date       today = new Date(7, 6, 2018);

                Settings.Instance.setEvaluationDate(today);

                Handle <Quote> spot             = new Handle <Quote>(new SimpleQuote(100.0));
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.1, dc));
                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc));

                double v0    = 0.005;
                double kappa = 1.0;
                double theta = 0.005;
                double sigma = 0.4;
                double rho   = -0.75;

                Date maturity = today + new Period(1, TimeUnit.Years);

                HestonProcess process =
                    new HestonProcess(
                        rTS, qTS, spot, v0, kappa, theta, sigma, rho);

                HestonModel model =
                    new HestonModel(process);

                FdHestonVanillaEngine hestonEngine =
                    new FdHestonVanillaEngine(
                        model, 6, 200, 13, 0, new FdmSchemeDesc().TrBDF2());

                VanillaOption option = new VanillaOption(new PlainVanillaPayoff(Option.Type.Call, spot.currentLink().value()),
                                                         new EuropeanExercise(maturity));

                option.setupArguments(hestonEngine.getArguments());

                List <Tuple <FdmSchemeDesc, string, bool> > descs = new List <Tuple <FdmSchemeDesc, string, bool> >();
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().CraigSneyd(), "Craig-Sneyd", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().Hundsdorfer(), "Hundsdorfer", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().ModifiedHundsdorfer(), "Mod. Hundsdorfer", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().Douglas(), "Douglas", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().CrankNicolson(), "Crank-Nicolson", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().ImplicitEuler(), "Implicit", false));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().TrBDF2(), "TR-BDF2", false));

                for (int j = 0; j < descs.Count; ++j)
                {
                    FdmHestonSolver solver =
                        new FdmHestonSolver(new Handle <HestonProcess>(process),
                                            hestonEngine.getSolverDesc(1.0),
                                            descs[j].Item1);

                    List <double> gammas = new List <double>();
                    for (double x = 99; x < 101.001; x += 0.1)
                    {
                        gammas.Add(solver.gammaAt(x, v0));
                    }

                    double maximum = Double.MinValue;
                    for (int i = 1; i < gammas.Count; ++i)
                    {
                        double diff = Math.Abs(gammas[i] - gammas[i - 1]);
                        if (diff > maximum)
                        {
                            maximum = diff;
                        }
                    }

                    double tol = 0.01;
                    bool   hasSpuriousOscillations = maximum > tol;

                    if (hasSpuriousOscillations != descs[j].Item3)
                    {
                        QAssert.Fail("unable to reproduce spurious oscillation behaviour "
                                     + "\n   scheme name          : " + descs[j].Item2
                                     + "\n   oscillations observed: "
                                     + hasSpuriousOscillations
                                     + "\n   oscillations expected: " + descs[j].Item3
                                     );
                    }
                }
            }
        }
Пример #5
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Actual365Fixed obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
Пример #6
0
        static void Main(string[] args)
        {
            const int xSteps       = 100;
            const int tSteps       = 25;
            const int dampingSteps = 0;

            Date today = new Date(15, Month.January, 2020);

            Settings.instance().setEvaluationDate(today);

            DayCounter dc = new Actual365Fixed();

            YieldTermStructureHandle rTS = new YieldTermStructureHandle(
                new FlatForward(today, 0.06, dc));
            YieldTermStructureHandle qTS = new YieldTermStructureHandle(
                new FlatForward(today, 0.02, dc));

            const double      strike = 110.0;
            StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Put, strike);

            Date   maturityDate = today.Add(new Period(1, TimeUnit.Years));
            double maturity     = dc.yearFraction(today, maturityDate);

            Exercise exercise = new AmericanExercise(today, maturityDate);

            Instrument vanillaOption = new VanillaOption(payoff, exercise);

            QuoteHandle spot = new QuoteHandle(new SimpleQuote(100.0));
            BlackVolTermStructureHandle volatility = new BlackVolTermStructureHandle(
                new BlackConstantVol(today, new TARGET(), 0.20, dc));

            BlackScholesMertonProcess process =
                new BlackScholesMertonProcess(spot, qTS, rTS, volatility);

            vanillaOption.setPricingEngine(new FdBlackScholesVanillaEngine(
                                               process, tSteps, xSteps, dampingSteps));

            double expected = vanillaOption.NPV();

            // build an PDE engine from scratch
            Fdm1dMesher equityMesher = new FdmBlackScholesMesher(
                xSteps, process, maturity, strike,
                nullDouble(), nullDouble(), 0.0001, 1.5,
                new DoublePair(strike, 0.1));

            FdmMesherComposite mesher = new FdmMesherComposite(equityMesher);

            FdmLinearOpComposite op = new FdmBlackScholesOp(mesher, process, strike);

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

            QlArray x   = new QlArray(equityMesher.size());
            QlArray rhs = new QlArray(equityMesher.size());

            FdmLinearOpIterator iter = mesher.layout().begin();

            for (uint i = 0; i < rhs.size(); ++i, iter.increment())
            {
                x.set(i, mesher.location(iter, 0));
                rhs.set(i, calc.avgInnerValue(iter, maturity));
            }

            FdmBoundaryConditionSet bcSet = new FdmBoundaryConditionSet();

            FdmStepConditionComposite stepCondition =
                FdmStepConditionComposite.vanillaComposite(
                    new DividendSchedule(), exercise, mesher, calc, today, dc);


            FdmLinearOpComposite proxyOp = new FdmLinearOpCompositeProxy(
                new FdmBSDelegate(op));

            FdmBackwardSolver solver = new FdmBackwardSolver(
                proxyOp, bcSet, stepCondition, FdmSchemeDesc.Douglas());

            solver.rollback(rhs, maturity, 0.0, tSteps, dampingSteps);

            double logS = Math.Log(spot.value());

            double calculated = new CubicNaturalSpline(x, rhs).call(logS);

            Console.WriteLine("Homebrew PDE engine        : {0:0.0000}", calculated);
            Console.WriteLine("FdBlackScholesVanillaEngine: {0:0.0000}", expected);
        }
Пример #7
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            /*********************
             ***  MARKET DATA  ***
             *********************/

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(18, Month.September, 2008);
            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int fixingDays = 3;
            int settlementDays = 3;

            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);
            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);

            Console.WriteLine("Today: {0}, {1}", todaysDate.DayOfWeek, todaysDate);
            Console.WriteLine("Settlement date: {0}, {1}", settlementDate.DayOfWeek, settlementDate);

            // Building of the bonds discounting yield curve

            /*********************
             ***  RATE HELPERS ***
             *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // Common data

            // ZC rates for the short end
             double zc3mQuote=0.0096;
             double zc6mQuote=0.0145;
             double zc1yQuote=0.0194;

             Quote zc3mRate = new SimpleQuote(zc3mQuote);
             Quote zc6mRate = new SimpleQuote(zc6mQuote);
             Quote zc1yRate = new SimpleQuote(zc1yQuote);

             DayCounter zcBondsDayCounter = new Actual365Fixed();

             RateHelper zc3m = new DepositRateHelper(new Handle<Quote>(zc3mRate),
                                                          new Period(3, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc6m = new DepositRateHelper(new Handle<Quote>(zc6mRate),
                                                          new Period(6, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc1y = new DepositRateHelper(new Handle<Quote>(zc1yRate),
                                                          new Period(1, TimeUnit.Years), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);

            // setup bonds
            double redemption = 100.0;

            const int numberOfBonds = 5;

            Date[] issueDates = {
                    new Date (15, Month.March, 2005),
                    new Date (15, Month.June, 2005),
                    new Date (30, Month.June, 2006),
                    new Date (15, Month.November, 2002),
                    new Date (15, Month.May, 1987)
            };

            Date[] maturities = {
                    new Date (31, Month.August, 2010),
                    new Date (31, Month.August, 2011),
                    new Date (31, Month.August, 2013),
                    new Date (15, Month.August, 2018),
                    new Date (15, Month.May, 2038)
            };

            double[] couponRates = {
                    0.02375,
                    0.04625,
                    0.03125,
                    0.04000,
                    0.04500
            };

            double[] marketQuotes = {
                    100.390625,
                    106.21875,
                    100.59375,
                    101.6875,
                    102.140625
            };

            List<SimpleQuote> quote = new List<SimpleQuote>();
            for (int i=0; i<numberOfBonds; i++) {
                SimpleQuote cp = new SimpleQuote(marketQuotes[i]);
                quote.Add(cp);
            }

            List<RelinkableHandle<Quote>> quoteHandle = new InitializedList<RelinkableHandle<Quote>>(numberOfBonds);
            for (int i=0; i<numberOfBonds; i++) {
                quoteHandle[i].linkTo(quote[i]);
            }

            // Definition of the rate helpers
            List<FixedRateBondHelper> bondsHelpers = new List<FixedRateBondHelper>();
            for (int i=0; i<numberOfBonds; i++) {

                Schedule schedule = new Schedule(issueDates[i], maturities[i], new Period(Frequency.Semiannual),
                                                 new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                                 DateGeneration.Rule.Backward, false);

                FixedRateBondHelper bondHelper = new FixedRateBondHelper(quoteHandle[i],
                                                                         settlementDays,
                                                                         100.0,
                                                                         schedule,
                                                                         new List<double>() { couponRates[i] },
                                                                         new ActualActual(ActualActual.Convention.Bond),
                                                                         BusinessDayConvention.Unadjusted,
                                                                         redemption,
                                                                         issueDates[i]);

                bondsHelpers.Add(bondHelper);
            }

            /*********************
             **  CURVE BUILDING **
             *********************/

             // Any DayCounter would be fine.
             // ActualActual::ISDA ensures that 30 years is 30.0
             DayCounter termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA);

             double tolerance = 1.0e-15;

             // A depo-bond curve
             List<RateHelper> bondInstruments = new List<RateHelper>();

             // Adding the ZC bonds to the curve for the short end
             bondInstruments.Add(zc3m);
             bondInstruments.Add(zc6m);
             bondInstruments.Add(zc1y);

             // Adding the Fixed rate bonds to the curve for the long end
             for (int i=0; i<numberOfBonds; i++) {
                 bondInstruments.Add(bondsHelpers[i]);
             }

             YieldTermStructure bondDiscountingTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>(
                                                                     settlementDate, bondInstruments,
                                                                     termStructureDayCounter,
                                                                     new List<Handle<Quote>>(),
                                                                     new List<Date>(),
                                                                     tolerance);

             // Building of the Libor forecasting curve
             // deposits
             double d1wQuote=0.043375;
             double d1mQuote=0.031875;
             double d3mQuote=0.0320375;
             double d6mQuote=0.03385;
             double d9mQuote=0.0338125;
             double d1yQuote=0.0335125;
             // swaps
             double s2yQuote=0.0295;
             double s3yQuote=0.0323;
             double s5yQuote=0.0359;
             double s10yQuote=0.0412;
             double s15yQuote=0.0433;

             /********************
              ***    QUOTES    ***
              ********************/

             // SimpleQuote stores a value which can be manually changed;
             // other Quote subclasses could read the value from a database
             // or some kind of data feed.

             // deposits
             Quote d1wRate = new SimpleQuote(d1wQuote);
             Quote d1mRate = new SimpleQuote(d1mQuote);
             Quote d3mRate = new SimpleQuote(d3mQuote);
             Quote d6mRate = new SimpleQuote(d6mQuote);
             Quote d9mRate = new SimpleQuote(d9mQuote);
             Quote d1yRate = new SimpleQuote(d1yQuote);
             // swaps
             Quote s2yRate = new SimpleQuote(s2yQuote);
             Quote s3yRate = new SimpleQuote(s3yQuote);
             Quote s5yRate = new SimpleQuote(s5yQuote);
             Quote s10yRate = new SimpleQuote(s10yQuote);
             Quote s15yRate = new SimpleQuote(s15yQuote);

             /*********************
              ***  RATE HELPERS ***
              *********************/

             // RateHelpers are built from the above quotes together with
             // other instrument dependant infos.  Quotes are passed in
             // relinkable handles which could be relinked to some other
             // data source later.

             // deposits
             DayCounter depositDayCounter = new Actual360();

             RateHelper d1w = new DepositRateHelper(
                     new Handle<Quote>(d1wRate),
                     new Period(1, TimeUnit.Weeks), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d1m = new DepositRateHelper(
                     new Handle<Quote>(d1mRate),
                     new Period(1, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d3m = new DepositRateHelper(
                     new Handle<Quote>(d3mRate),
                     new Period(3, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d6m = new DepositRateHelper(
                     new Handle<Quote>(d6mRate),
                     new Period(6, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d9m = new DepositRateHelper(
                     new Handle<Quote>(d9mRate),
                     new Period(9, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d1y = new DepositRateHelper(
                     new Handle<Quote>(d1yRate),
                     new Period(1, TimeUnit.Years), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);

             // setup swaps
             Frequency swFixedLegFrequency =Frequency.Annual;
             BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
             DayCounter swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
             IborIndex swFloatingLegIndex = new Euribor6M();

             Period forwardStart = new Period(1, TimeUnit.Days);

             RateHelper s2y = new SwapRateHelper(
                     new Handle<Quote>(s2yRate), new Period(2, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s3y = new SwapRateHelper(
                     new Handle<Quote>(s3yRate), new Period(3, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s5y = new SwapRateHelper(
                     new Handle<Quote>(s5yRate), new Period(5, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s10y = new SwapRateHelper(
                     new Handle<Quote>(s10yRate), new Period(10, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s15y = new SwapRateHelper(
                     new Handle<Quote>(s15yRate), new Period(15, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);

             /*********************
              **  CURVE BUILDING **
              *********************/

             // Any DayCounter would be fine.
             // ActualActual::ISDA ensures that 30 years is 30.0

             // A depo-swap curve
             List<RateHelper> depoSwapInstruments = new List<RateHelper>();
             depoSwapInstruments.Add(d1w);
             depoSwapInstruments.Add(d1m);
             depoSwapInstruments.Add(d3m);
             depoSwapInstruments.Add(d6m);
             depoSwapInstruments.Add(d9m);
             depoSwapInstruments.Add(d1y);
             depoSwapInstruments.Add(s2y);
             depoSwapInstruments.Add(s3y);
             depoSwapInstruments.Add(s5y);
             depoSwapInstruments.Add(s10y);
             depoSwapInstruments.Add(s15y);
             YieldTermStructure depoSwapTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>(
                             settlementDate, depoSwapInstruments,
                             termStructureDayCounter,
                             new List<Handle<Quote> >(),
                             new List<Date>(),
                             tolerance);

             // Term structures that will be used for pricing:
             // the one used for discounting cash flows
             RelinkableHandle<YieldTermStructure> discountingTermStructure = new RelinkableHandle<YieldTermStructure>();
             // the one used for forward rate forecasting
             RelinkableHandle<YieldTermStructure> forecastingTermStructure = new RelinkableHandle<YieldTermStructure>();

             /*********************
              * BONDS TO BE PRICED *
              **********************/

             // Common data
             double faceAmount = 100;

             // Pricing engine
             IPricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);

             // Zero coupon bond
             ZeroCouponBond zeroCouponBond = new ZeroCouponBond(
                     settlementDays,
                     new UnitedStates(UnitedStates.Market.GovernmentBond),
                     faceAmount,
                     new Date(15, Month.August,2013),
                     BusinessDayConvention.Following,
                     116.92,
                     new Date(15, Month.August,2003));

             zeroCouponBond.setPricingEngine(bondEngine);

             // Fixed 4.5% US Treasury Note
             Schedule fixedBondSchedule = new Schedule(new Date(15, Month.May, 2007),
                     new Date(15,Month.May,2017), new Period(Frequency.Semiannual),
                     new UnitedStates(UnitedStates.Market.GovernmentBond),
                     BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

             FixedRateBond fixedRateBond = new FixedRateBond(
                     settlementDays,
                     faceAmount,
                     fixedBondSchedule,
                     new List<double>() { 0.045 },
                     new ActualActual(ActualActual.Convention.Bond),
                     BusinessDayConvention.ModifiedFollowing,
                     100.0, new Date(15, Month.May, 2007));

             fixedRateBond.setPricingEngine(bondEngine);

             // Floating rate bond (3M USD Libor + 0.1%)
             // Should and will be priced on another curve later...

             RelinkableHandle<YieldTermStructure> liborTermStructure = new RelinkableHandle<YieldTermStructure>();
             IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);
             libor3m.addFixing(new Date(17, Month.July, 2008),0.0278625);

             Schedule floatingBondSchedule = new Schedule(new Date(21, Month.October, 2005),
                     new Date(21, Month.October, 2010), new Period(Frequency.Quarterly),
                     new UnitedStates(UnitedStates.Market.NYSE),
                     BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true);

             FloatingRateBond floatingRateBond = new FloatingRateBond(
                     settlementDays,
                     faceAmount,
                     floatingBondSchedule,
                     libor3m,
                     new Actual360(),
                     BusinessDayConvention.ModifiedFollowing,
                     2,
                     // Gearings
                     new List<double>() { 1.0 },
                     // Spreads
                     new List<double>() { 0.001 },
                     // Caps
                     new List<double>(),
                     // Floors
                     new List<double>(),
                     // Fixing in arrears
                     true,
                     100.0,
                     new Date(21, Month.October, 2005));

             floatingRateBond.setPricingEngine(bondEngine);

             // Coupon pricers
             IborCouponPricer pricer = new BlackIborCouponPricer();

             // optionLet volatilities
             double volatility = 0.0;
             Handle<OptionletVolatilityStructure> vol;
             vol = new Handle<OptionletVolatilityStructure>(
                                new ConstantOptionletVolatility(
                                     settlementDays,
                                     calendar,
                                     BusinessDayConvention.ModifiedFollowing,
                                     volatility,
                                     new Actual365Fixed()));

             pricer.setCapletVolatility(vol);
             Utils.setCouponPricer(floatingRateBond.cashflows(),pricer);

             // Yield curve bootstrapping
             forecastingTermStructure.linkTo(depoSwapTermStructure);
             discountingTermStructure.linkTo(bondDiscountingTermStructure);

             // We are using the depo & swap curve to estimate the future Libor rates
             liborTermStructure.linkTo(depoSwapTermStructure);

             /***************
              * BOND PRICING *
              ****************/

             // write column headings
             int[] widths = { 18, 10, 10, 10 };

            Console.WriteLine("{0,18}{1,10}{2,10}{3,10}", "", "ZC", "Fixed", "Floating");

            string separator = " | ";
            int width = widths[0]
                                 + widths[1]
                                          + widths[2]
                                                   + widths[3];
            string rule = "".PadLeft(width, '-'), dblrule = "".PadLeft(width, '=');
            string tab = "".PadLeft(8, ' ');

            Console.WriteLine(rule);

            Console.WriteLine("Net present value".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.NPV(),
                                fixedRateBond.NPV(),
                                floatingRateBond.NPV());

            Console.WriteLine("Clean price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.cleanPrice(),
                                fixedRateBond.cleanPrice(),
                                floatingRateBond.cleanPrice());

            Console.WriteLine("Dirty price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.dirtyPrice(),
                                fixedRateBond.dirtyPrice(),
                                floatingRateBond.dirtyPrice());

            Console.WriteLine("Accrued coupon".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.accruedAmount(),
                                fixedRateBond.accruedAmount(),
                                floatingRateBond.accruedAmount());

            Console.WriteLine("Previous coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                                "N/A",
                                fixedRateBond.previousCoupon(),
                                floatingRateBond.previousCoupon());

            Console.WriteLine("Next coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.nextCoupon(),
                              floatingRateBond.nextCoupon());

            Console.WriteLine("Yield".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual));

            Console.WriteLine();

            // Other computations
            Console.WriteLine("Sample indirect computations (for the floating rate bond): ");
            Console.WriteLine(rule);

            Console.WriteLine("Yield to Clean Price: {0:n2}",
                floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                                                                   new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                                   settlementDate));

            Console.WriteLine("Clean Price to Yield: {0:0.00%}",
                floatingRateBond.yield(floatingRateBond.cleanPrice(),new Actual360(), Compounding.Compounded, Frequency.Annual,
                                       settlementDate));

            /* "Yield to Price"
               "Price to Yield" */

            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #8
0
        public void consistency()
        {
            // check inflation leg vs calculation directly from inflation TS
            CommonVars common = new CommonVars();

            // ZeroInflationSwap aka CPISwap
            CPISwap.Type type    = CPISwap.Type.Payer;
            double       nominal = 1000000.0;
            bool         subtractInflationNominal = true;
            // float+spread leg
            double                spread                 = 0.0;
            DayCounter            floatDayCount          = new Actual365Fixed();
            BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing;
            int       fixingDays = 0;
            IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK);

            // fixed x inflation leg
            double                fixedRate                = 0.1;   //1% would be 0.01
            double                baseCPI                  = 206.1; // would be 206.13871 if we were interpolating
            DayCounter            fixedDayCount            = new Actual365Fixed();
            BusinessDayConvention fixedPaymentConvention   = BusinessDayConvention.ModifiedFollowing;
            Calendar              fixedPaymentCalendar     = new UnitedKingdom();
            ZeroInflationIndex    fixedIndex               = common.ii;
            Period                contractObservationLag   = common.contractObservationLag;
            InterpolationType     observationInterpolation = common.contractObservationInterpolation;

            // set the schedules
            Date     startDate     = new Date(2, Month.October, 2007);
            Date     endDate       = new Date(2, Month.October, 2052);
            Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(floatPaymentConvention)
                                     .backwards().value();
            Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(BusinessDayConvention.Unadjusted)
                                     .backwards().value();


            CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal,
                                       spread, floatDayCount, floatSchedule,
                                       floatPaymentConvention, fixingDays, floatIndex,
                                       fixedRate, baseCPI, fixedDayCount, fixedSchedule,
                                       fixedPaymentConvention, contractObservationLag,
                                       fixedIndex, observationInterpolation);
            Date asofDate = Settings.evaluationDate();

            double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 };
            double[] cpiFix   = { 211.4, 217.2, 211.4, 213.4, -2, -2 };
            for (int i = 0; i < floatSchedule.Count; i++)
            {
                if (floatSchedule[i] < common.evaluationDate)
                {
                    floatIndex.addFixing(floatSchedule[i], floatFix[i], true); //true=overwrite
                }

                CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon;
                if (zic != null)
                {
                    if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months)))
                    {
                        fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true);
                    }
                }
            }

            // simple structure so simple pricing engine - most work done by index
            DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK);

            zisV.setPricingEngine(dse);

            // get float+spread & fixed*inflation leg prices separately
            double testInfLegNPV = 0.0;
            double diff;

            for (int i = 0; i < zisV.leg(0).Count; i++)
            {
                Date zicPayDate = (zisV.leg(0))[i].date();
                if (zicPayDate > asofDate)
                {
                    testInfLegNPV += (zisV.leg(0))[i].amount() * common.nominalUK.link.discount(zicPayDate);
                }

                CPICoupon zicV = zisV.cpiLeg()[i] as CPICoupon;
                if (zicV != null)
                {
                    diff = Math.Abs(zicV.rate() - (fixedRate * (zicV.indexFixing() / baseCPI)));
                    QAssert.IsTrue(diff < 1e-8, "failed " + i + "th coupon reconstruction as "
                                   + (fixedRate * (zicV.indexFixing() / baseCPI)) + " vs rate = "
                                   + zicV.rate() + ", with difference: " + diff);
                }
            }

            double error = Math.Abs(testInfLegNPV - zisV.legNPV(0).Value);

            QAssert.IsTrue(error < 1e-5, "failed manual inf leg NPV calc vs pricing engine: " + testInfLegNPV + " vs " +
                           zisV.legNPV(0));

            diff = Math.Abs(1 - zisV.NPV() / 4191660.0);
#if QL_USE_INDEXED_COUPON
            double max_diff = 1e-5;
#else
            double max_diff = 3e-5;
#endif
            QAssert.IsTrue(diff < max_diff, "failed stored consistency value test, ratio = " + diff);

            // remove circular refernce
            common.hcpi.linkTo(null);
        }
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            /*********************
            ***  MARKET DATA  ***
            *********************/

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(18, Month.September, 2008);

            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int fixingDays     = 3;
            int settlementDays = 3;

            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);

            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);

            Console.WriteLine("Today: {0}, {1}", todaysDate.DayOfWeek, todaysDate);
            Console.WriteLine("Settlement date: {0}, {1}", settlementDate.DayOfWeek, settlementDate);


            // Building of the bonds discounting yield curve

            /*********************
            ***  RATE HELPERS ***
            *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // Common data

            // ZC rates for the short end
            double zc3mQuote = 0.0096;
            double zc6mQuote = 0.0145;
            double zc1yQuote = 0.0194;

            Quote zc3mRate = new SimpleQuote(zc3mQuote);
            Quote zc6mRate = new SimpleQuote(zc6mQuote);
            Quote zc1yRate = new SimpleQuote(zc1yQuote);

            DayCounter zcBondsDayCounter = new Actual365Fixed();

            RateHelper zc3m = new DepositRateHelper(new Handle <Quote>(zc3mRate),
                                                    new Period(3, TimeUnit.Months), fixingDays,
                                                    calendar, BusinessDayConvention.ModifiedFollowing,
                                                    true, zcBondsDayCounter);
            RateHelper zc6m = new DepositRateHelper(new Handle <Quote>(zc6mRate),
                                                    new Period(6, TimeUnit.Months), fixingDays,
                                                    calendar, BusinessDayConvention.ModifiedFollowing,
                                                    true, zcBondsDayCounter);
            RateHelper zc1y = new DepositRateHelper(new Handle <Quote>(zc1yRate),
                                                    new Period(1, TimeUnit.Years), fixingDays,
                                                    calendar, BusinessDayConvention.ModifiedFollowing,
                                                    true, zcBondsDayCounter);

            // setup bonds
            double redemption = 100.0;

            const int numberOfBonds = 5;

            Date[] issueDates =
            {
                new Date(15, Month.March,    2005),
                new Date(15, Month.June,     2005),
                new Date(30, Month.June,     2006),
                new Date(15, Month.November, 2002),
                new Date(15, Month.May, 1987)
            };

            Date[] maturities =
            {
                new Date(31, Month.August, 2010),
                new Date(31, Month.August, 2011),
                new Date(31, Month.August, 2013),
                new Date(15, Month.August, 2018),
                new Date(15, Month.May, 2038)
            };

            double[] couponRates =
            {
                0.02375,
                0.04625,
                0.03125,
                0.04000,
                0.04500
            };

            double[] marketQuotes =
            {
                100.390625,
                106.21875,
                100.59375,
                101.6875,
                102.140625
            };

            List <SimpleQuote> quote = new List <SimpleQuote>();

            for (int i = 0; i < numberOfBonds; i++)
            {
                SimpleQuote cp = new SimpleQuote(marketQuotes[i]);
                quote.Add(cp);
            }

            List <RelinkableHandle <Quote> > quoteHandle = new InitializedList <RelinkableHandle <Quote> >(numberOfBonds);

            for (int i = 0; i < numberOfBonds; i++)
            {
                quoteHandle[i].linkTo(quote[i]);
            }

            // Definition of the rate helpers
            List <FixedRateBondHelper> bondsHelpers = new List <FixedRateBondHelper>();

            for (int i = 0; i < numberOfBonds; i++)
            {
                Schedule schedule = new Schedule(issueDates[i], maturities[i], new Period(Frequency.Semiannual),
                                                 new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                                 DateGeneration.Rule.Backward, false);

                FixedRateBondHelper bondHelper = new FixedRateBondHelper(quoteHandle[i],
                                                                         settlementDays,
                                                                         100.0,
                                                                         schedule,
                                                                         new List <double>()
                {
                    couponRates[i]
                },
                                                                         new ActualActual(ActualActual.Convention.Bond),
                                                                         BusinessDayConvention.Unadjusted,
                                                                         redemption,
                                                                         issueDates[i]);

                bondsHelpers.Add(bondHelper);
            }

            /*********************
            **  CURVE BUILDING **
            *********************/

            // Any DayCounter would be fine.
            // ActualActual::ISDA ensures that 30 years is 30.0
            DayCounter termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA);

            double tolerance = 1.0e-15;

            // A depo-bond curve
            List <RateHelper> bondInstruments = new List <RateHelper>();

            // Adding the ZC bonds to the curve for the short end
            bondInstruments.Add(zc3m);
            bondInstruments.Add(zc6m);
            bondInstruments.Add(zc1y);

            // Adding the Fixed rate bonds to the curve for the long end
            for (int i = 0; i < numberOfBonds; i++)
            {
                bondInstruments.Add(bondsHelpers[i]);
            }

            YieldTermStructure bondDiscountingTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, bondInstruments,
                termStructureDayCounter,
                new List <Handle <Quote> >(),
                new List <Date>(),
                tolerance);

            // Building of the Libor forecasting curve
            // deposits
            double d1wQuote = 0.043375;
            double d1mQuote = 0.031875;
            double d3mQuote = 0.0320375;
            double d6mQuote = 0.03385;
            double d9mQuote = 0.0338125;
            double d1yQuote = 0.0335125;
            // swaps
            double s2yQuote  = 0.0295;
            double s3yQuote  = 0.0323;
            double s5yQuote  = 0.0359;
            double s10yQuote = 0.0412;
            double s15yQuote = 0.0433;


            /********************
            ***    QUOTES    ***
            ********************/

            // SimpleQuote stores a value which can be manually changed;
            // other Quote subclasses could read the value from a database
            // or some kind of data feed.

            // deposits
            Quote d1wRate = new SimpleQuote(d1wQuote);
            Quote d1mRate = new SimpleQuote(d1mQuote);
            Quote d3mRate = new SimpleQuote(d3mQuote);
            Quote d6mRate = new SimpleQuote(d6mQuote);
            Quote d9mRate = new SimpleQuote(d9mQuote);
            Quote d1yRate = new SimpleQuote(d1yQuote);
            // swaps
            Quote s2yRate  = new SimpleQuote(s2yQuote);
            Quote s3yRate  = new SimpleQuote(s3yQuote);
            Quote s5yRate  = new SimpleQuote(s5yQuote);
            Quote s10yRate = new SimpleQuote(s10yQuote);
            Quote s15yRate = new SimpleQuote(s15yQuote);

            /*********************
            ***  RATE HELPERS ***
            *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // deposits
            DayCounter depositDayCounter = new Actual360();

            RateHelper d1w = new DepositRateHelper(
                new Handle <Quote>(d1wRate),
                new Period(1, TimeUnit.Weeks), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d1m = new DepositRateHelper(
                new Handle <Quote>(d1mRate),
                new Period(1, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d3m = new DepositRateHelper(
                new Handle <Quote>(d3mRate),
                new Period(3, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d6m = new DepositRateHelper(
                new Handle <Quote>(d6mRate),
                new Period(6, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d9m = new DepositRateHelper(
                new Handle <Quote>(d9mRate),
                new Period(9, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d1y = new DepositRateHelper(
                new Handle <Quote>(d1yRate),
                new Period(1, TimeUnit.Years), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);

            // setup swaps
            Frequency             swFixedLegFrequency  = Frequency.Annual;
            BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
            DayCounter            swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
            IborIndex             swFloatingLegIndex   = new Euribor6M();

            Period forwardStart = new Period(1, TimeUnit.Days);

            RateHelper s2y = new SwapRateHelper(
                new Handle <Quote>(s2yRate), new Period(2, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s3y = new SwapRateHelper(
                new Handle <Quote>(s3yRate), new Period(3, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s5y = new SwapRateHelper(
                new Handle <Quote>(s5yRate), new Period(5, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s10y = new SwapRateHelper(
                new Handle <Quote>(s10yRate), new Period(10, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s15y = new SwapRateHelper(
                new Handle <Quote>(s15yRate), new Period(15, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);


            /*********************
            **  CURVE BUILDING **
            *********************/

            // Any DayCounter would be fine.
            // ActualActual::ISDA ensures that 30 years is 30.0

            // A depo-swap curve
            List <RateHelper> depoSwapInstruments = new List <RateHelper>();

            depoSwapInstruments.Add(d1w);
            depoSwapInstruments.Add(d1m);
            depoSwapInstruments.Add(d3m);
            depoSwapInstruments.Add(d6m);
            depoSwapInstruments.Add(d9m);
            depoSwapInstruments.Add(d1y);
            depoSwapInstruments.Add(s2y);
            depoSwapInstruments.Add(s3y);
            depoSwapInstruments.Add(s5y);
            depoSwapInstruments.Add(s10y);
            depoSwapInstruments.Add(s15y);
            YieldTermStructure depoSwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoSwapInstruments,
                termStructureDayCounter,
                new List <Handle <Quote> >(),
                new List <Date>(),
                tolerance);

            // Term structures that will be used for pricing:
            // the one used for discounting cash flows
            RelinkableHandle <YieldTermStructure> discountingTermStructure = new RelinkableHandle <YieldTermStructure>();
            // the one used for forward rate forecasting
            RelinkableHandle <YieldTermStructure> forecastingTermStructure = new RelinkableHandle <YieldTermStructure>();

            /*********************
             * BONDS TO BE PRICED *
             **********************/

            // Common data
            double faceAmount = 100;

            // Pricing engine
            IPricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);

            // Zero coupon bond
            ZeroCouponBond zeroCouponBond = new ZeroCouponBond(
                settlementDays,
                new UnitedStates(UnitedStates.Market.GovernmentBond),
                faceAmount,
                new Date(15, Month.August, 2013),
                BusinessDayConvention.Following,
                116.92,
                new Date(15, Month.August, 2003));

            zeroCouponBond.setPricingEngine(bondEngine);

            // Fixed 4.5% US Treasury Note
            Schedule fixedBondSchedule = new Schedule(new Date(15, Month.May, 2007),
                                                      new Date(15, Month.May, 2017), new Period(Frequency.Semiannual),
                                                      new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                      BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

            FixedRateBond fixedRateBond = new FixedRateBond(
                settlementDays,
                faceAmount,
                fixedBondSchedule,
                new List <double>()
            {
                0.045
            },
                new ActualActual(ActualActual.Convention.Bond),
                BusinessDayConvention.ModifiedFollowing,
                100.0, new Date(15, Month.May, 2007));

            fixedRateBond.setPricingEngine(bondEngine);

            // Floating rate bond (3M USD Libor + 0.1%)
            // Should and will be priced on another curve later...

            RelinkableHandle <YieldTermStructure> liborTermStructure = new RelinkableHandle <YieldTermStructure>();
            IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);

            libor3m.addFixing(new Date(17, Month.July, 2008), 0.0278625);

            Schedule floatingBondSchedule = new Schedule(new Date(21, Month.October, 2005),
                                                         new Date(21, Month.October, 2010), new Period(Frequency.Quarterly),
                                                         new UnitedStates(UnitedStates.Market.NYSE),
                                                         BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true);

            FloatingRateBond floatingRateBond = new FloatingRateBond(
                settlementDays,
                faceAmount,
                floatingBondSchedule,
                libor3m,
                new Actual360(),
                BusinessDayConvention.ModifiedFollowing,
                2,
                // Gearings
                new List <double>()
            {
                1.0
            },
                // Spreads
                new List <double>()
            {
                0.001
            },
                // Caps
                new List <double>(),
                // Floors
                new List <double>(),
                // Fixing in arrears
                true,
                100.0,
                new Date(21, Month.October, 2005));

            floatingRateBond.setPricingEngine(bondEngine);

            // Coupon pricers
            IborCouponPricer pricer = new BlackIborCouponPricer();

            // optionLet volatilities
            double volatility = 0.0;
            Handle <OptionletVolatilityStructure> vol;

            vol = new Handle <OptionletVolatilityStructure>(
                new ConstantOptionletVolatility(
                    settlementDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    volatility,
                    new Actual365Fixed()));

            pricer.setCapletVolatility(vol);
            Utils.setCouponPricer(floatingRateBond.cashflows(), pricer);

            // Yield curve bootstrapping
            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(bondDiscountingTermStructure);

            // We are using the depo & swap curve to estimate the future Libor rates
            liborTermStructure.linkTo(depoSwapTermStructure);

            /***************
             * BOND PRICING *
             ****************/

            // write column headings
            int[] widths = { 18, 10, 10, 10 };

            Console.WriteLine("{0,18}{1,10}{2,10}{3,10}", "", "ZC", "Fixed", "Floating");

            string separator = " | ";
            int    width     = widths[0]
                               + widths[1]
                               + widths[2]
                               + widths[3];
            string rule = "".PadLeft(width, '-'), dblrule = "".PadLeft(width, '=');
            string tab = "".PadLeft(8, ' ');

            Console.WriteLine(rule);

            Console.WriteLine("Net present value".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.NPV(),
                              fixedRateBond.NPV(),
                              floatingRateBond.NPV());

            Console.WriteLine("Clean price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.cleanPrice(),
                              fixedRateBond.cleanPrice(),
                              floatingRateBond.cleanPrice());

            Console.WriteLine("Dirty price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.dirtyPrice(),
                              fixedRateBond.dirtyPrice(),
                              floatingRateBond.dirtyPrice());

            Console.WriteLine("Accrued coupon".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.accruedAmount(),
                              fixedRateBond.accruedAmount(),
                              floatingRateBond.accruedAmount());

            Console.WriteLine("Previous coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.previousCoupon(),
                              floatingRateBond.previousCoupon());

            Console.WriteLine("Next coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.nextCoupon(),
                              floatingRateBond.nextCoupon());

            Console.WriteLine("Yield".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual));

            Console.WriteLine();

            // Other computations
            Console.WriteLine("Sample indirect computations (for the floating rate bond): ");
            Console.WriteLine(rule);

            Console.WriteLine("Yield to Clean Price: {0:n2}",
                              floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                                                          new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                          settlementDate));

            Console.WriteLine("Clean Price to Yield: {0:0.00%}",
                              floatingRateBond.yield(floatingRateBond.cleanPrice(), new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                     settlementDate));

            /* "Yield to Price"
            *  "Price to Yield" */

            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #10
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            ////////////////  DATES  //////////////////////////////////////////////
            Calendar calendar       = new TARGET();
            Date     todaysDate     = new Date(15, Month.January, 2017);
            Date     settlementDate = new Date(todaysDate);

            Settings.setEvaluationDate(todaysDate);
            DayCounter dayCounter = new Actual365Fixed();


            ////////////////  MARKET  //////////////////////////////////////////////
            double underlying    = 100.0;
            double dividendYield = 0.035;
            double riskFreeRate  = 0.01;
            double intensity     = 0.02;
            double volatility    = 0.20;

            Handle <YieldTermStructure> flatRfTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            Handle <DefaultProbabilityTermStructure> flatHazardStructure = new Handle <DefaultProbabilityTermStructure>(new FlatHazardRate(settlementDate, intensity, dayCounter));

            Period     forwardStart         = new Period(1, TimeUnit.Days);
            DayCounter swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
            IborIndex  swFloatingLegIndex   = new Euribor6M();


            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));
            Handle <YieldTermStructure>             flatDividendTS = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            Handle <BlackVolTermStructure>          flatVolTS      = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            GeneralizedBlackScholesProcessTolerance bsmProcess     = new GeneralizedBlackScholesProcessTolerance(underlyingH, flatDividendTS, flatRfTermStructure, flatVolTS);


            Console.WriteLine("Underlying price = " + underlying);
            Console.WriteLine("Risk-free interest rate = {0:0.00%}", riskFreeRate);
            Console.WriteLine("Dividend yield = {0:0.00%}", dividendYield);
            Console.WriteLine("Volatility = {0:0.00%}", volatility);
            Console.Write("\n");

            ////////////////  SIMPLEX  //////////////////////////////////////////////

            /*
             * CostFunction corstFunction = new CostFunction();
             *
             * List<double> X = new InitializedList<double>();
             * X.Add(0.0);
             * Vector vectX = new Vector (X);
             *
             * List<double> Dir = new InitializedList<double>();
             * Dir.Add(1);
             * Vector vectDir = new Vector (Dir);
             *
             * Constraint constraint = new PositiveConstraint();
             * constraint
             * Vector initValues = new Vector();
             *
             * Problem myProb = new Problem(corstFunction, constraint, initValues);
             */

            ////////////////  SURFACE  //////////////////////////////////////////////

            /*
             * freeArbSVI testSurface = new freeArbSVI(strikesVol, timesVol, spotATP, flatTermStructure, flatDividendTS, blackVolMatrix,50);
             *
             * testSurface.matricesBuildingForwardMoneyness();
             * testSurface.matricesBuildingTotalVariance();
             * testSurface.matricesBuildingBSPrices();
             * testSurface.splincalculation();
             * testSurface.matricesBuildingA();
             * testSurface.matricesBuildingB();
             */

            //Console.WriteLine("value [0,0] = {0}", blackVolMatrix[1,1]);



            // End test
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
        public void calculate(GBMParaViewModel para)
        {
            // set up dates
            Calendar calendar = new TARGET();
            //Date todaysDate = new Date(DateTime.Now);
            Date settlementDate = new Date(para.ReferenceDate_);

            Settings.setEvaluationDate(settlementDate);

            // our options
            Option.Type type = this.callPutEnum_;

            double underlying    = para.CurrentPrice_;
            double strike        = this.strike_;
            double dividendYield = para.Dividend_ / 100;
            double riskFreeRate  = para.Drift_ / 100;
            double volatility    = 0.0;

            if (this.callPutEnum_ == Option.Type.Call)
            {
                try
                {
                    volatility     = para.Call_Interpolation_.value(this.strike_) / 100;
                    this.imVolCal_ = Math.Round(para.Call_Interpolation_.value(this.strike_), 1);
                }
                catch (Exception)
                {
                    volatility     = para.Call_Interpolation_.value(this.strike_, true) / 100;
                    this.imVolCal_ = Math.Round(para.Call_Interpolation_.value(this.strike_, true), 1);
                }
            }
            else if (this.callPutEnum_ == Option.Type.Put)
            {
                try
                {
                    volatility     = para.Call_Interpolation_.value(this.strike_) / 100;
                    this.imVolCal_ = Math.Round(para.Put_Interpolation_.value(this.strike_), 1);
                }
                catch (Exception)
                {
                    volatility     = para.Call_Interpolation_.value(this.strike_, true) / 100;
                    this.imVolCal_ = Math.Round(para.Put_Interpolation_.value(this.strike_, true), 1);
                }
            }



            Date maturity = new Date(this.maturiry_);

            DayCounter dayCounter = new Actual365Fixed();

            //// write column headings
            //int[] widths = new int[] { 35, 14, 14, 14 };
            //Console.Write("{0,-" + widths[0] + "}", "Method");
            //Console.Write("{0,-" + widths[1] + "}", "European");
            //Console.Write("{0,-" + widths[2] + "}", "Bermudan");
            //Console.WriteLine("{0,-" + widths[3] + "}", "American");

            //List<Date> exerciseDates = new List<Date>(); ;
            //for (int i = 1; i <= 4; i++)
            //    exerciseDates.Add(settlementDate + new Period(3 * i, TimeUnit.Months));

            Exercise europeanExercise = new EuropeanExercise(maturity);
            //Exercise bermudanExercise = new BermudanExercise(exerciseDates);
            //Exercise americanExercise = new AmericanExercise(settlementDate, maturity);

            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // bootstrap the yield/dividend/vol curves
            var flatTermStructure    = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            var flatDividendTS       = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            var flatVolTS            = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
            var bsmProcess           = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

            // options
            VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise);

            // Analytic formulas:
            // Black-Scholes for European
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));

            this.npv_      = Math.Round(europeanOption.NPV(), 6);
            this.deltaCal_ = Math.Round(europeanOption.delta(), 6);
            this.gammaCal_ = Math.Round(europeanOption.gamma(), 6);
            this.vegaCal_  = Math.Round(europeanOption.vega() / 100, 6);
            this.thetaCal_ = Math.Round(europeanOption.theta() / 365, 6);
            this.rhoCal_   = Math.Round(europeanOption.rho() / 100, 6);
        }
Пример #12
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            ////////////////  DATES  //////////////////////////////////////////////

            Calendar calendar       = new TARGET();
            Date     todaysDate     = new Date(15, Month.January, 2017);
            Date     settlementDate = new Date(todaysDate);

            Settings.setEvaluationDate(todaysDate);
            DayCounter dayCounter = new Actual365Fixed();


            ////////////////  MARKET  //////////////////////////////////////////////

            // Spot
            double         underlying  = 100;
            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // riskfree
            double riskFreeRate = 0.01;
            Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));


            // dividend
            double dividendYield = 0.035;
            double fixedDiv      = 5.0;

            Handle <YieldTermStructure> flatDividendTS        = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            Handle <YieldTermStructure> FixedDivTermStructure = new Handle <YieldTermStructure>(new FixedForward(settlementDate, fixedDiv, underlying, dayCounter));

            // flatvol
            double volatility = 0.20;
            Handle <BlackVolTermStructure> flatVolTS = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));

            Console.WriteLine("Underlying price = " + underlying);
            Console.WriteLine("Risk-free interest rate = {0:0.00%}", riskFreeRate);
            Console.WriteLine("Dividend yield = {0:0.00%}", dividendYield);
            Console.WriteLine("Flat Volatility = {0:0.00%}", volatility);
            Console.Write("\n");

            // volSurface

            List <Date>   datesVol       = new InitializedList <Date>();
            List <double> strikesVol     = new InitializedList <double>();
            double        spotATP        = 100;
            Date          StartDateVol   = settlementDate + new Period(1, TimeUnit.Months);
            Matrix        blackVolMatrix = new Matrix(5, 5, 0.2);


            List <double> timesVol = new InitializedList <double>();

            for (int i = 0; i < blackVolMatrix.rows(); i++)
            {
                timesVol.Add(i + 1);
            }

            for (int j = 0; j < blackVolMatrix.columns(); j++)
            {
                datesVol.Add(StartDateVol + new Period(j, TimeUnit.Years));
                for (int i = 0; i < blackVolMatrix.rows(); i++)
                {
                    blackVolMatrix[i, j] = 0.2 + Math.Pow(2.5, (i)) / 100;
                }
            }
            for (int j = 0; j < blackVolMatrix.columns(); j++)
            {
                strikesVol.Add(spotATP * (1 - (double)((int)(blackVolMatrix.rows() / 2)) / 10) + spotATP * 0.1 * j);
            }



            BlackVarianceSurface mySurface = new BlackVarianceSurface(settlementDate, calendar, datesVol,
                                                                      strikesVol, blackVolMatrix, dayCounter);

            Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(mySurface);


            // process
            GeneralizedBlackScholesProcessTolerance bsmProcessVolSurface = new GeneralizedBlackScholesProcessTolerance(underlyingH, FixedDivTermStructure, flatTermStructure, mySurfaceH);
            GeneralizedBlackScholesProcessTolerance bsmProcess           = new GeneralizedBlackScholesProcessTolerance(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);


            ////////////////  INSTRUMENT  //////////////////////////////////////////////

            double tolerance = 0.2;

            List <Date> fixingdates = new InitializedList <Date>();
            double      coupon      = 0.05;
            double      barrierlvl  = 0.6;

            for (int i = 1; i <= 4; i++)
            {
                fixingdates.Add(settlementDate + new Period(i, TimeUnit.Years));
            }

            GenericAutocall myGenericAutocall = new GenericAutocall(fixingdates, coupon, barrierlvl, underlying);
            IPricingEngine  mcengine          = new MakeMGenericInstrument <PseudoRandom>(bsmProcessVolSurface)
                                                .withAbsoluteTolerance(tolerance)
                                                .withStepsPerYear(52)
                                                .withSeed(50)
                                                .value();

            myGenericAutocall.setPricingEngine(mcengine);


            ////////////////  Printing Results  //////////////////////////////////////////////

            Console.WriteLine("NPV Generic Autocall = {0:0.0000}", myGenericAutocall.NPV());
            Console.WriteLine("Err = {0:0.0000%}", myGenericAutocall.errorEstimate() / myGenericAutocall.NPV());
            Console.WriteLine("Samples = {0}", myGenericAutocall.samples());
            Console.Write("\n");

            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocall.inspout("ProbaCall " + i), i + 1);
            }
            Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocall.inspout("ProbaMid"));
            Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocall.inspout("ProbaDown"));
            Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocall.inspout("AvgDown") / myGenericAutocall.inspout("ProbaDown"));

            Console.Write("\n");
            Console.WriteLine("Test - NoValue = {0:0.0000%}", myGenericAutocall.inspout("NoValue"));


            // inspout() function
            Console.Write("\n");
            myGenericAutocall.inspout();

            Console.Write("\n");
            myGenericAutocall.inspout(2, true);

            // End test
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #13
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            // set up dates
            Calendar calendar = new TARGET();
            Date todaysDate = new Date(15, Month.May, 1998);
            Date settlementDate = new Date(17, Month.May, 1998);
            Settings.setEvaluationDate(todaysDate);

            // our options
            Option.Type type = Option.Type.Put;
            double underlying = 36;
            double strike = 40;
            double dividendYield = 0.00;
            double riskFreeRate = 0.06;
            double volatility = 0.20;
            Date maturity = new Date(17, Month.May, 1999);
            DayCounter dayCounter = new Actual365Fixed();

            Console.WriteLine("Option type = " + type);
            Console.WriteLine("Maturity = "    + maturity);
            Console.WriteLine("Underlying price = " + underlying);
            Console.WriteLine("Strike = "      + strike);
            Console.WriteLine("Risk-free interest rate = {0:0.000000%}", riskFreeRate);
            Console.WriteLine("Dividend yield = {0:0.000000%}", dividendYield);
            Console.WriteLine("Volatility = {0:0.000000%}", volatility);
            Console.Write("\n");

            string method;

            Console.Write("\n");

            // write column headings
            int[] widths = new int[]{ 35, 14, 14, 14 };
            Console.Write("{0,-" + widths[0] + "}", "Method");
            Console.Write("{0,-" + widths[1] + "}", "European");
            Console.Write("{0,-" + widths[2] + "}", "Bermudan");
            Console.WriteLine("{0,-" + widths[3] + "}", "American");

            List<Date> exerciseDates = new List<Date>(); ;
            for (int i = 1; i <= 4; i++)
                exerciseDates.Add(settlementDate + new Period(3 * i, TimeUnit.Months));

            Exercise europeanExercise = new EuropeanExercise(maturity);
            Exercise bermudanExercise = new BermudanExercise(exerciseDates);
            Exercise americanExercise = new AmericanExercise(settlementDate, maturity);

            Handle<Quote> underlyingH = new Handle<Quote>(new SimpleQuote(underlying));

            // bootstrap the yield/dividend/vol curves
            var flatTermStructure = new Handle<YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            var flatDividendTS = new Handle<YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            var flatVolTS = new Handle<BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
            var bsmProcess = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

            // options
            VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise);
            VanillaOption bermudanOption = new VanillaOption(payoff, bermudanExercise);
            VanillaOption americanOption = new VanillaOption(payoff, americanExercise);

            // Analytic formulas:

            // Black-Scholes for European
            method = "Black-Scholes";
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + "}", "N/A");

            // Barone-Adesi and Whaley approximation for American
            method = "Barone-Adesi/Whaley";
            americanOption.setPricingEngine(new BaroneAdesiWhaleyApproximationEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + "}", "N/A");
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Bjerksund and Stensland approximation for American
            method = "Bjerksund/Stensland";
            americanOption.setPricingEngine(new BjerksundStenslandApproximationEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + "}", "N/A");
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Integral
            method = "Integral";
            europeanOption.setPricingEngine(new IntegralEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + "}", "N/A");

            // Finite differences
            int timeSteps = 801;
            method = "Finite differences";
            europeanOption.setPricingEngine(new FDEuropeanEngine(bsmProcess,timeSteps,timeSteps-1));
            bermudanOption.setPricingEngine(new FDBermudanEngine(bsmProcess,timeSteps,timeSteps-1));
            americanOption.setPricingEngine(new FDAmericanEngine(bsmProcess,timeSteps,timeSteps-1));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Jarrow-Rudd
            method = "Binomial Jarrow-Rudd";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<JarrowRudd>(bsmProcess,timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<JarrowRudd>(bsmProcess,timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<JarrowRudd>(bsmProcess,timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            method = "Binomial Cox-Ross-Rubinstein";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<CoxRossRubinstein>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Additive equiprobabilities
            method = "Additive equiprobabilities";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<AdditiveEQPBinomialTree>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Trigeorgis
            method = "Binomial Trigeorgis";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<Trigeorgis>(bsmProcess,timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<Trigeorgis>(bsmProcess,timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<Trigeorgis>(bsmProcess,timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Tian
            method = "Binomial Tian";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<Tian>(bsmProcess,timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<Tian>(bsmProcess,timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<Tian>(bsmProcess,timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Leisen-Reimer
            method = "Binomial Leisen-Reimer";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<LeisenReimer>(bsmProcess,timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<LeisenReimer>(bsmProcess,timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<LeisenReimer>(bsmProcess,timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Joshi
            method = "Binomial Joshi";
            europeanOption.setPricingEngine(new BinomialVanillaEngine<Joshi4>(bsmProcess,timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine<Joshi4>(bsmProcess,timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine<Joshi4>(bsmProcess,timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Monte Carlo Method: MC (crude)
            timeSteps = 1;
            method = "MC (crude)";
            ulong mcSeed = 42;
            IPricingEngine mcengine1 = new MakeMCEuropeanEngine<PseudoRandom>(bsmProcess)
                                            .withSteps(timeSteps)
                                            .withAbsoluteTolerance(0.02)
                                            .withSeed(mcSeed)
                                            .value();
            europeanOption.setPricingEngine(mcengine1);
            // Real errorEstimate = europeanOption.errorEstimate();
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", "N/A");

            // Monte Carlo Method: QMC (Sobol)
            method = "QMC (Sobol)";
            int nSamples = 32768;  // 2^15

            IPricingEngine mcengine2 = new MakeMCEuropeanEngine<LowDiscrepancy>(bsmProcess)
                                            .withSteps(timeSteps)
                                            .withSamples(nSamples)
                                            .value();
            europeanOption.setPricingEngine(mcengine2);
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", "N/A");

            // Monte Carlo Method: MC (Longstaff Schwartz)
            method = "MC (Longstaff Schwartz)";
            IPricingEngine mcengine3 = new MakeMCAmericanEngine<PseudoRandom>(bsmProcess)
                                        .withSteps(100)
                                        .withAntitheticVariate()
                                        .withCalibrationSamples(4096)
                                        .withAbsoluteTolerance(0.02)
                                        .withSeed(mcSeed)
                                        .value();
            americanOption.setPricingEngine(mcengine3);
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", "N/A");
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // End test
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #14
0
        /// <summary>
        /// Evaluates the specified option contract to compute a theoretical price, IV and greeks
        /// </summary>
        /// <param name="security">The option security object</param>
        /// <param name="slice">The current data slice. This can be used to access other information
        /// available to the algorithm</param>
        /// <param name="contract">The option contract to evaluate</param>
        /// <returns>An instance of <see cref="OptionPriceModelResult"/> containing the theoretical
        /// price of the specified option contract</returns>
        public OptionPriceModelResult Evaluate(Security security, Slice slice, OptionContract contract)
        {
            try
            {
                // setting up option pricing parameters
                var calendar       = new UnitedStates();
                var dayCounter     = new Actual365Fixed();
                var optionSecurity = (Option)security;

                var settlementDate       = contract.Time.Date.AddDays(Option.DefaultSettlementDays);
                var maturityDate         = contract.Expiry.Date.AddDays(Option.DefaultSettlementDays);
                var underlyingQuoteValue = new SimpleQuote((double)optionSecurity.Underlying.Price);

                var dividendYieldValue = new SimpleQuote(_dividendYieldEstimator.Estimate(security, slice, contract));
                var dividendYield      = new Handle <YieldTermStructure>(new FlatForward(0, calendar, dividendYieldValue, dayCounter));

                var riskFreeRateValue = new SimpleQuote(_riskFreeRateEstimator.Estimate(security, slice, contract));
                var riskFreeRate      = new Handle <YieldTermStructure>(new FlatForward(0, calendar, riskFreeRateValue, dayCounter));

                var underlyingVolValue = new SimpleQuote(_underlyingVolEstimator.Estimate(security, slice, contract));
                var underlyingVol      = new Handle <BlackVolTermStructure>(new BlackConstantVol(0, calendar, new Handle <Quote>(underlyingVolValue), dayCounter));

                // preparing stochastic process and payoff functions
                var stochasticProcess = new BlackScholesMertonProcess(new Handle <Quote>(underlyingQuoteValue), dividendYield, riskFreeRate, underlyingVol);
                var payoff            = new PlainVanillaPayoff(contract.Right == OptionRight.Call ? QLNet.Option.Type.Call : QLNet.Option.Type.Put, (double)contract.Strike);

                // creating option QL object
                var option = contract.Symbol.ID.OptionStyle == OptionStyle.American ?
                             new VanillaOption(payoff, new AmericanExercise(settlementDate, maturityDate)) :
                             new VanillaOption(payoff, new EuropeanExercise(maturityDate));

                Settings.setEvaluationDate(settlementDate);

                // preparing pricing engine QL object
                option.setPricingEngine(_pricingEngineFunc(contract.Symbol, stochasticProcess));

                // running calculations
                var npv = EvaluateOption(option);

                // function extracts QL greeks catching exception if greek is not generated by the pricing engine and reevaluates option to get numerical estimate of the seisitivity
                Func <Func <double>, Func <double>, decimal> tryGetGreekOrReevaluate = (greek, reevalFunc) =>
                {
                    try
                    {
                        return((decimal)greek());
                    }
                    catch (Exception)
                    {
                        return(optionSecurity.EnableGreekApproximation ? (decimal)reevalFunc() : 0.0m);
                    }
                };

                // function extracts QL greeks catching exception if greek is not generated by the pricing engine
                Func <Func <double>, decimal> tryGetGreek = greek => tryGetGreekOrReevaluate(greek, () => 0.0);

                // function extracts QL IV catching exception if IV is not generated by the pricing engine
                Func <decimal> tryGetImpliedVol = () =>
                {
                    try
                    {
                        return((decimal)option.impliedVolatility((double)optionSecurity.Price, stochasticProcess));
                    }
                    catch (Exception err)
                    {
                        Log.Debug("tryGetImpliedVol() error: " + err.Message);
                        return(0m);
                    }
                };

                Func <Tuple <decimal, decimal> > evalDeltaGamma = () =>
                {
                    try
                    {
                        return(Tuple.Create((decimal)option.delta(), (decimal)option.gamma()));
                    }
                    catch (Exception)
                    {
                        if (optionSecurity.EnableGreekApproximation)
                        {
                            var step    = 0.01;
                            var initial = underlyingQuoteValue.value();
                            underlyingQuoteValue.setValue(initial - step);
                            var npvMinus = EvaluateOption(option);
                            underlyingQuoteValue.setValue(initial + step);
                            var npvPlus = EvaluateOption(option);
                            underlyingQuoteValue.setValue(initial);

                            return(Tuple.Create((decimal)((npvPlus - npvMinus) / (2 * step)),
                                                (decimal)((npvPlus - 2 * npv + npvMinus) / (step * step))));
                        }
                        else
                        {
                            return(Tuple.Create(0.0m, 0.0m));
                        }
                    }
                };

                Func <double> reevalVega = () =>
                {
                    var step    = 0.001;
                    var initial = underlyingVolValue.value();
                    underlyingVolValue.setValue(initial + step);
                    var npvPlus = EvaluateOption(option);
                    underlyingVolValue.setValue(initial);

                    return((npvPlus - npv) / step);
                };

                Func <double> reevalTheta = () =>
                {
                    var step = 1.0 / 365.0;

                    Settings.setEvaluationDate(settlementDate.AddDays(-1));
                    var npvMinus = EvaluateOption(option);
                    Settings.setEvaluationDate(settlementDate);

                    return((npv - npvMinus) / step);
                };

                Func <double> reevalRho = () =>
                {
                    var step    = 0.001;
                    var initial = riskFreeRateValue.value();
                    riskFreeRateValue.setValue(initial + step);
                    var npvPlus = EvaluateOption(option);
                    riskFreeRateValue.setValue(initial);

                    return((npvPlus - npv) / step);
                };

                // producing output with lazy calculations of IV and greeks

                return(new OptionPriceModelResult((decimal)npv,
                                                  tryGetImpliedVol,
                                                  () => new Greeks(evalDeltaGamma,
                                                                   () => tryGetGreekOrReevaluate(() => option.vega(), reevalVega),
                                                                   () => tryGetGreekOrReevaluate(() => option.theta(), reevalTheta),
                                                                   () => tryGetGreekOrReevaluate(() => option.rho(), reevalRho),
                                                                   () => tryGetGreek(() => option.elasticity()))));
            }
            catch (Exception err)
            {
                Log.Debug("QLOptionPriceModel.Evaluate() error: " + err.Message);
                return(new OptionPriceModelResult(0m, new Greeks()));
            }
        }
Пример #15
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            // set up dates
            Calendar calendar       = new TARGET();
            Date     todaysDate     = new Date(15, Month.May, 1998);
            Date     settlementDate = new Date(17, Month.May, 1998);

            Settings.setEvaluationDate(todaysDate);

            // our options
            Option.Type type          = Option.Type.Put;
            double      underlying    = 36;
            double      strike        = 40;
            double      dividendYield = 0.00;
            double      riskFreeRate  = 0.06;
            double      volatility    = 0.20;
            Date        maturity      = new Date(17, Month.May, 1999);
            DayCounter  dayCounter    = new Actual365Fixed();

            Console.WriteLine("Option type = " + type);
            Console.WriteLine("Maturity = " + maturity);
            Console.WriteLine("Underlying price = " + underlying);
            Console.WriteLine("Strike = " + strike);
            Console.WriteLine("Risk-free interest rate = {0:0.000000%}", riskFreeRate);
            Console.WriteLine("Dividend yield = {0:0.000000%}", dividendYield);
            Console.WriteLine("Volatility = {0:0.000000%}", volatility);
            Console.Write("\n");

            string method;

            Console.Write("\n");

            // write column headings
            int[] widths = new int[] { 35, 14, 14, 14 };
            Console.Write("{0,-" + widths[0] + "}", "Method");
            Console.Write("{0,-" + widths[1] + "}", "European");
            Console.Write("{0,-" + widths[2] + "}", "Bermudan");
            Console.WriteLine("{0,-" + widths[3] + "}", "American");

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

            for (int i = 1; i <= 4; i++)
            {
                exerciseDates.Add(settlementDate + new Period(3 * i, TimeUnit.Months));
            }

            Exercise europeanExercise = new EuropeanExercise(maturity);
            Exercise bermudanExercise = new BermudanExercise(exerciseDates);
            Exercise americanExercise = new AmericanExercise(settlementDate, maturity);

            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // bootstrap the yield/dividend/vol curves
            var flatTermStructure    = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            var flatDividendTS       = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            var flatVolTS            = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter));
            StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike);
            var bsmProcess           = new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

            // options
            VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise);
            VanillaOption bermudanOption = new VanillaOption(payoff, bermudanExercise);
            VanillaOption americanOption = new VanillaOption(payoff, americanExercise);


            // Analytic formulas:

            // Black-Scholes for European
            method = "Black-Scholes";
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + "}", "N/A");


            // Barone-Adesi and Whaley approximation for American
            method = "Barone-Adesi/Whaley";
            americanOption.setPricingEngine(new BaroneAdesiWhaleyApproximationEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + "}", "N/A");
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());


            // Bjerksund and Stensland approximation for American
            method = "Bjerksund/Stensland";
            americanOption.setPricingEngine(new BjerksundStenslandApproximationEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + "}", "N/A");
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Integral
            method = "Integral";
            europeanOption.setPricingEngine(new IntegralEngine(bsmProcess));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + "}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + "}", "N/A");


            // Finite differences
            int timeSteps = 801;

            method = "Finite differences";
            europeanOption.setPricingEngine(new FDEuropeanEngine(bsmProcess, timeSteps, timeSteps - 1));
            bermudanOption.setPricingEngine(new FDBermudanEngine(bsmProcess, timeSteps, timeSteps - 1));
            americanOption.setPricingEngine(new FDAmericanEngine(bsmProcess, timeSteps, timeSteps - 1));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Jarrow-Rudd
            method = "Binomial Jarrow-Rudd";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <JarrowRudd>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <JarrowRudd>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <JarrowRudd>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());


            method = "Binomial Cox-Ross-Rubinstein";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <CoxRossRubinstein>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <CoxRossRubinstein>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <CoxRossRubinstein>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Additive equiprobabilities
            method = "Additive equiprobabilities";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <AdditiveEQPBinomialTree>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <AdditiveEQPBinomialTree>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <AdditiveEQPBinomialTree>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Trigeorgis
            method = "Binomial Trigeorgis";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <Trigeorgis>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <Trigeorgis>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <Trigeorgis>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Tian
            method = "Binomial Tian";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <Tian>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <Tian>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <Tian>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Leisen-Reimer
            method = "Binomial Leisen-Reimer";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <LeisenReimer>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <LeisenReimer>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <LeisenReimer>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // Binomial method: Binomial Joshi
            method = "Binomial Joshi";
            europeanOption.setPricingEngine(new BinomialVanillaEngine <Joshi4>(bsmProcess, timeSteps));
            bermudanOption.setPricingEngine(new BinomialVanillaEngine <Joshi4>(bsmProcess, timeSteps));
            americanOption.setPricingEngine(new BinomialVanillaEngine <Joshi4>(bsmProcess, timeSteps));

            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", bermudanOption.NPV());
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());


            // Monte Carlo Method: MC (crude)
            timeSteps = 1;
            method    = "MC (crude)";
            ulong          mcSeed    = 42;
            IPricingEngine mcengine1 = new MakeMCEuropeanEngine <PseudoRandom>(bsmProcess)
                                       .withSteps(timeSteps)
                                       .withAbsoluteTolerance(0.02)
                                       .withSeed(mcSeed)
                                       .value();

            europeanOption.setPricingEngine(mcengine1);
            // Real errorEstimate = europeanOption.errorEstimate();
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", "N/A");


            // Monte Carlo Method: QMC (Sobol)
            method = "QMC (Sobol)";
            int nSamples = 32768; // 2^15

            IPricingEngine mcengine2 = new MakeMCEuropeanEngine <LowDiscrepancy>(bsmProcess)
                                       .withSteps(timeSteps)
                                       .withSamples(nSamples)
                                       .value();

            europeanOption.setPricingEngine(mcengine2);
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", europeanOption.NPV());
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", "N/A");

            // Monte Carlo Method: MC (Longstaff Schwartz)
            method = "MC (Longstaff Schwartz)";
            IPricingEngine mcengine3 = new MakeMCAmericanEngine <PseudoRandom>(bsmProcess)
                                       .withSteps(100)
                                       .withAntitheticVariate()
                                       .withCalibrationSamples(4096)
                                       .withAbsoluteTolerance(0.02)
                                       .withSeed(mcSeed)
                                       .value();

            americanOption.setPricingEngine(mcengine3);
            Console.Write("{0,-" + widths[0] + "}", method);
            Console.Write("{0,-" + widths[1] + ":0.000000}", "N/A");
            Console.Write("{0,-" + widths[2] + ":0.000000}", "N/A");
            Console.WriteLine("{0,-" + widths[3] + ":0.000000}", americanOption.NPV());

            // End test
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Пример #16
0
        public void testImpliedHazardRate()
        {
            // Testing implied hazard-rate for credit-default swaps...

            using (SavedSettings backup = new SavedSettings())
            {
                // Initialize curves
                Calendar calendar = new TARGET();
                Date     today    = calendar.adjust(Date.Today);
                Settings.setEvaluationDate(today);

                double     h1 = 0.30, h2 = 0.40;
                DayCounter dayCounter = new Actual365Fixed();

                List <Date>   dates       = new List <Date>(3);
                List <double> hazardRates = new List <double>(3);
                dates.Add(today);
                hazardRates.Add(h1);

                dates.Add(today + new Period(5, TimeUnit.Years));
                hazardRates.Add(h1);

                dates.Add(today + new Period(10, TimeUnit.Years));
                hazardRates.Add(h2);

                RelinkableHandle <DefaultProbabilityTermStructure> probabilityCurve =
                    new RelinkableHandle <DefaultProbabilityTermStructure>();
                probabilityCurve.linkTo(new InterpolatedHazardRateCurve <BackwardFlat>(dates,
                                                                                       hazardRates,
                                                                                       dayCounter));

                RelinkableHandle <YieldTermStructure> discountCurve = new RelinkableHandle <YieldTermStructure>();
                discountCurve.linkTo(new FlatForward(today, 0.03, new Actual360()));

                Frequency             frequency  = Frequency.Semiannual;
                BusinessDayConvention convention = BusinessDayConvention.ModifiedFollowing;

                Date       issueDate    = calendar.advance(today, -6, TimeUnit.Months);
                double     fixedRate    = 0.0120;
                DayCounter cdsDayCount  = new Actual360();
                double     notional     = 10000.0;
                double     recoveryRate = 0.4;

                double?latestRate = null;
                for (int n = 6; n <= 10; ++n)
                {
                    Date     maturity = calendar.advance(issueDate, n, TimeUnit.Years);
                    Schedule schedule = new Schedule(issueDate, maturity, new Period(frequency), calendar,
                                                     convention, convention,
                                                     DateGeneration.Rule.Forward, false);

                    CreditDefaultSwap cds = new CreditDefaultSwap(Protection.Side.Seller, notional, fixedRate,
                                                                  schedule, convention, cdsDayCount, true, true);
                    cds.setPricingEngine(new MidPointCdsEngine(probabilityCurve, recoveryRate, discountCurve));

                    double NPV      = cds.NPV();
                    double flatRate = cds.impliedHazardRate(NPV, discountCurve,
                                                            dayCounter,
                                                            recoveryRate);

                    if (flatRate < h1 || flatRate > h2)
                    {
                        QAssert.Fail("implied hazard rate outside expected range\n"
                                     + "    maturity: " + n + " years\n"
                                     + "    expected minimum: " + h1 + "\n"
                                     + "    expected maximum: " + h2 + "\n"
                                     + "    implied rate:     " + flatRate);
                    }

                    if (n > 6 && flatRate < latestRate)
                    {
                        QAssert.Fail("implied hazard rate decreasing with swap maturity\n"
                                     + "    maturity: " + n + " years\n"
                                     + "    previous rate: " + latestRate + "\n"
                                     + "    implied rate:  " + flatRate);
                    }

                    latestRate = flatRate;

                    RelinkableHandle <DefaultProbabilityTermStructure> probability = new RelinkableHandle <DefaultProbabilityTermStructure>();
                    probability.linkTo(new FlatHazardRate(today, new Handle <Quote>(new SimpleQuote(flatRate)), dayCounter));

                    CreditDefaultSwap cds2 = new CreditDefaultSwap(Protection.Side.Seller, notional, fixedRate,
                                                                   schedule, convention, cdsDayCount, true, true);
                    cds2.setPricingEngine(new MidPointCdsEngine(probability, recoveryRate, discountCurve));

                    double NPV2      = cds2.NPV();
                    double tolerance = 1.0;
                    if (Math.Abs(NPV - NPV2) > tolerance)
                    {
                        QAssert.Fail("failed to reproduce NPV with implied rate\n"
                                     + "    expected:   " + NPV + "\n"
                                     + "    calculated: " + NPV2);
                    }
                }
            }
        }
Пример #17
0
        public void testFdmHestonVarianceMesher()
        {
            //Testing FDM Heston variance mesher...
            using (SavedSettings backup = new SavedSettings())
            {
                Date       today = new Date(22, 2, 2018);
                DayCounter dc    = new Actual365Fixed();
                Settings.Instance.setEvaluationDate(today);

                HestonProcess process = new HestonProcess(new Handle <YieldTermStructure>(Utilities.flatRate(0.02, dc)),
                                                          new Handle <YieldTermStructure>(Utilities.flatRate(0.02, dc)),
                                                          new Handle <Quote>(new SimpleQuote(100.0)),
                                                          0.09, 1.0, 0.09, 0.2, -0.5);

                FdmHestonVarianceMesher mesher    = new FdmHestonVarianceMesher(5, process, 1.0);
                List <double>           locations = mesher.locations();

                double[] expected = new double[] { 0.0, 6.652314e-02, 9.000000e-02, 1.095781e-01, 2.563610e-01 };

                double tol = 1e-6;
                double diff;
                for (int i = 0; i < locations.Count; ++i)
                {
                    diff = Math.Abs(expected[i] - locations[i]);

                    if (diff > tol)
                    {
                        QAssert.Fail("Failed to reproduce Heston variance mesh"
                                     + "\n    calculated: " + locations[i]
                                     + "\n    expected:   " + expected[i]
                                     + "\n    difference  " + diff
                                     + "\n    tolerance:  " + tol);
                    }
                }

                LocalVolTermStructure lVol = new LocalConstantVol(today, 2.5, dc);
                FdmHestonLocalVolatilityVarianceMesher constSlvMesher = new FdmHestonLocalVolatilityVarianceMesher(5, process, lVol, 1.0);

                double expectedVol   = 2.5 * mesher.volaEstimate();
                double calculatedVol = constSlvMesher.volaEstimate();

                diff = Math.Abs(calculatedVol - expectedVol);
                if (diff > tol)
                {
                    QAssert.Fail("Failed to reproduce Heston local volatility variance estimate"
                                 + "\n    calculated: " + calculatedVol
                                 + "\n    expected:   " + expectedVol
                                 + "\n    difference  " + diff
                                 + "\n    tolerance:  " + tol);
                }

                double alpha = 0.01;
                LocalVolTermStructure leverageFct = new ParableLocalVolatility(today, 100.0, alpha, dc);

                FdmHestonLocalVolatilityVarianceMesher slvMesher
                    = new FdmHestonLocalVolatilityVarianceMesher(5, process, leverageFct, 0.5, 1, 0.01);

                double initialVolEstimate = new FdmHestonVarianceMesher(5, process, 0.5, 1, 0.01).volaEstimate();

                // double vEst = leverageFct.currentLink().localVol(0, 100) * initialVolEstimate;
                // Mathematica solution
                //    N[Integrate[
                //      alpha*((100*Exp[vEst*x*Sqrt[0.5]] - 100)^2 + 25)*
                //       PDF[NormalDistribution[0, 1], x], {x ,
                //       InverseCDF[NormalDistribution[0, 1], 0.01],
                //       InverseCDF[NormalDistribution[0, 1], 0.99]}]]

                double leverageAvg = 0.455881 / (1 - 0.02);

                double volaEstExpected =
                    0.5 * (leverageAvg + leverageFct.localVol(0, 100)) * initialVolEstimate;

                double volaEstCalculated = slvMesher.volaEstimate();

                if (Math.Abs(volaEstExpected - volaEstCalculated) > 0.001)
                {
                    QAssert.Fail("Failed to reproduce Heston local volatility variance estimate"
                                 + "\n    calculated: " + calculatedVol
                                 + "\n    expected:   " + expectedVol
                                 + "\n    difference  " + Math.Abs(volaEstExpected - volaEstCalculated)
                                 + "\n    tolerance:  " + tol);
                }
            }
        }
Пример #18
0
        public void cpibondconsistency()
        {
            CommonVars common = new CommonVars();

            // ZeroInflationSwap aka CPISwap

            CPISwap.Type type    = CPISwap.Type.Payer;
            double       nominal = 1000000.0;
            bool         subtractInflationNominal = true;
            // float+spread leg
            double                spread                 = 0.0;
            DayCounter            floatDayCount          = new Actual365Fixed();
            BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing;
            int       fixingDays = 0;
            IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK);

            // fixed x inflation leg
            double                fixedRate                = 0.1;   //1% would be 0.01
            double                baseCPI                  = 206.1; // would be 206.13871 if we were interpolating
            DayCounter            fixedDayCount            = new Actual365Fixed();
            BusinessDayConvention fixedPaymentConvention   = BusinessDayConvention.ModifiedFollowing;
            Calendar              fixedPaymentCalendar     = new UnitedKingdom();
            ZeroInflationIndex    fixedIndex               = common.ii;
            Period                contractObservationLag   = common.contractObservationLag;
            InterpolationType     observationInterpolation = common.contractObservationInterpolation;

            // set the schedules
            Date     startDate     = new Date(2, Month.October, 2007);
            Date     endDate       = new Date(2, Month.October, 2052);
            Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(floatPaymentConvention)
                                     .backwards().value();
            Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(BusinessDayConvention.Unadjusted)
                                     .backwards().value();

            CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal,
                                       spread, floatDayCount, floatSchedule,
                                       floatPaymentConvention, fixingDays, floatIndex,
                                       fixedRate, baseCPI, fixedDayCount, fixedSchedule,
                                       fixedPaymentConvention, contractObservationLag,
                                       fixedIndex, observationInterpolation);

            double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 };
            double[] cpiFix   = { 211.4, 217.2, 211.4, 213.4, -2, -2 };
            for (int i = 0; i < floatSchedule.Count; i++)
            {
                if (floatSchedule[i] < common.evaluationDate)
                {
                    floatIndex.addFixing(floatSchedule[i], floatFix[i], true); //true=overwrite
                }

                CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon;
                if (zic != null)
                {
                    if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months)))
                    {
                        fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true);
                    }
                }
            }

            // simple structure so simple pricing engine - most work done by index
            DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK);

            zisV.setPricingEngine(dse);

            // now do the bond equivalent
            List <double> fixedRates     = new InitializedList <double>(1, fixedRate);
            int           settlementDays = 1;// cannot be zero!
            bool          growthOnly     = true;
            CPIBond       cpiB           = new CPIBond(settlementDays, nominal, growthOnly,
                                                       baseCPI, contractObservationLag, fixedIndex,
                                                       observationInterpolation, fixedSchedule,
                                                       fixedRates, fixedDayCount, fixedPaymentConvention);

            DiscountingBondEngine dbe = new DiscountingBondEngine(common.nominalUK);

            cpiB.setPricingEngine(dbe);

            QAssert.IsTrue(Math.Abs(cpiB.NPV() - zisV.legNPV(0).GetValueOrDefault()) < 1e-5,
                           "cpi bond does not equal equivalent cpi swap leg");
            // remove circular refernce
            common.hcpi.linkTo(null);
        }
Пример #19
0
        public void testFdmHestonBarrierVsBlackScholes()
        {
            //Testing FDM with barrier option in Heston model...
            using (SavedSettings backup = new SavedSettings())
            {
                NewBarrierOptionData[] values = new NewBarrierOptionData[] {
                    /* The data below are from
                     * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag. 72
                     */
                    //                          barrierType,        barrier, rebate,         type,  strike,     s,    q,    r,    t,    v
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.00, 0.08, 1.00, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.00, 0.08, 0.25, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.00, 0.08, 0.25, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.00, 0.08, 0.40, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.15),

                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.00, 0.08, 0.40, 0.35),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.15),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.00, 0.00, 1.00, 0.20),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.00, 0.08, 1.00, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),

                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.00, 0.04, 1.00, 0.15),

                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 1.00, 0.15),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30)
                };

                DayCounter dc           = new Actual365Fixed();
                Date       todaysDate   = new Date(28, 3, 2004);
                Date       exerciseDate = new Date(28, 3, 2005);
                Settings.Instance.setEvaluationDate(todaysDate);

                Handle <Quote> spot             = new Handle <Quote>(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 bsProcess = new BlackScholesMertonProcess(spot, qTS, rTS, volTS);

                IPricingEngine analyticEngine = new AnalyticBarrierEngine(bsProcess);

                for (int i = 0; i < values.Length; i++)
                {
                    Date     exDate   = todaysDate + Convert.ToInt32(values[i].t * 365 + 0.5);
                    Exercise exercise = new EuropeanExercise(exDate);

                    (spot.currentLink() as SimpleQuote).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);

                    BarrierOption barrierOption = new BarrierOption(values[i].barrierType, values[i].barrier,
                                                                    values[i].rebate, payoff, exercise);

                    double        v0            = vol.value() * vol.value();
                    HestonProcess hestonProcess =
                        new HestonProcess(rTS, qTS, spot, v0, 1.0, v0, 0.005, 0.0);

                    barrierOption.setPricingEngine(new FdHestonBarrierEngine(new HestonModel(hestonProcess), 200, 101, 3));

                    double calculatedHE = barrierOption.NPV();

                    barrierOption.setPricingEngine(analyticEngine);
                    double expected = barrierOption.NPV();

                    double tol = 0.0025;
                    if (Math.Abs(calculatedHE - expected) / expected > tol)
                    {
                        QAssert.Fail("Failed to reproduce expected Heston npv"
                                     + "\n    calculated: " + calculatedHE
                                     + "\n    expected:   " + expected
                                     + "\n    tolerance:  " + tol);
                    }
                }
            }
        }
Пример #20
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(Actual365Fixed obj) {
   return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
 }
Пример #21
0
        static void Main(string[] args)
        {
            try
            {
                DateTime    timer      = DateTime.Now;
                Option.Type type       = Option.Type.Put;
                double      underlying = 36.0;
                double      spreadRate = 0.005;

                double dividendYield = 0.02;
                double riskFreeRate  = 0.06;
                double volatility    = 0.2;

                int    settlementDays  = 3;
                int    length          = 5;
                double redemption      = 100.0;
                double conversionRatio = redemption / underlying; // at the money

                // set up dates/schedules
                Calendar calendar = new TARGET();
                Date     today    = calendar.adjust(Date.Today);

                Settings.setEvaluationDate(today);
                Date settlementDate = calendar.advance(today, settlementDays, TimeUnit.Days);
                Date exerciseDate   = calendar.advance(settlementDate, length, TimeUnit.Years);
                Date issueDate      = calendar.advance(exerciseDate, -length, TimeUnit.Years);

                BusinessDayConvention convention = BusinessDayConvention.ModifiedFollowing;

                Frequency frequency = Frequency.Annual;

                Schedule schedule = new Schedule(issueDate, exerciseDate,
                                                 new Period(frequency), calendar, convention, convention,
                                                 DateGeneration.Rule.Backward, false);

                DividendSchedule    dividends   = new DividendSchedule();
                CallabilitySchedule callability = new CallabilitySchedule();

                List <double> coupons      = new InitializedList <double>(1, 0.05);
                DayCounter    bondDayCount = new Thirty360();

                int[] callLength = { 2, 4 }; // Call dates, years 2,4.
                int[] putLength  = { 3 };    // Put dates year 3.

                double[] callPrices = { 101.5, 100.85 };
                double[] putPrices  = { 105.0 };

                // Load call schedules
                for (int i = 0; i < callLength.Length; i++)
                {
                    SoftCallability s = new SoftCallability(
                        new Callability.Price(callPrices[i], Callability.Price.Type.Clean), schedule.date(callLength[i]),
                        1.20);
                    callability.Add(s);
                }

                for (int j = 0; j < putLength.Length; j++)
                {
                    Callability s = new Callability(new Callability.Price(putPrices[j], Callability.Price.Type.Clean),
                                                    Callability.Type.Put, schedule.date(putLength[j]));
                    callability.Add(s);
                }

                // Assume dividends are paid every 6 months .
                for (Date d = today + new Period(6, TimeUnit.Months); d < exerciseDate; d += new Period(6, TimeUnit.Months))
                {
                    Dividend div = new FixedDividend(1.0, d);
                    dividends.Add(div);
                }

                DayCounter dayCounter = new Actual365Fixed();
                double     maturity   = dayCounter.yearFraction(settlementDate, exerciseDate);

                Console.WriteLine("option type = " + type);
                Console.WriteLine("Time to maturity = " + maturity);
                Console.WriteLine("Underlying price = " + underlying);
                Console.WriteLine("Risk-free interest rate = {0:0.0%}", riskFreeRate);
                Console.WriteLine("Dividend yield = {0:0.0%}%", dividendYield);
                Console.WriteLine("Volatility = {0:0.0%}%", volatility);
                Console.WriteLine("");


                // write column headings
                int[]  widths     = { 35, 14, 14 };
                int    totalWidth = widths[0] + widths[1] + widths[2];
                string rule       = new string('-', totalWidth);
                string dblrule    = new string('=', totalWidth);

                Console.WriteLine(dblrule);
                Console.WriteLine("Tsiveriotis-Fernandes method");
                Console.WriteLine(dblrule);
                Console.WriteLine("Tree Type                           European     American        ");
                Console.WriteLine(rule);


                Exercise exercise   = new EuropeanExercise(exerciseDate);
                Exercise amexercise = new AmericanExercise(settlementDate, exerciseDate);

                Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));
                Handle <YieldTermStructure> flatTermStructure =
                    new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
                Handle <YieldTermStructure> flatDividendTS =
                    new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
                Handle <BlackVolTermStructure> flatVolTS =
                    new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility,
                                                                            dayCounter));

                BlackScholesMertonProcess stochasticProcess =
                    new BlackScholesMertonProcess(underlyingH, flatDividendTS, flatTermStructure, flatVolTS);

                int timeSteps = 801;

                Handle <Quote> creditSpread = new Handle <Quote>(new SimpleQuote(spreadRate));

                Quote rate = new SimpleQuote(riskFreeRate);

                Handle <YieldTermStructure> discountCurve =
                    new Handle <YieldTermStructure>(new FlatForward(today, new Handle <Quote>(rate), dayCounter));

                IPricingEngine engine = new BinomialConvertibleEngine <JarrowRudd>(stochasticProcess, timeSteps);

                ConvertibleFixedCouponBond europeanBond = new ConvertibleFixedCouponBond(exercise, conversionRatio,
                                                                                         dividends, callability, creditSpread, issueDate, settlementDays, coupons, bondDayCount, schedule,
                                                                                         redemption);

                europeanBond.setPricingEngine(engine);

                ConvertibleFixedCouponBond americanBond = new ConvertibleFixedCouponBond(amexercise, conversionRatio,
                                                                                         dividends, callability, creditSpread, issueDate, settlementDays, coupons, bondDayCount, schedule,
                                                                                         redemption);
                americanBond.setPricingEngine(engine);


                Console.WriteLine("Jarrow-Rudd                         {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());

                americanBond.setPricingEngine(new BinomialConvertibleEngine <CoxRossRubinstein>(stochasticProcess, timeSteps));
                europeanBond.setPricingEngine(new BinomialConvertibleEngine <CoxRossRubinstein>(stochasticProcess, timeSteps));

                Console.WriteLine("CoxRossRubinstein                   {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());

                americanBond.setPricingEngine(new BinomialConvertibleEngine <AdditiveEQPBinomialTree>(stochasticProcess, timeSteps));
                europeanBond.setPricingEngine(new BinomialConvertibleEngine <AdditiveEQPBinomialTree>(stochasticProcess, timeSteps));

                Console.WriteLine("AdditiveEQPBinomialTree             {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());

                americanBond.setPricingEngine(new BinomialConvertibleEngine <Trigeorgis>(stochasticProcess, timeSteps));
                europeanBond.setPricingEngine(new BinomialConvertibleEngine <Trigeorgis>(stochasticProcess, timeSteps));

                Console.WriteLine("Trigeorgis                          {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());

                americanBond.setPricingEngine(new BinomialConvertibleEngine <Tian>(stochasticProcess, timeSteps));
                europeanBond.setPricingEngine(new BinomialConvertibleEngine <Tian>(stochasticProcess, timeSteps));

                Console.WriteLine("Tian                                {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());

                americanBond.setPricingEngine(new BinomialConvertibleEngine <LeisenReimer>(stochasticProcess, timeSteps));
                europeanBond.setPricingEngine(new BinomialConvertibleEngine <LeisenReimer>(stochasticProcess, timeSteps));

                Console.WriteLine("LeisenReimer                        {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());

                americanBond.setPricingEngine(new BinomialConvertibleEngine <Joshi4>(stochasticProcess, timeSteps));
                europeanBond.setPricingEngine(new BinomialConvertibleEngine <Joshi4>(stochasticProcess, timeSteps));

                Console.WriteLine("Joshi4                              {0:0.000000}   {1:0.000000}", europeanBond.NPV(), americanBond.NPV());
                Console.WriteLine("===========================================================================");

                Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
                Console.WriteLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }