Example #1
0
        public void testLiborFixing()
        {
            // "Testing use of today's LIBOR fixings in swap curve...");

            CommonVars vars = new CommonVars();

            var       swapHelpers = new InitializedList <RateHelper>();
            IborIndex euribor6m   = new Euribor6M();

            for (int i = 0; i < vars.swaps; i++)
            {
                Handle <Quote> r = new Handle <Quote>(vars.rates[i + vars.deposits]);
                swapHelpers.Add(new SwapRateHelper(r, new Period(vars.swapData[i].n, vars.swapData[i].units),
                                                   vars.calendar,
                                                   vars.fixedLegFrequency, vars.fixedLegConvention,
                                                   vars.fixedLegDayCounter, euribor6m));
            }

            vars.termStructure = new PiecewiseYieldCurve <Discount, LogLinear>(vars.settlement, swapHelpers, new Actual360());

            Handle <YieldTermStructure> curveHandle = new Handle <YieldTermStructure>(vars.termStructure);

            IborIndex index = new Euribor6M(curveHandle);

            for (int i = 0; i < vars.swaps; i++)
            {
                Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units);

                VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0)
                                   .withEffectiveDate(vars.settlement)
                                   .withFixedLegDayCount(vars.fixedLegDayCounter)
                                   .withFixedLegTenor(new Period(vars.fixedLegFrequency))
                                   .withFixedLegConvention(vars.fixedLegConvention)
                                   .withFixedLegTerminationDateConvention(vars.fixedLegConvention)
                                   .value();

                double expectedRate  = vars.swapData[i].rate / 100,
                       estimatedRate = swap.fairRate();
                double tolerance     = 1.0e-9;
                if (Math.Abs(expectedRate - estimatedRate) > tolerance)
                {
                    QAssert.Fail("before LIBOR fixing:\n"
                                 + vars.swapData[i].n + " year(s) swap:\n"
                                 + "    estimated rate: "
                                 + (estimatedRate) + "\n"
                                 + "    expected rate:  "
                                 + (expectedRate));
                }
            }

            Flag f = new Flag();

            vars.termStructure.registerWith(f.update);
            f.lower();

            index.addFixing(vars.today, 0.0425);

            if (!f.isUp())
            {
                QAssert.Fail("Observer was not notified of rate fixing");
            }

            for (int i = 0; i < vars.swaps; i++)
            {
                Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units);

                VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0)
                                   .withEffectiveDate(vars.settlement)
                                   .withFixedLegDayCount(vars.fixedLegDayCounter)
                                   .withFixedLegTenor(new Period(vars.fixedLegFrequency))
                                   .withFixedLegConvention(vars.fixedLegConvention)
                                   .withFixedLegTerminationDateConvention(vars.fixedLegConvention)
                                   .value();

                double expectedRate  = vars.swapData[i].rate / 100,
                       estimatedRate = swap.fairRate();
                double tolerance     = 1.0e-9;
                if (Math.Abs(expectedRate - estimatedRate) > tolerance)
                {
                    QAssert.Fail("after LIBOR fixing:\n"
                                 + vars.swapData[i].n + " year(s) swap:\n"
                                 + "    estimated rate: "
                                 + (estimatedRate) + "\n"
                                 + "    expected rate:  "
                                 + (expectedRate));
                }
            }
        }
