This example prices a bermudan swaption using different models calibrated to market swaptions. The calibration examples include Hull and White's using both an analytic formula as well as numerically, and Black and Karasinski's model. Using these three calibrations, Bermudan swaptions are priced for at-the-money, out-of-the-money and in-the-money volatilities.
#include <ql/qldefines.hpp>
#ifdef BOOST_MSVC
# include <ql/auto_link.hpp>
#endif
#include <ql/instruments/swaption.hpp>
#include <ql/pricingengines/swap/discountingswapengine.hpp>
#include <ql/pricingengines/swaption/treeswaptionengine.hpp>
#include <ql/pricingengines/swaption/jamshidianswaptionengine.hpp>
#include <ql/pricingengines/swaption/g2swaptionengine.hpp>
#include <ql/pricingengines/swaption/fdhullwhiteswaptionengine.hpp>
#include <ql/pricingengines/swaption/fdg2swaptionengine.hpp>
#include <ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp>
#include <ql/models/shortrate/onefactormodels/blackkarasinski.hpp>
#include <ql/math/optimization/levenbergmarquardt.hpp>
#include <ql/indexes/ibor/euribor.hpp>
#include <ql/cashflows/coupon.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/target.hpp>
#include <ql/time/daycounters/thirty360.hpp>
#include <ql/utilities/dataformatters.hpp>
#include <iostream>
#include <iomanip>
#if defined(QL_ENABLE_SESSIONS)
ThreadKey sessionId() { return 0; }
}
#endif
1, 2, 3, 4, 5};
0.1490, 0.1340, 0.1228, 0.1189, 0.1148,
0.1290, 0.1201, 0.1146, 0.1108, 0.1040,
0.1149, 0.1112, 0.1070, 0.1010, 0.0957,
0.1047, 0.1021, 0.0980, 0.0951, 0.1270,
0.1000, 0.0950, 0.0900, 0.1230, 0.1160};
void calibrateModel(
const ext::shared_ptr<ShortRateModel>& model,
const std::vector<ext::shared_ptr<BlackCalibrationHelper> >& swaptions) {
std::vector<ext::shared_ptr<CalibrationHelper> > helpers(swaptions.begin(), swaptions.end());
LevenbergMarquardt om;
model->calibrate(helpers, om,
EndCriteria(400, 100, 1.0e-8, 1.0e-8, 1.0e-8));
for (
Size i=0; i<numRows; i++) {
Real npv = swaptions[i]->modelValue();
Volatility implied = swaptions[i]->impliedVolatility(npv, 1e-4,
1000, 0.05, 0.50);
std::cout << i+1 << "x" << swapLengths[j]
<< std::setprecision(5) << std::noshowpos
<< ", market " << std::setw(7)
<< " (" << std::setw(7) << std::showpos
}
}
int main(int, char* []) {
try {
std::cout << std::endl;
Date todaysDate(15, February, 2002);
Calendar calendar = TARGET();
Date settlementDate(19, February, 2002);
ext::shared_ptr<Quote> flatRate(new SimpleQuote(0.04875825));
Handle<YieldTermStructure> rhTermStructure(
ext::make_shared<FlatForward>(
settlementDate, Handle<Quote>(flatRate),
Actual365Fixed()));
DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
VanillaSwap::Type type = VanillaSwap::Payer;
Rate dummyFixedRate = 0.03;
ext::shared_ptr<IborIndex> indexSixMonths(new
Euribor6M(rhTermStructure));
Date startDate = calendar.advance(settlementDate,1,Years,
floatingLegConvention);
Date maturity = calendar.advance(startDate,5,Years,
floatingLegConvention);
Schedule fixedSchedule(startDate,maturity,Period(fixedLegFrequency),
calendar,fixedLegConvention,fixedLegConvention,
Schedule floatSchedule(startDate,maturity,Period(floatingLegFrequency),
calendar,floatingLegConvention,floatingLegConvention,
ext::shared_ptr<VanillaSwap> swap(new VanillaSwap(
type, 1000.0,
fixedSchedule, dummyFixedRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter()));
swap->setPricingEngine(ext::shared_ptr<PricingEngine>(
new DiscountingSwapEngine(rhTermStructure)));
Rate fixedATMRate = swap->fairRate();
Rate fixedOTMRate = fixedATMRate * 1.2;
Rate fixedITMRate = fixedATMRate * 0.8;
ext::shared_ptr<VanillaSwap> atmSwap(new VanillaSwap(
type, 1000.0,
fixedSchedule, fixedATMRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter()));
ext::shared_ptr<VanillaSwap> otmSwap(new VanillaSwap(
type, 1000.0,
fixedSchedule, fixedOTMRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter()));
ext::shared_ptr<VanillaSwap> itmSwap(new VanillaSwap(
type, 1000.0,
fixedSchedule, fixedITMRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter()));
std::vector<Period> swaptionMaturities;
swaptionMaturities.push_back(Period(1, Years));
swaptionMaturities.push_back(Period(2, Years));
swaptionMaturities.push_back(Period(3, Years));
swaptionMaturities.push_back(Period(4, Years));
swaptionMaturities.push_back(Period(5, Years));
std::vector<ext::shared_ptr<BlackCalibrationHelper> > swaptions;
std::list<Time> times;
for (i=0; i<numRows; i++) {
ext::shared_ptr<Quote> vol(new SimpleQuote(swaptionVols[k]));
swaptions.push_back(ext::shared_ptr<BlackCalibrationHelper>(new
SwaptionHelper(swaptionMaturities[i],
Period(swapLengths[j], Years),
Handle<Quote>(vol),
indexSixMonths,
indexSixMonths->tenor(),
indexSixMonths->dayCounter(),
indexSixMonths->dayCounter(),
rhTermStructure)));
swaptions.back()->addTimesTo(times);
}
TimeGrid grid(times.begin(), times.end(), 30);
ext::shared_ptr<G2> modelG2(new G2(rhTermStructure));
ext::shared_ptr<HullWhite> modelHW(new HullWhite(rhTermStructure));
ext::shared_ptr<HullWhite> modelHW2(new HullWhite(rhTermStructure));
ext::shared_ptr<BlackKarasinski> modelBK(
new BlackKarasinski(rhTermStructure));
std::cout << "G2 (analytic formulae) calibration" << std::endl;
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(ext::shared_ptr<PricingEngine>(
new G2SwaptionEngine(modelG2, 6.0, 16)));
calibrateModel(modelG2, swaptions);
std::cout << "calibrated to:\n"
<< "a = " << modelG2->params()[0] << ", "
<< "sigma = " << modelG2->params()[1] << "\n"
<< "b = " << modelG2->params()[2] << ", "
<< "eta = " << modelG2->params()[3] << "\n"
<< "rho = " << modelG2->params()[4]
<< std::endl << std::endl;
std::cout << "Hull-White (analytic formulae) calibration" << std::endl;
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(ext::shared_ptr<PricingEngine>(
new JamshidianSwaptionEngine(modelHW)));
calibrateModel(modelHW, swaptions);
std::cout << "calibrated to:\n"
<< "a = " << modelHW->params()[0] << ", "
<< "sigma = " << modelHW->params()[1]
<< std::endl << std::endl;
std::cout << "Hull-White (numerical) calibration" << std::endl;
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW2, grid)));
calibrateModel(modelHW2, swaptions);
std::cout << "calibrated to:\n"
<< "a = " << modelHW2->params()[0] << ", "
<< "sigma = " << modelHW2->params()[1]
<< std::endl << std::endl;
std::cout << "Black-Karasinski (numerical) calibration" << std::endl;
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelBK, grid)));
calibrateModel(modelBK, swaptions);
std::cout << "calibrated to:\n"
<< "a = " << modelBK->params()[0] << ", "
<< "sigma = " << modelBK->params()[1]
<< std::endl << std::endl;
std::cout << "Payer bermudan swaption "
<<
"struck at " <<
io::rate(fixedATMRate)
<< " (ATM)" << std::endl;
std::vector<Date> bermudanDates;
const std::vector<ext::shared_ptr<CashFlow> >& leg =
swap->fixedLeg();
for (i=0; i<leg.size(); i++) {
ext::shared_ptr<Coupon> coupon =
ext::dynamic_pointer_cast<Coupon>(leg[i]);
bermudanDates.push_back(coupon->accrualStartDate());
}
ext::shared_ptr<Exercise> bermudanExercise(
new BermudanExercise(bermudanDates));
Swaption bermudanSwaption(atmSwap, bermudanExercise);
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelG2, 50)));
std::cout << "G2 (tree): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdG2SwaptionEngine(modelG2)));
std::cout << "G2 (fdm) : " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW, 50)));
std::cout << "HW (tree): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdHullWhiteSwaptionEngine(modelHW)));
std::cout << "HW (fdm) : " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW2, 50)));
std::cout << "HW (num, tree): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdHullWhiteSwaptionEngine(modelHW2)));
std::cout << "HW (num, fdm) : " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelBK, 50)));
std::cout << "BK: " << bermudanSwaption.NPV() << std::endl;
std::cout << "Payer bermudan swaption "
<<
"struck at " <<
io::rate(fixedOTMRate)
<< " (OTM)" << std::endl;
Swaption otmBermudanSwaption(otmSwap,bermudanExercise);
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelG2, 300)));
std::cout << "G2 (tree): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdG2SwaptionEngine(modelG2)));
std::cout << "G2 (fdm) : " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW, 50)));
std::cout << "HW (tree): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdHullWhiteSwaptionEngine(modelHW)));
std::cout << "HW (fdm) : " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW2, 50)));
std::cout << "HW (num, tree): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdHullWhiteSwaptionEngine(modelHW2)));
std::cout << "HW (num, fdm): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelBK, 50)));
std::cout << "BK: " << otmBermudanSwaption.NPV()
<< std::endl;
std::cout << "Payer bermudan swaption "
<<
"struck at " <<
io::rate(fixedITMRate)
<< " (ITM)" << std::endl;
Swaption itmBermudanSwaption(itmSwap,bermudanExercise);
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelG2, 50)));
std::cout << "G2 (tree): " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdG2SwaptionEngine(modelG2)));
std::cout << "G2 (fdm) : " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW, 50)));
std::cout << "HW (tree): " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdHullWhiteSwaptionEngine(modelHW)));
std::cout << "HW (fdm) : " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelHW2, 50)));
std::cout << "HW (num, tree): " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new FdHullWhiteSwaptionEngine(modelHW2)));
std::cout << "HW (num, fdm) : " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::shared_ptr<PricingEngine>(
new TreeSwaptionEngine(modelBK, 50)));
std::cout << "BK: " << itmBermudanSwaption.NPV()
<< std::endl;
return 0;
} catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "unknown error" << std::endl;
return 1;
}
}