Beispiel #1
0
        public void testFairRate()
        {
            Calendar calendar = new TARGET();

             Date settlementDate = new Date(10, Month.Mar, 2010);

             /*********************
             * LOAN TO BE PRICED *
             **********************/

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

             // Principal leg
             Frequency pricipalLegFrequency = Frequency.Annual;

             int lenghtInMonths = 3;
             Loan.Type loanType = Loan.Type.Payer;

             Date maturity = settlementDate + new Period(lenghtInMonths, TimeUnit.Years);
             Schedule fixedSchedule = new Schedule(settlementDate, maturity, new Period(fixedLegFrequency),
                                  calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false);
             Schedule principalSchedule = new Schedule(settlementDate, maturity, new Period(pricipalLegFrequency),
                                  calendar, principalLegConvention, principalLegConvention, DateGeneration.Rule.Forward, false);
             Loan testLoan = new FixedLoan(loanType, nominal, fixedSchedule, fixedRate, fixedLegDayCounter,
                                     principalSchedule, principalLegConvention);
        }
Beispiel #2
0
        public void testAmortizingBond1()
        {
            // Input Values
             double faceValue = 40000;
             double marketValue = 43412;
             double couponRate = 0.06;
             Date issueDate = new Date(1, Month.January, 2001);
             Date maturirtyDate = new Date(1, Month.January, 2005);
             Date tradeDate = new Date(1, Month.January, 2004);
             Frequency paymentFrequency = Frequency.Semiannual;
             DayCounter dc = new Thirty360(Thirty360.Thirty360Convention.USA);

             // Build Bond
             AmortizingBond bond = BondFactory.makeAmortizingBond(faceValue, marketValue, couponRate,
            issueDate, maturirtyDate, tradeDate, paymentFrequency, dc, AmortizingMethod.EffectiveInterestRate);

             // Amortizing Yield ( Effective Rate )
             double y1 = bond.Yield();
             Assert.AreEqual(-0.0236402, y1, 0.001, "Amortizing Yield is different");

             // Amortized Cost at Date
             double Amort1 = bond.AmortizationValue(new Date(31, Month.August, 2004));
             Assert.AreEqual(41126.01, Amort1, 100, "Amortized Cost at 08/31/2004 is different");

             double Amort2 = bond.AmortizationValue(new Date(30, Month.September, 2004));
             Assert.AreEqual(40842.83, Amort2, 100, "Amortized Cost at 09/30/2004 is different");
        }
Beispiel #3
0
        public double getCPR(Date valDate)
        {
            Thirty360 dayCounter = new Thirty360();
             int d = dayCounter.dayCount(_startDate,valDate)/30 + 1;

             return (d <= 30 ? 0.06 * (d / 30d) : 0.06) * _multi;
        }
Beispiel #4
0
        public double getCPR(Date valDate)
        {
            Thirty360 dayCounter = new Thirty360();
            int       d          = dayCounter.dayCount(_startDate, valDate) / 30 + 1;

            return((d <= 30 ? 0.06 * (d / 30d) : 0.06) * _multi);
        }
Beispiel #5
0
 public CPILeg(Schedule schedule,
               ZeroInflationIndex index,
               double baseCPI,
               Period observationLag)
 {
     schedule_          = schedule;
     index_             = index;
     baseCPI_           = baseCPI;
     observationLag_    = observationLag;
     paymentDayCounter_ = new Thirty360();
     paymentAdjustment_ = BusinessDayConvention.ModifiedFollowing;
     fixingDays_        = new List <int>()
     {
         0
     };
     observationInterpolation_ = InterpolationType.AsIndex;
     subtractInflationNominal_ = true;
     spreads_ = new List <double>()
     {
         0
     };
 }
Beispiel #6
0
 public CPILeg(Schedule schedule,
             ZeroInflationIndex index,
             double baseCPI,
             Period observationLag)
 {
     schedule_ = schedule;
      index_ = index;
      baseCPI_ = baseCPI;
      observationLag_ = observationLag;
      paymentDayCounter_ = new Thirty360();
      paymentAdjustment_ = BusinessDayConvention.ModifiedFollowing;
      paymentCalendar_ = schedule.calendar();
      fixingDays_ = new List<int>() { 0 };
      observationInterpolation_ = InterpolationType.AsIndex;
      subtractInflationNominal_ = true;
      spreads_ = new List<double>() { 0 };
 }
