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