public FuturesRateHelper(double price,
                                 Date iborStartDate,
                                 Date iborEndDate,
                                 DayCounter dayCounter,
                                 double convAdj    = 0,
                                 Futures.Type type = Futures.Type.IMM)
            : base(price)
        {
            convAdj_ = new Handle <Quote>(new SimpleQuote(convAdj));

            switch (type)
            {
            case Futures.Type.IMM:
                Utils.QL_REQUIRE(IMM.isIMMdate(iborStartDate, false), () =>
                                 iborStartDate + " is not a valid IMM date");
                if (iborEndDate == null)
                {
                    // advance 3 months
                    maturityDate_ = IMM.nextDate(iborStartDate, false);
                    maturityDate_ = IMM.nextDate(maturityDate_, false);
                    maturityDate_ = IMM.nextDate(maturityDate_, false);
                }
                else
                {
                    Utils.QL_REQUIRE(iborEndDate > iborStartDate, () =>
                                     "end date (" + iborEndDate +
                                     ") must be greater than start date (" +
                                     iborStartDate + ")");
                    maturityDate_ = iborEndDate;
                }
                break;

            case Futures.Type.ASX:
                Utils.QL_REQUIRE(ASX.isASXdate(iborStartDate, false), () =>
                                 iborStartDate + " is not a valid ASX date");
                if (iborEndDate == null)
                {
                    // advance 3 months
                    maturityDate_ = ASX.nextDate(iborStartDate, false);
                    maturityDate_ = ASX.nextDate(maturityDate_, false);
                    maturityDate_ = ASX.nextDate(maturityDate_, false);
                }
                else
                {
                    Utils.QL_REQUIRE(iborEndDate > iborStartDate, () =>
                                     "end date (" + iborEndDate +
                                     ") must be greater than start date (" +
                                     iborStartDate + ")");
                    maturityDate_ = iborEndDate;
                }
                break;

            default:
                Utils.QL_FAIL("unknown futures type (" + type + ")");
                break;
            }
            earliestDate_ = iborStartDate;
            yearFraction_ = dayCounter.yearFraction(earliestDate_, maturityDate_);
            pillarDate_   = latestDate_ = latestRelevantDate_ = maturityDate_;
        }
Exemple #2
0
        public void testIMMDates()
        {
            // ("Testing IMM dates...");

            string[] IMMcodes = new string[]
            {
                "F0", "G0", "H0", "J0", "K0", "M0", "N0", "Q0", "U0", "V0", "X0", "Z0",
                "F1", "G1", "H1", "J1", "K1", "M1", "N1", "Q1", "U1", "V1", "X1", "Z1",
                "F2", "G2", "H2", "J2", "K2", "M2", "N2", "Q2", "U2", "V2", "X2", "Z2",
                "F3", "G3", "H3", "J3", "K3", "M3", "N3", "Q3", "U3", "V3", "X3", "Z3",
                "F4", "G4", "H4", "J4", "K4", "M4", "N4", "Q4", "U4", "V4", "X4", "Z4",
                "F5", "G5", "H5", "J5", "K5", "M5", "N5", "Q5", "U5", "V5", "X5", "Z5",
                "F6", "G6", "H6", "J6", "K6", "M6", "N6", "Q6", "U6", "V6", "X6", "Z6",
                "F7", "G7", "H7", "J7", "K7", "M7", "N7", "Q7", "U7", "V7", "X7", "Z7",
                "F8", "G8", "H8", "J8", "K8", "M8", "N8", "Q8", "U8", "V8", "X8", "Z8",
                "F9", "G9", "H9", "J9", "K9", "M9", "N9", "Q9", "U9", "V9", "X9", "Z9"
            };

            Date counter = Date.minDate();
            // 10 years of futures must not exceed Date::maxDate
            Date last = Date.maxDate() - new Period(121, TimeUnit.Months);
            Date imm;

            while (counter <= last)
            {
                imm = IMM.nextDate(counter, false);

                // check that imm is greater than counter
                if (imm <= counter)
                {
                    QAssert.Fail(imm.DayOfWeek + " " + imm
                                 + " is not greater than "
                                 + counter.DayOfWeek + " " + counter);
                }

                // check that imm is an IMM date
                if (!IMM.isIMMdate(imm, false))
                {
                    QAssert.Fail(imm.DayOfWeek + " " + imm
                                 + " is not an IMM date (calculated from "
                                 + counter.DayOfWeek + " " + counter + ")");
                }

                // check that imm is <= to the next IMM date in the main cycle
                if (imm > IMM.nextDate(counter, true))
                {
                    QAssert.Fail(imm.DayOfWeek + " " + imm
                                 + " is not less than or equal to the next future in the main cycle "
                                 + IMM.nextDate(counter, true));
                }

                //// check that if counter is an IMM date, then imm==counter
                //if (IMM::isIMMdate(counter, false) && (imm!=counter))
                //    BOOST_FAIL("\n  "
                //               << counter.weekday() << " " << counter
                //               << " is already an IMM date, while nextIMM() returns "
                //               << imm.weekday() << " " << imm);

                // check that for every date IMMdate is the inverse of IMMcode
                if (IMM.date(IMM.code(imm), counter) != imm)
                {
                    QAssert.Fail(IMM.code(imm)
                                 + " at calendar day " + counter
                                 + " is not the IMM code matching " + imm);
                }

                // check that for every date the 120 IMM codes refer to future dates
                for (int i = 0; i < 40; ++i)
                {
                    if (IMM.date(IMMcodes[i], counter) < counter)
                    {
                        QAssert.Fail(IMM.date(IMMcodes[i], counter)
                                     + " is wrong for " + IMMcodes[i]
                                     + " at reference date " + counter);
                    }
                }

                counter = counter + 1;
            }
        }
