index() public method

public index ( double t ) : int
t double
return int
        public void testMonteCarloCapletPricing()
        {
            //"Testing caplet LMM Monte-Carlo caplet pricing..."

            //SavedSettings backup;

            /* factor loadings are taken from Hull & White article
               plus extra normalisation to get orthogonal eigenvectors
               http://www.rotman.utoronto.ca/~amackay/fin/libormktmodel2.pdf */
            double[] compValues = {0.85549771, 0.46707264, 0.22353259,
                                 0.91915359, 0.37716089, 0.11360610,
                                 0.96438280, 0.26413316,-0.01412414,
                                 0.97939148, 0.13492952,-0.15028753,
                                 0.95970595,-0.00000000,-0.28100621,
                                 0.97939148,-0.13492952,-0.15028753,
                                 0.96438280,-0.26413316,-0.01412414,
                                 0.91915359,-0.37716089, 0.11360610,
                                 0.85549771,-0.46707264, 0.22353259};

            Matrix volaComp=new Matrix(9,3);
            List<double> lcompValues=new InitializedList<double>(27,0);
            List<double> ltemp = new InitializedList<double>(3, 0);
            lcompValues=compValues.ToList();
            //std::copy(compValues, compValues+9*3, volaComp.begin());
            for (int i = 0; i < 9; i++)
            {
                ltemp = lcompValues.GetRange(3*i, 3);
                for (int j = 0; j < 3; j++)
                    volaComp[i, j] = ltemp[j];
            }
            LiborForwardModelProcess process1 = makeProcess();
            LiborForwardModelProcess process2 = makeProcess(volaComp);

            List<double> tmp = process1.fixingTimes();
            TimeGrid grid=new TimeGrid(tmp ,12);

            List<int> location=new List<int>();
            for (int i=0; i < tmp.Count; ++i) {
                location.Add(grid.index(tmp[i])) ;
            }

            // set-up a small Monte-Carlo simulation to price caplets
            // and ratchet caps using a one- and a three factor libor market model

             ulong seed = 42;
             LowDiscrepancy.icInstance = new InverseCumulativeNormal();
             IRNG rsg1 = (IRNG)new LowDiscrepancy().make_sequence_generator(
                                                            process1.factors()*(grid.size()-1), seed);
             IRNG rsg2 = (IRNG)new LowDiscrepancy().make_sequence_generator(
                                                            process2.factors()*(grid.size()-1), seed);

            MultiPathGenerator<IRNG> generator1=new MultiPathGenerator<IRNG> (process1, grid, rsg1, false);
            MultiPathGenerator<IRNG> generator2=new MultiPathGenerator<IRNG> (process2, grid, rsg2, false);

            const int nrTrails = 250000;
            List<GeneralStatistics> stat1 = new InitializedList<GeneralStatistics>(process1.size());
            List<GeneralStatistics> stat2 = new InitializedList<GeneralStatistics>(process2.size());
            List<GeneralStatistics> stat3 = new InitializedList<GeneralStatistics>(process2.size() - 1);
            for (int i=0; i<nrTrails; ++i) {
                Sample<MultiPath> path1 = generator1.next();
                Sample<MultiPath> path2 = generator2.next();

                List<double> rates1=new InitializedList<double>(len);
                List<double> rates2 = new InitializedList<double>(len);
                for (int j=0; j<process1.size(); ++j) {
                    rates1[j] = path1.value[j][location[j]];
                    rates2[j] = path2.value[j][location[j]];
                }

                List<double> dis1 = process1.discountBond(rates1);
                List<double> dis2 = process2.discountBond(rates2);

                for (int k=0; k<process1.size(); ++k) {
                    double accrualPeriod =  process1.accrualEndTimes()[k]
                                        - process1.accrualStartTimes()[k];
                    // caplet payoff function, cap rate at 4%
                    double payoff1 = Math.Max(rates1[k] - 0.04, 0.0) * accrualPeriod;

                    double payoff2 = Math.Max(rates2[k] - 0.04, 0.0) * accrualPeriod;
                    stat1[k].add(dis1[k] * payoff1);
                    stat2[k].add(dis2[k] * payoff2);

                    if (k != 0) {
                        // ratchet cap payoff function
                        double payoff3 =  Math.Max(rates2[k] - (rates2[k-1]+0.0025), 0.0)
                                      * accrualPeriod;
                        stat3[k-1].add(dis2[k] * payoff3);
                    }
                }

            }

            double[] capletNpv = {0.000000000000, 0.000002841629, 0.002533279333,
                                0.009577143571, 0.017746502618, 0.025216116835,
                                0.031608230268, 0.036645683881, 0.039792254012,
                                0.041829864365};

            double[] ratchetNpv = {0.0082644895, 0.0082754754, 0.0082159966,
                                 0.0082982822, 0.0083803357, 0.0084366961,
                                 0.0084173270, 0.0081803406, 0.0079533814};

            for (int k=0; k < process1.size(); ++k) {

                double calculated1 = stat1[k].mean();
                double tolerance1  = stat1[k].errorEstimate();
                double expected    = capletNpv[k];

                if (Math.Abs(calculated1 - expected) > tolerance1) {
                    Assert.Fail("Failed to reproduce expected caplet NPV"
                                + "\n    calculated: " + calculated1
                                + "\n    error int:  " + tolerance1
                                + "\n    expected:   " + expected);
                }

                double calculated2 = stat2[k].mean();
                double tolerance2  = stat2[k].errorEstimate();

                if (Math.Abs(calculated2 - expected) > tolerance2) {
                    Assert.Fail("Failed to reproduce expected caplet NPV"
                                + "\n    calculated: " + calculated2
                                + "\n    error int:  " + tolerance2
                                + "\n    expected:   " + expected);
                }

                if (k != 0) {
                    double calculated3 = stat3[k-1].mean();
                    double tolerance3  = stat3[k-1].errorEstimate();
                    expected    = ratchetNpv[k-1];

                    double refError = 1e-5; // 1e-5. error bars of the reference values

                    if (Math.Abs(calculated3 - expected) > tolerance3 + refError) {
                        Assert.Fail("Failed to reproduce expected caplet NPV"
                                    + "\n    calculated: " + calculated3
                                    + "\n    error int:  " + tolerance3 + refError
                                    + "\n    expected:   " + expected);
                    }
                }
            }
        }
