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.
#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
#endif
#include <iostream>
#include <iomanip>
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++) {
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
<< ": model " << std::setw(7) << io::volatility(implied)
<< ", market " << std::setw(7)
<< io::volatility(swaptionVols[k])
<< " (" << std::setw(7) << std::showpos
<< io::volatility(diff) << std::noshowpos << ")\n";
}
}
int main(int, char* []) {
try {
std::cout << std::endl;
Date todaysDate(15, February, 2002);
Date settlementDate(19, February, 2002);
Settings::instance().evaluationDate() = todaysDate;
auto flatRate = ext::make_shared<SimpleQuote>(0.04875825);
ext::make_shared<FlatForward>(
Rate dummyFixedRate = 0.03;
auto indexSixMonths = ext::make_shared<Euribor6M>(rhTermStructure);
Date startDate = calendar.
advance(settlementDate,1,Years,
floatingLegConvention);
floatingLegConvention);
calendar,fixedLegConvention,fixedLegConvention,
DateGeneration::Forward,false);
Schedule floatSchedule(startDate,maturity,
Period(floatingLegFrequency),
calendar,floatingLegConvention,floatingLegConvention,
DateGeneration::Forward,false);
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 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;
for (i=0; i<numRows; i++) {
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 =
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;
}
}
Actual/365 (Fixed) day count convention.
Date advance(const Date &, Integer n, TimeUnit unit, BusinessDayConvention convention=Following, bool endOfMonth=false) const
Criteria to end optimization process:
Shared handle to an observable.
Levenberg-Marquardt optimization method.
30/360 day count convention
Coupon accruing over a fixed period.
finite differences swaption engine
finite differences swaption engine
flat forward rate term structure
Swaption pricing engine for two-factor additive Gaussian Model G2++.
Frequency
Frequency of events.
BusinessDayConvention
Business Day conventions.
Real Volatility
volatility
QL_INTEGER Integer
integer number
std::size_t Size
size of a container
Swaption engine using Jamshidian's decomposition Concerning the start delay cf. http://ssrn....
Levenberg-Marquardt optimization method.
void swap(Array &v, Array &w) noexcept
Global definitions and compiler switches.
Swaption calibration helper.
Numerical lattice engine for swaptions.
Simple fixed-rate vs Libor swap.