Beispiel #7
0
        public void testMBSFixedBondCached()
        {
            // Test MBS Bond against cached values
             // from Fabozzi MBS Products Structuring and Analytical Techniques
             // Second Edition - WILEY ISBN 978-1-118-00469-2
             // pag 58,61,63

             #region Cached Values
             double[] OutstandingBalance = {400000000,399396651,398724866,397984841,397176808,396301034,395357823,394347512,393270474,
                                        392127117,390917882,389643247,388303720,386899847,385432204,383901402,382308084,380652925,
                                        378936631,377159941,375323622,373428474,371475324,369465030,367398478,365276580,363100276,
                                        360870534,358588346,356317966,354059336,351812393,349577078,347353331,345141093,342940305,
                                        340750907,338572840,336406048,334250471,332106052,329972733,327850458,325739170,323638812,
                                        321549327,319470661,317402757,315345560,313299014,311263066,309237660,307222743,305218260,
                                        303224158,301240383,299266882,297303602,295350492,293407497,291474567,289551650,287638694,
                                        285735647,283842460,281959081,280085459,278221545,276367288,274522640,272687550,270861969,
                                        269045848,267239140,265441794,263653764,261875001,260105457,258345086,256593839,254851671,
                                        253118533,251394381,249679167,247972846,246275371,244586698,242906782,241235576,239573036,
                                        237919118,236273777,234636970,233008651,231388779,229777308,228174197,226579401,224992878,
                                        223414586,221844483,220282525,218728672,217182881,215645111,214115321,212593469,211079516,
                                        209573419,208075140,206584637,205101871,203626802,202159389,200699595,199247379,197802703,
                                        196365528,194935815,193513525,192098622,190691066,189290820,187897846,186512107,185133566,
                                        183762186,182397929,181040759,179690640,178347535,177011409,175682225,174359947,173044541,
                                        171735971,170434201,169139197,167850924,166569347,165294431,164026143,162764449,161509314,
                                        160260704,159018587,157782929,156553696,155330855,154114374,152904220,151700360,150502762,
                                        149311394,148126224,146947219,145774348,144607580,143446882,142292225,141143576,140000905,
                                        138864182,137733374,136608453,135489388,134376148,133268704,132167026,131071083,129980848,
                                        128896290,127817380,126744089,125676388,124614249,123557642,122506539,121460913,120420734,
                                        119385975,118356608,117332605,116313939,115300582,114292506,113289685,112292092,111299699,
                                        110312480,109330408,108353458,107381601,106414813,105453067,104496337,103544598,102597823,
                                        101655987,100719066,99787032 ,98859862 ,97937530 ,97020012 ,96107282 ,95199317 ,94296091 ,
                                        93397579 ,92503759 ,91614606 ,90730095 ,89850202 ,88974905 ,88104180 ,87238002 ,86376348 ,
                                        85519196 ,84666522 ,83818303 ,82974516 ,82135138 ,81300146 ,80469519 ,79643233 ,78821266 ,
                                        78003597 ,77190202 ,76381060 ,75576149 ,74775447 ,73978932 ,73186584 ,72398380 ,71614300 ,
                                        70834321 ,70058424 ,69286586 ,68518787 ,67755007 ,66995224 ,66239418 ,65487568 ,64739655 ,
                                        63995657 ,63255556 ,62519330 ,61786959 ,61058425 ,60333707 ,59612785 ,58895641 ,58182253 ,
                                        57472605 ,56766675 ,56064445 ,55365895 ,54671008 ,53979764 ,53292143 ,52608129 ,51927702 ,
                                        51250843 ,50577534 ,49907758 ,49241495 ,48578728 ,47919438 ,47263609 ,46611221 ,45962258 ,
                                        45316701 ,44674534 ,44035738 ,43400297 ,42768192 ,42139408 ,41513926 ,40891731 ,40272804 ,
                                        39657129 ,39044690 ,38435469 ,37829450 ,37226618 ,36626954 ,36030443 ,35437069 ,34846816 ,
                                        34259667 ,33675607 ,33094619 ,32516689 ,31941799 ,31369935 ,30801080 ,30235220 ,29672339 ,
                                        29112422 ,28555453 ,28001417 ,27450300 ,26902085 ,26356759 ,25814305 ,25274711 ,24737960 ,
                                        24204038 ,23672931 ,23144624 ,22619103 ,22096353 ,21576360 ,21059110 ,20544589 ,20032782 ,
                                        19523677 ,19017258 ,18513512 ,18012425 ,17513984 ,17018175 ,16524985 ,16034399 ,15546405 ,
                                        15060989 ,14578138 ,14097838 ,13620077 ,13144842 ,12672119 ,12201896 ,11734160 ,11268897 ,
                                        10806096 ,10345743 ,9887826  ,9432332  ,8979249  ,8528565  ,8080267  ,7634342  ,7190780  ,
                                        6749566  ,6310691  ,5874140  ,5439903  ,5007967  ,4578321  ,4150953  ,3725851  ,3303003  ,
                                        2882398  ,2464024  ,2047870  ,1633925  ,1222176  ,812614   ,405225   };
             double[] Prepayments = { 200350,266975,333463,399780,465892,531764,597362,662652,727600,792172,856336,920057,983303,
                                  1046041,1108239,1169864,1230887,1291274,1350996,1410023,1468325,1525872,1582637,1638590,1693706,1747956,
                                  1801315,1853758,1842021,1830345,1818729,1807174,1795678,1784241,1772864,1761546,1750286,1739085,1727941,
                                  1716855,1705827,1694856,1683941,1673083,1662281,1651536,1640845,1630210,1619631,1609106,1598635,1588219,
                                  1577856,1567548,1557292,1547090,1536941,1526844,1516799,1506807,1496866,1486977,1477139,1467352,1457616,
                                  1447930,1438294,1428708,1419172,1409686,1400248,1390859,1381519,1372228,1362985,1353789,1344641,1335541,
                                  1326488,1317481,1308522,1299608,1290741,1281920,1273145,1264415,1255731,1247091,1238497,1229947,1221441,
                                  1212979,1204562,1196187,1187857,1179569,1171325,1163123,1154964,1146847,1138773,1130740,1122749,1114799,
                                  1106891,1099023,1091197,1083411,1075665,1067960,1060295,1052669,1045083,1037537,1030029,1022561,1015131,
                                  1007740,1000388,993073,985797,978558,971357,964193,957067,949977,942924,935908,928929,921985,915078,
                                  908207,901371,894571,887806,881077,874382,867722,861097,854506,847950,841427,834939,828484,822063,
                                  815675,809320,802998,796710,790454,784230,778039,771880,765753,759658,753595,747563,741563,735594,
                                  729656,723749,717872,712026,706211,700426,694671,688946,683251,677585,671949,666342,660765,655216,
                                  649697,644206,638744,633310,627904,622527,617178,611856,606563,601297,596058,590847,585662,580505,
                                  575375,570271,565194,560144,555120,550122,545150,540204,535284,530390,525521,520677,515859,511066,
                                  506298,501555,496836,492142,487473,482828,478207,473611,469038,464490,459965,455463,450986,446531,
                                  442100,437692,433307,428945,424606,420289,415995,411724,407474,403247,399042,394860,390698,386559,
                                  382442,378345,374271,370217,366185,362174,358184,354215,350266,346339,342431,338545,334678,330832,
                                  327006,323200,319414,315648,311901,308174,304467,300779,297110,293461,289831,286220,282627,279054,
                                  275499,271963,268445,264946,261466,258003,254559,251133,247724,244334,240961,237606,234269,230949,
                                  227647,224362,221094,217844,214610,211394,208194,205012,201845,198696,195563,192447,189347,186263,
                                  183195,180144,177109,174089,171086,168098,165126,162170,159229,156304,153394,150500,147620,144756,
                                  141907,139073,136254,133450,130660,127885,125125,122380,119648,116932,114229,111541,108867,106207,
                                  103561,100930,98312,95707,93117,90540,87977,85428,82891,80369,77859,75363,72880,70410,67954,65510,
                                  63079,60661,58256,55863,53483,51116,48761,46419,44089,41772,39466,37173,34893,32624,30367,28122,
                                  25889,23668,21459,19261,17075,14901,12738,10587,8447,6318,4201,2095,0};
             double[] NetInterest = { 1833333,1830568,1827489,1824097,1820394,1816380,1812057,1807426,1802490,1797249,1791707,1785865,
                                  1779725,1773291,1766564,1759548,1752245,1744659,1736793,1728650,1720233,1711547,1702595,1693381,
                                  1683910,1674184,1664210,1653990,1643530,1633124,1622772,1612473,1602228,1592036,1581897,1571810,
                                  1561775,1551792,1541861,1531981,1522153,1512375,1502648,1492971,1483345,1473768,1464241,1454763,
                                  1445334,1435954,1426622,1417339,1408104,1398917,1389777,1380685,1371640,1362642,1353690,1344784,
                                  1335925,1327112,1318344,1309622,1300945,1292312,1283725,1275182,1266683,1258229,1249818,1241451,
                                  1233127,1224846,1216608,1208413,1200260,1192150,1184082,1176055,1168070,1160127,1152224,1144363,
                                  1136542,1128762,1121022,1113323,1105663,1098043,1090463,1082921,1075419,1067956,1060532,1053146,
                                  1045798,1038489,1031217,1023984,1016787,1009628,1002506,995422,988373,981362,974387,967448,960545,
                                  953678,946846,940050,933290,926564,919873,913217,906596,900009,893456,886937,880452,874001,867583,
                                  861198,854847,848529,842243,835991,829770,823582,817426,811302,805210,799150,793121,787123,781157,
                                  775221,769317,763443,757599,751786,746004,740251,734528,728835,723172,717538,711933,706358,700811,
                                  695293,689804,684344,678912,673508,668132,662785,657465,652173,646908,641671,636461,631278,626122,
                                  620993,615891,610815,605766,600742,595746,590775,585830,580910,576017,571149,566306,561488,556696,
                                  551928,547186,542468,537774,533106,528461,523841,519244,514672,510124,505599,501098,496620,492166,
                                  487735,483327,478942,474579,470240,465923,461629,457357,453108,448880,444675,440492,436330,432190,
                                  428072,423976,419900,415846,411813,407802,403811,399841,395892,391963,388055,384167,380300,376453,
                                  372626,368819,365031,361264,357516,353788,350080,346391,342721,339070,335439,331826,328232,324657,
                                  321101,317564,314044,310544,307061,303597,300151,296723,293313,289921,286547,283190,279851,276529,
                                  273225,269938,266669,263416,260181,256962,253760,250575,247407,244256,241121,238002,234900,231814,
                                  228744,225690,222653,219631,216625,213635,210660,207702,204758,201830,198918,196021,193139,190272,
                                  187420,184584,181762,178955,176163,173385,170622,167874,165140,162420,159715,157023,154347,151684,
                                  149035,146400,143779,141172,138578,135998,133432,130879,128340,125814,123301,120802,118316,115842,
                                  113382,110935,108501,106080,103671,101275,98892,96521,94163,91817,89484,87162,84854,82557,80272,
                                  78000,75740,73491,71254,69030,66816,64615,62425,60247,58081,55925,53782,51649,49528,47418,45319,
                                  43232,41155,39089,37035,34991,32958,30936,28924,26923,24933,22953,20984,19025,17077,15139,13211,
                                  11293,9386,7489,5602,3724,1857};
             double[] ScheduledPrincipal = { 402998,404810,406562,408253,409882,411447,412949,414386,415758,417063,418300,419470,420571,
                                         421602,422563,423454,424273,425020,425694,426296,426824,427278,427657,427962,428192,428347,
                                         428427,428430,428358,428286,428213,428141,428069,427997,427924,427852,427780,427708,427636,
                                         427564,427491,427419,427347,427275,427203,427131,427059,426987,426915,426843,426771,426699,
                                         426627,426555,426483,426411,426339,426267,426195,426123,426051,425979,425907,425835,425764,
                                         425692,425620,425548,425476,425405,425333,425261,425189,425118,425046,424974,424902,424831,
                                         424759,424687,424616,424544,424472,424401,424329,424258,424186,424114,424043,423971,423900,
                                         423828,423757,423685,423614,423542,423471,423399,423328,423256,423185,423114,423042,422971,
                                         422900,422828,422757,422685,422614,422543,422472,422400,422329,422258,422187,422115,422044,
                                         421973,421902,421830,421759,421688,421617,421546,421475,421404,421332,421261,421190,421119,
                                         421048,420977,420906,420835,420764,420693,420622,420551,420480,420409,420338,420267,420196,
                                         420126,420055,419984,419913,419842,419771,419700,419630,419559,419488,419417,419346,419276,
                                         419205,419134,419064,418993,418922,418851,418781,418710,418639,418569,418498,418428,418357,
                                         418286,418216,418145,418075,418004,417934,417863,417793,417722,417652,417581,417511,417440,
                                         417370,417299,417229,417159,417088,417018,416947,416877,416807,416736,416666,416596,416526,
                                         416455,416385,416315,416245,416174,416104,416034,415964,415893,415823,415753,415683,415613,
                                         415543,415473,415403,415332,415262,415192,415122,415052,414982,414912,414842,414772,414702,
                                         414632,414562,414492,414422,414352,414282,414213,414143,414073,414003,413933,413863,413793,
                                         413724,413654,413584,413514,413444,413375,413305,413235,413165,413096,413026,412956,412887,
                                         412817,412747,412678,412608,412538,412469,412399,412330,412260,412191,412121,412051,411982,
                                         411912,411843,411773,411704,411635,411565,411496,411426,411357,411287,411218,411149,411079,
                                         411010,410941,410871,410802,410733,410663,410594,410525,410455,410386,410317,410248,410178,
                                         410109,410040,409971,409902,409833,409763,409694,409625,409556,409487,409418,409349,409280,
                                         409211,409142,409073,409003,408934,408865,408796,408728,408659,408590,408521,408452,408383,
                                         408314,408245,408176,408107,408038,407970,407901,407832,407763,407694,407625,407557,407488,
                                         407419,407350,407282,407213,407144,407076,407007,406938,406870,406801,406732,406664,406595,
                                         406526,406458,406389,406321,406252,406184,406115,406047,405978,405910,405841,405773,405704,
                                         405636,405567,405499,405430,405362,405294,405225};
             #endregion

             Date startDate = new Date(1, 2, 2007);
             Settings.setEvaluationDate(startDate);

             Period bondLength = new Period(358, TimeUnit.Months);
             Period originalLenght = new Period(360, TimeUnit.Months);
             DayCounter dCounter = new Thirty360();
             Frequency payFrequency = Frequency.Monthly;
             double amount = 400000000;
             double WACrate = 0.06;
             double PassThroughRate = 0.055;
             PSACurve psa100 = new PSACurve(startDate);

             var discountCurve = new Handle<YieldTermStructure>(Utilities.flatRate(startDate, new SimpleQuote(WACrate), new Thirty360()));

             // 400 Million Pass-Through with a 5.5% Pass-through Rate, a WAC of 6.0%, and a WAM of 358 Months,
             // Assuming 100% PSA
             MBSFixedRateBond bond = BondFactory.makeMBSFixedBond(startDate,
                                                               bondLength,
                                                               originalLenght,
                                                               dCounter,
                                                               payFrequency,
                                                               amount,
                                                               WACrate,
                                                               PassThroughRate,
                                                               psa100);

             IPricingEngine bondEngine = new DiscountingBondEngine(discountCurve);
             bond.setPricingEngine(bondEngine);

             // Calculate Monthly Expecting Cashflow
             List<CashFlow> cf = bond.expectedCashflows();

             // Outstanding Balance
             int i = 0;
             foreach (CashFlow c in cf)
             {
            if (c is QLNet.FixedRateCoupon)
            {
               FixedRateCoupon frc = c as FixedRateCoupon;
               Assert.AreEqual(OutstandingBalance[i], frc.nominal(), 1, "Outstanding Balance " + i++ + "is different");
            }
             }

             // Prepayments
             i = 0;
             foreach (CashFlow c in cf)
             {
            if (c is QLNet.VoluntaryPrepay)
            {
               Assert.AreEqual(Prepayments[i], c.amount(), 1, "Prepayments " + i++ + "is different");
            }
             }

             // Net Interest
             i = 0;
             foreach (CashFlow c in cf)
             {
            if (c is QLNet.FixedRateCoupon)
            {
               FixedRateCoupon frc = c as FixedRateCoupon;
               Assert.AreEqual(NetInterest[i], frc.amount(), 1, "Net Interest " + i++ + "is different");
            }
             }

             // Scheduled Principal
             i = 0;
             foreach (CashFlow c in cf)
             {
            if (c is QLNet.AmortizingPayment)
            {
               Assert.AreEqual(ScheduledPrincipal[i], c.amount(), 1, "Scheduled Principal " + i++ + "is different");
            }
             }

             // Monthly Yield
             Assert.AreEqual(0.00458333333333381, bond.MonthlyYield(), 0.000000001, "MonthlyYield is different");

             // Bond Equivalent Yield
             Assert.AreEqual(0.0556, bond.BondEquivalentYield(), 0.0001, " Bond Equivalent Yield is different");
        }
Beispiel #8
0
        public void testAmortizingBond2()
        {
            // Par – 500,000
             // Cost – 471,444
             // Coupon Rate - .0520
             // Issue Date – March 15 1999
             // Maturity Date – May 15 2028
             // Trade Date – December 31 2007
             // Payment Frequency - Semi-Annual; May/Nov
             // Day Count Method - 30/360

             // Input Values
             double faceValue = 500000;
             double marketValue = 471444;
             double couponRate = 0.0520;
             Date issueDate = new Date(15, Month.March, 1999);
             Date maturirtyDate = new Date(15, Month.May, 2028);
             Date tradeDate = new Date(31, Month.December, 2007);
             Frequency paymentFrequency = Frequency.Semiannual;
             DayCounter dc = new Thirty360(Thirty360.Thirty360Convention.USA);

             // Build Bond
             AmortizingBond bond = BondFactory.makeAmortizingBond(faceValue, marketValue, couponRate,
            issueDate, maturirtyDate, tradeDate, paymentFrequency, dc, AmortizingMethod.EffectiveInterestRate);

             // Amortizing Yield ( Effective Rate )
             double y1 = bond.Yield();
             Assert.AreEqual(0.0575649, y1, 0.001, "Amortizing Yield is different");

             // Amortized Cost at Date
             double Amort1 = bond.AmortizationValue(new Date(30, Month.November, 2012));
             Assert.AreEqual(475698.12, Amort1, 100, "Amortized Cost at 11/30/2012 is different");

             double Amort2 = bond.AmortizationValue(new Date(30, Month.December, 2012));
             Assert.AreEqual(475779.55, Amort1, 100, "Amortized Cost at 12/30/2012 is different");
        }