Example #2
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  = 1.0;
            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // Curves
            double riskFreeRate  = 0.01;
            double dividendYield = 0.035;
            double cstVol        = 0.2;
            double hazardRate    = 0.02;

            Handle <YieldTermStructure>              flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            Handle <YieldTermStructure>              flatDividendTS    = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            Handle <BlackVolTermStructure>           mySurfaceH        = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, cstVol, dayCounter));
            Handle <DefaultProbabilityTermStructure> defaultTSH        = new Handle <DefaultProbabilityTermStructure>(new FlatHazardRate(settlementDate, hazardRate, dayCounter));

            // Process
            GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, flatDividendTS, flatTermStructure, mySurfaceH);


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

            List <Date> fixings = new InitializedList <Date>();

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

            double couponBond   = 0.0525;
            double couponBinary = 0.077;
            double barrierlvl   = 0.7;
            double strike       = 1.0;
            double recovery     = 0.4;

            double absoluteTolerance = 0.0001;

            GenericScriptRepack repack   = new GenericScriptRepack(fixings, couponBond, couponBinary, barrierlvl, strike, recovery);
            IPricingEngine      mcengine = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess)
                                           .withAbsoluteTolerance(absoluteTolerance)
                                           .withStepsPerYear(52)
                                           .withSeed(50)
                                           .withCredit(defaultTSH)
                                           .value();

            repack.setPricingEngine(mcengine);
            Console.WriteLine("Repack pricing = {0:0.0000}", repack.NPV());
            repack.inspout(5, true);

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

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Example #3
0
        public override void calculate()
        {
            /* this engine cannot really check for the averageType==Geometric
               since it can be used as control variate for the Arithmetic version
                QL_REQUIRE(arguments_.averageType == Average::Geometric,
                           "not a geometric average option");
            */

            if(!(arguments_.exercise.type() == Exercise.Type.European))
                throw new ApplicationException("not an European Option");

            double runningLog;
            int pastFixings;
            if (arguments_.averageType == Average.Type.Geometric) {
                if(!(arguments_.runningAccumulator>0.0))
                    throw new ApplicationException("positive running product required: "
                           + arguments_.runningAccumulator + " not allowed");
                runningLog =
                    Math.Log(arguments_.runningAccumulator.GetValueOrDefault());
                pastFixings = arguments_.pastFixings.GetValueOrDefault();
            } else {  // it is being used as control variate
                runningLog = 1.0;
                pastFixings = 0;
            }

            PlainVanillaPayoff payoff = (PlainVanillaPayoff)(arguments_.payoff);
            if (payoff == null)
                throw new ApplicationException("non-plain payoff given");

            Date referenceDate = process_.riskFreeRate().link.referenceDate();
            DayCounter rfdc  = process_.riskFreeRate().link.dayCounter();
            DayCounter divdc = process_.dividendYield().link.dayCounter();
            DayCounter voldc = process_.blackVolatility().link.dayCounter();
            List<double> fixingTimes = new InitializedList<double>(arguments_.fixingDates.Count());
            int i;
            for (i=0; i<arguments_.fixingDates.Count(); i++) {
                if (arguments_.fixingDates[i]>=referenceDate) {
                    double t = voldc.yearFraction(referenceDate,
                        arguments_.fixingDates[i]);
                    fixingTimes.Add(t);
                }
            }

            int remainingFixings = fixingTimes.Count();
            int numberOfFixings = pastFixings + remainingFixings;
            double N = numberOfFixings;

            double pastWeight   = pastFixings/N;
            double futureWeight = 1.0-pastWeight;

            /*double timeSum = std::accumulate(fixingTimes.begin(),
                                           fixingTimes.end(), 0.0);*/
            double timeSum = 0;
            fixingTimes.ForEach((ii, vv) => timeSum += fixingTimes[ii]);

            double vola = process_.blackVolatility().link.blackVol(
                                                  arguments_.exercise.lastDate(),
                                                  payoff.strike());
            double temp = 0.0;
            for (i=pastFixings+1; i<numberOfFixings; i++)
                temp += fixingTimes[i-pastFixings-1]*(N-i);
            double variance = vola*vola /N/N * (timeSum+ 2.0*temp);
            double dsigG_dsig = Math.Sqrt((timeSum + 2.0*temp))/N;
            double sigG = vola * dsigG_dsig;
            double dmuG_dsig = -(vola * timeSum)/N;

            Date exDate = arguments_.exercise.lastDate();
            double dividendRate = process_.dividendYield().link.
                zeroRate(exDate, divdc,  Compounding.Continuous, Frequency.NoFrequency).rate();
            double riskFreeRate = process_.riskFreeRate().link.
                zeroRate(exDate, rfdc,  Compounding.Continuous, Frequency.NoFrequency).rate();
            double nu = riskFreeRate - dividendRate - 0.5*vola*vola;

            double s = process_.stateVariable().link.value();
            if(!(s > 0.0))
                throw new ApplicationException("positive underlying value required");

            int M = (pastFixings == 0 ? 1 : pastFixings);
            double muG = pastWeight * runningLog/M +
                futureWeight * Math.Log(s) + nu*timeSum/N;
            double forwardPrice = Math.Exp(muG + variance / 2.0);

            double riskFreeDiscount = process_.riskFreeRate().link.discount(
                                                 arguments_.exercise.lastDate());

            BlackCalculator black = new BlackCalculator(payoff, forwardPrice, Math.Sqrt(variance),
                                  riskFreeDiscount);

            results_.value = black.value();
            results_.delta = futureWeight*black.delta(forwardPrice)*forwardPrice/s;
            results_.gamma = forwardPrice*futureWeight/(s*s)
                    *(  black.gamma(forwardPrice)*futureWeight*forwardPrice
                      - pastWeight*black.delta(forwardPrice) );

            double Nx_1, nx_1;
            CumulativeNormalDistribution CND = new CumulativeNormalDistribution();
            NormalDistribution ND = new NormalDistribution();
            if (sigG > Const.QL_Epsilon) {
                double x_1  = (muG-Math.Log(payoff.strike())+variance)/sigG;
                Nx_1 = CND.value(x_1);
                nx_1 = ND.value( x_1);
            } else {
                Nx_1 = (muG > Math.Log(payoff.strike()) ? 1.0 : 0.0);
                nx_1 = 0.0;
            }
            results_.vega = forwardPrice * riskFreeDiscount *
                       ( (dmuG_dsig + sigG * dsigG_dsig)*Nx_1 + nx_1*dsigG_dsig );

            if (payoff.optionType() == Option.Type.Put)
                results_.vega -= riskFreeDiscount * forwardPrice *
                                                  (dmuG_dsig + sigG * dsigG_dsig);

            double tRho = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(),
                                          arguments_.exercise.lastDate());
            results_.rho = black.rho(tRho)*timeSum/(N*tRho)
                          - (tRho-timeSum/N)*results_.value;

            double tDiv = divdc.yearFraction(
                               process_.dividendYield().link.referenceDate(),
                               arguments_.exercise.lastDate());

            results_.dividendRho = black.dividendRho(tDiv)*timeSum /(N*tDiv);

            results_.strikeSensitivity = black.strikeSensitivity();

            results_.theta =  Utils.blackScholesTheta(process_,
                                               results_.value.GetValueOrDefault(),
                                               results_.delta.GetValueOrDefault(),
                                               results_.gamma.GetValueOrDefault());
        }
