Skip to content

Commit

Permalink
Avoid an out-of-bounds access in fitted discount curve (#1950)
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio authored Apr 16, 2024
2 parents acc3b12 + 1e62474 commit e8bd858
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ql/termstructures/yield/fittedbonddiscountcurve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ namespace QuantLib {
if (!l2_.empty()) {
QL_REQUIRE(l2_.size() == size(),
"Given penalty factors do not cover all parameters");

QL_REQUIRE(!curve_->guessSolution_.empty(), "L2 penalty requires a guess");
}
}

Expand Down
30 changes: 30 additions & 0 deletions test-suite/fittedbonddiscountcurve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,36 @@ BOOST_AUTO_TEST_CASE(testFlatExtrapolation) {

}

BOOST_AUTO_TEST_CASE(testRequiredGuess) {

BOOST_TEST_MESSAGE("Testing that fitted bond curves require a guess when given an L2 penalty...");

Date today = Settings::instance().evaluationDate();
auto bond1 = ext::make_shared<ZeroCouponBond>(3, TARGET(), 100.0, today + Period(1, Years));
auto bond2 = ext::make_shared<ZeroCouponBond>(3, TARGET(), 100.0, today + Period(2, Years));
auto bond3 = ext::make_shared<ZeroCouponBond>(3, TARGET(), 100.0, today + Period(5, Years));
auto bond4 = ext::make_shared<ZeroCouponBond>(3, TARGET(), 100.0, today + Period(10, Years));

std::vector<ext::shared_ptr<BondHelper> > helpers(4);
helpers[0] = ext::make_shared<BondHelper>(makeQuoteHandle(99.0), bond1);
helpers[1] = ext::make_shared<BondHelper>(makeQuoteHandle(98.0), bond2);
helpers[2] = ext::make_shared<BondHelper>(makeQuoteHandle(95.0), bond3);
helpers[3] = ext::make_shared<BondHelper>(makeQuoteHandle(90.0), bond4);

Array weights = {};
ext::shared_ptr<OptimizationMethod> optimizer = {};
Array l2 = { 0.25, 0.25, 0.25, 0.25 };
NelsonSiegelFitting fittingMethod(weights, optimizer, l2);

Real accuracy = 1e-10;
Size maxIterations = 10000;
FittedBondDiscountCurve curve(0, TARGET(), helpers, Actual365Fixed(),
fittingMethod, accuracy, maxIterations);

BOOST_CHECK_EXCEPTION(curve.discount(3.0), Error,
ExpectedErrorMessage("L2 penalty requires a guess"));
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit e8bd858

Please sign in to comment.