Exemple #3
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

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

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(22, Month.September, 2004);

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

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

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


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


            // deposits
            double d1wQuote = 0.0382;
            double d1mQuote = 0.0372;
            double d3mQuote = 0.0363;
            double d6mQuote = 0.0353;
            double d9mQuote = 0.0348;
            double d1yQuote = 0.0345;
            // FRAs
            double fra3x6Quote  = 0.037125;
            double fra6x9Quote  = 0.037125;
            double fra6x12Quote = 0.037125;
            // futures
            double fut1Quote = 96.2875;
            double fut2Quote = 96.7875;
            double fut3Quote = 96.9875;
            double fut4Quote = 96.6875;
            double fut5Quote = 96.4875;
            double fut6Quote = 96.3875;
            double fut7Quote = 96.2875;
            double fut8Quote = 96.0875;
            // swaps
            double s2yQuote  = 0.037125;
            double s3yQuote  = 0.0398;
            double s5yQuote  = 0.0443;
            double s10yQuote = 0.05165;
            double s15yQuote = 0.055175;


            /********************
            ***    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);
            // FRAs
            Quote fra3x6Rate  = new SimpleQuote(fra3x6Quote);
            Quote fra6x9Rate  = new SimpleQuote(fra6x9Quote);
            Quote fra6x12Rate = new SimpleQuote(fra6x12Quote);
            // futures
            Quote fut1Price = new SimpleQuote(fut1Quote);
            Quote fut2Price = new SimpleQuote(fut2Quote);
            Quote fut3Price = new SimpleQuote(fut3Quote);
            Quote fut4Price = new SimpleQuote(fut4Quote);
            Quote fut5Price = new SimpleQuote(fut5Quote);
            Quote fut6Price = new SimpleQuote(fut6Quote);
            Quote fut7Price = new SimpleQuote(fut7Quote);
            Quote fut8Price = new SimpleQuote(fut8Quote);
            // 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 FRAs
            RateHelper fra3x6 = new FraRateHelper(new Handle <Quote>(fra3x6Rate), 3, 6, fixingDays, calendar,
                                                  BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper fra6x9 = new FraRateHelper(new Handle <Quote>(fra6x9Rate), 6, 9, fixingDays, calendar,
                                                  BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);
            RateHelper fra6x12 = new FraRateHelper(new Handle <Quote>(fra6x12Rate), 6, 12, fixingDays, calendar,
                                                   BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);


            // setup futures
            // Handle<Quote> convexityAdjustment = new Handle<Quote>(new SimpleQuote(0.0));
            int  futMonths = 3;
            Date imm       = IMM.nextDate(settlementDate);

            RateHelper fut1 = new FuturesRateHelper(new Handle <Quote>(fut1Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut2 = new FuturesRateHelper(new Handle <Quote>(fut2Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut3 = new FuturesRateHelper(new Handle <Quote>(fut3Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut4 = new FuturesRateHelper(new Handle <Quote>(fut4Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut5 = new FuturesRateHelper(new Handle <Quote>(fut5Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut6 = new FuturesRateHelper(new Handle <Quote>(fut6Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut7 = new FuturesRateHelper(new Handle <Quote>(fut7Price), imm, futMonths, calendar,
                                                    BusinessDayConvention.ModifiedFollowing, true, depositDayCounter);

            imm = IMM.nextDate(imm + 1);
            RateHelper fut8 = new FuturesRateHelper(new Handle <Quote>(fut8Price), imm, futMonths, 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();

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



            /*********************
            **  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-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);


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

            depoFutSwapInstruments.Add(d1w);
            depoFutSwapInstruments.Add(d1m);
            depoFutSwapInstruments.Add(fut1);
            depoFutSwapInstruments.Add(fut2);
            depoFutSwapInstruments.Add(fut3);
            depoFutSwapInstruments.Add(fut4);
            depoFutSwapInstruments.Add(fut5);
            depoFutSwapInstruments.Add(fut6);
            depoFutSwapInstruments.Add(fut7);
            depoFutSwapInstruments.Add(fut8);
            depoFutSwapInstruments.Add(s3y);
            depoFutSwapInstruments.Add(s5y);
            depoFutSwapInstruments.Add(s10y);
            depoFutSwapInstruments.Add(s15y);
            YieldTermStructure depoFutSwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoFutSwapInstruments, termStructureDayCounter, new List <Handle <Quote> >(), new List <Date>(), tolerance);


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

            depoFRASwapInstruments.Add(d1w);
            depoFRASwapInstruments.Add(d1m);
            depoFRASwapInstruments.Add(d3m);
            depoFRASwapInstruments.Add(fra3x6);
            depoFRASwapInstruments.Add(fra6x9);
            depoFRASwapInstruments.Add(fra6x12);
            depoFRASwapInstruments.Add(s2y);
            depoFRASwapInstruments.Add(s3y);
            depoFRASwapInstruments.Add(s5y);
            depoFRASwapInstruments.Add(s10y);
            depoFRASwapInstruments.Add(s15y);
            YieldTermStructure depoFRASwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoFRASwapInstruments, 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>();


            /*********************
             * SWAPS TO BE PRICED *
             **********************/

            // constant nominal 1,000,000 Euro
            double nominal = 1000000.0;
            // fixed leg
            Frequency             fixedLegFrequency     = Frequency.Annual;
            BusinessDayConvention fixedLegConvention    = BusinessDayConvention.Unadjusted;
            BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter            fixedLegDayCounter    = new Thirty360(Thirty360.Thirty360Convention.European);
            double     fixedRate             = 0.04;
            DayCounter floatingLegDayCounter = new Actual360();

            // floating leg
            Frequency floatingLegFrequency = Frequency.Semiannual;
            IborIndex euriborIndex         = new Euribor6M(forecastingTermStructure);
            double    spread = 0.0;

            int lenghtInYears = 5;

            VanillaSwap.Type swapType = VanillaSwap.Type.Payer;

            Date     maturity      = settlementDate + new Period(lenghtInYears, TimeUnit.Years);
            Schedule fixedSchedule = new Schedule(settlementDate, maturity, new Period(fixedLegFrequency),
                                                  calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false);
            Schedule floatSchedule = new Schedule(settlementDate, maturity, new Period(floatingLegFrequency),
                                                  calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false);
            VanillaSwap spot5YearSwap = new VanillaSwap(swapType, nominal, fixedSchedule, fixedRate, fixedLegDayCounter,
                                                        floatSchedule, euriborIndex, spread, floatingLegDayCounter);

            Date     fwdStart         = calendar.advance(settlementDate, 1, TimeUnit.Years);
            Date     fwdMaturity      = fwdStart + new Period(lenghtInYears, TimeUnit.Years);
            Schedule fwdFixedSchedule = new Schedule(fwdStart, fwdMaturity, new Period(fixedLegFrequency),
                                                     calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false);
            Schedule fwdFloatSchedule = new Schedule(fwdStart, fwdMaturity, new Period(floatingLegFrequency),
                                                     calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false);
            VanillaSwap oneYearForward5YearSwap = new VanillaSwap(swapType, nominal, fwdFixedSchedule, fixedRate, fixedLegDayCounter,
                                                                  fwdFloatSchedule, euriborIndex, spread, floatingLegDayCounter);


            /***************
             * SWAP PRICING *
             ****************/

            // utilities for reporting
            List <string> headers = new List <string>();

            headers.Add("term structure");
            headers.Add("net present value");
            headers.Add("fair spread");
            headers.Add("fair fixed rate");
            string separator = " | ";
            int    width     = headers[0].Length + separator.Length
                               + headers[1].Length + separator.Length
                               + headers[2].Length + separator.Length
                               + headers[3].Length + separator.Length - 1;
            string rule = string.Format("").PadLeft(width, '-'), dblrule = string.Format("").PadLeft(width, '=');
            string tab = string.Format("").PadLeft(8, ' ');

            // calculations

            Console.WriteLine(dblrule);
            Console.WriteLine("5-year market swap-rate = {0:0.00%}", s5yRate.value());
            Console.WriteLine(dblrule);

            Console.WriteLine(tab + "5-years swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            double NPV;
            double fairRate;
            double fairSpread;

            IPricingEngine swapEngine = new DiscountingSwapEngine(discountingTermStructure);

            spot5YearSwap.setPricingEngine(swapEngine);
            oneYearForward5YearSwap.setPricingEngine(swapEngine);

            // Of course, you're not forced to really use different curves
            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            // let's check that the 5 years swap has been correctly re-priced
            if (!(Math.Abs(fairRate - s5yQuote) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yQuote));
            }


            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yQuote) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yQuote));
            }

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yQuote) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yQuote));
            }

            Console.WriteLine(rule);

            // now let's price the 1Y forward 5Y swap
            Console.WriteLine(tab + "5-years, 1-year forward swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            // now let's say that the 5-years swap rate goes up to 4.60%.
            // A smarter market element--say, connected to a data source-- would
            // notice the change itself. Since we're using SimpleQuotes,
            // we'll have to change the value manually--which forces us to
            // downcast the handle and use the SimpleQuote
            // interface. In any case, the point here is that a change in the
            // value contained in the Quote triggers a new bootstrapping
            // of the curve and a repricing of the swap.

            SimpleQuote fiveYearsRate = s5yRate as SimpleQuote;

            fiveYearsRate.setValue(0.0460);

            Console.WriteLine(dblrule);
            Console.WriteLine("5-year market swap-rate = {0:0.00%}", s5yRate.value());
            Console.WriteLine(dblrule);

            Console.WriteLine(tab + "5-years swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            // now get the updated results
            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yRate.value()) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yRate.value()));
            }

            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yRate.value()) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yRate.value()));
            }

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = spot5YearSwap.NPV();
            fairSpread = spot5YearSwap.fairSpread();
            fairRate   = spot5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            if (!(Math.Abs(fairRate - s5yRate.value()) < 1e-8))
            {
                throw new ApplicationException("5-years swap mispriced by " + Math.Abs(fairRate - s5yRate.value()));
            }

            Console.WriteLine(rule);

            // the 1Y forward 5Y swap changes as well

            Console.WriteLine(tab + "5-years, 1-year forward swap paying {0:0.00%}", fixedRate);
            Console.WriteLine(headers[0] + separator
                              + headers[1] + separator
                              + headers[2] + separator
                              + headers[3] + separator);
            Console.WriteLine(rule);

            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(depoSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFutSwapTermStructure);
            discountingTermStructure.linkTo(depoFutSwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-fut-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);

            forecastingTermStructure.linkTo(depoFRASwapTermStructure);
            discountingTermStructure.linkTo(depoFRASwapTermStructure);

            NPV        = oneYearForward5YearSwap.NPV();
            fairSpread = oneYearForward5YearSwap.fairSpread();
            fairRate   = oneYearForward5YearSwap.fairRate();

            Console.Write("{0," + headers[0].Length + ":0.00}" + separator, "depo-FRA-swap");
            Console.Write("{0," + headers[1].Length + ":0.00}" + separator, NPV);
            Console.Write("{0," + headers[2].Length + ":0.00%}" + separator, fairSpread);
            Console.WriteLine("{0," + headers[3].Length + ":0.00%}" + separator, fairRate);


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

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }