FRA.cpp

This example evaluates a forward-rate agreement.

00001 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 
00020 /*  This example shows how to set up a term structure and price a simple
00021     forward-rate agreement.
00022 */
00023 
00024 // the only header you need to use QuantLib
00025 #define BOOST_LIB_DIAGNOSTIC
00026 #  include <ql/quantlib.hpp>
00027 #undef BOOST_LIB_DIAGNOSTIC
00028 
00029 #ifdef BOOST_MSVC
00030 /* Uncomment the following lines to unmask floating-point
00031    exceptions. Warning: unpredictable results can arise...
00032 
00033    See http://www.wilmott.com/messageview.cfm?catid=10&threadid=9481
00034    Is there anyone with a definitive word about this?
00035 */
00036 // #include <float.h>
00037 // namespace { unsigned int u = _controlfp(_EM_INEXACT, _MCW_EM); }
00038 #endif
00039 
00040 #include <boost/timer.hpp>
00041 #include <iostream>
00042 
00043 #define LENGTH(a) (sizeof(a)/sizeof(a[0]))
00044 
00045 using namespace std;
00046 using namespace QuantLib;
00047 
00048 #if defined(QL_ENABLE_SESSIONS)
00049 namespace QuantLib {
00050 
00051     Integer sessionId() { return 0; }
00052 
00053 }
00054 #endif
00055 
00056 int main(int, char* []) {
00057 
00058     try {
00059 
00060         boost::timer timer;
00061         std::cout << std::endl;
00062 
00063         /*********************
00064          ***  MARKET DATA  ***
00065          *********************/
00066 
00067         RelinkableHandle<YieldTermStructure> euriborTermStructure;
00068         boost::shared_ptr<IborIndex> euribor3m(
00069                                        new Euribor3M(euriborTermStructure));
00070 
00071         Date todaysDate = Date(23, May, 2006);
00072         Settings::instance().evaluationDate() = todaysDate;
00073 
00074         Calendar calendar = euribor3m->fixingCalendar();
00075         Integer fixingDays = euribor3m->fixingDays();
00076         Date settlementDate = calendar.advance(todaysDate, fixingDays, Days);
00077 
00078         std::cout << "Today: " << todaysDate.weekday()
00079                   << ", " << todaysDate << std::endl;
00080 
00081         std::cout << "Settlement date: " << settlementDate.weekday()
00082                   << ", " << settlementDate << std::endl;
00083 
00084 
00085         // 3 month term FRA quotes (index refers to monthsToStart)
00086         Rate threeMonthFraQuote[10];
00087 
00088         threeMonthFraQuote[1]=0.030;
00089         threeMonthFraQuote[2]=0.031;
00090         threeMonthFraQuote[3]=0.032;
00091         threeMonthFraQuote[6]=0.033;
00092         threeMonthFraQuote[9]=0.034;
00093 
00094         /********************
00095          ***    QUOTES    ***
00096          ********************/
00097 
00098         // SimpleQuote stores a value which can be manually changed;
00099         // other Quote subclasses could read the value from a database
00100         // or some kind of data feed.
00101 
00102 
00103         // FRAs
00104         boost::shared_ptr<SimpleQuote> fra1x4Rate(
00105                                       new SimpleQuote(threeMonthFraQuote[1]));
00106         boost::shared_ptr<SimpleQuote> fra2x5Rate(
00107                                       new SimpleQuote(threeMonthFraQuote[2]));
00108         boost::shared_ptr<SimpleQuote> fra3x6Rate(
00109                                       new SimpleQuote(threeMonthFraQuote[3]));
00110         boost::shared_ptr<SimpleQuote> fra6x9Rate(
00111                                       new SimpleQuote(threeMonthFraQuote[6]));
00112         boost::shared_ptr<SimpleQuote> fra9x12Rate(
00113                                       new SimpleQuote(threeMonthFraQuote[9]));
00114 
00115         RelinkableHandle<Quote> h1x4;  h1x4.linkTo(fra1x4Rate);
00116         RelinkableHandle<Quote> h2x5;  h2x5.linkTo(fra2x5Rate);
00117         RelinkableHandle<Quote> h3x6;  h3x6.linkTo(fra3x6Rate);
00118         RelinkableHandle<Quote> h6x9;  h6x9.linkTo(fra6x9Rate);
00119         RelinkableHandle<Quote> h9x12; h9x12.linkTo(fra9x12Rate);
00120 
00121         /*********************
00122          ***  RATE HELPERS ***
00123          *********************/
00124 
00125         // RateHelpers are built from the above quotes together with
00126         // other instrument dependant infos.  Quotes are passed in
00127         // relinkable handles which could be relinked to some other
00128         // data source later.
00129 
00130         DayCounter fraDayCounter = euribor3m->dayCounter();
00131         BusinessDayConvention convention = euribor3m->businessDayConvention();
00132         bool endOfMonth = euribor3m->endOfMonth();
00133 
00134         boost::shared_ptr<RateHelper> fra1x4(
00135                            new FraRateHelper(h1x4, 1, 4,
00136                                              fixingDays, calendar, convention,
00137                                              endOfMonth, fixingDays,
00138                                              fraDayCounter));
00139 
00140         boost::shared_ptr<RateHelper> fra2x5(
00141                            new FraRateHelper(h2x5, 2, 5,
00142                                              fixingDays, calendar, convention,
00143                                              endOfMonth, fixingDays,
00144                                              fraDayCounter));
00145 
00146         boost::shared_ptr<RateHelper> fra3x6(
00147                            new FraRateHelper(h3x6, 3, 6,
00148                                              fixingDays, calendar, convention,
00149                                              endOfMonth, fixingDays,
00150                                              fraDayCounter));
00151 
00152         boost::shared_ptr<RateHelper> fra6x9(
00153                            new FraRateHelper(h6x9, 6, 9,
00154                                              fixingDays, calendar, convention,
00155                                              endOfMonth, fixingDays,
00156                                              fraDayCounter));
00157 
00158         boost::shared_ptr<RateHelper> fra9x12(
00159                            new FraRateHelper(h9x12, 9, 12,
00160                                              fixingDays, calendar, convention,
00161                                              endOfMonth, fixingDays,
00162                                              fraDayCounter));
00163 
00164 
00165         /*********************
00166          **  CURVE BUILDING **
00167          *********************/
00168 
00169         // Any DayCounter would be fine.
00170         // ActualActual::ISDA ensures that 30 years is 30.0
00171         DayCounter termStructureDayCounter =
00172             ActualActual(ActualActual::ISDA);
00173 
00174         double tolerance = 1.0e-15;
00175 
00176         // A FRA curve
00177         std::vector<boost::shared_ptr<RateHelper> > fraInstruments;
00178 
00179         fraInstruments.push_back(fra1x4);
00180         fraInstruments.push_back(fra2x5);
00181         fraInstruments.push_back(fra3x6);
00182         fraInstruments.push_back(fra6x9);
00183         fraInstruments.push_back(fra9x12);
00184 
00185         boost::shared_ptr<YieldTermStructure> fraTermStructure(
00186                      new PiecewiseYieldCurve<Discount,LogLinear>(
00187                                          settlementDate, fraInstruments,
00188                                          termStructureDayCounter, tolerance));
00189 
00190 
00191         // Term structures used for pricing/discounting
00192 
00193         RelinkableHandle<YieldTermStructure> discountingTermStructure;
00194         discountingTermStructure.linkTo(fraTermStructure);
00195 
00196 
00197         /***********************
00198          ***  construct FRA's ***
00199          ***********************/
00200 
00201         Calendar fraCalendar = euribor3m->fixingCalendar();
00202         BusinessDayConvention fraBusinessDayConvention =
00203             euribor3m->businessDayConvention();
00204         Position::Type fraFwdType = Position::Long;
00205         Real fraNotional = 100.0;
00206         const Integer FraTermMonths = 3;
00207         Integer monthsToStart[] = { 1, 2, 3, 6, 9 };
00208 
00209         euriborTermStructure.linkTo(fraTermStructure);
00210 
00211         cout << endl;
00212         cout << "Test FRA construction, NPV calculation, and FRA purchase"
00213              << endl
00214              << endl;
00215 
00216         Size i;
00217         for (i=0; i<LENGTH(monthsToStart); i++) {
00218 
00219             Date fraValueDate = fraCalendar.advance(
00220                                        settlementDate,monthsToStart[i],Months,
00221                                        fraBusinessDayConvention);
00222 
00223             Date fraMaturityDate = fraCalendar.advance(
00224                                             fraValueDate,FraTermMonths,Months,
00225                                             fraBusinessDayConvention);
00226 
00227             Rate fraStrikeRate = threeMonthFraQuote[monthsToStart[i]];
00228 
00229             ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
00230                                        fraFwdType,fraStrikeRate,
00231                                        fraNotional, euribor3m,
00232                                        discountingTermStructure);
00233 
00234             cout << "3m Term FRA, Months to Start: "
00235                  << monthsToStart[i]
00236                  << endl;
00237             cout << "strike FRA rate: "
00238                  << io::rate(fraStrikeRate)
00239                  << endl;
00240             cout << "FRA 3m forward rate: "
00241                  << myFRA.forwardRate()
00242                  << endl;
00243             cout << "FRA market quote: "
00244                  << io::rate(threeMonthFraQuote[monthsToStart[i]])
00245                  << endl;
00246             cout << "FRA spot value: "
00247                  << myFRA.spotValue()
00248                  << endl;
00249             cout << "FRA forward value: "
00250                  << myFRA.forwardValue()
00251                  << endl;
00252             cout << "FRA implied Yield: "
00253                  << myFRA.impliedYield(myFRA.spotValue(),
00254                                        myFRA.forwardValue(),
00255                                        settlementDate,
00256                                        Simple,
00257                                        fraDayCounter)
00258                  << endl;
00259             cout << "market Zero Rate: "
00260                  << discountingTermStructure->zeroRate(fraMaturityDate,
00261                                                        fraDayCounter,
00262                                                        Simple)
00263                  << endl;
00264             cout << "FRA NPV [should be zero]: "
00265                  << myFRA.NPV()
00266                  << endl
00267                  << endl;
00268 
00269         }
00270 
00271 
00272 
00273 
00274         cout << endl << endl;
00275         cout << "Now take a 100 basis-point upward shift in FRA quotes "
00276              << "and examine NPV"
00277              << endl
00278              << endl;
00279 
00280         const Real BpsShift = 0.01;
00281 
00282         threeMonthFraQuote[1]=0.030+BpsShift;
00283         threeMonthFraQuote[2]=0.031+BpsShift;
00284         threeMonthFraQuote[3]=0.032+BpsShift;
00285         threeMonthFraQuote[6]=0.033+BpsShift;
00286         threeMonthFraQuote[9]=0.034+BpsShift;
00287 
00288         fra1x4Rate->setValue(threeMonthFraQuote[1]);
00289         fra2x5Rate->setValue(threeMonthFraQuote[2]);
00290         fra3x6Rate->setValue(threeMonthFraQuote[3]);
00291         fra6x9Rate->setValue(threeMonthFraQuote[6]);
00292         fra9x12Rate->setValue(threeMonthFraQuote[9]);
00293 
00294 
00295         for (i=0; i<LENGTH(monthsToStart); i++) {
00296 
00297             Date fraValueDate = fraCalendar.advance(
00298                                        settlementDate,monthsToStart[i],Months,
00299                                        fraBusinessDayConvention);
00300 
00301             Date fraMaturityDate = fraCalendar.advance(
00302                                             fraValueDate,FraTermMonths,Months,
00303                                             fraBusinessDayConvention);
00304 
00305             Rate fraStrikeRate =
00306                 threeMonthFraQuote[monthsToStart[i]] - BpsShift;
00307 
00308             ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
00309                                        fraFwdType, fraStrikeRate,
00310                                        fraNotional, euribor3m,
00311                                        discountingTermStructure);
00312 
00313             cout << "3m Term FRA, 100 notional, Months to Start = "
00314                  << monthsToStart[i]
00315                  << endl;
00316             cout << "strike FRA rate: "
00317                  << io::rate(fraStrikeRate)
00318                  << endl;
00319             cout << "FRA 3m forward rate: "
00320                  << myFRA.forwardRate()
00321                  << endl;
00322             cout << "FRA market quote: "
00323                  << io::rate(threeMonthFraQuote[monthsToStart[i]])
00324                  << endl;
00325             cout << "FRA spot value: "
00326                  << myFRA.spotValue()
00327                  << endl;
00328             cout << "FRA forward value: "
00329                  << myFRA.forwardValue()
00330                  << endl;
00331             cout << "FRA implied Yield: "
00332                  << myFRA.impliedYield(myFRA.spotValue(),
00333                                        myFRA.forwardValue(),
00334                                        settlementDate,
00335                                        Simple,
00336                                        fraDayCounter)
00337                  << endl;
00338             cout << "market Zero Rate: "
00339                  << discountingTermStructure->zeroRate(fraMaturityDate,
00340                                                        fraDayCounter,
00341                                                        Simple)
00342                  << endl;
00343             cout << "FRA NPV [should be positive]: "
00344                  << myFRA.NPV()
00345                  << endl
00346                  << endl;
00347         }
00348 
00349         Real seconds = timer.elapsed();
00350         Integer hours = int(seconds/3600);
00351         seconds -= hours * 3600;
00352         Integer minutes = int(seconds/60);
00353         seconds -= minutes * 60;
00354         cout << " \nRun completed in ";
00355         if (hours > 0)
00356             cout << hours << " h ";
00357         if (hours > 0 || minutes > 0)
00358             cout << minutes << " m ";
00359         cout << fixed << setprecision(0)
00360              << seconds << " s\n" << endl;
00361 
00362         return 0;
00363 
00364     } catch (exception& e) {
00365         cout << e.what() << endl;
00366         return 1;
00367     } catch (...) {
00368         cout << "unknown error" << endl;
00369         return 1;
00370     }
00371 }
00372