Ejemplo n.º 1
0
            public CommonVars()
            {
                Settings.setEvaluationDate(new Date(16, Month.September, 2015));
                conventions.setConventions();

                // ATM swaptionvolmatrix
                atm.setMarketData();

                atmVolMatrix = new RelinkableHandle <SwaptionVolatilityStructure>(
                    new SwaptionVolatilityMatrix(conventions.calendar, conventions.optionBdc, atm.tenors.options,
                                                 atm.tenors.swaps, atm.volsHandle, conventions.dayCounter));
                // Swaptionvolcube
                cube.setMarketData();

                termStructure.linkTo(Utilities.flatRate(0.05, new Actual365Fixed()));

                swapIndexBase      = new EuriborSwapIsdaFixA(new Period(2, TimeUnit.Years), termStructure);
                shortSwapIndexBase = new EuriborSwapIsdaFixA(new Period(1, TimeUnit.Years), termStructure);

                vegaWeighedSmileFit = false;
            }
Ejemplo n.º 2
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(EuriborSwapIsdaFixA obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
Ejemplo n.º 3
0
            // setup
            public CommonVars()
            {
                backup = new SavedSettings();

                Calendar calendar = new TARGET();

                Date referenceDate = calendar.adjust(Date.Today);

                Settings.Instance.setEvaluationDate(referenceDate);

                termStructure = new RelinkableHandle <YieldTermStructure>();
                termStructure.linkTo(Utilities.flatRate(referenceDate, 0.05, new Actual365Fixed()));

                // ATM Volatility structure
                List <Period> atmOptionTenors = new List <Period>();

                atmOptionTenors.Add(new Period(1, TimeUnit.Months));
                atmOptionTenors.Add(new Period(6, TimeUnit.Months));
                atmOptionTenors.Add(new Period(1, TimeUnit.Years));
                atmOptionTenors.Add(new Period(5, TimeUnit.Years));
                atmOptionTenors.Add(new Period(10, TimeUnit.Years));
                atmOptionTenors.Add(new Period(30, TimeUnit.Years));

                List <Period> atmSwapTenors = new List <Period>();

                atmSwapTenors.Add(new Period(1, TimeUnit.Years));
                atmSwapTenors.Add(new Period(5, TimeUnit.Years));
                atmSwapTenors.Add(new Period(10, TimeUnit.Years));
                atmSwapTenors.Add(new Period(30, TimeUnit.Years));

                Matrix m = new Matrix(atmOptionTenors.Count, atmSwapTenors.Count);

                m[0, 0] = 0.1300; m[0, 1] = 0.1560; m[0, 2] = 0.1390; m[0, 3] = 0.1220;
                m[1, 0] = 0.1440; m[1, 1] = 0.1580; m[1, 2] = 0.1460; m[1, 3] = 0.1260;
                m[2, 0] = 0.1600; m[2, 1] = 0.1590; m[2, 2] = 0.1470; m[2, 3] = 0.1290;
                m[3, 0] = 0.1640; m[3, 1] = 0.1470; m[3, 2] = 0.1370; m[3, 3] = 0.1220;
                m[4, 0] = 0.1400; m[4, 1] = 0.1300; m[4, 2] = 0.1250; m[4, 3] = 0.1100;
                m[5, 0] = 0.1130; m[5, 1] = 0.1090; m[5, 2] = 0.1070; m[5, 3] = 0.0930;

                atmVol = new Handle <SwaptionVolatilityStructure>(
                    new SwaptionVolatilityMatrix(calendar, BusinessDayConvention.Following, atmOptionTenors,
                                                 atmSwapTenors, m, new Actual365Fixed()));

                // Vol cubes
                List <Period> optionTenors = new List <Period>();

                optionTenors.Add(new Period(1, TimeUnit.Years));
                optionTenors.Add(new Period(10, TimeUnit.Years));
                optionTenors.Add(new Period(30, TimeUnit.Years));

                List <Period> swapTenors = new List <Period>();

                swapTenors.Add(new Period(2, TimeUnit.Years));
                swapTenors.Add(new Period(10, TimeUnit.Years));
                swapTenors.Add(new Period(30, TimeUnit.Years));

                List <double> strikeSpreads = new List <double>();

                strikeSpreads.Add(-0.020);
                strikeSpreads.Add(-0.005);
                strikeSpreads.Add(+0.000);
                strikeSpreads.Add(+0.005);
                strikeSpreads.Add(+0.020);

                int    nRows            = optionTenors.Count * swapTenors.Count;
                int    nCols            = strikeSpreads.Count;
                Matrix volSpreadsMatrix = new Matrix(nRows, nCols);

                volSpreadsMatrix[0, 0] = 0.0599;
                volSpreadsMatrix[0, 1] = 0.0049;
                volSpreadsMatrix[0, 2] = 0.0000;
                volSpreadsMatrix[0, 3] = -0.0001;
                volSpreadsMatrix[0, 4] = 0.0127;

                volSpreadsMatrix[1, 0] = 0.0729;
                volSpreadsMatrix[1, 1] = 0.0086;
                volSpreadsMatrix[1, 2] = 0.0000;
                volSpreadsMatrix[1, 3] = -0.0024;
                volSpreadsMatrix[1, 4] = 0.0098;

                volSpreadsMatrix[2, 0] = 0.0738;
                volSpreadsMatrix[2, 1] = 0.0102;
                volSpreadsMatrix[2, 2] = 0.0000;
                volSpreadsMatrix[2, 3] = -0.0039;
                volSpreadsMatrix[2, 4] = 0.0065;

                volSpreadsMatrix[3, 0] = 0.0465;
                volSpreadsMatrix[3, 1] = 0.0063;
                volSpreadsMatrix[3, 2] = 0.0000;
                volSpreadsMatrix[3, 3] = -0.0032;
                volSpreadsMatrix[3, 4] = -0.0010;

                volSpreadsMatrix[4, 0] = 0.0558;
                volSpreadsMatrix[4, 1] = 0.0084;
                volSpreadsMatrix[4, 2] = 0.0000;
                volSpreadsMatrix[4, 3] = -0.0050;
                volSpreadsMatrix[4, 4] = -0.0057;

                volSpreadsMatrix[5, 0] = 0.0576;
                volSpreadsMatrix[5, 1] = 0.0083;
                volSpreadsMatrix[5, 2] = 0.0000;
                volSpreadsMatrix[5, 3] = -0.0043;
                volSpreadsMatrix[5, 4] = -0.0014;

                volSpreadsMatrix[6, 0] = 0.0437;
                volSpreadsMatrix[6, 1] = 0.0059;
                volSpreadsMatrix[6, 2] = 0.0000;
                volSpreadsMatrix[6, 3] = -0.0030;
                volSpreadsMatrix[6, 4] = -0.0006;

                volSpreadsMatrix[7, 0] = 0.0533;
                volSpreadsMatrix[7, 1] = 0.0078;
                volSpreadsMatrix[7, 2] = 0.0000;
                volSpreadsMatrix[7, 3] = -0.0045;
                volSpreadsMatrix[7, 4] = -0.0046;

                volSpreadsMatrix[8, 0] = 0.0545;
                volSpreadsMatrix[8, 1] = 0.0079;
                volSpreadsMatrix[8, 2] = 0.0000;
                volSpreadsMatrix[8, 3] = -0.0042;
                volSpreadsMatrix[8, 4] = -0.0020;

                List <List <Handle <Quote> > > volSpreads = new InitializedList <List <Handle <Quote> > >(nRows);

                for (int i = 0; i < nRows; ++i)
                {
                    volSpreads[i] = new InitializedList <Handle <Quote> >(nCols);
                    for (int j = 0; j < nCols; ++j)
                    {
                        volSpreads[i][j] = new Handle <Quote>(new SimpleQuote(volSpreadsMatrix[i, j]));
                    }
                }

                iborIndex = new Euribor6M(termStructure);
                SwapIndex swapIndexBase      = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years), termStructure);
                SwapIndex shortSwapIndexBase = new EuriborSwapIsdaFixA(new Period(2, TimeUnit.Years), termStructure);

                bool vegaWeightedSmileFit = false;

                SabrVolCube2 = new Handle <SwaptionVolatilityStructure>(
                    new SwaptionVolCube2(atmVol,
                                         optionTenors,
                                         swapTenors,
                                         strikeSpreads,
                                         volSpreads,
                                         swapIndexBase,
                                         shortSwapIndexBase,
                                         vegaWeightedSmileFit));
                SabrVolCube2.link.enableExtrapolation();

                List <List <Handle <Quote> > > guess = new InitializedList <List <Handle <Quote> > >(nRows);

                for (int i = 0; i < nRows; ++i)
                {
                    guess[i]    = new InitializedList <Handle <Quote> >(4);
                    guess[i][0] = new Handle <Quote>(new SimpleQuote(0.2));
                    guess[i][1] = new Handle <Quote>(new SimpleQuote(0.5));
                    guess[i][2] = new Handle <Quote>(new SimpleQuote(0.4));
                    guess[i][3] = new Handle <Quote>(new SimpleQuote(0.0));
                }
                List <bool> isParameterFixed = new InitializedList <bool>(4, false);

                isParameterFixed[1] = true;

                // FIXME
                bool isAtmCalibrated = false;

                SabrVolCube1 = new Handle <SwaptionVolatilityStructure>(
                    new SwaptionVolCube1x(atmVol,
                                          optionTenors,
                                          swapTenors,
                                          strikeSpreads,
                                          volSpreads,
                                          swapIndexBase,
                                          shortSwapIndexBase,
                                          vegaWeightedSmileFit,
                                          guess,
                                          isParameterFixed,
                                          isAtmCalibrated));
                SabrVolCube1.link.enableExtrapolation();

                yieldCurveModels = new List <GFunctionFactory.YieldCurveModel>();
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.Standard);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.ExactYield);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.ParallelShifts);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.NonParallelShifts);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.NonParallelShifts); // for linear tsr model

                Handle <Quote> zeroMeanRev = new Handle <Quote>(new SimpleQuote(0.0));

                numericalPricers = new List <CmsCouponPricer>();
                analyticPricers  = new List <CmsCouponPricer>();
                for (int j = 0; j < yieldCurveModels.Count; ++j)
                {
                    if (j < yieldCurveModels.Count - 1)
                    {
                        numericalPricers.Add(new NumericHaganPricer(atmVol, yieldCurveModels[j], zeroMeanRev));
                    }
                    else
                    {
                        numericalPricers.Add(new LinearTsrPricer(atmVol, zeroMeanRev));
                    }

                    analyticPricers.Add(new AnalyticHaganPricer(atmVol, yieldCurveModels[j], zeroMeanRev));
                }
            }