Beispiel #9
0
        public void testYield()
        {
            //"Testing consistency of bond price/yield calculation...");

             CommonVars vars = new CommonVars();

             double tolerance = 1.0e-7;
             int maxEvaluations = 100;

             int[] issueMonths = new int[] { -24, -18, -12, -6, 0, 6, 12, 18, 24 };
             int[] lengths = new int[] { 3, 5, 10, 15, 20 };
             int settlementDays = 3;
             double[] coupons = new double[] { 0.02, 0.05, 0.08 };
             Frequency[] frequencies = new Frequency[] { Frequency.Semiannual, Frequency.Annual };
             DayCounter bondDayCount = new Thirty360();
             BusinessDayConvention accrualConvention = BusinessDayConvention.Unadjusted;
             BusinessDayConvention paymentConvention = BusinessDayConvention.ModifiedFollowing;
             double redemption = 100.0;

             double[] yields = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 };
             Compounding[] compounding = new Compounding[] { Compounding.Compounded, Compounding.Continuous };

             for (int i = 0; i < issueMonths.Length; i++)
             {
            for (int j = 0; j < lengths.Length; j++)
            {
               for (int k = 0; k < coupons.Length; k++)
               {
                  for (int l = 0; l < frequencies.Length; l++)
                  {
                     for (int n = 0; n < compounding.Length; n++)
                     {

                        Date dated = vars.calendar.advance(vars.today, issueMonths[i], TimeUnit.Months);
                        Date issue = dated;
                        Date maturity = vars.calendar.advance(issue, lengths[j], TimeUnit.Years);

                        Schedule sch = new Schedule(dated, maturity, new Period(frequencies[l]), vars.calendar,
                                                    accrualConvention, accrualConvention, DateGeneration.Rule.Backward, false);

                        FixedRateBond bond = new FixedRateBond(settlementDays, vars.faceAmount, sch,
                                                               new List<double>() { coupons[k] },
                                                               bondDayCount, paymentConvention,
                                                               redemption, issue);

                        for (int m = 0; m < yields.Length; m++)
                        {

                           double price = bond.cleanPrice(yields[m], bondDayCount, compounding[n], frequencies[l]);
                           double calculated = bond.yield(price, bondDayCount, compounding[n], frequencies[l], null,
                                                          tolerance, maxEvaluations);

                           if (Math.Abs(yields[m] - calculated) > tolerance)
                           {
                              // the difference might not matter
                              double price2 = bond.cleanPrice(calculated, bondDayCount, compounding[n], frequencies[l]);
                              if (Math.Abs(price - price2) / price > tolerance)
                              {
                                 Assert.Fail("yield recalculation failed:\n"
                                     + "    issue:     " + issue + "\n"
                                     + "    maturity:  " + maturity + "\n"
                                     + "    coupon:    " + coupons[k] + "\n"
                                     + "    frequency: " + frequencies[l] + "\n\n"
                                     + "    yield:  " + yields[m] + " "
                                     + (compounding[n] == Compounding.Compounded ? "compounded" : "continuous") + "\n"
                                     + "    price:  " + price + "\n"
                                     + "    yield': " + calculated + "\n"
                                     + "    price': " + price2);
                              }
                           }
                        }
                     }
                  }
               }
            }
             }
        }
