Пример #1
0
        public void testBootstrap()
        {
            // Testing Eonia-swap curve building...
             CommonVars vars = new CommonVars();

             List<RateHelper> eoniaHelpers = new List<RateHelper>();
             List<RateHelper> swap3mHelpers = new List<RateHelper>();

             IborIndex euribor3m = new Euribor3M();
             Eonia eonia = new Eonia();

             for (int i = 0; i < depositData.Length; i++)
             {
            double rate = 0.01 * depositData[i].rate;
            SimpleQuote simple = new SimpleQuote(rate);
            Handle<Quote> quote = new Handle<Quote>(simple);

            Period term = new Period(depositData[i].n , depositData[i].unit);
            RateHelper helper = new DepositRateHelper(quote,
                                         term,
                                         depositData[i].settlementDays,
                                         euribor3m.fixingCalendar(),
                                         euribor3m.businessDayConvention(),
                                         euribor3m.endOfMonth(),
                                         euribor3m.dayCounter());

            if (term <= new Period(2,TimeUnit.Days))
               eoniaHelpers.Add(helper);
            if (term <= new Period(3,TimeUnit.Months))
               swap3mHelpers.Add(helper);
             }

             for (int i = 0; i < fraData.Length; i++)
             {

            double rate = 0.01 * fraData[i].rate;
            SimpleQuote simple = new SimpleQuote(rate);
            Handle<Quote> quote = new Handle<Quote>(simple);
            RateHelper helper = new FraRateHelper(quote,
                                             fraData[i].nExpiry,
                                             fraData[i].nMaturity,
                                             fraData[i].settlementDays,
                                             euribor3m.fixingCalendar(),
                                             euribor3m.businessDayConvention(),
                                             euribor3m.endOfMonth(),
                                             euribor3m.dayCounter());
            swap3mHelpers.Add(helper);
             }

             for (int i = 0; i < eoniaSwapData.Length; i++)
             {

            double rate = 0.01 * eoniaSwapData[i].rate;
            SimpleQuote simple = new SimpleQuote(rate);
            Handle<Quote> quote = new Handle<Quote>(simple);
            Period term = new Period(eoniaSwapData[i].n , eoniaSwapData[i].unit);
            RateHelper helper = new OISRateHelper(eoniaSwapData[i].settlementDays,
                                                       term,
                                                       quote,
                                                       eonia);
            eoniaHelpers.Add(helper);
             }

             for (int i = 0; i < swapData.Length; i++)
             {
            double rate = 0.01 * swapData[i].rate;
            SimpleQuote simple = new SimpleQuote(rate);
            Handle<Quote> quote = new Handle<Quote>(simple);
            Period tenor = new Period(swapData[i].nIndexUnits , swapData[i].indexUnit);
            Period term = new Period(swapData[i].nTermUnits , swapData[i].termUnit);

            RateHelper helper = new SwapRateHelper(quote,
                                                        term,
                                                        vars.calendar,
                                                        vars.fixedSwapFrequency,
                                                        vars.fixedSwapConvention,
                                                        vars.fixedSwapDayCount,
                                                        euribor3m);
            if (tenor == new Period(3,TimeUnit.Months))
               swap3mHelpers.Add(helper);
             }

             PiecewiseYieldCurve<Discount, LogLinear> eoniaTS = new PiecewiseYieldCurve<Discount, LogLinear>(vars.today,
                                                                  eoniaHelpers,
                                                                  new Actual365Fixed());

             PiecewiseYieldCurve<Discount, LogLinear> swapTS = new PiecewiseYieldCurve<Discount, LogLinear>(vars.today,
                                                                 swap3mHelpers,
                                                                 new Actual365Fixed());

             vars.eoniaTermStructure.linkTo(eoniaTS);

             // test curve consistency
             double tolerance = 1.0e-10;
             for (int i = 0; i < eoniaSwapData.Length; i++)
             {

            double expected = eoniaSwapData[i].rate;
            Period term = new Period(eoniaSwapData[i].n , eoniaSwapData[i].unit);
            OvernightIndexedSwap swap = vars.makeSwap(term, 0.0, 0.0);
            double? calculated = 100.0 * swap.fairRate();

            if (Math.Abs(expected-calculated.Value) > tolerance)
               Assert.Fail("curve inconsistency:\n"
                           + "    swap length:     " + term + "\n"
                           + "    quoted rate:     " + expected + "\n"
                           + "    calculated rate: " + calculated);
             }
        }
Пример #2
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();
        }
