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