Skip to content

Commit

Permalink
Finished refactoring of bermudan
Browse files Browse the repository at this point in the history
  • Loading branch information
eddelbuettel committed Jul 22, 2024
1 parent 9da60a0 commit 61c5fc5
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 56 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2024-07-22 Dirk Eddelbuettel <[email protected]>

* src/bermudan.cpp: Finalised refactoring and C++ update

2024-07-21 Dirk Eddelbuettel <[email protected]>

* src/hullwhite.cpp: Minor refactoring and C++ update
Expand Down
105 changes: 49 additions & 56 deletions src/bermudan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// RQuantLib function BermudanSwaption
//
// Copyright (C) 2005 - 2007 Dominick Samperi
// Copyright (C) 2007 - 2023 Dirk Eddelbuettel
// Copyright (C) 2007 - 2024 Dirk Eddelbuettel
// Copyright (C) 2016 - 2023 Terry Leitch
//
// This file is part of RQuantLib.
Expand Down Expand Up @@ -170,7 +170,6 @@ Rcpp::List bermudanFromYieldEngine(Rcpp::List rparam,
// List of times that have to be included in the timegrid
std::list<QuantLib::Time> times;
for (i=0; i<(QuantLib::Size)numRows; i++) {
//QuantLib::ext::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(swaptionVols[i][numCols-i-1]));
auto vol = qlext::make_shared<QuantLib::SimpleQuote>(swaptionVols(i, numCols-i-1));
swaptions.push_back(qlext::make_shared<QuantLib::SwaptionHelper>(swaptionMaturities[i],
QuantLib::Period(swapLengths[numCols-i-1], QuantLib::Years),
Expand Down Expand Up @@ -198,7 +197,6 @@ Rcpp::List bermudanFromYieldEngine(Rcpp::List rparam,

// Price based on method selected.
if (method.compare("G2Analytic") == 0) {

auto modelG2 = qlext::make_shared<QuantLib::G2>(rhTermStructure);
Rprintf((char*)"G2/Jamshidian (analytic) calibration\n");
for (i = 0; i < swaptions.size(); i++)
Expand All @@ -217,7 +215,6 @@ Rcpp::List bermudanFromYieldEngine(Rcpp::List rparam,
//Rcpp::Named("params") = params);

} else if (method.compare("HWAnalytic") == 0) {

auto modelHW = qlext::make_shared<QuantLib::HullWhite>(rhTermStructure);
Rprintf((char*)"Hull-White (analytic) calibration\n");
for (i=0; i<swaptions.size(); i++)
Expand Down Expand Up @@ -249,13 +246,13 @@ Rcpp::List bermudanFromYieldEngine(Rcpp::List rparam,
//Rcpp::Named("params") = params);

} else if (method.compare("BKTree") == 0) {
QuantLib::ext::shared_ptr<QuantLib::BlackKarasinski> modelBK(new QuantLib::BlackKarasinski(rhTermStructure));
auto modelBK = qlext::make_shared<QuantLib::BlackKarasinski>(rhTermStructure);
Rprintf((char*)"Black-Karasinski (tree) calibration\n");
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::TreeSwaptionEngine(modelBK,grid)));
swaptions[i]->setPricingEngine(qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelBK,grid));
calibrateModel(modelBK, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);

QuantLib::ext::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelBK, 50));
auto engine = qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelBK, 50);
QuantLib::Swaption bermudanSwaption(mySwap, bermudaExercise);
bermudanSwaption.setPricingEngine(engine);
return Rcpp::List::create(Rcpp::Named("a") = modelBK->params()[0],
Expand Down Expand Up @@ -339,7 +336,7 @@ Rcpp::List bermudanWithRebuiltCurveEngine(Rcpp::List rparam,
QuantLib::DayCounter fixedLegDayCounter = QuantLib::Thirty360(QuantLib::Thirty360::European);
QuantLib::Frequency floatingLegFrequency = QuantLib::Semiannual;
QuantLib::Rate dummyFixedRate = 0.03;
QuantLib::ext::shared_ptr<QuantLib::IborIndex> indexSixMonths(new QuantLib::Euribor6M(rhTermStructure));
auto indexSixMonths = qlext::make_shared<QuantLib::Euribor6M>(rhTermStructure);

//QuantLib::Date startDate = calendar.advance(settlementDate, 1, QuantLib::Years, floatingLegConvention); //took out hard coded
//QuantLib::Date maturity = calendar.advance(startDate, 5, QuantLib::Years, floatingLegConvention); //dates
Expand All @@ -360,12 +357,12 @@ Rcpp::List bermudanWithRebuiltCurveEngine(Rcpp::List rparam,
}


QuantLib::ext::shared_ptr<QuantLib::VanillaSwap>
swap(new QuantLib::VanillaSwap(type, notional,
fixedSchedule, dummyFixedRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter()));
swap->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::DiscountingSwapEngine(rhTermStructure)));
auto swap = qlext::make_shared<QuantLib::VanillaSwap>(type, notional,
fixedSchedule, dummyFixedRate,
fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter());
swap->setPricingEngine(qlext::make_shared<QuantLib::DiscountingSwapEngine>(rhTermStructure));

// Find the ATM or break-even rate
QuantLib::Rate fixedATMRate = swap->fairRate();
Expand All @@ -377,12 +374,12 @@ Rcpp::List bermudanWithRebuiltCurveEngine(Rcpp::List rparam,
fixedRate = strike;

// The swap underlying the Bermudan swaption.
QuantLib::ext::shared_ptr<QuantLib::VanillaSwap>
mySwap(new QuantLib::VanillaSwap(type, notional,
fixedSchedule, fixedRate, fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter()));
swap->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::DiscountingSwapEngine(rhTermStructure)));
auto mySwap = qlext::make_shared<QuantLib::VanillaSwap>(type, notional,
fixedSchedule, fixedRate,
fixedLegDayCounter,
floatSchedule, indexSixMonths, 0.0,
indexSixMonths->dayCounter());
swap->setPricingEngine(qlext::make_shared<QuantLib::DiscountingSwapEngine>(rhTermStructure));

// Build swaptions that will be used to calibrate model to
// the volatility matrix.
Expand All @@ -396,17 +393,15 @@ Rcpp::List bermudanWithRebuiltCurveEngine(Rcpp::List rparam,
// List of times that have to be included in the timegrid
std::list<QuantLib::Time> times;
for (i=0; i<(QuantLib::Size)numRows; i++) {

//QuantLib::ext::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(swaptionVols[i][numCols-i-1]));
QuantLib::ext::shared_ptr<QuantLib::Quote> vol(new QuantLib::SimpleQuote(swaptionVols(i, numCols-i-1)));
swaptions.push_back(QuantLib::ext::shared_ptr<QuantLib::BlackCalibrationHelper>(new QuantLib::SwaptionHelper(swaptionMaturities[i],
QuantLib::Period(swapLengths[numCols-i-1], QuantLib::Years),
QuantLib::Handle<QuantLib::Quote>(vol),
indexSixMonths,
indexSixMonths->tenor(),
indexSixMonths->dayCounter(),
indexSixMonths->dayCounter(),
rhTermStructure)));
auto vol = qlext::make_shared<QuantLib::SimpleQuote>(swaptionVols(i, numCols-i-1));
swaptions.push_back(qlext::make_shared<QuantLib::SwaptionHelper>(swaptionMaturities[i],
QuantLib::Period(swapLengths[numCols-i-1], QuantLib::Years),
QuantLib::Handle<QuantLib::Quote>(vol),
indexSixMonths,
indexSixMonths->tenor(),
indexSixMonths->dayCounter(),
indexSixMonths->dayCounter(),
rhTermStructure));
swaptions.back()->addTimesTo(times);
}

Expand All @@ -418,56 +413,54 @@ Rcpp::List bermudanWithRebuiltCurveEngine(Rcpp::List rparam,
std::vector<QuantLib::Date> bermudanDates;
const std::vector<QuantLib::ext::shared_ptr<QuantLib::CashFlow> >& leg = swap->fixedLeg();
for (i=0; i<leg.size(); i++) {
QuantLib::ext::shared_ptr<QuantLib::Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(leg[i]);
auto coupon = QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(leg[i]);
bermudanDates.push_back(coupon->accrualStartDate());
}

QuantLib::ext::shared_ptr<QuantLib::Exercise> bermudaExercise(new QuantLib::BermudanExercise(bermudanDates));
auto bermudaExercise = qlext::make_shared<QuantLib::BermudanExercise>(bermudanDates);

// Price based on method selected.
if (method.compare("G2Analytic") == 0) {

QuantLib::ext::shared_ptr<QuantLib::G2> modelG2(new QuantLib::G2(rhTermStructure));
auto modelG2 = qlext::make_shared<QuantLib::G2>(rhTermStructure);
Rprintf((char*)"G2/Jamshidian (analytic) calibration\n");
for(i = 0; i < swaptions.size(); i++)
swaptions[i]->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::G2SwaptionEngine(modelG2, 6.0, 16)));
swaptions[i]->setPricingEngine(qlext::make_shared<QuantLib::G2SwaptionEngine>(modelG2, 6.0, 16));
calibrateModel(modelG2, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);
QuantLib::ext::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelG2, 50));
auto engine = qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelG2, 50);
QuantLib::Swaption bermudanSwaption(mySwap, bermudaExercise);
bermudanSwaption.setPricingEngine(engine);
return Rcpp::List::create(Rcpp::Named("a") = modelG2->params()[0],
Rcpp::Named("sigma") = modelG2->params()[1],
Rcpp::Named("b") = modelG2->params()[2],
Rcpp::Named("eta") = modelG2->params()[3],
Rcpp::Named("rho") = modelG2->params()[4],
Rcpp::Named("price") = bermudanSwaption.NPV(),
Rcpp::Named("ATMStrike") = fixedATMRate);
Rcpp::Named("b") = modelG2->params()[2],
Rcpp::Named("eta") = modelG2->params()[3],
Rcpp::Named("rho") = modelG2->params()[4],
Rcpp::Named("price") = bermudanSwaption.NPV(),
Rcpp::Named("ATMStrike") = fixedATMRate);
//Rcpp::Named("params") = params);

} else if (method.compare("HWAnalytic") == 0) {

QuantLib::ext::shared_ptr<QuantLib::HullWhite> modelHW(new QuantLib::HullWhite(rhTermStructure));
auto modelHW = qlext::make_shared<QuantLib::HullWhite>(rhTermStructure);
Rprintf((char*)"Hull-White (analytic) calibration\n");
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::JamshidianSwaptionEngine(modelHW)));
swaptions[i]->setPricingEngine(qlext::make_shared<QuantLib::JamshidianSwaptionEngine>(modelHW));
calibrateModel(modelHW, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);
QuantLib::ext::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelHW, 50));
auto engine = qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelHW, 50);
QuantLib::Swaption bermudanSwaption(mySwap, bermudaExercise);
bermudanSwaption.setPricingEngine(engine);
return Rcpp::List::create(Rcpp::Named("a") = modelHW->params()[0],
Rcpp::Named("sigma") = modelHW->params()[1],
Rcpp::Named("price") = bermudanSwaption.NPV(),
Rcpp::Named("ATMStrike") = fixedATMRate);
Rcpp::Named("price") = bermudanSwaption.NPV(),
Rcpp::Named("ATMStrike") = fixedATMRate);
//Rcpp::Named("params") = params);

} else if (method.compare("HWTree") == 0) {
QuantLib::ext::shared_ptr<QuantLib::HullWhite> modelHW2(new QuantLib::HullWhite(rhTermStructure));
auto modelHW2 = qlext::make_shared<QuantLib::HullWhite>(rhTermStructure);
Rprintf((char*)"Hull-White (tree) calibration\n");
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::TreeSwaptionEngine(modelHW2,grid)));
swaptions[i]->setPricingEngine(qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelHW2,grid));

