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