Beispiel #10
0
        public void testAmortizingFixedBond()
        {
            Date startDate = new Date(2, 1, 2007);
             Settings.setEvaluationDate(startDate);

             Period bondLength = new Period(12, TimeUnit.Months);
             DayCounter dCounter = new Thirty360();
             Frequency payFrequency = Frequency.Monthly;
             double amount = 400000000;
             double rate = 0.06;
             var discountCurve = new Handle<YieldTermStructure>(Utilities.flatRate(startDate, new SimpleQuote(rate), new Thirty360()));

             AmortizingFixedRateBond bond = BondFactory.makeAmortizingFixedBond(startDate, bondLength, dCounter, payFrequency, amount, rate);
             IPricingEngine bondEngine = new DiscountingBondEngine(discountCurve);
             bond.setPricingEngine(bondEngine);

             // cached values
             int totCashflow = 24;
             int totNotionals = 13;
             double PVDifference = 13118862.59;
             double[] notionals = {400000000,367573428,334984723,302233075,269317669,236237685,202992302,169580691,136002023,
                               102255461,68340166,34255295,0 };

             // test total cashflow count
             Assert.AreEqual(bond.cashflows().Count, totCashflow, "Cashflow size different");

             // test notional cashflow count
             Assert.AreEqual(bond.notionals().Count, totNotionals, "Notionals size different");

             // test notional amortization values
             for (int i = 0; i < totNotionals; i++)
             {
            Assert.AreEqual(bond.notionals()[i], notionals[i], 1, "Notionals " + i + "is different");
             }

             // test PV difference
             double cash = bond.CASH();
             Assert.AreEqual(cash - amount, PVDifference, 0.1, "PV Difference wrong");
        }
        static void Main(string[] args)
        {

            DateTime timer = DateTime.Now;

            Date todaysDate = new Date(15, 2, 2002);
            Calendar calendar = new TARGET();
            Date settlementDate = new Date(19, 2, 2002);
            Settings.setEvaluationDate(todaysDate);

            // flat yield term structure impling 1x5 swap at 5%
            Quote flatRate = new SimpleQuote(0.04875825);
            Handle<YieldTermStructure> rhTermStructure = new Handle<YieldTermStructure>(
                          new FlatForward(settlementDate, new Handle<Quote>(flatRate),
                                          new Actual365Fixed()));

            // Define the ATM/OTM/ITM swaps
            Frequency fixedLegFrequency = Frequency.Annual;
            BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted;
            BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
            Frequency floatingLegFrequency = Frequency.Semiannual;
            VanillaSwap.Type type = VanillaSwap.Type.Payer;
            double dummyFixedRate = 0.03;
            IborIndex indexSixMonths = new Euribor6M(rhTermStructure);

            Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years,
                                              floatingLegConvention);
            Date maturity = calendar.advance(startDate, 5, TimeUnit.Years,
                                             floatingLegConvention);
            Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(fixedLegFrequency),
                                                    calendar, fixedLegConvention, fixedLegConvention,
                                                    DateGeneration.Rule.Forward, false);
            Schedule floatSchedule = new Schedule(startDate, maturity, new Period(floatingLegFrequency),
                                                    calendar, floatingLegConvention, floatingLegConvention,
                                                    DateGeneration.Rule.Forward, false);

            VanillaSwap swap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, dummyFixedRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            swap.setPricingEngine(new DiscountingSwapEngine(rhTermStructure));
            double fixedAtmRate = swap.fairRate();
            double fixedOtmRate = fixedAtmRate * 1.2;
            double fixedItmRate = fixedAtmRate * 0.8;

            VanillaSwap atmSwap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, fixedAtmRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            VanillaSwap otmSwap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, fixedOtmRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            VanillaSwap itmSwap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, fixedItmRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());

            // defining the swaptions to be used in model calibration
            List<Period> swaptionMaturities = new List<Period>(5);
            swaptionMaturities.Add(new Period(1, TimeUnit.Years));
            swaptionMaturities.Add(new Period(2, TimeUnit.Years));
            swaptionMaturities.Add(new Period(3, TimeUnit.Years));
            swaptionMaturities.Add(new Period(4, TimeUnit.Years));
            swaptionMaturities.Add(new Period(5, TimeUnit.Years));

            List<CalibrationHelper> swaptions = new List<CalibrationHelper>();

            // List of times that have to be included in the timegrid
            List<double> times = new List<double>();

            for (int i = 0; i < NumRows; i++)
            {
                int j = NumCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1
                int k = i * NumCols + j;
                Quote vol = new SimpleQuote(SwaptionVols[k]);
                swaptions.Add(new SwaptionHelper(swaptionMaturities[i],
                                   new Period(SwapLenghts[j], TimeUnit.Years),
                                   new Handle<Quote>(vol),
                                   indexSixMonths,
                                   indexSixMonths.tenor(),
                                   indexSixMonths.dayCounter(),
                                   indexSixMonths.dayCounter(),
                                   rhTermStructure, false));
                swaptions.Last().addTimesTo(times);
            }

            // Building time-grid
            TimeGrid grid = new TimeGrid(times, 30);


            // defining the models
            G2 modelG2 = new G2(rhTermStructure);
            HullWhite modelHw = new HullWhite(rhTermStructure);
            HullWhite modelHw2 = new HullWhite(rhTermStructure);
            BlackKarasinski modelBk = new BlackKarasinski(rhTermStructure);


            // model calibrations

            Console.WriteLine("G2 (analytic formulae) calibration");
            for (int i = 0; i < swaptions.Count; i++)
                swaptions[i].setPricingEngine(new G2SwaptionEngine(modelG2, 6.0, 16));
            CalibrateModel(modelG2, swaptions);
            Console.WriteLine("calibrated to:\n" +
                                "a     = {0:0.000000}, " +
                                "sigma = {1:0.0000000}\n" +
                                "b     = {2:0.000000}, " +
                                "eta   = {3:0.0000000}\n" +
                                "rho   = {4:0.00000}\n",
                                modelG2.parameters()[0],
                                modelG2.parameters()[1],
                                modelG2.parameters()[2],
                                modelG2.parameters()[3],
                                modelG2.parameters()[4]);

            Console.WriteLine("Hull-White (analytic formulae) calibration");
            for (int i = 0; i < swaptions.Count; i++)
                swaptions[i].setPricingEngine(new JamshidianSwaptionEngine(modelHw));
            CalibrateModel(modelHw, swaptions);
            Console.WriteLine("calibrated to:\n" +
                              "a = {0:0.000000}, " +
                              "sigma = {1:0.0000000}\n",
                              modelHw.parameters()[0],
                              modelHw.parameters()[1]);

            Console.WriteLine("Hull-White (numerical) calibration");
            for (int i = 0; i < swaptions.Count(); i++)
                swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelHw2, grid));
            CalibrateModel(modelHw2, swaptions);
            Console.WriteLine("calibrated to:\n" +
                              "a = {0:0.000000}, " +
                              "sigma = {1:0.0000000}\n",
                              modelHw2.parameters()[0],
                              modelHw2.parameters()[1]);

            Console.WriteLine("Black-Karasinski (numerical) calibration");
            for (int i = 0; i < swaptions.Count; i++)
                swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelBk, grid));
            CalibrateModel(modelBk, swaptions);
            Console.WriteLine("calibrated to:\n" +
                              "a = {0:0.000000}, " +
                              "sigma = {1:0.00000}\n",
                              modelBk.parameters()[0],
                              modelBk.parameters()[1]);


            // ATM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption "
                              + "struck at {0:0.00000 %} (ATM)",
                              fixedAtmRate);

            List<Date> bermudanDates = new List<Date>();
            List<CashFlow> leg = swap.fixedLeg();
            for (int i = 0; i < leg.Count; i++)
            {
                Coupon coupon = (Coupon)leg[i];
                bermudanDates.Add(coupon.accrualStartDate());
            }

            Exercise bermudanExercise = new BermudanExercise(bermudanDates);

            Swaption bermudanSwaption = new Swaption(atmSwap, bermudanExercise);

            // Do the pricing for each model

            // G2 price the European swaption here, it should switch to bermudan
            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50));
            Console.WriteLine("G2:       {0:0.00}", bermudanSwaption.NPV());

            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50));
            Console.WriteLine("HW:       {0:0.000}", bermudanSwaption.NPV());

            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50));
            Console.WriteLine("HW (num): {0:0.000}", bermudanSwaption.NPV());

            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50));
            Console.WriteLine("BK:       {0:0.000}", bermudanSwaption.NPV());


            // OTM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption "
                              + "struck at {0:0.00000 %} (OTM)",
                              fixedOtmRate);

            Swaption otmBermudanSwaption = new Swaption(otmSwap, bermudanExercise);

            // Do the pricing for each model
            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50));
            Console.WriteLine("G2:       {0:0.0000}", otmBermudanSwaption.NPV());

            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50));
            Console.WriteLine("HW:       {0:0.0000}", otmBermudanSwaption.NPV());

            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50));
            Console.WriteLine("HW (num): {0:0.000}", otmBermudanSwaption.NPV());

            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50));
            Console.WriteLine("BK:       {0:0.0000}", otmBermudanSwaption.NPV());

            // ITM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption "
                              + "struck at {0:0.00000 %} (ITM)",
                              fixedItmRate);

            Swaption itmBermudanSwaption = new Swaption(itmSwap, bermudanExercise);

            // Do the pricing for each model
            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50));
            Console.WriteLine("G2:       {0:0.000}", itmBermudanSwaption.NPV());

            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50));
            Console.WriteLine("HW:       {0:0.000}", itmBermudanSwaption.NPV());

            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50));
            Console.WriteLine("HW (num): {0:0.000}", itmBermudanSwaption.NPV());

            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50));
            Console.WriteLine("BK:       {0:0.000}", itmBermudanSwaption.NPV());


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

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Beispiel #12
0
        public void testCachedMarketValue()
        {
            // Testing credit-default swap against cached market values...

            SavedSettings backup = new SavedSettings();

            Settings.setEvaluationDate(new Date(9,Month.June,2006));
            Date evalDate = Settings.evaluationDate();
            Calendar calendar = new UnitedStates();

            List<Date> discountDates = new List<Date>();
            discountDates.Add(evalDate);
            discountDates.Add(calendar.advance(evalDate, 1, TimeUnit.Weeks,  BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 1, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 2, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 3, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 6, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate,12, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 2, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 3, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 4, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 5, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 6, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 7, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 8, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate, 9, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate,10, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            discountDates.Add(calendar.advance(evalDate,15, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));

            List<double> dfs = new List<double>();
            dfs.Add(1.0);
            dfs.Add(0.9990151375768731);
            dfs.Add(0.99570502636871183);
            dfs.Add(0.99118260474528685);
            dfs.Add(0.98661167950906203);
            dfs.Add(0.9732592953359388 );
            dfs.Add(0.94724424481038083);
            dfs.Add(0.89844996737120875 );
            dfs.Add(0.85216647839921411 );
            dfs.Add(0.80775477692556874 );
            dfs.Add(0.76517289234200347 );
            dfs.Add(0.72401019553182933 );
            dfs.Add(0.68503909569219212 );
            dfs.Add(0.64797499814013748 );
            dfs.Add(0.61263171936255534 );
            dfs.Add(0.5791942350748791  );
            dfs.Add(0.43518868769953606 );

            DayCounter curveDayCounter = new Actual360();

            RelinkableHandle<YieldTermStructure> discountCurve = new RelinkableHandle<YieldTermStructure>();
            discountCurve.linkTo( new InterpolatedDiscountCurve<LogLinear>( discountDates, dfs, curveDayCounter,null,null,null,new LogLinear() ) );

            DayCounter dayCounter = new Thirty360();
            List<Date> dates = new List<Date>();
            dates.Add(evalDate);
            dates.Add(calendar.advance(evalDate, 6, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate, 1, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate, 2, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate, 3, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate, 4, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate, 5, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate, 7, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));
            dates.Add(calendar.advance(evalDate,10, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing));

            List<double> defaultProbabilities = new List<double>();
            defaultProbabilities.Add(0.0000);
            defaultProbabilities.Add(0.0047);
            defaultProbabilities.Add(0.0093);
            defaultProbabilities.Add(0.0286);
            defaultProbabilities.Add(0.0619);
            defaultProbabilities.Add(0.0953);
            defaultProbabilities.Add(0.1508);
            defaultProbabilities.Add(0.2288);
            defaultProbabilities.Add(0.3666);

            List<double> hazardRates = new List<double>();
            hazardRates.Add(0.0);
            for (int i=1; i<dates.Count; ++i)
            {
                double t1 = dayCounter.yearFraction(dates[0], dates[i-1]);
                double t2 = dayCounter.yearFraction(dates[0], dates[i]);
                double S1 = 1.0 - defaultProbabilities[i-1];
                double S2 = 1.0 - defaultProbabilities[i];
                hazardRates.Add(Math.Log(S1/S2)/(t2-t1));
            }

            RelinkableHandle<DefaultProbabilityTermStructure> piecewiseFlatHazardRate = new RelinkableHandle<DefaultProbabilityTermStructure>();
            piecewiseFlatHazardRate.linkTo(new InterpolatedHazardRateCurve<BackwardFlat>(dates,hazardRates,new Thirty360()));

            // Testing credit default swap

            // Build the schedule
            Date issueDate = new Date(20, Month.March, 2006);
            Date maturity = new Date(20, Month.June, 2013);
            Frequency cdsFrequency = Frequency.Semiannual;
            BusinessDayConvention cdsConvention = BusinessDayConvention.ModifiedFollowing;

            Schedule schedule = new Schedule(issueDate, maturity, new Period(cdsFrequency), calendar,
                                                   cdsConvention, cdsConvention,
                                                   DateGeneration.Rule.Forward, false);

            // Build the CDS
            double recoveryRate = 0.25;
            double fixedRate=0.0224;
            DayCounter dayCount= new Actual360();
            double cdsNotional=100.0;

            CreditDefaultSwap cds = new CreditDefaultSwap(Protection.Side.Seller, cdsNotional, fixedRate,
                                        schedule, cdsConvention, dayCount, true, true);
            cds.setPricingEngine(new MidPointCdsEngine(piecewiseFlatHazardRate, recoveryRate,discountCurve));

            double calculatedNpv = cds.NPV();
            double calculatedFairRate = cds.fairSpread();

            double npv = -1.364048777;        // from Bloomberg we have 98.15598868 - 100.00;
            double fairRate =  0.0248429452; // from Bloomberg we have 0.0258378;

            double tolerance = 1e-9;

            if (Math.Abs(npv - calculatedNpv) > tolerance)
                Assert.Fail(
                    "Failed to reproduce the npv for the given credit-default swap\n"
                    + "    computed NPV:  " + calculatedNpv + "\n"
                    + "    Given NPV:     " + npv);

            if ( Math.Abs( fairRate - calculatedFairRate ) > tolerance )
                Assert.Fail( "Failed to reproduce the fair rate for the given credit-default swap\n"
                    + "    computed fair rate:  " + calculatedFairRate + "\n"
                    + "    Given fair rate:     " + fairRate );
        }
Beispiel #13
0
		static void Main(string[] args) {
			DateTime timer = DateTime.Now;

			Date repoSettlementDate = new Date(14,Month.February,2000);;
			Date repoDeliveryDate = new Date(15,Month.August,2000);
			double repoRate = 0.05;
			DayCounter repoDayCountConvention = new Actual360();
			int repoSettlementDays = 0;
			Compounding repoCompounding = Compounding.Simple;
			Frequency repoCompoundFreq = Frequency.Annual;

			// assume a ten year bond- this is irrelevant
			Date bondIssueDate = new Date(15,Month.September,1995);
			Date bondDatedDate = new Date(15,Month.September,1995);
			Date bondMaturityDate = new Date(15,Month.September,2005);
			double bondCoupon = 0.08;
			Frequency bondCouponFrequency = Frequency.Semiannual;
			// unknown what calendar fincad is using
			Calendar bondCalendar = new NullCalendar();
			DayCounter bondDayCountConvention = new Thirty360(Thirty360.Thirty360Convention.BondBasis);
			// unknown what fincad is using. this may affect accrued calculation
			int bondSettlementDays = 0;
			BusinessDayConvention bondBusinessDayConvention = BusinessDayConvention.Unadjusted;
			double bondCleanPrice = 89.97693786;
			double bondRedemption = 100.0;
			double faceAmount = 100.0;


			Settings.setEvaluationDate(repoSettlementDate);

			RelinkableHandle<YieldTermStructure> bondCurve = new RelinkableHandle<YieldTermStructure>();
			bondCurve.linkTo(new FlatForward(repoSettlementDate,
											   .01, // dummy rate
											   bondDayCountConvention,
											   Compounding.Compounded,
											   bondCouponFrequency));

			/*
			boost::shared_ptr<FixedRateBond> bond(
						   new FixedRateBond(faceAmount,
											 bondIssueDate,
											 bondDatedDate,
											 bondMaturityDate,
											 bondSettlementDays,
											 std::vector<Rate>(1,bondCoupon),
											 bondCouponFrequency,
											 bondCalendar,
											 bondDayCountConvention,
											 bondBusinessDayConvention,
											 bondBusinessDayConvention,
											 bondRedemption,
											 bondCurve));
			*/

			Schedule bondSchedule = new Schedule(bondDatedDate, bondMaturityDate,
								  new Period(bondCouponFrequency),
								  bondCalendar,bondBusinessDayConvention,
								  bondBusinessDayConvention,
								  DateGeneration.Rule.Backward,false);
			FixedRateBond bond = new FixedRateBond(bondSettlementDays,
											 faceAmount,
											 bondSchedule,
											 new List<double>() { bondCoupon },
											 bondDayCountConvention,
											 bondBusinessDayConvention,
											 bondRedemption,
											 bondIssueDate);
			bond.setPricingEngine(new DiscountingBondEngine(bondCurve));

			bondCurve.linkTo(new FlatForward(repoSettlementDate,
									   bond.yield(bondCleanPrice,
												   bondDayCountConvention,
												   Compounding.Compounded,
												   bondCouponFrequency),
									   bondDayCountConvention,
									   Compounding.Compounded,
									   bondCouponFrequency));

			Position.Type fwdType = Position.Type.Long;
			double dummyStrike = 91.5745;

			RelinkableHandle<YieldTermStructure> repoCurve = new RelinkableHandle<YieldTermStructure>();
			repoCurve.linkTo(new FlatForward(repoSettlementDate,
											   repoRate,
											   repoDayCountConvention,
											   repoCompounding,
											   repoCompoundFreq));


			FixedRateBondForward bondFwd = new FixedRateBondForward(repoSettlementDate,
										 repoDeliveryDate,
										 fwdType,
										 dummyStrike,
										 repoSettlementDays,
										 repoDayCountConvention,
										 bondCalendar,
										 bondBusinessDayConvention,
										 bond,
										 repoCurve,
										 repoCurve);


			Console.WriteLine("Underlying bond clean price: " + bond.cleanPrice());
			Console.WriteLine("Underlying bond dirty price: " + bond.dirtyPrice());
			Console.WriteLine("Underlying bond accrued at settlement: "
				 + bond.accruedAmount(repoSettlementDate));
			Console.WriteLine("Underlying bond accrued at delivery:   "
				 + bond.accruedAmount(repoDeliveryDate));
			Console.WriteLine("Underlying bond spot income: "
				 + bondFwd.spotIncome(repoCurve));
			Console.WriteLine("Underlying bond fwd income:  "
				 + bondFwd.spotIncome(repoCurve)/
					repoCurve.link.discount(repoDeliveryDate));
			Console.WriteLine("Repo strike: " + dummyStrike);
			Console.WriteLine("Repo NPV:    " + bondFwd.NPV());
			Console.WriteLine("Repo clean forward price: "
				 + bondFwd.cleanForwardPrice());
			Console.WriteLine("Repo dirty forward price: "
				 + bondFwd.forwardPrice());
			Console.WriteLine("Repo implied yield: "
				 + bondFwd.impliedYield(bond.dirtyPrice(),
										 dummyStrike,
										 repoSettlementDate,
										 repoCompounding,
										 repoDayCountConvention));
			Console.WriteLine("Market repo rate:   "
				 + repoCurve.link.zeroRate(repoDeliveryDate,
										repoDayCountConvention,
										repoCompounding,
										repoCompoundFreq));

			Console.WriteLine("\nCompare with example given at \n"
				 + "http://www.fincad.com/support/developerFunc/mathref/BFWD.htm");
			Console.WriteLine("Clean forward price = 88.2408");
			Console.WriteLine("\nIn that example, it is unknown what bond calendar they are\n"
				 + "using, as well as settlement Days. For that reason, I have\n"
				 + "made the simplest possible assumptions here: NullCalendar\n"
				 + "and 0 settlement days.\n");


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

      Console.Write("Press any key to continue ...");
      Console.ReadKey();
		}
Beispiel #14
0
        public VanillaSwap value()
        {
            Date startDate;

            if (effectiveDate_ != null)
            {
                startDate = effectiveDate_;
            }
            else
            {
                //int fixingDays = iborIndex_.fixingDays();
                Date refDate = Settings.evaluationDate();
                // if the evaluation date is not a business day
                // then move to the next business day
                refDate = floatCalendar_.adjust(refDate);
                Date spotDate = floatCalendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days));
                startDate = spotDate + forwardStart_;
                if (forwardStart_.length() < 0)
                {
                    startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Preceding);
                }
                else
                {
                    startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Following);
                }
            }

            Date endDate = terminationDate_;

            if (endDate == null)
            {
                if (floatEndOfMonth_)
                {
                    endDate = floatCalendar_.advance(startDate,
                                                     swapTenor_,
                                                     BusinessDayConvention.ModifiedFollowing,
                                                     floatEndOfMonth_);
                }
                else
                {
                    endDate = startDate + swapTenor_;
                }
            }

            Currency curr       = iborIndex_.currency();
            Period   fixedTenor = null;

            if (fixedTenor_ != null)
            {
                fixedTenor = fixedTenor_;
            }
            else
            {
                if ((curr == new EURCurrency()) ||
                    (curr == new USDCurrency()) ||
                    (curr == new CHFCurrency()) ||
                    (curr == new SEKCurrency()) ||
                    (curr == new GBPCurrency() && swapTenor_ <= new Period(1, TimeUnit.Years)))
                {
                    fixedTenor = new Period(1, TimeUnit.Years);
                }
                else if ((curr == new GBPCurrency() && swapTenor_ > new Period(1, TimeUnit.Years) ||
                          (curr == new JPYCurrency()) ||
                          (curr == new AUDCurrency() && swapTenor_ >= new Period(4, TimeUnit.Years))))
                {
                    fixedTenor = new Period(6, TimeUnit.Months);
                }
                else if ((curr == new HKDCurrency() ||
                          (curr == new AUDCurrency() && swapTenor_ < new Period(4, TimeUnit.Years))))
                {
                    fixedTenor = new Period(3, TimeUnit.Months);
                }
                else
                {
                    Utils.QL_FAIL("unknown fixed leg default tenor for " + curr);
                }
            }

            Schedule fixedSchedule = new Schedule(startDate, endDate,
                                                  fixedTenor, fixedCalendar_,
                                                  fixedConvention_, fixedTerminationDateConvention_,
                                                  fixedRule_, fixedEndOfMonth_,
                                                  fixedFirstDate_, fixedNextToLastDate_);

            Schedule floatSchedule = new Schedule(startDate, endDate,
                                                  floatTenor_, floatCalendar_,
                                                  floatConvention_, floatTerminationDateConvention_,
                                                  floatRule_, floatEndOfMonth_,
                                                  floatFirstDate_, floatNextToLastDate_);

            DayCounter fixedDayCount = null;

            if (fixedDayCount_ != null)
            {
                fixedDayCount = fixedDayCount_;
            }
            else
            {
                if (curr == new USDCurrency())
                {
                    fixedDayCount = new Actual360();
                }
                else if (curr == new EURCurrency() || curr == new CHFCurrency() || curr == new SEKCurrency())
                {
                    fixedDayCount = new Thirty360(Thirty360.Thirty360Convention.BondBasis);
                }
                else if (curr == new GBPCurrency() || curr == new JPYCurrency() || curr == new AUDCurrency() ||
                         curr == new HKDCurrency())
                {
                    fixedDayCount = new Actual365Fixed();
                }
                else
                {
                    Utils.QL_FAIL("unknown fixed leg day counter for " + curr);
                }
            }

            double?usedFixedRate = fixedRate_;

            if (fixedRate_ == null)
            {
                VanillaSwap temp = new VanillaSwap(type_, nominal_, fixedSchedule, 0.0, fixedDayCount,
                                                   floatSchedule, iborIndex_, floatSpread_, floatDayCount_);

                if (engine_ == null)
                {
                    Handle <YieldTermStructure> disc = iborIndex_.forwardingTermStructure();
                    Utils.QL_REQUIRE(!disc.empty(), () =>
                                     "null term structure set to this instance of " + iborIndex_.name());
                    bool           includeSettlementDateFlows = false;
                    IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                    temp.setPricingEngine(engine);
                }
                else
                {
                    temp.setPricingEngine(engine_);
                }

                usedFixedRate = temp.fairRate();
            }

            VanillaSwap swap = new VanillaSwap(type_, nominal_, fixedSchedule, usedFixedRate.Value, fixedDayCount,
                                               floatSchedule, iborIndex_, floatSpread_, floatDayCount_);

            if (engine_ == null)
            {
                Handle <YieldTermStructure> disc          = iborIndex_.forwardingTermStructure();
                bool           includeSettlementDateFlows = false;
                IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                swap.setPricingEngine(engine);
            }
            else
            {
                swap.setPricingEngine(engine_);
            }

            return(swap);
        }
