This is an example of using the QuantLib short rate models.
00001
00002
00022 #define BOOST_LIB_DIAGNOSTIC
00023 # include <ql/quantlib.hpp>
00024 #undef BOOST_LIB_DIAGNOSTIC
00025
00026 #ifdef BOOST_MSVC
00027
00028
00029
00030
00031
00032
00033
00034
00035 #endif
00036
00037 #include <boost/timer.hpp>
00038 #include <iostream>
00039 #include <iomanip>
00040
00041 using namespace QuantLib;
00042
00043 #if defined(QL_ENABLE_SESSIONS)
00044 namespace QuantLib {
00045
00046 Integer sessionId() { return 0; }
00047
00048 }
00049 #endif
00050
00051
00052
00053
00054 Size numRows = 5;
00055 Size numCols = 5;
00056
00057 Integer swapLenghts[] = {
00058 1, 2, 3, 4, 5};
00059 Volatility swaptionVols[] = {
00060 0.1490, 0.1340, 0.1228, 0.1189, 0.1148,
00061 0.1290, 0.1201, 0.1146, 0.1108, 0.1040,
00062 0.1149, 0.1112, 0.1070, 0.1010, 0.0957,
00063 0.1047, 0.1021, 0.0980, 0.0951, 0.1270,
00064 0.1000, 0.0950, 0.0900, 0.1230, 0.1160};
00065
00066 void calibrateModel(
00067 const boost::shared_ptr<ShortRateModel>& model,
00068 const std::vector<boost::shared_ptr<CalibrationHelper> >& helpers) {
00069
00070 LevenbergMarquardt om;
00071 model->calibrate(helpers, om);
00072
00073
00074 for (Size i=0; i<numRows; i++) {
00075 Size j = numCols - i -1;
00076 Size k = i*numCols + j;
00077 Real npv = helpers[i]->modelValue();
00078 Volatility implied = helpers[i]->impliedVolatility(npv, 1e-4,
00079 1000, 0.05, 0.50);
00080 Volatility diff = implied - swaptionVols[k];
00081
00082 std::cout << i+1 << "x" << swapLenghts[j]
00083 << std::setprecision(5) << std::noshowpos
00084 << ": model " << std::setw(7) << io::volatility(implied)
00085 << ", market " << std::setw(7)
00086 << io::volatility(swaptionVols[k])
00087 << " (" << std::setw(7) << std::showpos
00088 << io::volatility(diff) << std::noshowpos << ")\n";
00089 }
00090 }
00091
00092 int main(int, char* [])
00093 {
00094 try {
00095 QL_IO_INIT
00096
00097 boost::timer timer;
00098 std::cout << std::endl;
00099
00100 Date todaysDate(15, February, 2002);
00101 Calendar calendar = TARGET();
00102 Date settlementDate(19, February, 2002);
00103 Settings::instance().evaluationDate() = todaysDate;
00104
00105
00106 boost::shared_ptr<Quote> flatRate(new SimpleQuote(0.04875825));
00107 boost::shared_ptr<FlatForward> myTermStructure(
00108 new FlatForward(settlementDate, Handle<Quote>(flatRate),
00109 Actual365Fixed()));
00110 Handle<YieldTermStructure> rhTermStructure;
00111 rhTermStructure.linkTo(myTermStructure);
00112
00113
00114 Frequency fixedLegFrequency = Annual;
00115 BusinessDayConvention fixedLegConvention = Unadjusted;
00116 BusinessDayConvention floatingLegConvention = ModifiedFollowing;
00117 DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
00118 Frequency floatingLegFrequency = Semiannual;
00119 bool payFixedRate = true;
00120 Rate dummyFixedRate = 0.03;
00121 boost::shared_ptr<Xibor> indexSixMonths(
00122 new Euribor6M(rhTermStructure));
00123
00124 Date startDate = calendar.advance(settlementDate,1,Years,
00125 floatingLegConvention);
00126 Date maturity = calendar.advance(startDate,5,Years,
00127 floatingLegConvention);
00128 Schedule fixedSchedule(startDate,maturity,Period(fixedLegFrequency),
00129 calendar,fixedLegConvention,fixedLegConvention,
00130 false,false);
00131 Schedule floatSchedule(startDate,maturity,Period(floatingLegFrequency),
00132 calendar,floatingLegConvention,floatingLegConvention,
00133 false,false);
00134
00135 boost::shared_ptr<VanillaSwap> swap(new VanillaSwap(
00136 payFixedRate, 1000.0,
00137 fixedSchedule, dummyFixedRate, fixedLegDayCounter,
00138 floatSchedule, indexSixMonths, 0.0,
00139 indexSixMonths->dayCounter(), rhTermStructure));
00140 Rate fixedATMRate = swap->fairRate();
00141 Rate fixedOTMRate = fixedATMRate * 1.2;
00142 Rate fixedITMRate = fixedATMRate * 0.8;
00143
00144 boost::shared_ptr<VanillaSwap> atmSwap(new VanillaSwap(
00145 payFixedRate, 1000.0,
00146 fixedSchedule, fixedATMRate, fixedLegDayCounter,
00147 floatSchedule, indexSixMonths, 0.0,
00148 indexSixMonths->dayCounter(), rhTermStructure));
00149 boost::shared_ptr<VanillaSwap> otmSwap(new VanillaSwap(
00150 payFixedRate, 1000.0,
00151 fixedSchedule, fixedOTMRate, fixedLegDayCounter,
00152 floatSchedule, indexSixMonths, 0.0,
00153 indexSixMonths->dayCounter(), rhTermStructure));
00154 boost::shared_ptr<VanillaSwap> itmSwap(new VanillaSwap(
00155 payFixedRate, 1000.0,
00156 fixedSchedule, fixedITMRate, fixedLegDayCounter,
00157 floatSchedule, indexSixMonths, 0.0,
00158 indexSixMonths->dayCounter(), rhTermStructure));
00159
00160
00161 std::vector<Period> swaptionMaturities;
00162 swaptionMaturities.push_back(Period(1, Years));
00163 swaptionMaturities.push_back(Period(2, Years));
00164 swaptionMaturities.push_back(Period(3, Years));
00165 swaptionMaturities.push_back(Period(4, Years));
00166 swaptionMaturities.push_back(Period(5, Years));
00167
00168 std::vector<boost::shared_ptr<CalibrationHelper> > swaptions;
00169
00170
00171 std::list<Time> times;
00172
00173 Size i;
00174 for (i=0; i<numRows; i++) {
00175 Size j = numCols - i -1;
00176 Size k = i*numCols + j;
00177 boost::shared_ptr<Quote> vol(new SimpleQuote(swaptionVols[k]));
00178 swaptions.push_back(boost::shared_ptr<CalibrationHelper>(new
00179 SwaptionHelper(swaptionMaturities[i],
00180 Period(swapLenghts[j], Years),
00181 Handle<Quote>(vol),
00182 indexSixMonths,
00183 indexSixMonths->tenor(),
00184 indexSixMonths->dayCounter(),
00185 indexSixMonths->dayCounter(),
00186 rhTermStructure)));
00187 swaptions.back()->addTimesTo(times);
00188 }
00189
00190
00191 TimeGrid grid(times.begin(), times.end(), 30);
00192
00193
00194
00195 boost::shared_ptr<G2> modelG2(new G2(rhTermStructure));
00196 boost::shared_ptr<HullWhite> modelHW(new HullWhite(rhTermStructure));
00197 boost::shared_ptr<HullWhite> modelHW2(new HullWhite(rhTermStructure));
00198 boost::shared_ptr<BlackKarasinski> modelBK(
00199 new BlackKarasinski(rhTermStructure));
00200
00201
00202
00203
00204 std::cout << "G2 (analytic formulae) calibration" << std::endl;
00205 for (i=0; i<swaptions.size(); i++)
00206 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00207 new G2SwaptionEngine(modelG2, 6.0, 16)));
00208
00209 calibrateModel(modelG2, swaptions);
00210 std::cout << "calibrated to:\n"
00211 << "a = " << modelG2->params()[0] << ", "
00212 << "sigma = " << modelG2->params()[1] << "\n"
00213 << "b = " << modelG2->params()[2] << ", "
00214 << "eta = " << modelG2->params()[3] << "\n"
00215 << "rho = " << modelG2->params()[4]
00216 << std::endl << std::endl;
00217
00218
00219
00220 std::cout << "Hull-White (analytic formulae) calibration" << std::endl;
00221 for (i=0; i<swaptions.size(); i++)
00222 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00223 new JamshidianSwaptionEngine(modelHW)));
00224
00225 calibrateModel(modelHW, swaptions);
00226 std::cout << "calibrated to:\n"
00227 << "a = " << modelHW->params()[0] << ", "
00228 << "sigma = " << modelHW->params()[1]
00229 << std::endl << std::endl;
00230
00231 std::cout << "Hull-White (numerical) calibration" << std::endl;
00232 for (i=0; i<swaptions.size(); i++)
00233 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00234 new TreeSwaptionEngine(modelHW2,grid)));
00235
00236 calibrateModel(modelHW2, swaptions);
00237 std::cout << "calibrated to:\n"
00238 << "a = " << modelHW2->params()[0] << ", "
00239 << "sigma = " << modelHW2->params()[1]
00240 << std::endl << std::endl;
00241
00242 std::cout << "Black-Karasinski (numerical) calibration" << std::endl;
00243 for (i=0; i<swaptions.size(); i++)
00244 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00245 new TreeSwaptionEngine(modelBK,grid)));
00246
00247 calibrateModel(modelBK, swaptions);
00248 std::cout << "calibrated to:\n"
00249 << "a = " << modelBK->params()[0] << ", "
00250 << "sigma = " << modelBK->params()[1]
00251 << std::endl << std::endl;
00252
00253
00254
00255
00256 std::cout << "Payer bermudan swaption "
00257 << "struck at " << io::rate(fixedATMRate)
00258 << " (ATM)" << std::endl;
00259
00260 std::vector<Date> bermudanDates;
00261 const std::vector<boost::shared_ptr<CashFlow> >& leg =
00262 swap->fixedLeg();
00263 for (i=0; i<leg.size(); i++) {
00264 boost::shared_ptr<Coupon> coupon =
00265 boost::dynamic_pointer_cast<Coupon>(leg[i]);
00266 bermudanDates.push_back(coupon->accrualStartDate());
00267 }
00268
00269 boost::shared_ptr<Exercise> bermudanExercise(
00270 new BermudanExercise(bermudanDates));
00271
00272 Swaption bermudanSwaption(atmSwap, bermudanExercise, rhTermStructure,
00273 boost::shared_ptr<PricingEngine>());
00274
00275
00276
00277
00278 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(new
00279 TreeSwaptionEngine(modelG2, 50)));
00280 std::cout << "G2: " << bermudanSwaption.NPV() << std::endl;
00281
00282 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00283 new TreeSwaptionEngine(modelHW, 50)));
00284 std::cout << "HW: " << bermudanSwaption.NPV() << std::endl;
00285
00286 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(new
00287 TreeSwaptionEngine(modelHW2, 50)));
00288 std::cout << "HW (num): " << bermudanSwaption.NPV() << std::endl;
00289
00290 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(new
00291 TreeSwaptionEngine(modelBK, 50)));
00292 std::cout << "BK: " << bermudanSwaption.NPV() << std::endl;
00293
00294
00295
00296
00297 std::cout << "Payer bermudan swaption "
00298 << "struck at " << io::rate(fixedOTMRate)
00299 << " (OTM)" << std::endl;
00300
00301 Swaption otmBermudanSwaption(otmSwap,bermudanExercise,rhTermStructure,
00302 boost::shared_ptr<PricingEngine>());
00303
00304
00305 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00306 new TreeSwaptionEngine(modelG2, 50)));
00307 std::cout << "G2: " << otmBermudanSwaption.NPV() << std::endl;
00308
00309 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00310 new TreeSwaptionEngine(modelHW, 50)));
00311 std::cout << "HW: " << otmBermudanSwaption.NPV() << std::endl;
00312
00313 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00314 new TreeSwaptionEngine(modelHW2, 50)));
00315 std::cout << "HW (num): " << otmBermudanSwaption.NPV() << std::endl;
00316
00317 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00318 new TreeSwaptionEngine(modelBK, 50)));
00319 std::cout << "BK: " << otmBermudanSwaption.NPV() << std::endl;
00320
00321
00322
00323
00324 std::cout << "Payer bermudan swaption "
00325 << "struck at " << io::rate(fixedITMRate)
00326 << " (ITM)" << std::endl;
00327
00328 Swaption itmBermudanSwaption(itmSwap,bermudanExercise,rhTermStructure,
00329 boost::shared_ptr<PricingEngine>());
00330
00331
00332 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00333 new TreeSwaptionEngine(modelG2, 50)));
00334 std::cout << "G2: " << itmBermudanSwaption.NPV() << std::endl;
00335
00336 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00337 new TreeSwaptionEngine(modelHW, 50)));
00338 std::cout << "HW: " << itmBermudanSwaption.NPV() << std::endl;
00339
00340 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00341 new TreeSwaptionEngine(modelHW2, 50)));
00342 std::cout << "HW (num): " << itmBermudanSwaption.NPV() << std::endl;
00343
00344 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00345 new TreeSwaptionEngine(modelBK, 50)));
00346 std::cout << "BK: " << itmBermudanSwaption.NPV() << std::endl;
00347
00348 Real seconds = timer.elapsed();
00349 Integer hours = int(seconds/3600);
00350 seconds -= hours * 3600;
00351 Integer minutes = int(seconds/60);
00352 seconds -= minutes * 60;
00353 std::cout << " \nRun completed in ";
00354 if (hours > 0)
00355 std::cout << hours << " h ";
00356 if (hours > 0 || minutes > 0)
00357 std::cout << minutes << " m ";
00358 std::cout << std::fixed << std::setprecision(0)
00359 << seconds << " s\n" << std::endl;
00360
00361 return 0;
00362 } catch (std::exception& e) {
00363 std::cout << e.what() << std::endl;
00364 return 1;
00365 } catch (...) {
00366 std::cout << "unknown error" << std::endl;
00367 return 1;
00368 }
00369 }
00370