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