Beispiel #15
0
        public void testZeroTermStructure()
        {
            // Testing zero inflation term structure...

            SavedSettings backup = new SavedSettings();

            // try the Zero UK
            Calendar calendar = new UnitedKingdom();
            BusinessDayConvention bdc = BusinessDayConvention.ModifiedFollowing;
            Date evaluationDate = new Date( 13, Month.August, 2007 );
            evaluationDate = calendar.adjust( evaluationDate );
            Settings.setEvaluationDate( evaluationDate );

            // fixing data
            Date from = new Date( 1, Month.January, 2005 );
            Date to = new Date( 13, Month.August, 2007 );
            Schedule rpiSchedule = new MakeSchedule().from( from ).to( to )
                                          .withTenor( new Period( 1, TimeUnit.Months ) )
                                          .withCalendar( new UnitedKingdom() )
                                          .withConvention( BusinessDayConvention.ModifiedFollowing )
                                          .value();

            double[] fixData = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,
                              192.2, 192.2, 192.6, 193.1, 193.3, 193.6,
                              194.1, 193.4, 194.2, 195.0, 196.5, 197.7,
                              198.5, 198.5, 199.2, 200.1, 200.4, 201.1,
                              202.7, 201.6, 203.1, 204.4, 205.4, 206.2,
                              207.3, 206.1,  -999.0 };

            RelinkableHandle<ZeroInflationTermStructure> hz = new RelinkableHandle<ZeroInflationTermStructure>();
            bool interp = false;
            UKRPI iiUKRPI = new UKRPI( interp, hz );
            for ( int i = 0; i < rpiSchedule.Count; i++ )
            {
                iiUKRPI.addFixing( rpiSchedule[i], fixData[i] );
            }

            ZeroInflationIndex ii = iiUKRPI as ZeroInflationIndex;
            YieldTermStructure nominalTS = nominalTermStructure();

            // now build the zero inflation curve

            Datum[] zcData = {
               new Datum( new Date(13, Month.August, 2008), 2.93 ),
               new Datum( new Date(13, Month.August, 2009), 2.95 ),
               new Datum( new Date(13, Month.August, 2010), 2.965 ),
               new Datum( new Date(15, Month.August, 2011), 2.98 ),
               new Datum( new Date(13, Month.August, 2012), 3.0 ),
               new Datum( new Date(13, Month.August, 2014), 3.06 ),
               new Datum( new Date(13, Month.August, 2017), 3.175 ),
               new Datum( new Date(13, Month.August, 2019), 3.243 ),
               new Datum( new Date(15, Month.August, 2022), 3.293 ),
               new Datum( new Date(14, Month.August, 2027), 3.338 ),
               new Datum( new Date(13, Month.August, 2032), 3.348 ),
               new Datum( new Date(15, Month.August, 2037), 3.348 ),
               new Datum( new Date(13, Month.August, 2047), 3.308 ),
               new Datum( new Date(13, Month.August, 2057), 3.228 )};

            Period observationLag = new Period( 2, TimeUnit.Months );
            DayCounter dc = new Thirty360();
            Frequency frequency = Frequency.Monthly;
            List<BootstrapHelper<ZeroInflationTermStructure>> helpers =
                makeHelpers( zcData, zcData.Length, ii,
                                                observationLag,
                                                calendar, bdc, dc );

            double baseZeroRate = zcData[0].rate / 100.0;
            PiecewiseZeroInflationCurve<Linear> pZITS = new PiecewiseZeroInflationCurve<Linear>(
                                evaluationDate, calendar, dc, observationLag,
                                frequency, ii.interpolated(), baseZeroRate,
                                new Handle<YieldTermStructure>( nominalTS ), helpers );
            pZITS.recalculate();

            // first check that the zero rates on the curve match the data
            // and that the helpers give the correct impled rates
            const double eps = 0.00000001;
            bool forceLinearInterpolation = false;
            for ( int i = 0; i < zcData.Length; i++ )
            {
                Assert.IsTrue( Math.Abs( zcData[i].rate / 100.0
                - pZITS.zeroRate( zcData[i].date, observationLag, forceLinearInterpolation ) ) < eps,
                "ZITS zeroRate != instrument "
                + pZITS.zeroRate( zcData[i].date, observationLag, forceLinearInterpolation )
                + " vs " + zcData[i].rate / 100.0
                + " interpolation: " + ii.interpolated()
                + " forceLinearInterpolation " + forceLinearInterpolation );

                Assert.IsTrue( Math.Abs( helpers[i].impliedQuote()
                - zcData[i].rate / 100.0 ) < eps,
                "ZITS implied quote != instrument "
                + helpers[i].impliedQuote()
                + " vs " + zcData[i].rate / 100.0 );
            }

            // now test the forecasting capability of the index.
            hz.linkTo( pZITS );
            from = hz.link.baseDate();
            to = hz.link.maxDate() - new Period( 1, TimeUnit.Months ); // a bit of margin for adjustments
            Schedule testIndex = new MakeSchedule().from( from ).to( to )
                                            .withTenor( new Period( 1, TimeUnit.Months ) )
                                            .withCalendar( new UnitedKingdom() )
                                            .withConvention( BusinessDayConvention.ModifiedFollowing ).value();

            // we are testing UKRPI which is not interpolated
            Date bd = hz.link.baseDate();
            double bf = ii.fixing( bd );
            for ( int i = 0; i < testIndex.Count; i++ )
            {
                Date d = testIndex[i];
                double z = hz.link.zeroRate( d, new Period( 0, TimeUnit.Days ) );
                double t = hz.link.dayCounter().yearFraction( bd, d );
                if ( !ii.interpolated() ) // because fixing constant over period
                    t = hz.link.dayCounter().yearFraction( bd,
                     Utils.inflationPeriod( d, ii.frequency() ).Key );
                double calc = bf * Math.Pow( 1 + z, t );
                if ( t <= 0 )
                    calc = ii.fixing( d, false ); // still historical
                if ( Math.Abs( calc - ii.fixing( d, true ) ) / 10000.0 > eps )
                    Assert.Fail( "ZC index does not forecast correctly for date " + d
                                + " from base date " + bd
                                + " with fixing " + bf
                                + ", correct:  " + calc
                                + ", fix: " + ii.fixing( d, true )
                                + ", t " + t );
            }

            //===========================================================================================
            // Test zero-inflation-indexed (i.e. cpi ratio) cashflow
            // just ordinary indexed cashflow with a zero inflation index

            Date baseDate = new Date( 1, Month.January, 2006 );
            Date fixDate = new Date( 1, Month.August, 2014 );
            Date payDate = new UnitedKingdom().adjust( fixDate + new Period( 3, TimeUnit.Months ), BusinessDayConvention.ModifiedFollowing );
            Index ind = ii as Index;
             Utils.QL_REQUIRE( ind != null, () => "dynamic_pointer_cast to Index from InflationIndex failed" );

            double notional = 1000000.0;//1m
            IndexedCashFlow iicf = new IndexedCashFlow( notional, ind, baseDate, fixDate, payDate );
            double correctIndexed = ii.fixing( iicf.fixingDate() ) / ii.fixing( iicf.baseDate() );
            double calculatedIndexed = iicf.amount() / iicf.notional();
            Assert.IsTrue( Math.Abs( correctIndexed - calculatedIndexed ) < eps,
                                  "IndexedCashFlow indexing wrong: " + calculatedIndexed + " vs correct = "
                                  + correctIndexed );

            //===========================================================================================
            // Test zero coupon swap

            // first make one ...

            ZeroInflationIndex zii = ii as ZeroInflationIndex;
             Utils.QL_REQUIRE( zii != null, () => "dynamic_pointer_cast to ZeroInflationIndex from UKRPI failed" );
            ZeroCouponInflationSwap nzcis =
                new ZeroCouponInflationSwap( ZeroCouponInflationSwap.Type.Payer,
                                                     1000000.0,
                                                     evaluationDate,
                                                     zcData[6].date,    // end date = maturity
                                                     calendar, bdc, dc, zcData[6].rate / 100.0, // fixed rate
                                                     zii, observationLag );

            // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via
            //      inflation curve attached to the inflation index.
            Handle<YieldTermStructure> hTS = new Handle<YieldTermStructure>( nominalTS );
            IPricingEngine sppe = new DiscountingSwapEngine( hTS );
            nzcis.setPricingEngine( sppe );

            // ... and price it, should be zero
            Assert.IsTrue( Math.Abs( nzcis.NPV() ) < 0.00001, "ZCIS does not reprice to zero "
                              + nzcis.NPV()
                              + evaluationDate + " to " + zcData[6].date + " becoming " + nzcis.maturityDate()
                              + " rate " + zcData[6].rate
                              + " fixed leg " + nzcis.legNPV( 0 )
                              + " indexed-predicted inflated leg " + nzcis.legNPV( 1 )
                              + " discount " + nominalTS.discount( nzcis.maturityDate() ) );

            //===========================================================================================
            // Test multiplicative seasonality in price
            //

            //Seasonality factors NOT normalized
            //and UKRPI is not interpolated
            Date trueBaseDate = Utils.inflationPeriod( hz.link.baseDate(), ii.frequency() ).Value;
            Date seasonallityBaseDate = new Date( 31, Month.January, trueBaseDate.year() );
            List<double> seasonalityFactors = new List<double>( 12 );
            seasonalityFactors.Add( 1.003245 );
            seasonalityFactors.Add( 1.000000 );
            seasonalityFactors.Add( 0.999715 );
            seasonalityFactors.Add( 1.000495 );
            seasonalityFactors.Add( 1.000929 );
            seasonalityFactors.Add( 0.998687 );
            seasonalityFactors.Add( 0.995949 );
            seasonalityFactors.Add( 0.994682 );
            seasonalityFactors.Add( 0.995949 );
            seasonalityFactors.Add( 1.000519 );
            seasonalityFactors.Add( 1.003705 );
            seasonalityFactors.Add( 1.004186 );

            //Creating two different seasonality objects
            //
            MultiplicativePriceSeasonality seasonality_1 = new MultiplicativePriceSeasonality();
            InitializedList<double> seasonalityFactors_1 = new InitializedList<double>( 12, 1.0 );
            seasonality_1.set( seasonallityBaseDate, Frequency.Monthly, seasonalityFactors_1 );

            MultiplicativePriceSeasonality seasonality_real =
                new MultiplicativePriceSeasonality( seasonallityBaseDate, Frequency.Monthly, seasonalityFactors );
            //Testing seasonality correction when seasonality factors are = 1
            //
            double[] fixing = {
            ii.fixing(new Date(14,Month.January  ,2013),true),
            ii.fixing(new Date(14,Month.February ,2013),true),
            ii.fixing(new Date(14,Month.March    ,2013),true),
            ii.fixing(new Date(14,Month.April    ,2013),true),
            ii.fixing(new Date(14,Month.May      ,2013),true),
            ii.fixing(new Date(14,Month.June     ,2013),true),
            ii.fixing(new Date(14,Month.July     ,2013),true),
            ii.fixing(new Date(14,Month.August   ,2013),true),
            ii.fixing(new Date(14,Month.September,2013),true),
            ii.fixing(new Date(14,Month.October  ,2013),true),
            ii.fixing(new Date(14,Month.November ,2013),true),
            ii.fixing(new Date(14,Month.December ,2013),true)
             };

            hz.link.setSeasonality( seasonality_1 );
             Utils.QL_REQUIRE( hz.link.hasSeasonality(), () => "[44] incorrectly believes NO seasonality correction" );

            double[] seasonalityFixing_1 = {
            ii.fixing(new Date(14,Month.January  ,2013),true),
            ii.fixing(new Date(14,Month.February ,2013),true),
            ii.fixing(new Date(14,Month.March    ,2013),true),
            ii.fixing(new Date(14,Month.April    ,2013),true),
            ii.fixing(new Date(14,Month.May      ,2013),true),
            ii.fixing(new Date(14,Month.June     ,2013),true),
            ii.fixing(new Date(14,Month.July     ,2013),true),
            ii.fixing(new Date(14,Month.August   ,2013),true),
            ii.fixing(new Date(14,Month.September,2013),true),
            ii.fixing(new Date(14,Month.October  ,2013),true),
            ii.fixing(new Date(14,Month.November ,2013),true),
            ii.fixing(new Date(14,Month.December ,2013),true)
             };

            for ( int i = 0; i < 12; i++ )
            {
                if ( Math.Abs( fixing[i] - seasonalityFixing_1[i] ) > eps )
                {
                    Assert.Fail( "Seasonality doesn't work correctly when seasonality factors are set = 1" );
                }
            }

            //Testing seasonality correction when seasonality factors are different from 1
            //
            //0.998687 is the seasonality factor corresponding to June (the base CPI curve month)
            //
            double[] expectedFixing = {
            ii.fixing(new Date(14,Month.January  ,2013),true) * 1.003245/0.998687,
            ii.fixing(new Date(14,Month.February ,2013),true) * 1.000000/0.998687,
            ii.fixing(new Date(14,Month.March    ,2013),true) * 0.999715/0.998687,
            ii.fixing(new Date(14,Month.April    ,2013),true) * 1.000495/0.998687,
            ii.fixing(new Date(14,Month.May      ,2013),true) * 1.000929/0.998687,
            ii.fixing(new Date(14,Month.June     ,2013),true) * 0.998687/0.998687,
            ii.fixing(new Date(14,Month.July     ,2013),true) * 0.995949/0.998687,
            ii.fixing(new Date(14,Month.August   ,2013),true) * 0.994682/0.998687,
            ii.fixing(new Date(14,Month.September,2013),true) * 0.995949/0.998687,
            ii.fixing(new Date(14,Month.October  ,2013),true) * 1.000519/0.998687,
            ii.fixing(new Date(14,Month.November ,2013),true) * 1.003705/0.998687,
            ii.fixing(new Date(14,Month.December ,2013),true) * 1.004186/0.998687
             };

            hz.link.setSeasonality( seasonality_real );

            double[] seasonalityFixing_real = {
            ii.fixing(new Date(14,Month.January  ,2013),true),
            ii.fixing(new Date(14,Month.February ,2013),true),
            ii.fixing(new Date(14,Month.March    ,2013),true),
            ii.fixing(new Date(14,Month.April    ,2013),true),
            ii.fixing(new Date(14,Month.May      ,2013),true),
            ii.fixing(new Date(14,Month.June     ,2013),true),
            ii.fixing(new Date(14,Month.July     ,2013),true),
            ii.fixing(new Date(14,Month.August   ,2013),true),
            ii.fixing(new Date(14,Month.September,2013),true),
            ii.fixing(new Date(14,Month.October  ,2013),true),
            ii.fixing(new Date(14,Month.November ,2013),true),
            ii.fixing(new Date(14,Month.December ,2013),true)
             };

            for ( int i = 0; i < 12; i++ )
            {
                if ( Math.Abs( expectedFixing[i] - seasonalityFixing_real[i] ) > 0.01 )
                {
                    Assert.Fail( "Seasonality doesn't work correctly when considering seasonality factors != 1 "
                                    + expectedFixing[i] + " vs " + seasonalityFixing_real[i] );
                }
            }

            //Testing Unset function
            //
             Utils.QL_REQUIRE( hz.link.hasSeasonality(), () => "[4] incorrectly believes NO seasonality correction" );
            hz.link.setSeasonality();
             Utils.QL_REQUIRE( !hz.link.hasSeasonality(), () => "[5] incorrectly believes HAS seasonality correction" );

            double[] seasonalityFixing_unset = {
            ii.fixing(new Date(14,Month.January  ,2013),true),
            ii.fixing(new Date(14,Month.February ,2013),true),
            ii.fixing(new Date(14,Month.March    ,2013),true),
            ii.fixing(new Date(14,Month.April    ,2013),true),
            ii.fixing(new Date(14,Month.May      ,2013),true),
            ii.fixing(new Date(14,Month.June     ,2013),true),
            ii.fixing(new Date(14,Month.July     ,2013),true),
            ii.fixing(new Date(14,Month.August   ,2013),true),
            ii.fixing(new Date(14,Month.September,2013),true),
            ii.fixing(new Date(14,Month.October  ,2013),true),
            ii.fixing(new Date(14,Month.November ,2013),true),
            ii.fixing(new Date(14,Month.December ,2013),true)
             };

            for ( int i = 0; i < 12; i++ )
            {
                if ( Math.Abs( seasonalityFixing_unset[i] - seasonalityFixing_1[i] ) > eps )
                {
                    Assert.Fail( "UnsetSeasonality doesn't work correctly "
                                    + seasonalityFixing_unset[i] + " vs " + seasonalityFixing_1[i] );
                }
            }

            //==============================================================================
            // now do an INTERPOLATED index, i.e. repeat everything on a fake version of
            // UKRPI (to save making another term structure)

            bool interpYES = true;
            UKRPI iiUKRPIyes = new UKRPI( interpYES, hz );
            for ( int i = 0; i < fixData.Length; i++ )
            {
                iiUKRPIyes.addFixing( rpiSchedule[i], fixData[i] );
            }

            ZeroInflationIndex iiyes = iiUKRPIyes as ZeroInflationIndex;

            // now build the zero inflation curve
            // same data, bigger lag or it will be a self-contradiction
            Period observationLagyes = new Period( 3, TimeUnit.Months );
            List<BootstrapHelper<ZeroInflationTermStructure>> helpersyes =
                makeHelpers( zcData, zcData.Length,
                iiyes, observationLagyes, calendar, bdc, dc );

            PiecewiseZeroInflationCurve<Linear> pZITSyes =
                    new PiecewiseZeroInflationCurve<Linear>(
                    evaluationDate, calendar, dc, observationLagyes,
                    frequency, iiyes.interpolated(), baseZeroRate,
                    new Handle<YieldTermStructure>( nominalTS ), helpersyes );
            pZITSyes.recalculate();

            // first check that the zero rates on the curve match the data
            // and that the helpers give the correct impled rates
            forceLinearInterpolation = false;   // still
            for ( int i = 0; i < zcData.Length; i++ )
            {
                Assert.IsTrue( Math.Abs( zcData[i].rate / 100.0
                                - pZITSyes.zeroRate( zcData[i].date, observationLagyes, forceLinearInterpolation ) ) < eps,
                                "ZITS INTERPOLATED zeroRate != instrument "
                                + pZITSyes.zeroRate( zcData[i].date, observationLagyes, forceLinearInterpolation )
                                + " date " + zcData[i].date + " observationLagyes " + observationLagyes
                                + " vs " + zcData[i].rate / 100.0
                                + " interpolation: " + iiyes.interpolated()
                                + " forceLinearInterpolation " + forceLinearInterpolation );
                Assert.IsTrue( Math.Abs( helpersyes[i].impliedQuote()
                                    - zcData[i].rate / 100.0 ) < eps,
                                "ZITS INTERPOLATED implied quote != instrument "
                                + helpersyes[i].impliedQuote()
                                + " vs " + zcData[i].rate / 100.0 );
            }

            //======================================================================================
            // now test the forecasting capability of the index.
            hz.linkTo( pZITSyes );
            from = hz.link.baseDate() + new Period( 1, TimeUnit.Months ); // to avoid historical linear bit for rest of base month
            to = hz.link.maxDate() - new Period( 1, TimeUnit.Months ); // a bit of margin for adjustments
            testIndex = new MakeSchedule().from( from ).to( to )
            .withTenor( new Period( 1, TimeUnit.Months ) )
            .withCalendar( new UnitedKingdom() )
            .withConvention( BusinessDayConvention.ModifiedFollowing ).value();

            // we are testing UKRPI which is FAKE interpolated for testing here
            bd = hz.link.baseDate();
            bf = iiyes.fixing( bd );
            for ( int i = 0; i < testIndex.Count; i++ )
            {
                Date d = testIndex[i];
                double z = hz.link.zeroRate( d, new Period( 0, TimeUnit.Days ) );
                double t = hz.link.dayCounter().yearFraction( bd, d );
                double calc = bf * Math.Pow( 1 + z, t );
                if ( t <= 0 ) calc = iiyes.fixing( d ); // still historical
                if ( Math.Abs( calc - iiyes.fixing( d ) ) > eps )
                    Assert.Fail( "ZC INTERPOLATED index does not forecast correctly for date " + d
                                    + " from base date " + bd
                                    + " with fixing " + bf
                                    + ", correct:  " + calc
                                    + ", fix: " + iiyes.fixing( d )
                                    + ", t " + t
                                    + ", zero " + z );
            }

            //===========================================================================================
            // Test zero coupon swap

            ZeroInflationIndex ziiyes = iiyes as ZeroInflationIndex;
             Utils.QL_REQUIRE( ziiyes != null, () => "dynamic_pointer_cast to ZeroInflationIndex from UKRPI-I failed" );
            ZeroCouponInflationSwap nzcisyes = new ZeroCouponInflationSwap( ZeroCouponInflationSwap.Type.Payer,
                                                              1000000.0,
                                                              evaluationDate,
                                                              zcData[6].date,    // end date = maturity
                                                              calendar, bdc, dc, zcData[6].rate / 100.0, // fixed rate
                                                              ziiyes, observationLagyes );

            // N.B. no coupon pricer because it is not a coupon, effect of inflation curve via
            //      inflation curve attached to the inflation index.
            nzcisyes.setPricingEngine( sppe );

            // ... and price it, should be zero
            Assert.IsTrue( Math.Abs( nzcisyes.NPV() ) < 0.00001, "ZCIS-I does not reprice to zero "
                                    + nzcisyes.NPV()
                                    + evaluationDate + " to " + zcData[6].date + " becoming " + nzcisyes.maturityDate()
                                    + " rate " + zcData[6].rate
                                    + " fixed leg " + nzcisyes.legNPV( 0 )
                                    + " indexed-predicted inflated leg " + nzcisyes.legNPV( 1 )
                                    + " discount " + nominalTS.discount( nzcisyes.maturityDate() )
                                    );

            // remove circular refernce
            hz.linkTo( new ZeroInflationTermStructure() );
        }
