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 EndCriteria(400, 100, 1.0e-8, 1.0e-8, 1.0e-8));
00073
00074
00075 for (Size i=0; i<numRows; i++) {
00076 Size j = numCols - i -1;
00077 Size k = i*numCols + j;
00078 Real npv = helpers[i]->modelValue();
00079 Volatility implied = helpers[i]->impliedVolatility(npv, 1e-4,
00080 1000, 0.05, 0.50);
00081 Volatility diff = implied - swaptionVols[k];
00082
00083 std::cout << i+1 << "x" << swapLenghts[j]
00084 << std::setprecision(5) << std::noshowpos
00085 << ": model " << std::setw(7) << io::volatility(implied)
00086 << ", market " << std::setw(7)
00087 << io::volatility(swaptionVols[k])
00088 << " (" << std::setw(7) << std::showpos
00089 << io::volatility(diff) << std::noshowpos << ")\n";
00090 }
00091 }
00092
00093 int main(int, char* []) {
00094
00095 try {
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 Handle<YieldTermStructure> rhTermStructure(
00108 boost::shared_ptr<FlatForward>(
00109 new FlatForward(settlementDate, Handle<Quote>(flatRate),
00110 Actual365Fixed())));
00111
00112
00113 Frequency fixedLegFrequency = Annual;
00114 BusinessDayConvention fixedLegConvention = Unadjusted;
00115 BusinessDayConvention floatingLegConvention = ModifiedFollowing;
00116 DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
00117 Frequency floatingLegFrequency = Semiannual;
00118 VanillaSwap::Type type = VanillaSwap::Payer;
00119 Rate dummyFixedRate = 0.03;
00120 boost::shared_ptr<IborIndex> indexSixMonths(new
00121 Euribor6M(rhTermStructure));
00122
00123 Date startDate = calendar.advance(settlementDate,1,Years,
00124 floatingLegConvention);
00125 Date maturity = calendar.advance(startDate,5,Years,
00126 floatingLegConvention);
00127 Schedule fixedSchedule(startDate,maturity,Period(fixedLegFrequency),
00128 calendar,fixedLegConvention,fixedLegConvention,
00129 false,false);
00130 Schedule floatSchedule(startDate,maturity,Period(floatingLegFrequency),
00131 calendar,floatingLegConvention,floatingLegConvention,
00132 false,false);
00133
00134 boost::shared_ptr<VanillaSwap> swap(new VanillaSwap(
00135 type, 1000.0,
00136 fixedSchedule, dummyFixedRate, fixedLegDayCounter,
00137 floatSchedule, indexSixMonths, 0.0,
00138 indexSixMonths->dayCounter(), rhTermStructure));
00139 Rate fixedATMRate = swap->fairRate();
00140 Rate fixedOTMRate = fixedATMRate * 1.2;
00141 Rate fixedITMRate = fixedATMRate * 0.8;
00142
00143 boost::shared_ptr<VanillaSwap> atmSwap(new VanillaSwap(
00144 type, 1000.0,
00145 fixedSchedule, fixedATMRate, fixedLegDayCounter,
00146 floatSchedule, indexSixMonths, 0.0,
00147 indexSixMonths->dayCounter(), rhTermStructure));
00148 boost::shared_ptr<VanillaSwap> otmSwap(new VanillaSwap(
00149 type, 1000.0,
00150 fixedSchedule, fixedOTMRate, fixedLegDayCounter,
00151 floatSchedule, indexSixMonths, 0.0,
00152 indexSixMonths->dayCounter(), rhTermStructure));
00153 boost::shared_ptr<VanillaSwap> itmSwap(new VanillaSwap(
00154 type, 1000.0,
00155 fixedSchedule, fixedITMRate, fixedLegDayCounter,
00156 floatSchedule, indexSixMonths, 0.0,
00157 indexSixMonths->dayCounter(), rhTermStructure));
00158
00159
00160 std::vector<Period> swaptionMaturities;
00161 swaptionMaturities.push_back(Period(1, Years));
00162 swaptionMaturities.push_back(Period(2, Years));
00163 swaptionMaturities.push_back(Period(3, Years));
00164 swaptionMaturities.push_back(Period(4, Years));
00165 swaptionMaturities.push_back(Period(5, Years));
00166
00167 std::vector<boost::shared_ptr<CalibrationHelper> > swaptions;
00168
00169
00170 std::list<Time> times;
00171
00172 Size i;
00173 for (i=0; i<numRows; i++) {
00174 Size j = numCols - i -1;
00175 Size k = i*numCols + j;
00176 boost::shared_ptr<Quote> vol(new SimpleQuote(swaptionVols[k]));
00177 swaptions.push_back(boost::shared_ptr<CalibrationHelper>(new
00178 SwaptionHelper(swaptionMaturities[i],
00179 Period(swapLenghts[j], Years),
00180 Handle<Quote>(vol),
00181 indexSixMonths,
00182 indexSixMonths->tenor(),
00183 indexSixMonths->dayCounter(),
00184 indexSixMonths->dayCounter(),
00185 rhTermStructure)));
00186 swaptions.back()->addTimesTo(times);
00187 }
00188
00189
00190 TimeGrid grid(times.begin(), times.end(), 30);
00191
00192
00193
00194 boost::shared_ptr<G2> modelG2(new G2(rhTermStructure));
00195 boost::shared_ptr<HullWhite> modelHW(new HullWhite(rhTermStructure));
00196 boost::shared_ptr<HullWhite> modelHW2(new HullWhite(rhTermStructure));
00197 boost::shared_ptr<BlackKarasinski> modelBK(
00198 new BlackKarasinski(rhTermStructure));
00199
00200
00201
00202
00203 std::cout << "G2 (analytic formulae) calibration" << std::endl;
00204 for (i=0; i<swaptions.size(); i++)
00205 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00206 new G2SwaptionEngine(modelG2, 6.0, 16)));
00207
00208 calibrateModel(modelG2, swaptions);
00209 std::cout << "calibrated to:\n"
00210 << "a = " << modelG2->params()[0] << ", "
00211 << "sigma = " << modelG2->params()[1] << "\n"
00212 << "b = " << modelG2->params()[2] << ", "
00213 << "eta = " << modelG2->params()[3] << "\n"
00214 << "rho = " << modelG2->params()[4]
00215 << std::endl << std::endl;
00216
00217
00218
00219 std::cout << "Hull-White (analytic formulae) calibration" << std::endl;
00220 for (i=0; i<swaptions.size(); i++)
00221 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00222 new JamshidianSwaptionEngine(modelHW)));
00223
00224 calibrateModel(modelHW, swaptions);
00225 std::cout << "calibrated to:\n"
00226 << "a = " << modelHW->params()[0] << ", "
00227 << "sigma = " << modelHW->params()[1]
00228 << std::endl << std::endl;
00229
00230 std::cout << "Hull-White (numerical) calibration" << std::endl;
00231 for (i=0; i<swaptions.size(); i++)
00232 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00233 new TreeSwaptionEngine(modelHW2,grid)));
00234
00235 calibrateModel(modelHW2, swaptions);
00236 std::cout << "calibrated to:\n"
00237 << "a = " << modelHW2->params()[0] << ", "
00238 << "sigma = " << modelHW2->params()[1]
00239 << std::endl << std::endl;
00240
00241 std::cout << "Black-Karasinski (numerical) calibration" << std::endl;
00242 for (i=0; i<swaptions.size(); i++)
00243 swaptions[i]->setPricingEngine(boost::shared_ptr<PricingEngine>(
00244 new TreeSwaptionEngine(modelBK,grid)));
00245
00246 calibrateModel(modelBK, swaptions);
00247 std::cout << "calibrated to:\n"
00248 << "a = " << modelBK->params()[0] << ", "
00249 << "sigma = " << modelBK->params()[1]
00250 << std::endl << std::endl;
00251
00252
00253
00254
00255 std::cout << "Payer bermudan swaption "
00256 << "struck at " << io::rate(fixedATMRate)
00257 << " (ATM)" << std::endl;
00258
00259 std::vector<Date> bermudanDates;
00260 const std::vector<boost::shared_ptr<CashFlow> >& leg =
00261 swap->fixedLeg();
00262 for (i=0; i<leg.size(); i++) {
00263 boost::shared_ptr<Coupon> coupon =
00264 boost::dynamic_pointer_cast<Coupon>(leg[i]);
00265 bermudanDates.push_back(coupon->accrualStartDate());
00266 }
00267
00268 boost::shared_ptr<Exercise> bermudanExercise(
00269 new BermudanExercise(bermudanDates));
00270
00271 Swaption bermudanSwaption(atmSwap, bermudanExercise, rhTermStructure,
00272 boost::shared_ptr<PricingEngine>());
00273
00274
00275
00276
00277 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(new
00278 TreeSwaptionEngine(modelG2, 50)));
00279 std::cout << "G2: " << bermudanSwaption.NPV() << std::endl;
00280
00281 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00282 new TreeSwaptionEngine(modelHW, 50)));
00283 std::cout << "HW: " << bermudanSwaption.NPV() << std::endl;
00284
00285 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(new
00286 TreeSwaptionEngine(modelHW2, 50)));
00287 std::cout << "HW (num): " << bermudanSwaption.NPV() << std::endl;
00288
00289 bermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(new
00290 TreeSwaptionEngine(modelBK, 50)));
00291 std::cout << "BK: " << bermudanSwaption.NPV() << std::endl;
00292
00293
00294
00295
00296 std::cout << "Payer bermudan swaption "
00297 << "struck at " << io::rate(fixedOTMRate)
00298 << " (OTM)" << std::endl;
00299
00300 Swaption otmBermudanSwaption(otmSwap,bermudanExercise,rhTermStructure,
00301 boost::shared_ptr<PricingEngine>());
00302
00303
00304 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00305 new TreeSwaptionEngine(modelG2, 50)));
00306 std::cout << "G2: " << otmBermudanSwaption.NPV() << std::endl;
00307
00308 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00309 new TreeSwaptionEngine(modelHW, 50)));
00310 std::cout << "HW: " << otmBermudanSwaption.NPV() << std::endl;
00311
00312 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00313 new TreeSwaptionEngine(modelHW2, 50)));
00314 std::cout << "HW (num): " << otmBermudanSwaption.NPV() << std::endl;
00315
00316 otmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00317 new TreeSwaptionEngine(modelBK, 50)));
00318 std::cout << "BK: " << otmBermudanSwaption.NPV() << std::endl;
00319
00320
00321
00322
00323 std::cout << "Payer bermudan swaption "
00324 << "struck at " << io::rate(fixedITMRate)
00325 << " (ITM)" << std::endl;
00326
00327 Swaption itmBermudanSwaption(itmSwap,bermudanExercise,rhTermStructure,
00328 boost::shared_ptr<PricingEngine>());
00329
00330
00331 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00332 new TreeSwaptionEngine(modelG2, 50)));
00333 std::cout << "G2: " << itmBermudanSwaption.NPV() << std::endl;
00334
00335 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00336 new TreeSwaptionEngine(modelHW, 50)));
00337 std::cout << "HW: " << itmBermudanSwaption.NPV() << std::endl;
00338
00339 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00340 new TreeSwaptionEngine(modelHW2, 50)));
00341 std::cout << "HW (num): " << itmBermudanSwaption.NPV() << std::endl;
00342
00343 itmBermudanSwaption.setPricingEngine(boost::shared_ptr<PricingEngine>(
00344 new TreeSwaptionEngine(modelBK, 50)));
00345 std::cout << "BK: " << itmBermudanSwaption.NPV() << std::endl;
00346
00347 Real seconds = timer.elapsed();
00348 Integer hours = int(seconds/3600);
00349 seconds -= hours * 3600;
00350 Integer minutes = int(seconds/60);
00351 seconds -= minutes * 60;
00352 std::cout << " \nRun completed in ";
00353 if (hours > 0)
00354 std::cout << hours << " h ";
00355 if (hours > 0 || minutes > 0)
00356 std::cout << minutes << " m ";
00357 std::cout << std::fixed << std::setprecision(0)
00358 << seconds << " s\n" << std::endl;
00359
00360 return 0;
00361 } catch (std::exception& e) {
00362 std::cout << e.what() << std::endl;
00363 return 1;
00364 } catch (...) {
00365 std::cout << "unknown error" << std::endl;
00366 return 1;
00367 }
00368 }
00369