Ejemplo n.º 4
0
        public void testParity()
        {
            // Testing put-call parity for capped-floored CMS coupons

            CommonVars vars = new CommonVars();

            List <Handle <SwaptionVolatilityStructure> > swaptionVols = new List <Handle <SwaptionVolatilityStructure> >();

            swaptionVols.Add(vars.atmVol);
            swaptionVols.Add(vars.SabrVolCube1);
            swaptionVols.Add(vars.SabrVolCube2);

            SwapIndex swapIndex = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years),
                                                          vars.iborIndex.forwardingTermStructure());
            Date   startDate               = vars.termStructure.link.referenceDate() + new Period(20, TimeUnit.Years);
            Date   paymentDate             = startDate + new Period(1, TimeUnit.Years);
            Date   endDate                 = paymentDate;
            double nominal                 = 1.0;
            double?infiniteCap             = null;
            double?infiniteFloor           = null;
            double gearing                 = 1.0;
            double spread                  = 0.0;
            double discount                = vars.termStructure.link.discount(paymentDate);
            CappedFlooredCmsCoupon swaplet = new CappedFlooredCmsCoupon(nominal, paymentDate,
                                                                        startDate, endDate, swapIndex.fixingDays(), swapIndex, gearing, spread, infiniteCap, infiniteFloor,
                                                                        startDate, endDate, vars.iborIndex.dayCounter());

            for (double strike = .02; strike < .12; strike += 0.05)
            {
                CappedFlooredCmsCoupon caplet = new CappedFlooredCmsCoupon(nominal, paymentDate,
                                                                           startDate, endDate, swapIndex.fixingDays(), swapIndex, gearing, spread, strike, infiniteFloor,
                                                                           startDate, endDate, vars.iborIndex.dayCounter());
                CappedFlooredCmsCoupon floorlet = new CappedFlooredCmsCoupon(nominal, paymentDate,
                                                                             startDate, endDate, swapIndex.fixingDays(), swapIndex, gearing, spread, infiniteCap, strike,
                                                                             startDate, endDate, vars.iborIndex.dayCounter());

                for (int i = 0; i < swaptionVols.Count; ++i)
                {
                    for (int j = 0; j < vars.yieldCurveModels.Count; ++j)
                    {
                        vars.numericalPricers[j].setSwaptionVolatility(swaptionVols[i]);
                        vars.analyticPricers[j].setSwaptionVolatility(swaptionVols[i]);
                        List <CmsCouponPricer> pricers = new List <CmsCouponPricer>(2);
                        pricers.Add(vars.numericalPricers[j]);
                        pricers.Add(vars.analyticPricers[j]);
                        for (int k = 0; k < pricers.Count; ++k)
                        {
                            swaplet.setPricer(pricers[k]);
                            caplet.setPricer(pricers[k]);
                            floorlet.setPricer(pricers[k]);
                            double swapletPrice = swaplet.price(vars.termStructure) +
                                                  nominal * swaplet.accrualPeriod() * strike * discount;
                            double capletPrice   = caplet.price(vars.termStructure);
                            double floorletPrice = floorlet.price(vars.termStructure);
                            double difference    = Math.Abs(capletPrice + floorletPrice - swapletPrice);
                            double tol           = 2.0e-5;
                            bool   linearTsr     = k == 0 && j == vars.yieldCurveModels.Count - 1;
                            if (linearTsr)
                            {
                                tol = 1.0e-7;
                            }
                            if (difference > tol)
                            {
                                QAssert.Fail("\nCoupon payment date: " + paymentDate +
                                             "\nCoupon start date:   " + startDate +
                                             "\nCoupon gearing:      " + (gearing) +
                                             "\nCoupon swap index:   " + swapIndex.name() +
                                             "\nCoupon spread:       " + (spread) +
                                             "\nstrike:              " + (strike) +
                                             "\nCoupon DayCounter:   " + vars.iborIndex.dayCounter() +
                                             "\nYieldCurve Model:    " + vars.yieldCurveModels[j] +
                                             (k == 0 ? "\nNumerical Pricer" : "\nAnalytic Pricer") +
                                             (linearTsr ? " (Linear TSR Model)" : "") +
                                             "\nSwaplet price:       " + (swapletPrice) +
                                             "\nCaplet price:        " + (capletPrice) +
                                             "\nFloorlet price:      " + (floorletPrice) +
                                             "\ndifference:          " + difference +
                                             "\ntolerance:           " + (tol));
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
            public void makeCoherenceTest(string description,
                                          SwaptionVolatilityDiscrete vol)
            {
                for (int i = 0; i < atm.tenors.options.Count; ++i)
                {
                    Date optionDate =
                        vol.optionDateFromTenor(atm.tenors.options[i]);
                    if (optionDate != vol.optionDates()[i])
                    {
                        Assert.Fail(
                            "optionDateFromTenor failure for " +
                            description + ":" +
                            "\n       option tenor: " + atm.tenors.options[i] +
                            "\nactual option date : " + optionDate +
                            "\n  exp. option date : " + vol.optionDates()[i]);
                    }
                    double optionTime = vol.timeFromReference(optionDate);
                    if (optionTime != vol.optionTimes()[i])
                    {
                        Assert.Fail(
                            "timeFromReference failure for " +
                            description + ":" +
                            "\n       option tenor: " + atm.tenors.options[i] +
                            "\n       option date : " + optionDate +
                            "\nactual option time : " + optionTime +
                            "\n  exp. option time : " + vol.optionTimes()[i]);
                    }
                }

                BlackSwaptionEngine engine = new  BlackSwaptionEngine(
                    termStructure,
                    new Handle <SwaptionVolatilityStructure>(vol));

                for (int j = 0; j < atm.tenors.swaps.Count; j++)
                {
                    double swapLength = vol.swapLength(atm.tenors.swaps[j]);

                    if (swapLength != atm.tenors.swaps[j].length())
                    {
                        Assert.Fail("convertSwapTenor failure for " +
                                    description + ":" +
                                    "\n        swap tenor : " + atm.tenors.swaps[j] +
                                    "\n actual swap length: " + swapLength +
                                    "\n   exp. swap length: " + atm.tenors.swaps[j].length());
                    }

                    SwapIndex swapIndex = new EuriborSwapIsdaFixA(atm.tenors.swaps[j], termStructure);

                    for (int i = 0; i < atm.tenors.options.Count; ++i)
                    {
                        double error, tolerance = 1.0e-16;
                        double actVol, expVol = atm.vols[i, j];

                        actVol = vol.volatility(atm.tenors.options[i],
                                                atm.tenors.swaps[j], 0.05, true);
                        error = Math.Abs(expVol - actVol);
                        if (error > tolerance)
                        {
                            Assert.Fail(
                                "recovery of atm vols failed for " +
                                description + ":" +
                                "\noption tenor = " + atm.tenors.options[i] +
                                "\n swap length = " + atm.tenors.swaps[j] +
                                "\nexpected vol = " + expVol +
                                "\n  actual vol = " + actVol +
                                "\n       error = " + error +
                                "\n   tolerance = " + tolerance);
                        }

                        Date optionDate =
                            vol.optionDateFromTenor(atm.tenors.options[i]);
                        actVol = vol.volatility(optionDate,
                                                atm.tenors.swaps[j], 0.05, true);
                        error = Math.Abs(expVol - actVol);
                        if (error > tolerance)
                        {
                            Assert.Fail(
                                "recovery of atm vols failed for " +
                                description + ":" +
                                "\noption tenor: " + atm.tenors.options[i] +
                                "\noption date : " + optionDate +
                                "\n  swap tenor: " + atm.tenors.swaps[j] +
                                "\n   exp. vol: " + expVol +
                                "\n actual vol: " + actVol +
                                "\n      error: " + error +
                                "\n  tolerance: " + tolerance);
                        }

                        double optionTime = vol.timeFromReference(optionDate);
                        actVol = vol.volatility(optionTime, swapLength,
                                                0.05, true);
                        error = Math.Abs(expVol - actVol);
                        if (error > tolerance)
                        {
                            Assert.Fail(
                                "recovery of atm vols failed for " +
                                description + ":" +
                                "\noption tenor: " + atm.tenors.options[i] +
                                "\noption time : " + optionTime +
                                "\n  swap tenor: " + atm.tenors.swaps[j] +
                                "\n swap length: " + swapLength +
                                "\n    exp. vol: " + expVol +
                                "\n  actual vol: " + actVol +
                                "\n       error: " + error +
                                "\n   tolerance: " + tolerance);
                        }

                        // ATM swaption
                        Swaption swaption = new MakeSwaption(
                            swapIndex, atm.tenors.options[i])
                                            .withPricingEngine(engine)
                                            .value();

                        Date exerciseDate = swaption.exercise().dates().First();
                        if (exerciseDate != vol.optionDates()[i])
                        {
                            Assert.Fail(
                                "optionDateFromTenor mismatch for " +
                                description + ":" +
                                "\n      option tenor: " + atm.tenors.options[i] +
                                "\nactual option date: " + exerciseDate +
                                "\n  exp. option date: " + vol.optionDates()[i]);
                        }

                        Date   start       = swaption.underlyingSwap().startDate();
                        Date   end         = swaption.underlyingSwap().maturityDate();
                        double swapLength2 = vol.swapLength(start, end);
                        if (swapLength2 != swapLength)
                        {
                            Assert.Fail(
                                "swapLength failure for " +
                                description + ":" +
                                "\n        swap tenor : " + atm.tenors.swaps[j] +
                                "\n actual swap length: " + swapLength2 +
                                "\n   exp. swap length: " + swapLength);
                        }

                        double npv = swaption.NPV();
                        actVol = swaption.impliedVolatility(npv, termStructure,
                                                            expVol * 0.98, 1e-6);
                        error = Math.Abs(expVol - actVol);
                        // TO BE FIXED
                        //    double tolerance2 = 0.000001;
                        //    if (error > tolerance2 & i != 0)//NOK for i=0 -> to debug
                        //        Assert.Fail(
                        //             "recovery of atm vols through BlackSwaptionEngine failed for " +
                        //             description + ":"+
                        //             "\noption tenor: " + atm.tenors.options[i] +
                        //             "\noption time : " + optionTime +
                        //             "\n  swap tenor: " + atm.tenors.swaps[j] +
                        //             "\n swap length: " + swapLength +
                        //             "\n   exp. vol: " + expVol +
                        //             "\n actual vol: " + actVol +
                        //             "\n      error: " + error +
                        //             "\n  tolerance: " + tolerance2);
                    }
                }
            }
Ejemplo n.º 6
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(EuriborSwapIsdaFixA obj) {
   return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
 }
Ejemplo n.º 7
0
        public void testFixings()
        {
            TestData d = new TestData();

            SwapIndex       cms10y   = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years), d.yts2, d.yts2);
            SwapIndex       cms2y    = new EuriborSwapIsdaFixA(new Period(2, TimeUnit.Years), d.yts2, d.yts2);
            SwapSpreadIndex cms10y2y = new SwapSpreadIndex("cms10y2y", cms10y, cms2y);

            Settings.Instance.enforcesTodaysHistoricFixings = false;

            try
            {
                cms10y2y.fixing(d.refDate - 1);
                QAssert.Fail("fixing on refDate did not throwed an error.");
            }
            catch
            {
            }

            try
            {
                cms10y2y.fixing(d.refDate);
            }
            catch
            {
                QAssert.Fail("fixing on refDate throwed an error.");
            }

            QAssert.IsTrue(cms10y2y.fixing(d.refDate) ==
                           cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate));
            cms10y.addFixing(d.refDate, 0.05);
            QAssert.IsTrue(cms10y2y.fixing(d.refDate) ==
                           cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate));
            cms2y.addFixing(d.refDate, 0.04);
            QAssert.IsTrue(cms10y2y.fixing(d.refDate) ==
                           cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate));
            Date futureFixingDate = new TARGET().adjust(d.refDate + new Period(1, TimeUnit.Years));

            QAssert.IsTrue(cms10y2y.fixing(futureFixingDate) ==
                           cms10y.fixing(futureFixingDate) -
                           cms2y.fixing(futureFixingDate));
            IndexManager.Instance.clearHistories();

            Settings.Instance.enforcesTodaysHistoricFixings = true;
            try
            {
                cms10y2y.fixing(d.refDate);
                QAssert.Fail("fixing on refDate did not throwed an error.");
            }
            catch
            {
            }

            cms10y.addFixing(d.refDate, 0.05);

            try
            {
                cms10y2y.fixing(d.refDate);
                QAssert.Fail("fixing on refDate did not throwed an error.");
            }
            catch
            {
            }
            cms2y.addFixing(d.refDate, 0.04);

            QAssert.IsTrue(cms10y2y.fixing(d.refDate) ==
                           cms10y.fixing(d.refDate) - cms2y.fixing(d.refDate));
            IndexManager.Instance.clearHistories();
        }
