BermudanSwaption.cpp

This is an example of using the QuantLib short rate models.

00001 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 //Number of swaptions to be calibrated to...
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     // Output the implied Black volatilities
00059     for (Size i=0; i<numRows; i++) {
00060         Size j = numCols - i -1; // 1x5, 2x4, 3x3, 4x2, 5x1
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         // flat yield term structure impling 1x5 swap at 5%
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         // Define the ATM/OTM/ITM swaps
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         // defining the swaptions to be used in model calibration
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         // List of times that have to be included in the timegrid
00151         std::list<Time> times;
00152 
00153         Size i;
00154         for (i=0; i<numRows; i++) {
00155             Size j = numCols - i -1; // 1x5, 2x4, 3x3, 4x2, 5x1
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         // Building time-grid
00170         TimeGrid grid(times.begin(), times.end(), 30);
00171 
00172 
00173         // defining the models
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         // model calibrations
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         // ATM Bermudan swaption pricing
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         // Do the pricing for each model
00255 
00256         // G2 price the European swaption here, it should switch to bermudan
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         // OTM Bermudan swaption pricing
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         // Do the pricing for each model
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         // ITM Bermudan swaption pricing
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         // Do the pricing for each model
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 

QuantLib.org
QuantLib
Hosted by
SourceForge.net Logo
Documentation generated by
doxygen