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