Ejemplo n.º 8
0
        public void testCouponPricing()
        {
            TestData d   = new TestData();
            double   tol = 1E-6; // abs tolerance coupon rate

            SwapIndex       cms10y   = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years), d.yts2, d.yts2);
            SwapIndex       cms2y    = new EuriborSwapIsdaFixA(new Period(2, TimeUnit.Years), d.yts2, d.yts2);
            SwapSpreadIndex cms10y2y = new SwapSpreadIndex("cms10y2y", cms10y, cms2y);

            Date      valueDate = cms10y2y.valueDate(d.refDate);
            Date      payDate   = valueDate + new Period(1, TimeUnit.Years);
            CmsCoupon cpn1a     = new CmsCoupon(10000.0, payDate, valueDate, payDate, cms10y.fixingDays(), cms10y,
                                                1.0, 0.0, null, null, new Actual360(), false);
            CmsCoupon cpn1b = new CmsCoupon(10000.0, payDate, valueDate, payDate, cms2y.fixingDays(),
                                            cms2y, 1.0, 0.0, null, null, new Actual360(), false);
            CmsSpreadCoupon cpn1 = new CmsSpreadCoupon(
                10000.0, payDate, valueDate, payDate, cms10y2y.fixingDays(),
                cms10y2y, 1.0, 0.0, null, null, new Actual360(), false);

            QAssert.IsTrue(cpn1.fixingDate() == d.refDate);
            cpn1a.setPricer(d.cmsPricerLn);
            cpn1b.setPricer(d.cmsPricerLn);
            cpn1.setPricer(d.cmsspPricerLn);
            QAssert.IsTrue(cpn1.rate() == cpn1a.rate() - cpn1b.rate());
            cms10y.addFixing(d.refDate, 0.05);
            QAssert.IsTrue(cpn1.rate() == cpn1a.rate() - cpn1b.rate());
            cms2y.addFixing(d.refDate, 0.03);
            QAssert.IsTrue(cpn1.rate() == cpn1a.rate() - cpn1b.rate());
            IndexManager.Instance.clearHistories();

            CmsCoupon cpn2a = new CmsCoupon(10000.0, new Date(23, Month.February, 2029),
                                            new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2,
                                            cms10y, 1.0, 0.0, null, null, new Actual360(), false);
            CmsCoupon cpn2b = new CmsCoupon(10000.0, new Date(23, Month.February, 2029),
                                            new Date(23, Month.February, 2028), new Date(23, Month.February, 2029), 2,
                                            cms2y, 1.0, 0.0, null, null, new Actual360(), false);

            CappedFlooredCmsSpreadCoupon plainCpn =
                new CappedFlooredCmsSpreadCoupon(
                    new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028),
                    new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, null,
                    null, null, null, new Actual360(), false);
            CappedFlooredCmsSpreadCoupon cappedCpn =
                new CappedFlooredCmsSpreadCoupon(
                    new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028),
                    new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, 0.03,
                    null, null, null, new Actual360(), false);
            CappedFlooredCmsSpreadCoupon flooredCpn =
                new CappedFlooredCmsSpreadCoupon(
                    new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028),
                    new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, null,
                    0.01, null, null, new Actual360(), false);
            CappedFlooredCmsSpreadCoupon collaredCpn =
                new CappedFlooredCmsSpreadCoupon(
                    new Date(23, Month.February, 2029), 10000.0, new Date(23, Month.February, 2028),
                    new Date(23, Month.February, 2029), 2, cms10y2y, 1.0, 0.0, 0.03, 0.01,
                    null, null, new Actual360(), false);

            cpn2a.setPricer(d.cmsPricerLn);
            cpn2b.setPricer(d.cmsPricerLn);
            plainCpn.setPricer(d.cmsspPricerLn);
            cappedCpn.setPricer(d.cmsspPricerLn);
            flooredCpn.setPricer(d.cmsspPricerLn);
            collaredCpn.setPricer(d.cmsspPricerLn);

            QAssert.IsTrue(
                Math.Abs(plainCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue,
                                                            -Double.MaxValue, d.swLn,
                                                            d.correlation.currentLink().value())) <
                tol);
            QAssert.IsTrue(
                Math.Abs(cappedCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03,
                                                             -Double.MaxValue, d.swLn,
                                                             d.correlation.currentLink().value())) <
                tol);
            QAssert.IsTrue(
                Math.Abs(flooredCpn.rate() -
                         mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, 0.01, d.swLn,
                                          d.correlation.currentLink().value())) <

                tol);
            QAssert.IsTrue(
                Math.Abs(collaredCpn.rate() -
                         mcReferenceValue(cpn2a, cpn2b, 0.03, 0.01, d.swLn,
                                          d.correlation.currentLink().value())) <
                tol);

            cpn2a.setPricer(d.cmsPricerSln);
            cpn2b.setPricer(d.cmsPricerSln);
            plainCpn.setPricer(d.cmsspPricerSln);
            cappedCpn.setPricer(d.cmsspPricerSln);
            flooredCpn.setPricer(d.cmsspPricerSln);
            collaredCpn.setPricer(d.cmsspPricerSln);

            QAssert.IsTrue(
                Math.Abs(plainCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue,
                                                            -Double.MaxValue, d.swSln,
                                                            d.correlation.currentLink().value())) <
                tol);
            QAssert.IsTrue(
                Math.Abs(cappedCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03,
                                                             -Double.MaxValue, d.swSln,
                                                             d.correlation.currentLink().value())) <
                tol);
            QAssert.IsTrue(
                Math.Abs(flooredCpn.rate() -
                         mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, 0.01, d.swSln,
                                          d.correlation.currentLink().value())) <

                tol);
            QAssert.IsTrue(
                Math.Abs(collaredCpn.rate() -
                         mcReferenceValue(cpn2a, cpn2b, 0.03, 0.01, d.swSln,
                                          d.correlation.currentLink().value())) <
                tol);

            cpn2a.setPricer(d.cmsPricerN);
            cpn2b.setPricer(d.cmsPricerN);
            plainCpn.setPricer(d.cmsspPricerN);
            cappedCpn.setPricer(d.cmsspPricerN);
            flooredCpn.setPricer(d.cmsspPricerN);
            collaredCpn.setPricer(d.cmsspPricerN);

            QAssert.IsTrue(
                Math.Abs(plainCpn.rate() - mcReferenceValue(cpn2a, cpn2b, Double.MaxValue,
                                                            -Double.MaxValue, d.swN,
                                                            d.correlation.currentLink().value())) <
                tol);
            QAssert.IsTrue(
                Math.Abs(cappedCpn.rate() - mcReferenceValue(cpn2a, cpn2b, 0.03,
                                                             -Double.MaxValue, d.swN,
                                                             d.correlation.currentLink().value())) <
                tol);
            QAssert.IsTrue(Math.Abs(flooredCpn.rate() -
                                    mcReferenceValue(cpn2a, cpn2b, Double.MaxValue, 0.01,
                                                     d.swN, d.correlation.currentLink().value())) <

                           tol);
            QAssert.IsTrue(Math.Abs(collaredCpn.rate() -
                                    mcReferenceValue(cpn2a, cpn2b, 0.03, 0.01, d.swN,
                                                     d.correlation.currentLink().value())) <
                           tol);
        }