Example #2
0
        /*! This method checks whether the asset was rolled at the given time. */
        protected bool isOnTime(double t)
        {
            TimeGrid grid = method().timeGrid();

            return(Utils.close(grid[grid.index(t)], time()));
        }
Example #3
0
        public void testSwaptionPricing()
        {
            //"Testing forward swap and swaption pricing...");

            //SavedSettings backup;

            const int size  = 10;
            const int steps = 8*size;
            #if QL_USE_INDEXED_COUPON
            const double tolerance = 1e-6;
            #else
            const double tolerance = 1e-12;
            #endif

            List<Date> dates = new List<Date>();
            List<double> rates = new List<double>();
            dates.Add(new Date(4,9,2005));
            dates.Add(new Date(4,9,2011));
            rates.Add(0.04);
            rates.Add(0.08);

            IborIndex index = makeIndex(dates, rates);

            LiborForwardModelProcess process = new LiborForwardModelProcess(size, index);

            LmCorrelationModel corrModel = new LmExponentialCorrelationModel(size, 0.5);

            LmVolatilityModel volaModel = new LmLinearExponentialVolatilityModel(process.fixingTimes(),
                                                                                0.291, 1.483, 0.116, 0.00001);

               // set-up pricing engine
            process.setCovarParam((LfmCovarianceParameterization)
                                       new LfmCovarianceProxy(volaModel, corrModel));

            // set-up a small Monte-Carlo simulation to price swations
            List<double> tmp = process.fixingTimes();

            TimeGrid grid=new TimeGrid(tmp ,steps);

            List<int> location=new List<int>();
            for (int i=0; i < tmp.Count; ++i) {
                location.Add(grid.index(tmp[i])) ;
            }

            ulong seed=42;
            const int nrTrails = 5000;
            LowDiscrepancy.icInstance = new InverseCumulativeNormal();

            IRNG rsg = (InverseCumulativeRsg<RandomSequenceGenerator<MersenneTwisterUniformRng>
                                                                    ,InverseCumulativeNormal>)
            new PseudoRandom().make_sequence_generator(process.factors()*(grid.size()-1),seed);

            MultiPathGenerator<IRNG> generator=new MultiPathGenerator<IRNG>(process,
                                                                            grid,
                                                                            rsg, false);

            LiborForwardModel liborModel = new LiborForwardModel(process, volaModel, corrModel);

            Calendar calendar = index.fixingCalendar();
            DayCounter dayCounter = index.forwardingTermStructure().link.dayCounter();
            BusinessDayConvention convention = index.businessDayConvention();

            Date settlement = index.forwardingTermStructure().link.referenceDate();

            SwaptionVolatilityMatrix m = liborModel.getSwaptionVolatilityMatrix();

            for (int i=1; i < size; ++i) {
                for (int j=1; j <= size-i; ++j) {
                    Date fwdStart    = settlement + new Period(6*i, TimeUnit.Months);
                    Date fwdMaturity = fwdStart + new Period(6*j, TimeUnit.Months);

                    Schedule schedule =new Schedule(fwdStart, fwdMaturity, index.tenor(), calendar,
                                       convention, convention, DateGeneration.Rule.Forward, false);

                    double swapRate  = 0.0404;
                    VanillaSwap forwardSwap = new VanillaSwap(VanillaSwap.Type.Receiver, 1.0,
                                                                schedule, swapRate, dayCounter,
                                                                schedule, index, 0.0, index.dayCounter());
                    forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure()));

                    // check forward pricing first
                    double expected = forwardSwap.fairRate();
                    double calculated = liborModel.S_0(i-1,i+j-1);

                    if (Math.Abs(expected - calculated) > tolerance)
                        Assert.Fail("Failed to reproduce fair forward swap rate"
                                    + "\n    calculated: " + calculated
                                    + "\n    expected:   " + expected);

                    swapRate = forwardSwap.fairRate();
                    forwardSwap =
                        new VanillaSwap(VanillaSwap.Type.Receiver, 1.0,
                                        schedule, swapRate, dayCounter,
                                        schedule, index, 0.0, index.dayCounter());
                    forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure()));

                    if (i == j && i<=size/2) {
                        IPricingEngine engine =
                            new LfmSwaptionEngine(liborModel, index.forwardingTermStructure());
                        Exercise exercise =
                            new EuropeanExercise(process.fixingDates()[i]);

                        Swaption swaption =
                            new Swaption(forwardSwap, exercise);
                        swaption.setPricingEngine(engine);

                        GeneralStatistics stat = new GeneralStatistics();

                        for (int n=0; n<nrTrails; ++n) {
                            Sample<MultiPath> path = (n%2!=0) ? generator.antithetic()
                                                     : generator.next();

                            //Sample<MultiPath> path = generator.next();
                            List<double> rates_ = new InitializedList<double>(size);
                            for (int k=0; k<process.size(); ++k) {
                                rates_[k] = path.value[k][location[i]];
                            }
                            List<double> dis = process.discountBond(rates_);

                            double npv=0.0;
                            for (int k=i; k < i+j; ++k) {
                                npv += (swapRate - rates_[k])
                                       * (  process.accrualEndTimes()[k]
                                          - process.accrualStartTimes()[k])*dis[k];
                            }
                            stat.add(Math.Max(npv, 0.0));
                        }

                        if (Math.Abs(swaption.NPV() - stat.mean())
                            > stat.errorEstimate()*2.35)
                            Assert.Fail("Failed to reproduce swaption npv"
                                        + "\n    calculated: " + stat.mean()
                                        + "\n    expected:   " + swaption.NPV());
                    }
                }
            }
        }