#include <ql/quantlib.hpp>
using namespace QuantLib;
Size numRows = 5;
Size numCols = 10;
unsigned int swaptionLengths[] = {1,2,3,4,5,7,10,15,20,25,30};
double swaptionVols[] = {
23.92, 22.80, 19.8, 18.1, 16.0, 14.26, 13.56, 12.79, 12.3, 11.09,
21.85, 21.50, 19.5, 17.2, 14.7, 13.23, 12.59, 12.29, 11.1, 10.30,
19.46, 19.40, 17.9, 15.9, 13.9, 12.69, 12.15, 11.83, 10.8, 10.00,
17.97, 17.80, 16.7, 14.9, 13.4, 12.28, 11.89, 11.48, 10.5, 9.80,
16.29, 16.40, 15.1, 14.0, 12.9, 12.01, 11.46, 11.08, 10.4, 9.77,
14.71, 14.90, 14.3, 13.2, 12.3, 11.49, 11.12, 10.70, 10.1, 9.57,
12.93, 13.30, 12.8, 12.2, 11.6, 10.82, 10.47, 10.21, 9.8, 9.51,
12.70, 12.10, 11.9, 11.2, 10.8, 10.40, 10.20, 10.00, 9.5, 9.00,
12.30, 11.60, 11.6, 10.9, 10.5, 10.30, 10.00, 9.80, 9.3, 8.80,
12.00, 11.40, 11.5, 10.8, 10.3, 10.00, 9.80, 9.60, 9.5, 9.10,
11.50, 11.20, 11.3, 10.6, 10.2, 10.10, 9.70, 9.50, 9.4, 8.60};
void calibrateModel(const Handle<ShortRateModel>& model,
CalibrationSet& calibs,
double lambda) {
Simplex om(lambda, 1e-9);
om.setEndCriteria(EndCriteria(10000, 1e-7));
model->calibrate(calibs, om);
#if defined(QL_PATCH_DARWIN)
return;
#endif
Size i;
for (i=0; i<numRows; i++) {
std::cout << IntegerFormatter::toString(swaptionLengths[i],2) << "y|";
for (Size j=0; j<numCols; j++) {
Size k = i*numCols + j;
double npv = calibs[k]->modelValue();
double implied = calibs[k]->impliedVolatility(npv, 1e-4,
1000, 0.05, 0.50)*100.0;
std::cout << DoubleFormatter::toString(implied,1,4) << " (";
k = i*10 + j;
double diff = implied - swaptionVols[k];
std::cout << DoubleFormatter::toString(diff,1,4)
<< ")|";
}
std::cout << std::endl;
}
}
int main(int argc, char* argv[])
{
try {
QL_IO_INIT
Date todaysDate(15, February, 2002);
Calendar calendar = TARGET();
Date settlementDate(19, February, 2002);
std::vector<Handle<RateHelper> > instruments;
DayCounter depositDayCounter = Thirty360();
int settlementDays = 2;
Rate weekRates[3] = {3.295, 3.3, 3.3};
Size i;
for (i=0; i<3; i++) {
RelinkableHandle<Quote> depositRate(
Handle<Quote>(new SimpleQuote(weekRates[i]*0.01)));
Handle<RateHelper> depositHelper(new DepositRateHelper(
depositRate, i+1, Weeks, settlementDays, calendar,
ModifiedFollowing, depositDayCounter));
instruments.push_back(depositHelper);
}
Rate depositRates[12] = {
3.31, 3.32, 3.29, 3.35, 3.315, 3.33,
3.395, 3.41, 3.41, 3.49, 3.54, 3.53};
for (i=0; i<11; i++) {
RelinkableHandle<Quote> depositRate(
Handle<Quote>(new SimpleQuote(depositRates[i]*0.01)));
Handle<RateHelper> depositHelper(new DepositRateHelper(
depositRate, i+1, Months, settlementDays, calendar,
ModifiedFollowing, depositDayCounter));
instruments.push_back(depositHelper);
}
Rate swapRates[13] = {
3.6425, 4.0875, 4.38, 4.5815, 4.74325, 4.87375,
4.9775, 5.07, 5.13, 5.1825, 5.36, 5.45125, 5.43875};
int swapYears[13] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 30};
int swFixedLegFrequency = 1;
bool swFixedLegIsAdjusted = false;
DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European);
int swFloatingLegFrequency = 2;
for (i=0; i<13; i++) {
Handle<Quote> swapRate(new SimpleQuote(swapRates[i]*0.01));
Handle<RateHelper> swapHelper(new SwapRateHelper(
RelinkableHandle<Quote>(swapRate),
swapYears[i], Years, settlementDays,
calendar, ModifiedFollowing,
swFixedLegFrequency,
swFixedLegIsAdjusted, swFixedLegDayCounter,
swFloatingLegFrequency));
instruments.push_back(swapHelper);
}
Handle<PiecewiseFlatForward> myTermStructure(new
PiecewiseFlatForward(todaysDate, settlementDate, instruments,
depositDayCounter));
RelinkableHandle<TermStructure> rhTermStructure;
rhTermStructure.linkTo(myTermStructure);
int fixedLegFrequency = 1;
bool fixedLegIsAdjusted = false;
RollingConvention roll = ModifiedFollowing;
DayCounter fixedLegDayCounter = Thirty360(Thirty360::European);
int floatingLegFrequency = 2;
bool payFixedRate = true;
int fixingDays = 2;
Rate dummyFixedRate = 0.03;
Handle<Xibor> indexSixMonths(new Euribor(6, Months, rhTermStructure));
Handle<SimpleSwap> swap(new SimpleSwap(
payFixedRate, settlementDate.plusYears(1), 5, Years,
calendar, roll, 1000.0, fixedLegFrequency, dummyFixedRate,
fixedLegIsAdjusted, fixedLegDayCounter, floatingLegFrequency,
indexSixMonths, fixingDays, 0.0, rhTermStructure));
Rate fixedATMRate = swap->fairRate();
Handle<SimpleSwap> atmSwap(new SimpleSwap(
payFixedRate, settlementDate.plusYears(1), 5, Years,
calendar, roll, 1000.0, fixedLegFrequency, fixedATMRate,
fixedLegIsAdjusted, fixedLegDayCounter, floatingLegFrequency,
indexSixMonths, fixingDays, 0.0, rhTermStructure));
Handle<SimpleSwap> otmSwap(new SimpleSwap(
payFixedRate, settlementDate.plusYears(1), 5, Years,
calendar, roll, 1000.0, fixedLegFrequency, fixedATMRate * 1.2,
fixedLegIsAdjusted, fixedLegDayCounter, floatingLegFrequency,
indexSixMonths, fixingDays, 0.0, rhTermStructure));
Handle<SimpleSwap> itmSwap(new SimpleSwap(
payFixedRate, settlementDate.plusYears(1), 5, Years,
calendar, roll, 1000.0, fixedLegFrequency, fixedATMRate * 0.8,
fixedLegIsAdjusted, fixedLegDayCounter, floatingLegFrequency,
indexSixMonths, fixingDays, 0.0, rhTermStructure));
std::vector<Period> swaptionMaturities;
swaptionMaturities.push_back(Period(1, Months));
swaptionMaturities.push_back(Period(3, Months));
swaptionMaturities.push_back(Period(6, Months));
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));
swaptionMaturities.push_back(Period(7, Years));
swaptionMaturities.push_back(Period(10, Years));
CalibrationSet swaptions;
std::list<Time> times;
for (i=0; i<numRows; i++) {
for (unsigned int j=0; j<numCols; j++) {
unsigned int k = i*10 + j;
Handle<Quote> vol(new SimpleQuote(swaptionVols[k]*0.01));
swaptions.push_back(Handle<CalibrationHelper>(
new SwaptionHelper(swaptionMaturities[j],
Period(swaptionLengths[i], Years),
RelinkableHandle<Quote>(vol),
indexSixMonths,
rhTermStructure)));
swaptions.back()->addTimesTo(times);
}
}
const std::vector<Time> termTimes = myTermStructure->times();
for (i=0; i<termTimes.size(); i++)
times.push_back(termTimes[i]);
TimeGrid grid(times.begin(), times.end(), 30);
Handle<HullWhite> modelHW(new HullWhite(rhTermStructure));
Handle<HullWhite> modelHW2(new HullWhite(rhTermStructure));
Handle<BlackKarasinski> modelBK(new BlackKarasinski(rhTermStructure));
std::cout << "Calibrating to swaptions" << std::endl;
std::cout << "Hull-White (analytic formulae):" << std::endl;
swaptions.setPricingEngine(
Handle<PricingEngine>(new JamshidianSwaption(modelHW)));
calibrateModel(modelHW, swaptions, 0.05);
std::cout << "calibrated to "
<< modelHW->params()
<< std::endl
<< std::endl;
std::cout << "Hull-White (numerical calibration):" << std::endl;
swaptions.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW2, grid)));
calibrateModel(modelHW2, swaptions, 0.05);
std::cout << "calibrated to "
<< modelHW2->params()
<< std::endl
<< std::endl;
std::cout << "Black-Karasinski: " << std::endl;
swaptions.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelBK, grid)));
calibrateModel(modelBK, swaptions, 0.05);
std::cout << "calibrated to "
<< modelBK->params()
<< std::endl
<< std::endl;
std::cout << "Pricing an ATM bermudan swaption" << std::endl;
std::vector<Date> bermudanDates;
const std::vector<Handle<CashFlow> >& leg = swap->floatingLeg();
for (i=0; i<leg.size(); i++) {
#if defined(HAVE_BOOST)
Handle<Coupon> coupon =
boost::dynamic_pointer_cast<Coupon>(leg[i]);
#else
Handle<Coupon> coupon = leg[i];
#endif
bermudanDates.push_back(coupon->accrualStartDate());
}
Handle<Exercise> bermudaExercise(new BermudanExercise(
bermudanDates));
Swaption bermudanSwaption(atmSwap,
bermudaExercise,
rhTermStructure,
Handle<PricingEngine>(new TreeSwaption(modelHW, 100)));
bermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW, 100)));
std::cout << "HW: " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW2, 100)));
std::cout << "HW (num): " << bermudanSwaption.NPV() << std::endl;
bermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelBK, 100)));
std::cout << "BK: " << bermudanSwaption.NPV() << std::endl;
std::cout << "Pricing an OTM bermudan swaption" << std::endl;
Swaption otmBermudanSwaption(otmSwap,
bermudaExercise,
rhTermStructure,
Handle<PricingEngine>(new TreeSwaption(modelHW, 100)));
otmBermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW, 100)));
std::cout << "HW: " << otmBermudanSwaption.NPV() << std::endl;
otmBermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW2, 100)));
std::cout << "HW (num): " << otmBermudanSwaption.NPV() << std::endl;
otmBermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelBK, 100)));
std::cout << "BK: " << otmBermudanSwaption.NPV() << std::endl;
std::cout << "Pricing an ITM bermudan swaption" << std::endl;
Swaption itmBermudanSwaption(itmSwap,
bermudaExercise,
rhTermStructure,
Handle<PricingEngine>(new TreeSwaption(modelHW, 100)));
itmBermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW, 100)));
std::cout << "HW: " << itmBermudanSwaption.NPV() << std::endl;
itmBermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelHW2, 100)));
std::cout << "HW (num): " << itmBermudanSwaption.NPV() << std::endl;
itmBermudanSwaption.setPricingEngine(
Handle<PricingEngine>(new TreeSwaption(modelBK, 100)));
std::cout << "BK: " << itmBermudanSwaption.NPV() << std::endl;
return 0;
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
return 1;
} catch (...) {
std::cout << "unknown error" << std::endl;
return 1;
}
}