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         QL_IO_INIT
00060 
00061         boost::timer timer;
00062         std::cout << std::endl;
00063 
00064         /*********************
00065          ***  MARKET DATA  ***
00066          *********************/
00067 
00068         Handle<YieldTermStructure> euriborTermStructure;
00069         boost::shared_ptr<Xibor> euribor3m(
00070                                        new Euribor3M(euriborTermStructure));
00071 
00072         Date todaysDate = Date(23, May, 2006);
00073         Settings::instance().evaluationDate() = todaysDate;
00074 
00075         Calendar calendar = euribor3m->calendar();
00076         Integer fixingDays = euribor3m->settlementDays();
00077         Date settlementDate = calendar.advance(todaysDate, fixingDays, Days);
00078 
00079         std::cout << "Today: " << todaysDate.weekday()
00080                   << ", " << todaysDate << std::endl;
00081 
00082         std::cout << "Settlement date: " << settlementDate.weekday()
00083                   << ", " << settlementDate << std::endl;
00084 
00085 
00086         // 3 month term FRA quotes (index refers to monthsToStart)
00087         Rate threeMonthFraQuote[10];
00088 
00089         threeMonthFraQuote[1]=0.030;
00090         threeMonthFraQuote[2]=0.031;
00091         threeMonthFraQuote[3]=0.032;
00092         threeMonthFraQuote[6]=0.033;
00093         threeMonthFraQuote[9]=0.034;
00094 
00095         /********************
00096          ***    QUOTES    ***
00097          ********************/
00098 
00099         // SimpleQuote stores a value which can be manually changed;
00100         // other Quote subclasses could read the value from a database
00101         // or some kind of data feed.
00102 
00103 
00104         // FRAs
00105         boost::shared_ptr<SimpleQuote> fra1x4Rate(
00106                                       new SimpleQuote(threeMonthFraQuote[1]));
00107         boost::shared_ptr<SimpleQuote> fra2x5Rate(
00108                                       new SimpleQuote(threeMonthFraQuote[2]));
00109         boost::shared_ptr<SimpleQuote> fra3x6Rate(
00110                                       new SimpleQuote(threeMonthFraQuote[3]));
00111         boost::shared_ptr<SimpleQuote> fra6x9Rate(
00112                                       new SimpleQuote(threeMonthFraQuote[6]));
00113         boost::shared_ptr<SimpleQuote> fra9x12Rate(
00114                                       new SimpleQuote(threeMonthFraQuote[9]));
00115 
00116         Handle<Quote> h1x4;  h1x4.linkTo(fra1x4Rate);
00117         Handle<Quote> h2x5;  h2x5.linkTo(fra2x5Rate);
00118         Handle<Quote> h3x6;  h3x6.linkTo(fra3x6Rate);
00119         Handle<Quote> h6x9;  h6x9.linkTo(fra6x9Rate);
00120         Handle<Quote> h9x12; h9x12.linkTo(fra9x12Rate);
00121 
00122         /*********************
00123          ***  RATE HELPERS ***
00124          *********************/
00125 
00126         // RateHelpers are built from the above quotes together with
00127         // other instrument dependant infos.  Quotes are passed in
00128         // relinkable handles which could be relinked to some other
00129         // data source later.
00130 
00131         DayCounter fraDayCounter = euribor3m->dayCounter();
00132         BusinessDayConvention convention = euribor3m->businessDayConvention();
00133 
00134         boost::shared_ptr<RateHelper> fra1x4(
00135                            new FraRateHelper(h1x4, 1, 4,
00136                                              fixingDays, calendar, convention,
00137                                              fraDayCounter));
00138 
00139         boost::shared_ptr<RateHelper> fra2x5(
00140                            new FraRateHelper(h2x5, 2, 5,
00141                                              fixingDays, calendar, convention,
00142                                              fraDayCounter));
00143 
00144         boost::shared_ptr<RateHelper> fra3x6(
00145                            new FraRateHelper(h3x6, 3, 6,
00146                                              fixingDays, calendar, convention,
00147                                              fraDayCounter));
00148 
00149         boost::shared_ptr<RateHelper> fra6x9(
00150                            new FraRateHelper(h6x9, 6, 9,
00151                                              fixingDays, calendar, convention,
00152                                              fraDayCounter));
00153 
00154         boost::shared_ptr<RateHelper> fra9x12(
00155                            new FraRateHelper(h9x12, 9, 12,
00156                                              fixingDays, calendar, convention,
00157                                              fraDayCounter));
00158 
00159 
00160         /*********************
00161          **  CURVE BUILDING **
00162          *********************/
00163 
00164         // Any DayCounter would be fine.
00165         // ActualActual::ISDA ensures that 30 years is 30.0
00166         DayCounter termStructureDayCounter =
00167             ActualActual(ActualActual::ISDA);
00168 
00169         double tolerance = 1.0e-15;
00170 
00171         // A FRA curve
00172         std::vector<boost::shared_ptr<RateHelper> > fraInstruments;
00173 
00174         fraInstruments.push_back(fra1x4);
00175         fraInstruments.push_back(fra2x5);
00176         fraInstruments.push_back(fra3x6);
00177         fraInstruments.push_back(fra6x9);
00178         fraInstruments.push_back(fra9x12);
00179 
00180         boost::shared_ptr<YieldTermStructure> fraTermStructure(new
00181                     PiecewiseFlatForward(settlementDate, fraInstruments,
00182                                          termStructureDayCounter, tolerance));
00183 
00184 
00185         // Term structures used for pricing/discounting
00186 
00187         Handle<YieldTermStructure> discountingTermStructure;
00188         discountingTermStructure.linkTo(fraTermStructure);
00189 
00190 
00191         /***********************
00192          ***  construct FRA's ***
00193          ***********************/
00194 
00195         Calendar fraCalendar = euribor3m->calendar();
00196         BusinessDayConvention fraBusinessDayConvention =
00197             euribor3m->businessDayConvention();
00198         Position::Type fraFwdType = Position::Long;
00199         Real fraNotional = 100.0;
00200         const Integer FraTermMonths = 3;
00201         Integer monthsToStart[] = { 1, 2, 3, 6, 9 };
00202 
00203         euriborTermStructure.linkTo(fraTermStructure);
00204 
00205         cout << endl;
00206         cout << "Test FRA construction, NPV calculation, and FRA purchase"
00207              << endl
00208              << endl;
00209 
00210         Size i;
00211         for (i=0; i<LENGTH(monthsToStart); i++) {
00212 
00213             Date fraValueDate = fraCalendar.advance(
00214                                        settlementDate,monthsToStart[i],Months,
00215                                        fraBusinessDayConvention);
00216 
00217             Date fraMaturityDate = fraCalendar.advance(
00218                                             fraValueDate,FraTermMonths,Months,
00219                                             fraBusinessDayConvention);
00220 
00221             Rate fraStrikeRate = threeMonthFraQuote[monthsToStart[i]];
00222 
00223             ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
00224                                        fraFwdType,fraStrikeRate,
00225                                        fraNotional, euribor3m,
00226                                        discountingTermStructure);
00227 
00228             cout << "3m Term FRA, Months to Start: "
00229                  << monthsToStart[i]
00230                  << endl;
00231             cout << "strike FRA rate: "
00232                  << io::rate(fraStrikeRate)
00233                  << endl;
00234             cout << "FRA 3m forward rate: "
00235                  << myFRA.forwardRate()
00236                  << endl;
00237             cout << "FRA market quote: "
00238                  << io::rate(threeMonthFraQuote[monthsToStart[i]])
00239                  << endl;
00240             cout << "FRA spot value: "
00241                  << myFRA.spotValue()
00242                  << endl;
00243             cout << "FRA forward value: "
00244                  << myFRA.forwardValue()
00245                  << endl;
00246             cout << "FRA implied Yield: "
00247                  << myFRA.impliedYield(myFRA.spotValue(),
00248                                        myFRA.forwardValue(),
00249                                        settlementDate,
00250                                        Simple,
00251                                        fraDayCounter)
00252                  << endl;
00253             cout << "market Zero Rate: "
00254                  << discountingTermStructure->zeroRate(fraMaturityDate,
00255                                                        fraDayCounter,
00256                                                        Simple)
00257                  << endl;
00258             cout << "FRA NPV [should be zero]: "
00259                  << myFRA.NPV()
00260                  << endl
00261                  << endl;
00262 
00263         }
00264 
00265 
00266 
00267 
00268         cout << endl << endl;
00269         cout << "Now take a 100 basis-point upward shift in FRA quotes "
00270              << "and examine NPV"
00271              << endl
00272              << endl;
00273 
00274         const Real BpsShift = 0.01;
00275 
00276         threeMonthFraQuote[1]=0.030+BpsShift;
00277         threeMonthFraQuote[2]=0.031+BpsShift;
00278         threeMonthFraQuote[3]=0.032+BpsShift;
00279         threeMonthFraQuote[6]=0.033+BpsShift;
00280         threeMonthFraQuote[9]=0.034+BpsShift;
00281 
00282         fra1x4Rate->setValue(threeMonthFraQuote[1]);
00283         fra2x5Rate->setValue(threeMonthFraQuote[2]);
00284         fra3x6Rate->setValue(threeMonthFraQuote[3]);
00285         fra6x9Rate->setValue(threeMonthFraQuote[6]);
00286         fra9x12Rate->setValue(threeMonthFraQuote[9]);
00287 
00288 
00289         for (i=0; i<LENGTH(monthsToStart); i++) {
00290 
00291             Date fraValueDate = fraCalendar.advance(
00292                                        settlementDate,monthsToStart[i],Months,
00293                                        fraBusinessDayConvention);
00294 
00295             Date fraMaturityDate = fraCalendar.advance(
00296                                             fraValueDate,FraTermMonths,Months,
00297                                             fraBusinessDayConvention);
00298 
00299             Rate fraStrikeRate =
00300                 threeMonthFraQuote[monthsToStart[i]] - BpsShift;
00301 
00302             ForwardRateAgreement myFRA(fraValueDate, fraMaturityDate,
00303                                        fraFwdType, fraStrikeRate,
00304                                        fraNotional, euribor3m,
00305                                        discountingTermStructure);
00306 
00307             cout << "3m Term FRA, 100 notional, Months to Start = "
00308                  << monthsToStart[i]
00309                  << endl;
00310             cout << "strike FRA rate: "
00311                  << io::rate(fraStrikeRate)
00312                  << endl;
00313             cout << "FRA 3m forward rate: "
00314                  << myFRA.forwardRate()
00315                  << endl;
00316             cout << "FRA market quote: "
00317                  << io::rate(threeMonthFraQuote[monthsToStart[i]])
00318                  << endl;
00319             cout << "FRA spot value: "
00320                  << myFRA.spotValue()
00321                  << endl;
00322             cout << "FRA forward value: "
00323                  << myFRA.forwardValue()
00324                  << endl;
00325             cout << "FRA implied Yield: "
00326                  << myFRA.impliedYield(myFRA.spotValue(),
00327                                        myFRA.forwardValue(),
00328                                        settlementDate,
00329                                        Simple,
00330                                        fraDayCounter)
00331                  << endl;
00332             cout << "market Zero Rate: "
00333                  << discountingTermStructure->zeroRate(fraMaturityDate,
00334                                                        fraDayCounter,
00335                                                        Simple)
00336                  << endl;
00337             cout << "FRA NPV [should be positive]: "
00338                  << myFRA.NPV()
00339                  << endl
00340                  << endl;
00341         }
00342 
00343         Real seconds = timer.elapsed();
00344         Integer hours = int(seconds/3600);
00345         seconds -= hours * 3600;
00346         Integer minutes = int(seconds/60);
00347         seconds -= minutes * 60;
00348         cout << " \nRun completed in ";
00349         if (hours > 0)
00350             cout << hours << " h ";
00351         if (hours > 0 || minutes > 0)
00352             cout << minutes << " m ";
00353         cout << fixed << setprecision(0)
00354              << seconds << " s\n" << endl;
00355 
00356         return 0;
00357 
00358     } catch (exception& e) {
00359         cout << e.what() << endl;
00360         return 1;
00361     } catch (...) {
00362         cout << "unknown error" << endl;
00363         return 1;
00364     }
00365 }
00366