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>
#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
# include <ql/auto_link.hpp>
#endif
#include <ql/instruments/vanillaswap.hpp>
#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>
Size numRows = 5;
Size numCols = 5;
Integer swapLengths[] = {
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());
model->calibrate(helpers, om,
for (Size i=0; i<numRows; i++) {
Size j = numCols - i -1;
Size k = i*numCols + j;
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);
Date settlementDate(19, February, 2002);
auto flatRate = ext::make_shared<SimpleQuote>(0.04875825);
ext::make_shared<FlatForward>(
Frequency fixedLegFrequency =
Annual;
BusinessDayConvention fixedLegConvention =
Unadjusted;
Rate dummyFixedRate = 0.03;
auto indexSixMonths = ext::make_shared<Euribor6M>(rhTermStructure);
Date startDate = calendar.
advance(settlementDate,1,Years,
floatingLegConvention);
floatingLegConvention);
calendar,fixedLegConvention,fixedLegConvention,
Schedule floatSchedule(startDate,maturity,
Period(floatingLegFrequency),
calendar,floatingLegConvention,floatingLegConvention,
auto swap = ext::make_shared<VanillaSwap>(
type, 1000.0,
fixedSchedule, dummyFixedRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter());
swap->setPricingEngine(ext::make_shared<DiscountingSwapEngine>(rhTermStructure));
Rate fixedATMRate = swap->fairRate();
Rate fixedOTMRate = fixedATMRate * 1.2;
Rate fixedITMRate = fixedATMRate * 0.8;
auto atmSwap = ext::make_shared<VanillaSwap>(
type, 1000.0,
fixedSchedule, fixedATMRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter());
auto otmSwap = ext::make_shared<VanillaSwap>(
type, 1000.0,
fixedSchedule, fixedOTMRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter());
auto itmSwap = ext::make_shared<VanillaSwap>(
type, 1000.0,
fixedSchedule, fixedITMRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter());
std::vector<Period> swaptionMaturities;
swaptionMaturities.emplace_back(1, Years);
swaptionMaturities.emplace_back(2, Years);
swaptionMaturities.emplace_back(3, Years);
swaptionMaturities.emplace_back(4, Years);
swaptionMaturities.emplace_back(5, Years);
std::vector<ext::shared_ptr<BlackCalibrationHelper>> swaptions;
std::list<Time> times;
Size i;
for (i=0; i<numRows; i++) {
Size j = numCols - i -1;
Size k = i*numCols + j;
auto vol = ext::make_shared<SimpleQuote>(swaptionVols[k]);
swaptions.push_back(ext::make_shared<SwaptionHelper>(
swaptionMaturities[i],
Period(swapLengths[j], Years),
indexSixMonths,
indexSixMonths->tenor(),
indexSixMonths->dayCounter(),
indexSixMonths->dayCounter(),
rhTermStructure));
swaptions.back()->addTimesTo(times);
}
TimeGrid grid(times.begin(), times.end(), 30);
auto modelG2 = ext::make_shared<G2>(rhTermStructure);
auto modelHW = ext::make_shared<HullWhite>(rhTermStructure);
auto modelHW2 = ext::make_shared<HullWhite>(rhTermStructure);
auto modelBK = ext::make_shared<BlackKarasinski>(rhTermStructure);
std::cout << "G2 (analytic formulae) calibration" << std::endl;
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(ext::make_shared<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::make_shared<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::make_shared<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::make_shared<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++) {
auto coupon = ext::dynamic_pointer_cast<Coupon>(leg[i]);
bermudanDates.push_back(coupon->accrualStartDate());
}
auto bermudanExercise = ext::make_shared<BermudanExercise>(bermudanDates);
Swaption bermudanSwaption(atmSwap, bermudanExercise);
bermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelG2, 50));
std::cout << "G2 (tree): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::make_shared<FdG2SwaptionEngine>(modelG2));
std::cout << "G2 (fdm) : " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelHW, 50));
std::cout << "HW (tree): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::make_shared<FdHullWhiteSwaptionEngine>(modelHW));
std::cout << "HW (fdm) : " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelHW2, 50));
std::cout << "HW (num, tree): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::make_shared<FdHullWhiteSwaptionEngine>(modelHW2));
std::cout << "HW (num, fdm) : " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(ext::make_shared<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::make_shared<TreeSwaptionEngine>(modelG2, 300));
std::cout << "G2 (tree): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::make_shared<FdG2SwaptionEngine>(modelG2));
std::cout << "G2 (fdm) : " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelHW, 50));
std::cout << "HW (tree): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::make_shared<FdHullWhiteSwaptionEngine>(modelHW));
std::cout << "HW (fdm) : " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelHW2, 50));
std::cout << "HW (num, tree): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::make_shared<FdHullWhiteSwaptionEngine>(modelHW2));
std::cout << "HW (num, fdm): " << otmBermudanSwaption.NPV()
<< std::endl;
otmBermudanSwaption.setPricingEngine(ext::make_shared<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::make_shared<TreeSwaptionEngine>(modelG2, 50));
std::cout << "G2 (tree): " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::make_shared<FdG2SwaptionEngine>(modelG2));
std::cout << "G2 (fdm) : " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelHW, 50));
std::cout << "HW (tree): " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::make_shared<FdHullWhiteSwaptionEngine>(modelHW));
std::cout << "HW (fdm) : " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::make_shared<TreeSwaptionEngine>(modelHW2, 50));
std::cout << "HW (num, tree): " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::make_shared<FdHullWhiteSwaptionEngine>(modelHW2));
std::cout << "HW (num, fdm) : " << itmBermudanSwaption.NPV()
<< std::endl;
itmBermudanSwaption.setPricingEngine(ext::make_shared<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;
}
}