Beispiel #16
0
        public void testYYTermStructure()
        {
            // Testing year-on-year inflation term structure...

            SavedSettings backup = new SavedSettings();
            //IndexHistoryCleaner cleaner;

            // try the YY UK
            Calendar calendar = new UnitedKingdom();
            BusinessDayConvention bdc = BusinessDayConvention.ModifiedFollowing;
            Date evaluationDate = new Date(13, Month.August, 2007);
            evaluationDate = calendar.adjust(evaluationDate);
            Settings.setEvaluationDate(evaluationDate);

            // fixing data
            Date from = new Date(1, Month.January, 2005);
            Date to = new Date(13, Month.August, 2007);
            Schedule rpiSchedule = new MakeSchedule().from(from).to(to)
            .withTenor(new Period(1,TimeUnit.Months))
            .withCalendar(new UnitedKingdom())
            .withConvention(BusinessDayConvention.ModifiedFollowing).value();
            double[] fixData = { 189.9, 189.9, 189.6, 190.5, 191.6, 192.0,
                192.2, 192.2, 192.6, 193.1, 193.3, 193.6,
                194.1, 193.4, 194.2, 195.0, 196.5, 197.7,
                198.5, 198.5, 199.2, 200.1, 200.4, 201.1,
                202.7, 201.6, 203.1, 204.4, 205.4, 206.2,
                207.3 };

            RelinkableHandle<YoYInflationTermStructure> hy = new RelinkableHandle<YoYInflationTermStructure>();
            bool interp = false;
            YYUKRPIr iir = new YYUKRPIr(interp, hy);
            for (int i=0; i<fixData.Length; i++)
            {
                iir.addFixing(rpiSchedule[i], fixData[i]);
            }

            YieldTermStructure nominalTS = nominalTermStructure();

            // now build the YoY inflation curve
            Datum[] yyData = {
                new Datum( new Date(13, Month.August, 2008), 2.95 ),
                new Datum( new Date(13, Month.August, 2009), 2.95 ),
                new Datum( new Date(13, Month.August, 2010), 2.93 ),
                new Datum( new Date(15, Month.August, 2011), 2.955 ),
                new Datum( new Date(13, Month.August, 2012), 2.945 ),
                new Datum( new Date(13, Month.August, 2013), 2.985 ),
                new Datum( new Date(13, Month.August, 2014), 3.01 ),
                new Datum( new Date(13, Month.August, 2015), 3.035 ),
                new Datum( new Date(13, Month.August, 2016), 3.055 ),  // note that
                new Datum( new Date(13, Month.August, 2017), 3.075 ),  // some dates will be on
                new Datum( new Date(13, Month.August, 2019), 3.105 ),  // holidays but the payment
                new Datum( new Date(15, Month.August, 2022), 3.135 ),  // calendar will roll them
                new Datum( new Date(13, Month.August, 2027), 3.155 ),
                new Datum( new Date(13, Month.August, 2032), 3.145 ),
                new Datum( new Date(13, Month.August, 2037), 3.145 )
            };

            Period observationLag = new Period(2,TimeUnit.Months);
            DayCounter dc = new Thirty360();

            // now build the helpers ...
            List<BootstrapHelper<YoYInflationTermStructure>> helpers =
            makeHelpers (yyData, yyData.Length, iir,observationLag, calendar, bdc, dc);

            double baseYYRate = yyData[0].rate/100.0;
            PiecewiseYoYInflationCurve<Linear> pYYTS = new PiecewiseYoYInflationCurve<Linear>(
                            evaluationDate, calendar, dc, observationLag,
                            iir.frequency(),iir.interpolated(), baseYYRate,
                            new Handle<YieldTermStructure>(nominalTS), helpers);
            pYYTS.recalculate();

            // validation
            // yoy swaps should reprice to zero
            // yy rates should not equal yySwap rates
            double eps = 0.000001;
            // usual swap engine
            Handle<YieldTermStructure> hTS = new Handle<YieldTermStructure>(nominalTS);
            IPricingEngine sppe = new DiscountingSwapEngine(hTS);

            // make sure that the index has the latest yoy term structure
            hy.linkTo(pYYTS);

            for (int j = 1; j < yyData.Length; j++)
            {

                from = nominalTS.referenceDate();
                to = yyData[j].date;
                Schedule yoySchedule = new MakeSchedule().from(from).to(to)
                .withConvention(BusinessDayConvention.Unadjusted) // fixed leg gets calendar from
                .withCalendar(calendar)     // schedule
                .withTenor(new Period(1,TimeUnit.Years)).value(); // .back

                YearOnYearInflationSwap yyS2 = new YearOnYearInflationSwap(
                    YearOnYearInflationSwap.Type.Payer,
                    1000000.0,
                    yoySchedule,//fixed schedule, but same as yoy
                    yyData[j].rate/100.0,
                    dc,
                    yoySchedule,
                    iir,
                    observationLag,
                    0.0,        //spread on index
                    dc,
                    new UnitedKingdom());

                yyS2.setPricingEngine(sppe);

                Assert.IsTrue(Math.Abs(yyS2.NPV())<eps,"fresh yoy swap NPV!=0 from TS "
                            +"swap quote for pt " + j
                            + ", is " + yyData[j].rate/100.0
                            +" vs YoY rate "+ pYYTS.yoyRate(yyData[j].date-observationLag)
                            +" at quote date "+(yyData[j].date-observationLag)
                            +", NPV of a fresh yoy swap is " + yyS2.NPV()
                            +"\n      fair rate " + yyS2.fairRate()
                            +" payment "+yyS2.paymentConvention());
            }

            int jj=3;
            for (int k = 0; k < 14; k++)
            {
                from = nominalTS.referenceDate() - new Period(k,TimeUnit.Months);
                to = yyData[jj].date - new Period(k,TimeUnit.Months);
                Schedule yoySchedule = new MakeSchedule().from(from).to(to)
                .withConvention(BusinessDayConvention.Unadjusted) // fixed leg gets calendar from
                .withCalendar(calendar)     // schedule
                .withTenor(new Period(1,TimeUnit.Years))
                .value(); //backwards()

                YearOnYearInflationSwap yyS3 = new YearOnYearInflationSwap(
                    YearOnYearInflationSwap.Type.Payer,
                    1000000.0,
                    yoySchedule,//fixed schedule, but same as yoy
                    yyData[jj].rate/100.0,
                    dc,
                    yoySchedule,
                    iir,
                    observationLag,
                    0.0,        //spread on index
                    dc,
                    new UnitedKingdom());

                yyS3.setPricingEngine(sppe);

                Assert.IsTrue(Math.Abs(yyS3.NPV())< 20000.0,
                                            "unexpected size of aged YoY swap, aged "
                                            + k +" months: YY aged NPV = " + yyS3.NPV()
                                            +", legs "+ yyS3.legNPV(0) + " and " + yyS3.legNPV(1)
                                            );
            }
            // remove circular refernce
            hy.linkTo( new YoYInflationTermStructure());
        }
        static void Main(string[] args) {

            DateTime timer = DateTime.Now;

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

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(18, Month.September, 2008);
            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int fixingDays = 3;
            int settlementDays = 3;

            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);
            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);

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


            // Building of the bonds discounting yield curve

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

            // Common data

            // ZC rates for the short end
             double zc3mQuote=0.0096;
             double zc6mQuote=0.0145;
             double zc1yQuote=0.0194;

             Quote zc3mRate = new SimpleQuote(zc3mQuote);
             Quote zc6mRate = new SimpleQuote(zc6mQuote);
             Quote zc1yRate = new SimpleQuote(zc1yQuote);

             DayCounter zcBondsDayCounter = new Actual365Fixed();

             RateHelper zc3m = new DepositRateHelper(new Handle<Quote>(zc3mRate),
                                                          new Period(3, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc6m = new DepositRateHelper(new Handle<Quote>(zc6mRate),
                                                          new Period(6, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc1y = new DepositRateHelper(new Handle<Quote>(zc1yRate),
                                                          new Period(1, TimeUnit.Years), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);

            // setup bonds
            double redemption = 100.0;

            const int numberOfBonds = 5;

            Date[] issueDates = {
                    new Date (15, Month.March, 2005),
                    new Date (15, Month.June, 2005),
                    new Date (30, Month.June, 2006),
                    new Date (15, Month.November, 2002),
                    new Date (15, Month.May, 1987)
            };

            Date[] maturities = {
                    new Date (31, Month.August, 2010),
                    new Date (31, Month.August, 2011),
                    new Date (31, Month.August, 2013),
                    new Date (15, Month.August, 2018),
                    new Date (15, Month.May, 2038)
            };

            double[] couponRates = {
                    0.02375,
                    0.04625,
                    0.03125,
                    0.04000,
                    0.04500
            };

            double[] marketQuotes = {
                    100.390625,
                    106.21875,
                    100.59375,
                    101.6875,
                    102.140625
            };

            List<SimpleQuote> quote = new List<SimpleQuote>();
            for (int i=0; i<numberOfBonds; i++) {
                SimpleQuote cp = new SimpleQuote(marketQuotes[i]);
                quote.Add(cp);
            }

            List<RelinkableHandle<Quote>> quoteHandle = new InitializedList<RelinkableHandle<Quote>>(numberOfBonds);
            for (int i=0; i<numberOfBonds; i++) {
                quoteHandle[i].linkTo(quote[i]);
            }

            // Definition of the rate helpers
            List<FixedRateBondHelper> bondsHelpers = new List<FixedRateBondHelper>();
            for (int i=0; i<numberOfBonds; i++) {

                Schedule schedule = new Schedule(issueDates[i], maturities[i], new Period(Frequency.Semiannual), 
                                                 new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, 
                                                 DateGeneration.Rule.Backward, false);

                FixedRateBondHelper bondHelper = new FixedRateBondHelper(quoteHandle[i],
                                                                         settlementDays,
                                                                         100.0,
                                                                         schedule,
                                                                         new List<double>() { couponRates[i] },
                                                                         new ActualActual(ActualActual.Convention.Bond),
                                                                         BusinessDayConvention.Unadjusted,
                                                                         redemption,
                                                                         issueDates[i]);

                bondsHelpers.Add(bondHelper);
            }

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

             // Adding the ZC bonds to the curve for the short end
             bondInstruments.Add(zc3m);
             bondInstruments.Add(zc6m);
             bondInstruments.Add(zc1y);

             // Adding the Fixed rate bonds to the curve for the long end
             for (int i=0; i<numberOfBonds; i++) {
                 bondInstruments.Add(bondsHelpers[i]);
             }

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

             // Building of the Libor forecasting curve
             // deposits
             double d1wQuote=0.043375;
             double d1mQuote=0.031875;
             double d3mQuote=0.0320375;
             double d6mQuote=0.03385;
             double d9mQuote=0.0338125;
             double d1yQuote=0.0335125;
             // swaps
             double s2yQuote=0.0295;
             double s3yQuote=0.0323;
             double s5yQuote=0.0359;
             double s10yQuote=0.0412;
             double s15yQuote=0.0433;


             /********************
              ***    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);
             // 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 swaps
             Frequency swFixedLegFrequency =Frequency.Annual;
             BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
             DayCounter swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
             IborIndex swFloatingLegIndex = new Euribor6M();

             Period forwardStart = new Period(1, TimeUnit.Days);

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


             /*********************
              **  CURVE BUILDING **
              *********************/

             // Any DayCounter would be fine.
             // ActualActual::ISDA ensures that 30 years is 30.0

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

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

             /*********************
              * BONDS TO BE PRICED *
              **********************/

             // Common data
             double faceAmount = 100;

             // Pricing engine
             IPricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);

             // Zero coupon bond
             ZeroCouponBond zeroCouponBond = new ZeroCouponBond(
                     settlementDays,
                     new UnitedStates(UnitedStates.Market.GovernmentBond),
                     faceAmount,
                     new Date(15, Month.August,2013),
                     BusinessDayConvention.Following,
                     116.92,
                     new Date(15, Month.August,2003));

             zeroCouponBond.setPricingEngine(bondEngine);

             // Fixed 4.5% US Treasury Note
             Schedule fixedBondSchedule = new Schedule(new Date(15, Month.May, 2007),
                     new Date(15,Month.May,2017), new Period(Frequency.Semiannual),
                     new UnitedStates(UnitedStates.Market.GovernmentBond),
                     BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

             FixedRateBond fixedRateBond = new FixedRateBond(
                     settlementDays,
                     faceAmount,
                     fixedBondSchedule,
                     new List<double>() { 0.045 },
                     new ActualActual(ActualActual.Convention.Bond),
                     BusinessDayConvention.ModifiedFollowing,
                     100.0, new Date(15, Month.May, 2007));

             fixedRateBond.setPricingEngine(bondEngine);

             // Floating rate bond (3M USD Libor + 0.1%)
             // Should and will be priced on another curve later...

             RelinkableHandle<YieldTermStructure> liborTermStructure = new RelinkableHandle<YieldTermStructure>();
             IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);
             libor3m.addFixing(new Date(17, Month.July, 2008),0.0278625);

             Schedule floatingBondSchedule = new Schedule(new Date(21, Month.October, 2005),
                     new Date(21, Month.October, 2010), new Period(Frequency.Quarterly),
                     new UnitedStates(UnitedStates.Market.NYSE),
                     BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true);

             FloatingRateBond floatingRateBond = new FloatingRateBond(
                     settlementDays,
                     faceAmount,
                     floatingBondSchedule,
                     libor3m,
                     new Actual360(),
                     BusinessDayConvention.ModifiedFollowing,
                     2,
                     // Gearings
                     new List<double>() { 1.0 },
                     // Spreads
                     new List<double>() { 0.001 },
                     // Caps
                     new List<double>(),
                     // Floors
                     new List<double>(),
                     // Fixing in arrears
                     true,
                     100.0,
                     new Date(21, Month.October, 2005));

             floatingRateBond.setPricingEngine(bondEngine);

             // Coupon pricers
             IborCouponPricer pricer = new BlackIborCouponPricer();

             // optionLet volatilities
             double volatility = 0.0;
             Handle<OptionletVolatilityStructure> vol;
             vol = new Handle<OptionletVolatilityStructure>(
                                new ConstantOptionletVolatility(
                                     settlementDays,
                                     calendar,
                                     BusinessDayConvention.ModifiedFollowing,
                                     volatility,
                                     new Actual365Fixed()));

             pricer.setCapletVolatility(vol);
             Utils.setCouponPricer(floatingRateBond.cashflows(),pricer);

             // Yield curve bootstrapping
             forecastingTermStructure.linkTo(depoSwapTermStructure);
             discountingTermStructure.linkTo(bondDiscountingTermStructure);

             // We are using the depo & swap curve to estimate the future Libor rates
             liborTermStructure.linkTo(depoSwapTermStructure);

             /***************
              * BOND PRICING *
              ****************/

             // write column headings
             int[] widths = { 18, 10, 10, 10 };

            Console.WriteLine("{0,18}{1,10}{2,10}{3,10}", "", "ZC", "Fixed", "Floating");

            string separator = " | ";
            int width = widths[0]
                                 + widths[1]
                                          + widths[2]
                                                   + widths[3];
            string rule = "".PadLeft(width, '-'), dblrule = "".PadLeft(width, '=');
            string tab = "".PadLeft(8, ' ');

            Console.WriteLine(rule);

            Console.WriteLine("Net present value".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}", 
                                zeroCouponBond.NPV(),
                                fixedRateBond.NPV(),
                                floatingRateBond.NPV());

            Console.WriteLine("Clean price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.cleanPrice(),
                                fixedRateBond.cleanPrice(),
                                floatingRateBond.cleanPrice());

            Console.WriteLine("Dirty price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.dirtyPrice(),
                                fixedRateBond.dirtyPrice(),
                                floatingRateBond.dirtyPrice());

            Console.WriteLine("Accrued coupon".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.accruedAmount(),
                                fixedRateBond.accruedAmount(),
                                floatingRateBond.accruedAmount());

            Console.WriteLine("Previous coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                                "N/A",
                                fixedRateBond.previousCoupon(),
                                floatingRateBond.previousCoupon());

            Console.WriteLine("Next coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.nextCoupon(),
                              floatingRateBond.nextCoupon());

            Console.WriteLine("Yield".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual));

            Console.WriteLine();

            // Other computations
            Console.WriteLine("Sample indirect computations (for the floating rate bond): ");
            Console.WriteLine(rule);

            Console.WriteLine("Yield to Clean Price: {0:n2}",
                floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                                                                   new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                                   settlementDate));

            Console.WriteLine("Clean Price to Yield: {0:0.00%}",
                floatingRateBond.yield(floatingRateBond.cleanPrice(),new Actual360(), Compounding.Compounded, Frequency.Annual,
                                       settlementDate));

            /* "Yield to Price"
               "Price to Yield" */

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

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Beispiel #18
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();
        }