Example #4
0
        public void testPastFixings()
        {
            //BOOST_MESSAGE("Testing use of past fixings in Asian options...");
            DayCounter dc = new Actual360();
            Date today = Date.Today ;

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

            StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Put, 100.0);

            Exercise exercise = new EuropeanExercise(today + new Period(1,TimeUnit.Years));

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

            // MC arithmetic average-price
            double runningSum = 0.0;
            int pastFixings = 0;
            List<Date> fixingDates1 = new InitializedList<Date>();
            for (int i=0; i<=12; ++i)
                fixingDates1.Add(today + new Period(i,TimeUnit.Months));

            DiscreteAveragingAsianOption option1 =
                new DiscreteAveragingAsianOption(Average.Type.Arithmetic, runningSum,
                                                 pastFixings, fixingDates1,
                                                 payoff, exercise);

            pastFixings = 2;
            runningSum = pastFixings * spot.value() * 0.8;
            List<Date> fixingDates2 = new InitializedList<Date>();
            for (int i=-2; i<=12; ++i)
                fixingDates2.Add(today + new Period(i,TimeUnit.Months));

            DiscreteAveragingAsianOption option2 =
                new DiscreteAveragingAsianOption(Average.Type.Arithmetic, runningSum,
                                                 pastFixings, fixingDates2,
                                                 payoff, exercise);

            IPricingEngine engine =
               new MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy,Statistics>(stochProcess)
                .withStepsPerYear(1)
                .withSamples(2047)
                .value() ;

            option1.setPricingEngine(engine);
            option2.setPricingEngine(engine);

            double price1 = option1.NPV();
            double price2 = option2.NPV();

            if (Utils.close(price1, price2)) {
                Assert.Fail(
                     "past fixings had no effect on arithmetic average-price option"
                     + "\n  without fixings: " + price1
                     + "\n  with fixings:    " + price2);
            }

            // MC arithmetic average-strike
            engine = new MakeMCDiscreteArithmeticASEngine<LowDiscrepancy,Statistics>(stochProcess)
                .withSamples(2047)
                .value();

            option1.setPricingEngine(engine);
            option2.setPricingEngine(engine);

            price1 = option1.NPV();
            price2 = option2.NPV();

            if (Utils.close(price1, price2)) {
                Assert.Fail(
                     "past fixings had no effect on arithmetic average-strike option"
                     + "\n  without fixings: " + price1
                     + "\n  with fixings:    " + price2);
            }

            // analytic geometric average-price
            double runningProduct = 1.0;
            pastFixings = 0;

            DiscreteAveragingAsianOption option3 =
                new DiscreteAveragingAsianOption(Average.Type.Geometric, runningProduct,
                                                 pastFixings, fixingDates1,
                                                 payoff, exercise);

            pastFixings = 2;
            runningProduct = spot.value() * spot.value();

            DiscreteAveragingAsianOption option4 =
                new DiscreteAveragingAsianOption(Average.Type.Geometric, runningProduct,
                                                 pastFixings, fixingDates2,
                                                 payoff, exercise);

            engine = new AnalyticDiscreteGeometricAveragePriceAsianEngine(stochProcess);

            option3.setPricingEngine(engine);
            option4.setPricingEngine(engine);

            double price3 = option3.NPV();
            double price4 = option4.NPV();

            if (Utils.close(price3, price4)) {
                Assert.Fail(
                     "past fixings had no effect on geometric average-price option"
                     + "\n  without fixings: " + price3
                     + "\n  with fixings:    " + price4);
            }

            // MC geometric average-price
            engine = new MakeMCDiscreteGeometricAPEngine<LowDiscrepancy,Statistics>(stochProcess)
                        .withStepsPerYear(1)
                        .withSamples(2047)
                        .value();

            option3.setPricingEngine(engine);
            option4.setPricingEngine(engine);

            price3 = option3.NPV();
            price4 = option4.NPV();

            if (Utils.close(price3, price4)) {
                Assert.Fail(
                     "past fixings had no effect on geometric average-price option"
                     + "\n  without fixings: " + price3
                     + "\n  with fixings:    " + price4);
            }
        }
Example #5
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();
        }
Example #6
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();
        }