swapvaluation.cpp
This is an example of using the QuantLib Term Structure for pricing a simple swap.
00001 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 00002 00022 /* This example shows how to set up a Term Structure and then price a simple 00023 swap. 00024 */ 00025 00026 // the only header you need to use QuantLib 00027 #define BOOST_LIB_DIAGNOSTIC 00028 # include <ql/quantlib.hpp> 00029 #undef BOOST_LIB_DIAGNOSTIC 00030 00031 #ifdef BOOST_MSVC 00032 /* Uncomment the following lines to unmask floating-point 00033 exceptions. Warning: unpredictable results can arise... 00034 00035 See http://www.wilmott.com/messageview.cfm?catid=10&threadid=9481 00036 Is there anyone with a definitive word about this? 00037 */ 00038 // #include <float.h> 00039 // namespace { unsigned int u = _controlfp(_EM_INEXACT, _MCW_EM); } 00040 #endif 00041 00042 #include <boost/timer.hpp> 00043 #include <iostream> 00044 #include <iomanip> 00045 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 00057 int main(int, char* []) 00058 { 00059 try { 00060 QL_IO_INIT 00061 00062 boost::timer timer; 00063 std::cout << std::endl; 00064 00065 /********************* 00066 *** MARKET DATA *** 00067 *********************/ 00068 00069 Calendar calendar = TARGET(); 00070 // uncommenting the following line generates an error 00071 // calendar = Tokyo(); 00072 Date settlementDate(22, September, 2004); 00073 // must be a business day 00074 settlementDate = calendar.adjust(settlementDate); 00075 00076 Integer fixingDays = 2; 00077 Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days); 00078 // nothing to do with Date::todaysDate 00079 Settings::instance().evaluationDate() = todaysDate; 00080 00081 00082 todaysDate = Settings::instance().evaluationDate(); 00083 std::cout << "Today: " << todaysDate.weekday() 00084 << ", " << todaysDate << std::endl; 00085 00086 std::cout << "Settlement date: " << settlementDate.weekday() 00087 << ", " << settlementDate << std::endl; 00088 00089 // deposits 00090 Rate d1wQuote=0.0382; 00091 Rate d1mQuote=0.0372; 00092 Rate d3mQuote=0.0363; 00093 Rate d6mQuote=0.0353; 00094 Rate d9mQuote=0.0348; 00095 Rate d1yQuote=0.0345; 00096 // FRAs 00097 Rate fra3x6Quote=0.037125; 00098 Rate fra6x9Quote=0.037125; 00099 Rate fra6x12Quote=0.037125; 00100 // futures 00101 Real fut1Quote=96.2875; 00102 Real fut2Quote=96.7875; 00103 Real fut3Quote=96.9875; 00104 Real fut4Quote=96.6875; 00105 Real fut5Quote=96.4875; 00106 Real fut6Quote=96.3875; 00107 Real fut7Quote=96.2875; 00108 Real fut8Quote=96.0875; 00109 // swaps 00110 Rate s2yQuote=0.037125; 00111 Rate s3yQuote=0.0398; 00112 Rate s5yQuote=0.0443; 00113 Rate s10yQuote=0.05165; 00114 Rate s15yQuote=0.055175; 00115 00116 00117 /******************** 00118 *** QUOTES *** 00119 ********************/ 00120 00121 // SimpleQuote stores a value which can be manually changed; 00122 // other Quote subclasses could read the value from a database 00123 // or some kind of data feed. 00124 00125 // deposits 00126 boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote)); 00127 boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote)); 00128 boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote)); 00129 boost::shared_ptr<Quote> d6mRate(new SimpleQuote(d6mQuote)); 00130 boost::shared_ptr<Quote> d9mRate(new SimpleQuote(d9mQuote)); 00131 boost::shared_ptr<Quote> d1yRate(new SimpleQuote(d1yQuote)); 00132 // FRAs 00133 boost::shared_ptr<Quote> fra3x6Rate(new SimpleQuote(fra3x6Quote)); 00134 boost::shared_ptr<Quote> fra6x9Rate(new SimpleQuote(fra6x9Quote)); 00135 boost::shared_ptr<Quote> fra6x12Rate(new SimpleQuote(fra6x12Quote)); 00136 // futures 00137 boost::shared_ptr<Quote> fut1Price(new SimpleQuote(fut1Quote)); 00138 boost::shared_ptr<Quote> fut2Price(new SimpleQuote(fut2Quote)); 00139 boost::shared_ptr<Quote> fut3Price(new SimpleQuote(fut3Quote)); 00140 boost::shared_ptr<Quote> fut4Price(new SimpleQuote(fut4Quote)); 00141 boost::shared_ptr<Quote> fut5Price(new SimpleQuote(fut5Quote)); 00142 boost::shared_ptr<Quote> fut6Price(new SimpleQuote(fut6Quote)); 00143 boost::shared_ptr<Quote> fut7Price(new SimpleQuote(fut7Quote)); 00144 boost::shared_ptr<Quote> fut8Price(new SimpleQuote(fut8Quote)); 00145 // swaps 00146 boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote)); 00147 boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote)); 00148 boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote)); 00149 boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote)); 00150 boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote)); 00151 00152 00153 /********************* 00154 *** RATE HELPERS *** 00155 *********************/ 00156 00157 // RateHelpers are built from the above quotes together with 00158 // other instrument dependant infos. Quotes are passed in 00159 // relinkable handles which could be relinked to some other 00160 // data source later. 00161 00162 // deposits 00163 DayCounter depositDayCounter = Actual360(); 00164 00165 boost::shared_ptr<RateHelper> d1w(new DepositRateHelper( 00166 Handle<Quote>(d1wRate), 00167 1*Weeks, fixingDays, 00168 calendar, ModifiedFollowing, depositDayCounter)); 00169 boost::shared_ptr<RateHelper> d1m(new DepositRateHelper( 00170 Handle<Quote>(d1mRate), 00171 1*Months, fixingDays, 00172 calendar, ModifiedFollowing, depositDayCounter)); 00173 boost::shared_ptr<RateHelper> d3m(new DepositRateHelper( 00174 Handle<Quote>(d3mRate), 00175 3*Months, fixingDays, 00176 calendar, ModifiedFollowing, depositDayCounter)); 00177 boost::shared_ptr<RateHelper> d6m(new DepositRateHelper( 00178 Handle<Quote>(d6mRate), 00179 6*Months, fixingDays, 00180 calendar, ModifiedFollowing, depositDayCounter)); 00181 boost::shared_ptr<RateHelper> d9m(new DepositRateHelper( 00182 Handle<Quote>(d9mRate), 00183 9*Months, fixingDays, 00184 calendar, ModifiedFollowing, depositDayCounter)); 00185 boost::shared_ptr<RateHelper> d1y(new DepositRateHelper( 00186 Handle<Quote>(d1yRate), 00187 1*Years, fixingDays, 00188 calendar, ModifiedFollowing, depositDayCounter)); 00189 00190 00191 // setup FRAs 00192 boost::shared_ptr<RateHelper> fra3x6(new FraRateHelper( 00193 Handle<Quote>(fra3x6Rate), 00194 3, 6, fixingDays, calendar, ModifiedFollowing, 00195 depositDayCounter)); 00196 boost::shared_ptr<RateHelper> fra6x9(new FraRateHelper( 00197 Handle<Quote>(fra6x9Rate), 00198 6, 9, fixingDays, calendar, ModifiedFollowing, 00199 depositDayCounter)); 00200 boost::shared_ptr<RateHelper> fra6x12(new FraRateHelper( 00201 Handle<Quote>(fra6x12Rate), 00202 6, 12, fixingDays, calendar, ModifiedFollowing, 00203 depositDayCounter)); 00204 00205 00206 // setup futures 00207 Rate convexityAdjustment = 0.0; 00208 Integer futMonths = 3; 00209 Date imm = Date::nextIMMdate(settlementDate); 00210 boost::shared_ptr<RateHelper> fut1(new FuturesRateHelper( 00211 Handle<Quote>(fut1Price), 00212 imm, 00213 futMonths, calendar, ModifiedFollowing, 00214 depositDayCounter, convexityAdjustment)); 00215 imm = Date::nextIMMdate(imm+1); 00216 boost::shared_ptr<RateHelper> fut2(new FuturesRateHelper( 00217 Handle<Quote>(fut1Price), 00218 imm, 00219 futMonths, calendar, ModifiedFollowing, 00220 depositDayCounter, convexityAdjustment)); 00221 imm = Date::nextIMMdate(imm+1); 00222 boost::shared_ptr<RateHelper> fut3(new FuturesRateHelper( 00223 Handle<Quote>(fut1Price), 00224 imm, 00225 futMonths, calendar, ModifiedFollowing, 00226 depositDayCounter, convexityAdjustment)); 00227 imm = Date::nextIMMdate(imm+1); 00228 boost::shared_ptr<RateHelper> fut4(new FuturesRateHelper( 00229 Handle<Quote>(fut1Price), 00230 imm, 00231 futMonths, calendar, ModifiedFollowing, 00232 depositDayCounter, convexityAdjustment)); 00233 imm = Date::nextIMMdate(imm+1); 00234 boost::shared_ptr<RateHelper> fut5(new FuturesRateHelper( 00235 Handle<Quote>(fut1Price), 00236 imm, 00237 futMonths, calendar, ModifiedFollowing, 00238 depositDayCounter, convexityAdjustment)); 00239 imm = Date::nextIMMdate(imm+1); 00240 boost::shared_ptr<RateHelper> fut6(new FuturesRateHelper( 00241 Handle<Quote>(fut1Price), 00242 imm, 00243 futMonths, calendar, ModifiedFollowing, 00244 depositDayCounter, convexityAdjustment)); 00245 imm = Date::nextIMMdate(imm+1); 00246 boost::shared_ptr<RateHelper> fut7(new FuturesRateHelper( 00247 Handle<Quote>(fut1Price), 00248 imm, 00249 futMonths, calendar, ModifiedFollowing, 00250 depositDayCounter, convexityAdjustment)); 00251 imm = Date::nextIMMdate(imm+1); 00252 boost::shared_ptr<RateHelper> fut8(new FuturesRateHelper( 00253 Handle<Quote>(fut1Price), 00254 imm, 00255 futMonths, calendar, ModifiedFollowing, 00256 depositDayCounter, convexityAdjustment)); 00257 00258 00259 // setup swaps 00260 Frequency swFixedLegFrequency = Annual; 00261 BusinessDayConvention swFixedLegConvention = Unadjusted; 00262 DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European); 00263 boost::shared_ptr<Xibor> swFloatingLegIndex(new Euribor6M); 00264 00265 boost::shared_ptr<RateHelper> s2y(new SwapRateHelper( 00266 Handle<Quote>(s2yRate), 00267 2*Years, fixingDays, 00268 calendar, swFixedLegFrequency, 00269 swFixedLegConvention, swFixedLegDayCounter, 00270 swFloatingLegIndex)); 00271 boost::shared_ptr<RateHelper> s3y(new SwapRateHelper( 00272 Handle<Quote>(s3yRate), 00273 3*Years, fixingDays, 00274 calendar, swFixedLegFrequency, 00275 swFixedLegConvention, swFixedLegDayCounter, 00276 swFloatingLegIndex)); 00277 boost::shared_ptr<RateHelper> s5y(new SwapRateHelper( 00278 Handle<Quote>(s5yRate), 00279 5*Years, fixingDays, 00280 calendar, swFixedLegFrequency, 00281 swFixedLegConvention, swFixedLegDayCounter, 00282 swFloatingLegIndex)); 00283 boost::shared_ptr<RateHelper> s10y(new SwapRateHelper( 00284 Handle<Quote>(s10yRate), 00285 10*Years, fixingDays, 00286 calendar, swFixedLegFrequency, 00287 swFixedLegConvention, swFixedLegDayCounter, 00288 swFloatingLegIndex)); 00289 boost::shared_ptr<RateHelper> s15y(new SwapRateHelper( 00290 Handle<Quote>(s15yRate), 00291 15*Years, fixingDays, 00292 calendar, swFixedLegFrequency, 00293 swFixedLegConvention, swFixedLegDayCounter, 00294 swFloatingLegIndex)); 00295 00296 00297 /********************* 00298 ** CURVE BUILDING ** 00299 *********************/ 00300 00301 // Any DayCounter would be fine. 00302 // ActualActual::ISDA ensures that 30 years is 30.0 00303 DayCounter termStructureDayCounter = 00304 ActualActual(ActualActual::ISDA); 00305 00306 00307 double tolerance = 1.0e-15; 00308 00309 // A depo-swap curve 00310 std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments; 00311 depoSwapInstruments.push_back(d1w); 00312 depoSwapInstruments.push_back(d1m); 00313 depoSwapInstruments.push_back(d3m); 00314 depoSwapInstruments.push_back(d6m); 00315 depoSwapInstruments.push_back(d9m); 00316 depoSwapInstruments.push_back(d1y); 00317 depoSwapInstruments.push_back(s2y); 00318 depoSwapInstruments.push_back(s3y); 00319 depoSwapInstruments.push_back(s5y); 00320 depoSwapInstruments.push_back(s10y); 00321 depoSwapInstruments.push_back(s15y); 00322 boost::shared_ptr<YieldTermStructure> depoSwapTermStructure(new 00323 PiecewiseFlatForward(settlementDate, depoSwapInstruments, 00324 termStructureDayCounter, tolerance)); 00325 00326 00327 // A depo-futures-swap curve 00328 std::vector<boost::shared_ptr<RateHelper> > depoFutSwapInstruments; 00329 depoFutSwapInstruments.push_back(d1w); 00330 depoFutSwapInstruments.push_back(d1m); 00331 depoFutSwapInstruments.push_back(fut1); 00332 depoFutSwapInstruments.push_back(fut2); 00333 depoFutSwapInstruments.push_back(fut3); 00334 depoFutSwapInstruments.push_back(fut4); 00335 depoFutSwapInstruments.push_back(fut5); 00336 depoFutSwapInstruments.push_back(fut6); 00337 depoFutSwapInstruments.push_back(fut7); 00338 depoFutSwapInstruments.push_back(fut8); 00339 depoFutSwapInstruments.push_back(s3y); 00340 depoFutSwapInstruments.push_back(s5y); 00341 depoFutSwapInstruments.push_back(s10y); 00342 depoFutSwapInstruments.push_back(s15y); 00343 boost::shared_ptr<YieldTermStructure> depoFutSwapTermStructure(new 00344 PiecewiseFlatForward(settlementDate, depoFutSwapInstruments, 00345 termStructureDayCounter, tolerance)); 00346 00347 00348 // A depo-FRA-swap curve 00349 std::vector<boost::shared_ptr<RateHelper> > depoFRASwapInstruments; 00350 depoFRASwapInstruments.push_back(d1w); 00351 depoFRASwapInstruments.push_back(d1m); 00352 depoFRASwapInstruments.push_back(d3m); 00353 depoFRASwapInstruments.push_back(fra3x6); 00354 depoFRASwapInstruments.push_back(fra6x9); 00355 depoFRASwapInstruments.push_back(fra6x12); 00356 depoFRASwapInstruments.push_back(s2y); 00357 depoFRASwapInstruments.push_back(s3y); 00358 depoFRASwapInstruments.push_back(s5y); 00359 depoFRASwapInstruments.push_back(s10y); 00360 depoFRASwapInstruments.push_back(s15y); 00361 boost::shared_ptr<YieldTermStructure> depoFRASwapTermStructure(new 00362 PiecewiseFlatForward(settlementDate, depoFRASwapInstruments, 00363 termStructureDayCounter, tolerance)); 00364 00365 00366 // Term structures that will be used for pricing: 00367 // the one used for discounting cash flows 00368 Handle<YieldTermStructure> discountingTermStructure; 00369 // the one used for forward rate forecasting 00370 Handle<YieldTermStructure> forecastingTermStructure; 00371 00372 00373 /********************* 00374 * SWAPS TO BE PRICED * 00375 **********************/ 00376 00377 // constant nominal 1,000,000 Euro 00378 Real nominal = 1000000.0; 00379 // fixed leg 00380 Frequency fixedLegFrequency = Annual; 00381 BusinessDayConvention fixedLegConvention = Unadjusted; 00382 BusinessDayConvention floatingLegConvention = ModifiedFollowing; 00383 DayCounter fixedLegDayCounter = Thirty360(Thirty360::European); 00384 Rate fixedRate = 0.04; 00385 DayCounter floatingLegDayCounter = Actual360(); 00386 00387 // floating leg 00388 Frequency floatingLegFrequency = Semiannual; 00389 boost::shared_ptr<Xibor> euriborIndex( 00390 new Euribor6M(forecastingTermStructure)); 00391 Spread spread = 0.0; 00392 00393 Integer lenghtInYears = 5; 00394 bool payFixedRate = true; 00395 00396 Date maturity = settlementDate + lenghtInYears*Years; 00397 Schedule fixedSchedule(settlementDate, maturity, Period(fixedLegFrequency), 00398 calendar, fixedLegConvention, fixedLegConvention, 00399 false, false); 00400 Schedule floatSchedule(settlementDate, maturity, Period(floatingLegFrequency), 00401 calendar, floatingLegConvention, floatingLegConvention, 00402 false, false); 00403 VanillaSwap spot5YearSwap( 00404 payFixedRate, nominal, 00405 fixedSchedule, fixedRate, fixedLegDayCounter, 00406 floatSchedule, euriborIndex, spread, 00407 floatingLegDayCounter, discountingTermStructure); 00408 00409 Date fwdStart = calendar.advance(settlementDate, 1, Years); 00410 Date fwdMaturity = fwdStart + lenghtInYears*Years; 00411 Schedule fwdFixedSchedule(fwdStart, fwdMaturity, Period(fixedLegFrequency), 00412 calendar, fixedLegConvention, fixedLegConvention, 00413 false, false); 00414 Schedule fwdFloatSchedule(fwdStart, fwdMaturity, Period(floatingLegFrequency), 00415 calendar, floatingLegConvention, floatingLegConvention, 00416 false, false); 00417 VanillaSwap oneYearForward5YearSwap( 00418 payFixedRate, nominal, 00419 fwdFixedSchedule, fixedRate, fixedLegDayCounter, 00420 fwdFloatSchedule, euriborIndex, spread, 00421 floatingLegDayCounter, discountingTermStructure); 00422 00423 00424 /*************** 00425 * SWAP PRICING * 00426 ****************/ 00427 00428 // utilities for reporting 00429 std::vector<std::string> headers(4); 00430 headers[0] = "term structure"; 00431 headers[1] = "net present value"; 00432 headers[2] = "fair spread"; 00433 headers[3] = "fair fixed rate"; 00434 std::string separator = " | "; 00435 Size width = headers[0].size() + separator.size() 00436 + headers[1].size() + separator.size() 00437 + headers[2].size() + separator.size() 00438 + headers[3].size() + separator.size() - 1; 00439 std::string rule(width, '-'), dblrule(width, '='); 00440 std::string tab(8, ' '); 00441 00442 // calculations 00443 00444 std::cout << dblrule << std::endl; 00445 std::cout << "5-year market swap-rate = " 00446 << std::setprecision(2) << io::rate(s5yRate->value()) 00447 << std::endl; 00448 std::cout << dblrule << std::endl; 00449 00450 std::cout << tab << "5-years swap paying " 00451 << io::rate(fixedRate) << std::endl; 00452 std::cout << headers[0] << separator 00453 << headers[1] << separator 00454 << headers[2] << separator 00455 << headers[3] << separator << std::endl; 00456 std::cout << rule << std::endl; 00457 00458 Real NPV; 00459 Rate fairRate; 00460 Spread fairSpread; 00461 00462 // Of course, you're not forced to really use different curves 00463 forecastingTermStructure.linkTo(depoSwapTermStructure); 00464 discountingTermStructure.linkTo(depoSwapTermStructure); 00465 00466 NPV = spot5YearSwap.NPV(); 00467 fairSpread = spot5YearSwap.fairSpread(); 00468 fairRate = spot5YearSwap.fairRate(); 00469 00470 std::cout << std::setw(headers[0].size()) 00471 << "depo-swap" << separator; 00472 std::cout << std::setw(headers[1].size()) 00473 << std::fixed << std::setprecision(2) << NPV << separator; 00474 std::cout << std::setw(headers[2].size()) 00475 << io::rate(fairSpread) << separator; 00476 std::cout << std::setw(headers[3].size()) 00477 << io::rate(fairRate) << separator; 00478 std::cout << std::endl; 00479 00480 00481 // let's check that the 5 years swap has been correctly re-priced 00482 QL_REQUIRE(std::fabs(fairRate-s5yQuote)<1e-8, 00483 "5-years swap mispriced by " 00484 << io::rate(std::fabs(fairRate-s5yQuote))); 00485 00486 00487 forecastingTermStructure.linkTo(depoFutSwapTermStructure); 00488 discountingTermStructure.linkTo(depoFutSwapTermStructure); 00489 00490 NPV = spot5YearSwap.NPV(); 00491 fairSpread = spot5YearSwap.fairSpread(); 00492 fairRate = spot5YearSwap.fairRate(); 00493 00494 std::cout << std::setw(headers[0].size()) 00495 << "depo-fut-swap" << separator; 00496 std::cout << std::setw(headers[1].size()) 00497 << std::fixed << std::setprecision(2) << NPV << separator; 00498 std::cout << std::setw(headers[2].size()) 00499 << io::rate(fairSpread) << separator; 00500 std::cout << std::setw(headers[3].size()) 00501 << io::rate(fairRate) << separator; 00502 std::cout << std::endl; 00503 00504 QL_REQUIRE(std::fabs(fairRate-s5yQuote)<1e-8, 00505 "5-years swap mispriced!"); 00506 00507 00508 forecastingTermStructure.linkTo(depoFRASwapTermStructure); 00509 discountingTermStructure.linkTo(depoFRASwapTermStructure); 00510 00511 NPV = spot5YearSwap.NPV(); 00512 fairSpread = spot5YearSwap.fairSpread(); 00513 fairRate = spot5YearSwap.fairRate(); 00514 00515 std::cout << std::setw(headers[0].size()) 00516 << "depo-FRA-swap" << separator; 00517 std::cout << std::setw(headers[1].size()) 00518 << std::fixed << std::setprecision(2) << NPV << separator; 00519 std::cout << std::setw(headers[2].size()) 00520 << io::rate(fairSpread) << separator; 00521 std::cout << std::setw(headers[3].size()) 00522 << io::rate(fairRate) << separator; 00523 std::cout << std::endl; 00524 00525 QL_REQUIRE(std::fabs(fairRate-s5yQuote)<1e-8, 00526 "5-years swap mispriced!"); 00527 00528 00529 std::cout << rule << std::endl; 00530 00531 // now let's price the 1Y forward 5Y swap 00532 00533 std::cout << tab << "5-years, 1-year forward swap paying " 00534 << io::rate(fixedRate) << std::endl; 00535 std::cout << headers[0] << separator 00536 << headers[1] << separator 00537 << headers[2] << separator 00538 << headers[3] << separator << std::endl; 00539 std::cout << rule << std::endl; 00540 00541 00542 forecastingTermStructure.linkTo(depoSwapTermStructure); 00543 discountingTermStructure.linkTo(depoSwapTermStructure); 00544 00545 NPV = oneYearForward5YearSwap.NPV(); 00546 fairSpread = oneYearForward5YearSwap.fairSpread(); 00547 fairRate = oneYearForward5YearSwap.fairRate(); 00548 00549 std::cout << std::setw(headers[0].size()) 00550 << "depo-swap" << separator; 00551 std::cout << std::setw(headers[1].size()) 00552 << std::fixed << std::setprecision(2) << NPV << separator; 00553 std::cout << std::setw(headers[2].size()) 00554 << io::rate(fairSpread) << separator; 00555 std::cout << std::setw(headers[3].size()) 00556 << io::rate(fairRate) << separator; 00557 std::cout << std::endl; 00558 00559 00560 forecastingTermStructure.linkTo(depoFutSwapTermStructure); 00561 discountingTermStructure.linkTo(depoFutSwapTermStructure); 00562 00563 NPV = oneYearForward5YearSwap.NPV(); 00564 fairSpread = oneYearForward5YearSwap.fairSpread(); 00565 fairRate = oneYearForward5YearSwap.fairRate(); 00566 00567 std::cout << std::setw(headers[0].size()) 00568 << "depo-fut-swap" << separator; 00569 std::cout << std::setw(headers[1].size()) 00570 << std::fixed << std::setprecision(2) << NPV << separator; 00571 std::cout << std::setw(headers[2].size()) 00572 << io::rate(fairSpread) << separator; 00573 std::cout << std::setw(headers[3].size()) 00574 << io::rate(fairRate) << separator; 00575 std::cout << std::endl; 00576 00577 00578 forecastingTermStructure.linkTo(depoFRASwapTermStructure); 00579 discountingTermStructure.linkTo(depoFRASwapTermStructure); 00580 00581 NPV = oneYearForward5YearSwap.NPV(); 00582 fairSpread = oneYearForward5YearSwap.fairSpread(); 00583 fairRate = oneYearForward5YearSwap.fairRate(); 00584 00585 std::cout << std::setw(headers[0].size()) 00586 << "depo-FRA-swap" << separator; 00587 std::cout << std::setw(headers[1].size()) 00588 << std::fixed << std::setprecision(2) << NPV << separator; 00589 std::cout << std::setw(headers[2].size()) 00590 << io::rate(fairSpread) << separator; 00591 std::cout << std::setw(headers[3].size()) 00592 << io::rate(fairRate) << separator; 00593 std::cout << std::endl; 00594 00595 00596 // now let's say that the 5-years swap rate goes up to 4.60%. 00597 // A smarter market element--say, connected to a data source-- would 00598 // notice the change itself. Since we're using SimpleQuotes, 00599 // we'll have to change the value manually--which forces us to 00600 // downcast the handle and use the SimpleQuote 00601 // interface. In any case, the point here is that a change in the 00602 // value contained in the Quote triggers a new bootstrapping 00603 // of the curve and a repricing of the swap. 00604 00605 boost::shared_ptr<SimpleQuote> fiveYearsRate = 00606 boost::dynamic_pointer_cast<SimpleQuote>(s5yRate); 00607 fiveYearsRate->setValue(0.0460); 00608 00609 std::cout << dblrule << std::endl; 00610 std::cout << "5-year market swap-rate = " 00611 << io::rate(s5yRate->value()) << std::endl; 00612 std::cout << dblrule << std::endl; 00613 00614 std::cout << tab << "5-years swap paying " 00615 << io::rate(fixedRate) << std::endl; 00616 std::cout << headers[0] << separator 00617 << headers[1] << separator 00618 << headers[2] << separator 00619 << headers[3] << separator << std::endl; 00620 std::cout << rule << std::endl; 00621 00622 // now get the updated results 00623 forecastingTermStructure.linkTo(depoSwapTermStructure); 00624 discountingTermStructure.linkTo(depoSwapTermStructure); 00625 00626 NPV = spot5YearSwap.NPV(); 00627 fairSpread = spot5YearSwap.fairSpread(); 00628 fairRate = spot5YearSwap.fairRate(); 00629 00630 std::cout << std::setw(headers[0].size()) 00631 << "depo-swap" << separator; 00632 std::cout << std::setw(headers[1].size()) 00633 << std::fixed << std::setprecision(2) << NPV << separator; 00634 std::cout << std::setw(headers[2].size()) 00635 << io::rate(fairSpread) << separator; 00636 std::cout << std::setw(headers[3].size()) 00637 << io::rate(fairRate) << separator; 00638 std::cout << std::endl; 00639 00640 QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8, 00641 "5-years swap mispriced!"); 00642 00643 00644 forecastingTermStructure.linkTo(depoFutSwapTermStructure); 00645 discountingTermStructure.linkTo(depoFutSwapTermStructure); 00646 00647 NPV = spot5YearSwap.NPV(); 00648 fairSpread = spot5YearSwap.fairSpread(); 00649 fairRate = spot5YearSwap.fairRate(); 00650 00651 std::cout << std::setw(headers[0].size()) 00652 << "depo-fut-swap" << separator; 00653 std::cout << std::setw(headers[1].size()) 00654 << std::fixed << std::setprecision(2) << NPV << separator; 00655 std::cout << std::setw(headers[2].size()) 00656 << io::rate(fairSpread) << separator; 00657 std::cout << std::setw(headers[3].size()) 00658 << io::rate(fairRate) << separator; 00659 std::cout << std::endl; 00660 00661 QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8, 00662 "5-years swap mispriced!"); 00663 00664 00665 forecastingTermStructure.linkTo(depoFRASwapTermStructure); 00666 discountingTermStructure.linkTo(depoFRASwapTermStructure); 00667 00668 NPV = spot5YearSwap.NPV(); 00669 fairSpread = spot5YearSwap.fairSpread(); 00670 fairRate = spot5YearSwap.fairRate(); 00671 00672 std::cout << std::setw(headers[0].size()) 00673 << "depo-FRA-swap" << separator; 00674 std::cout << std::setw(headers[1].size()) 00675 << std::fixed << std::setprecision(2) << NPV << separator; 00676 std::cout << std::setw(headers[2].size()) 00677 << io::rate(fairSpread) << separator; 00678 std::cout << std::setw(headers[3].size()) 00679 << io::rate(fairRate) << separator; 00680 std::cout << std::endl; 00681 00682 QL_REQUIRE(std::fabs(fairRate-s5yRate->value())<1e-8, 00683 "5-years swap mispriced!"); 00684 00685 std::cout << rule << std::endl; 00686 00687 // the 1Y forward 5Y swap changes as well 00688 00689 std::cout << tab << "5-years, 1-year forward swap paying " 00690 << io::rate(fixedRate) << std::endl; 00691 std::cout << headers[0] << separator 00692 << headers[1] << separator 00693 << headers[2] << separator 00694 << headers[3] << separator << std::endl; 00695 std::cout << rule << std::endl; 00696 00697 00698 forecastingTermStructure.linkTo(depoSwapTermStructure); 00699 discountingTermStructure.linkTo(depoSwapTermStructure); 00700 00701 NPV = oneYearForward5YearSwap.NPV(); 00702 fairSpread = oneYearForward5YearSwap.fairSpread(); 00703 fairRate = oneYearForward5YearSwap.fairRate(); 00704 00705 std::cout << std::setw(headers[0].size()) 00706 << "depo-swap" << separator; 00707 std::cout << std::setw(headers[1].size()) 00708 << std::fixed << std::setprecision(2) << NPV << separator; 00709 std::cout << std::setw(headers[2].size()) 00710 << io::rate(fairSpread) << separator; 00711 std::cout << std::setw(headers[3].size()) 00712 << io::rate(fairRate) << separator; 00713 std::cout << std::endl; 00714 00715 00716 forecastingTermStructure.linkTo(depoFutSwapTermStructure); 00717 discountingTermStructure.linkTo(depoFutSwapTermStructure); 00718 00719 NPV = oneYearForward5YearSwap.NPV(); 00720 fairSpread = oneYearForward5YearSwap.fairSpread(); 00721 fairRate = oneYearForward5YearSwap.fairRate(); 00722 00723 std::cout << std::setw(headers[0].size()) 00724 << "depo-fut-swap" << separator; 00725 std::cout << std::setw(headers[1].size()) 00726 << std::fixed << std::setprecision(2) << NPV << separator; 00727 std::cout << std::setw(headers[2].size()) 00728 << io::rate(fairSpread) << separator; 00729 std::cout << std::setw(headers[3].size()) 00730 << io::rate(fairRate) << separator; 00731 std::cout << std::endl; 00732 00733 00734 forecastingTermStructure.linkTo(depoFRASwapTermStructure); 00735 discountingTermStructure.linkTo(depoFRASwapTermStructure); 00736 00737 NPV = oneYearForward5YearSwap.NPV(); 00738 fairSpread = oneYearForward5YearSwap.fairSpread(); 00739 fairRate = oneYearForward5YearSwap.fairRate(); 00740 00741 std::cout << std::setw(headers[0].size()) 00742 << "depo-FRA-swap" << separator; 00743 std::cout << std::setw(headers[1].size()) 00744 << std::fixed << std::setprecision(2) << NPV << separator; 00745 std::cout << std::setw(headers[2].size()) 00746 << io::rate(fairSpread) << separator; 00747 std::cout << std::setw(headers[3].size()) 00748 << io::rate(fairRate) << separator; 00749 std::cout << std::endl; 00750 00751 Real seconds = timer.elapsed(); 00752 Integer hours = int(seconds/3600); 00753 seconds -= hours * 3600; 00754 Integer minutes = int(seconds/60); 00755 seconds -= minutes * 60; 00756 std::cout << " \nRun completed in "; 00757 if (hours > 0) 00758 std::cout << hours << " h "; 00759 if (hours > 0 || minutes > 0) 00760 std::cout << minutes << " m "; 00761 std::cout << std::fixed << std::setprecision(0) 00762 << seconds << " s\n" << std::endl; 00763 00764 return 0; 00765 00766 } catch (std::exception& e) { 00767 std::cout << e.what() << std::endl; 00768 return 1; 00769 } catch (...) { 00770 std::cout << "unknown error" << std::endl; 00771 return 1; 00772 } 00773 } 00774