Пример #3
0
        static void Main()
        {
            DateTime timer = DateTime.Now;

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

            RelinkableHandle<YieldTermStructure> euriborTermStructure = new RelinkableHandle<YieldTermStructure>();
            IborIndex euribor3m = new Euribor3M(euriborTermStructure);

            Date todaysDate = new Date(23, Month.May, 2006);
            Settings.setEvaluationDate(todaysDate);

            Calendar calendar = euribor3m.fixingCalendar();
            int fixingDays = euribor3m.fixingDays();
            Date settlementDate = calendar.advance(todaysDate, fixingDays, TimeUnit.Days);

            Console.WriteLine("Today: " + todaysDate.DayOfWeek + ", " + todaysDate);
            Console.WriteLine("Settlement date: " + settlementDate.DayOfWeek + ", " + settlementDate);

            // 3 month term FRA quotes (index refers to monthsToStart)
            double[] threeMonthFraQuote = new double[10];

            threeMonthFraQuote[1]=0.030;
            threeMonthFraQuote[2]=0.031;
            threeMonthFraQuote[3]=0.032;
            threeMonthFraQuote[6]=0.033;
            threeMonthFraQuote[9]=0.034;

            /********************
             ***    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.

            // FRAs
            SimpleQuote fra1x4Rate = new SimpleQuote(threeMonthFraQuote[1]);
            SimpleQuote fra2x5Rate = new SimpleQuote(threeMonthFraQuote[2]);
            SimpleQuote fra3x6Rate = new SimpleQuote(threeMonthFraQuote[3]);
            SimpleQuote fra6x9Rate = new SimpleQuote(threeMonthFraQuote[6]);
            SimpleQuote fra9x12Rate = new SimpleQuote(threeMonthFraQuote[9]);

            RelinkableHandle<Quote> h1x4 = new RelinkableHandle<Quote>();  h1x4.linkTo(fra1x4Rate);
            RelinkableHandle<Quote> h2x5 = new RelinkableHandle<Quote>();  h2x5.linkTo(fra2x5Rate);
            RelinkableHandle<Quote> h3x6 = new RelinkableHandle<Quote>();  h3x6.linkTo(fra3x6Rate);
            RelinkableHandle<Quote> h6x9 = new RelinkableHandle<Quote>();  h6x9.linkTo(fra6x9Rate);
            RelinkableHandle<Quote> h9x12 = new RelinkableHandle<Quote>(); h9x12.linkTo(fra9x12Rate);

            /*********************
             ***  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.

            DayCounter fraDayCounter = euribor3m.dayCounter();
            BusinessDayConvention convention = euribor3m.businessDayConvention();
            bool endOfMonth = euribor3m.endOfMonth();

            RateHelper fra1x4 =  new FraRateHelper(h1x4, 1, 4,
                                                 fixingDays, calendar, convention,
                                                 endOfMonth, fraDayCounter);

            RateHelper fra2x5 = new FraRateHelper(h2x5, 2, 5,
                                                 fixingDays, calendar, convention,
                                                 endOfMonth, fraDayCounter);

            RateHelper fra3x6 = new FraRateHelper(h3x6, 3, 6,
                                                 fixingDays, calendar, convention,
                                                 endOfMonth, fraDayCounter);

            RateHelper fra6x9 = new FraRateHelper(h6x9, 6, 9,
                                                 fixingDays, calendar, convention,
                                                 endOfMonth, fraDayCounter);

            RateHelper fra9x12 = new FraRateHelper(h9x12, 9, 12,
                                                 fixingDays, calendar, convention,
                                                 endOfMonth, fraDayCounter);

            /*********************
             **  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 FRA curve
            List<RateHelper> fraInstruments = new List<RateHelper>();

            fraInstruments.Add(fra1x4);
            fraInstruments.Add(fra2x5);
            fraInstruments.Add(fra3x6);
            fraInstruments.Add(fra6x9);
            fraInstruments.Add(fra9x12);

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

            // Term structures used for pricing/discounting
            RelinkableHandle<YieldTermStructure> discountingTermStructure = new RelinkableHandle<YieldTermStructure>();
            discountingTermStructure.linkTo(fraTermStructure);

            /***********************
             ***  construct FRA's ***
             ***********************/

            Calendar fraCalendar = euribor3m.fixingCalendar();
            BusinessDayConvention fraBusinessDayConvention = euribor3m.businessDayConvention();
            Position.Type fraFwdType = Position.Type.Long;
            double fraNotional = 100.0;
            const int FraTermMonths = 3;
            int[] monthsToStart = new [] { 1, 2, 3, 6, 9 };

            euriborTermStructure.linkTo(fraTermStructure);

            Console.WriteLine("\nTest FRA construction, NPV calculation, and FRA purchase\n");

            int i;
            for (i=0; i<monthsToStart.Length; i++) {

                Date fraValueDate = fraCalendar.advance(
                                           settlementDate,monthsToStart[i], TimeUnit.Months,
                                           fraBusinessDayConvention);

                Date fraMaturityDate = fraCalendar.advance(
                                                fraValueDate, FraTermMonths, TimeUnit.Months,
                                                fraBusinessDayConvention);

                double fraStrikeRate = threeMonthFraQuote[monthsToStart[i]];

                ForwardRateAgreement myFRA = new ForwardRateAgreement(fraValueDate, fraMaturityDate,
                                           fraFwdType,fraStrikeRate,
                                           fraNotional, euribor3m,
                                           discountingTermStructure);

                Console.WriteLine("3m Term FRA, Months to Start: " + monthsToStart[i]);

                Console.WriteLine("strike FRA rate: {0:0.00%}", fraStrikeRate);
                Console.WriteLine("FRA 3m forward rate: {0:0.00%}", myFRA.forwardRate());
                Console.WriteLine("FRA market quote: {0:0.00%}", threeMonthFraQuote[monthsToStart[i]]);
                Console.WriteLine("FRA spot value: " + myFRA.spotValue());
                Console.WriteLine("FRA forward value: " + myFRA.forwardValue());
                Console.WriteLine("FRA implied Yield: {0:0.00%}",
                     myFRA.impliedYield(myFRA.spotValue(), myFRA.forwardValue(), settlementDate, Compounding.Simple, fraDayCounter));
                Console.WriteLine("market Zero Rate: {0:0.00%}",
                     discountingTermStructure.link.zeroRate(fraMaturityDate, fraDayCounter, Compounding.Simple));
                Console.WriteLine("FRA NPV [should be zero]: {0}\n", myFRA.NPV());
            }

            Console.WriteLine("\n");
            Console.WriteLine("Now take a 100 basis-point upward shift in FRA quotes and examine NPV\n");

            const double BpsShift = 0.01;

            threeMonthFraQuote[1]=0.030+BpsShift;
            threeMonthFraQuote[2]=0.031+BpsShift;
            threeMonthFraQuote[3]=0.032+BpsShift;
            threeMonthFraQuote[6]=0.033+BpsShift;
            threeMonthFraQuote[9]=0.034+BpsShift;

            fra1x4Rate.setValue(threeMonthFraQuote[1]);
            fra2x5Rate.setValue(threeMonthFraQuote[2]);
            fra3x6Rate.setValue(threeMonthFraQuote[3]);
            fra6x9Rate.setValue(threeMonthFraQuote[6]);
            fra9x12Rate.setValue(threeMonthFraQuote[9]);

            for (i=0; i<monthsToStart.Length; i++) {

                Date fraValueDate = fraCalendar.advance(
                                           settlementDate, monthsToStart[i], TimeUnit.Months,
                                           fraBusinessDayConvention);

                Date fraMaturityDate = fraCalendar.advance(
                                                fraValueDate, FraTermMonths, TimeUnit.Months,
                                                fraBusinessDayConvention);

                double fraStrikeRate = threeMonthFraQuote[monthsToStart[i]] - BpsShift;

                ForwardRateAgreement myFRA = new ForwardRateAgreement(fraValueDate, fraMaturityDate,
                                           fraFwdType, fraStrikeRate,
                                           fraNotional, euribor3m,
                                           discountingTermStructure);

                Console.WriteLine("3m Term FRA, 100 notional, Months to Start: " + monthsToStart[i]);
                Console.WriteLine("strike FRA rate: {0:0.00%}", fraStrikeRate);
                Console.WriteLine("FRA 3m forward rate: {0:0.00%}", myFRA.forwardRate());
                Console.WriteLine("FRA market quote: {0:0.00%}", threeMonthFraQuote[monthsToStart[i]]);
                Console.WriteLine("FRA spot value: " + myFRA.spotValue());
                Console.WriteLine("FRA forward value: " + myFRA.forwardValue());
                Console.WriteLine("FRA implied Yield: {0:0.00%}",
                     myFRA.impliedYield(myFRA.spotValue(), myFRA.forwardValue(), settlementDate, Compounding.Simple, fraDayCounter));
                Console.WriteLine("market Zero Rate: {0:0.00%}",
                     discountingTermStructure.link.zeroRate(fraMaturityDate, fraDayCounter, Compounding.Simple));
                Console.WriteLine("FRA NPV [should be positive]: {0}\n", myFRA.NPV());
            }

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

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