calibrateModel(modelHW2, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);
QuantLib::ext::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelHW2, 50));
auto engine = qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelHW2, 50);
QuantLib::Swaption bermudanSwaption(mySwap, bermudaExercise);
bermudanSwaption.setPricingEngine(engine);
return Rcpp::List::create(Rcpp::Named("a") = modelHW2->params()[0],
Expand All @@ -477,19 +470,19 @@ Rcpp::List bermudanWithRebuiltCurveEngine(Rcpp::List rparam,
//Rcpp::Named("params") = params);

} else if (method.compare("BKTree") == 0) {
QuantLib::ext::shared_ptr<QuantLib::BlackKarasinski> modelBK(new QuantLib::BlackKarasinski(rhTermStructure));
auto modelBK = qlext::make_shared<QuantLib::BlackKarasinski>(rhTermStructure);
Rprintf((char*)"Black-Karasinski (tree) calibration\n");
for (i=0; i<swaptions.size(); i++)
swaptions[i]->setPricingEngine(QuantLib::ext::shared_ptr<QuantLib::PricingEngine>(new QuantLib::TreeSwaptionEngine(modelBK,grid)));
swaptions[i]->setPricingEngine(qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelBK,grid));
calibrateModel(modelBK, swaptions, 0.05, swaptionMat, swapLengths, swaptionVols);

QuantLib::ext::shared_ptr<QuantLib::PricingEngine> engine(new QuantLib::TreeSwaptionEngine(modelBK, 50));
auto engine = qlext::make_shared<QuantLib::TreeSwaptionEngine>(modelBK, 50);
QuantLib::Swaption bermudanSwaption(mySwap, bermudaExercise);
bermudanSwaption.setPricingEngine(engine);
return Rcpp::List::create(Rcpp::Named("a") = modelBK->params()[0],
Rcpp::Named("sigma") = modelBK->params()[1],
Rcpp::Named("price") = bermudanSwaption.NPV(),
Rcpp::Named("ATMStrike") = fixedATMRate);
Rcpp::Named("price") = bermudanSwaption.NPV(),
Rcpp::Named("ATMStrike") = fixedATMRate);
//Rcpp::Named("params") = params);

} else {
Expand Down

0 comments on commit 61c5fc5

Please sign in to comment.