Skip to content

Commit

Permalink
Expose an IBOR coupon's decision about whether it has fixed or not (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio authored Jun 24, 2024
2 parents 3b597c6 + 3eac73c commit 37c84ff
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 23 deletions.
43 changes: 20 additions & 23 deletions ql/cashflows/iborcoupon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,24 @@ namespace QuantLib {
return fixingDate_;
}

Rate IborCoupon::indexFixing() const {
bool IborCoupon::hasFixed() const {
Date today = QuantLib::Settings::instance().evaluationDate();

if (fixingDate_ > today) {
return false;
} else if (fixingDate_ < today) {
return true;
} else {
// fixingDate_ == today
if (QuantLib::Settings::instance().enforcesTodaysHistoricFixings()) {
return true;
} else {
return index_->hasHistoricalFixing(fixingDate_);
}
}
}

Rate IborCoupon::indexFixing() const {
initializeCachedData();

/* instead of just returning index_->fixing(fixingValueDate_)
Expand All @@ -98,34 +114,15 @@ namespace QuantLib {
1) allows to save date/time recalculations, and
2) takes into account par coupon needs
*/
Date today = QuantLib::Settings::instance().evaluationDate();

if (fixingDate_>today)
return iborIndex_->forecastFixing(fixingValueDate_,
fixingEndDate_,
spanningTime_);

if (fixingDate_<today ||
QuantLib::Settings::instance().enforcesTodaysHistoricFixings()) {
// do not catch exceptions
if (hasFixed()) {
Rate result = index_->pastFixing(fixingDate_);
QL_REQUIRE(result != Null<Real>(),
"Missing " << index_->name() << " fixing for " << fixingDate_);
return result;
} else {
return iborIndex_->forecastFixing(fixingValueDate_, fixingEndDate_, spanningTime_);
}

try {
Rate result = index_->pastFixing(fixingDate_);
if (result!=Null<Real>())
return result;
else
; // fall through and forecast
} catch (Error&) {
; // fall through and forecast
}
return iborIndex_->forecastFixing(fixingValueDate_,
fixingEndDate_,
spanningTime_);
}

void IborCoupon::setPricer(const ext::shared_ptr<FloatingRateCouponPricer>& pricer) {
Expand Down
1 change: 1 addition & 0 deletions ql/cashflows/iborcoupon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace QuantLib {
//! \name Inspectors
//@{
const ext::shared_ptr<IborIndex>& iborIndex() const { return iborIndex_; }
bool hasFixed() const;
//@}
//! \name FloatingRateCoupon interface
//@{
Expand Down
55 changes: 55 additions & 0 deletions test-suite/cashflows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,61 @@ BOOST_AUTO_TEST_CASE(testFixedIborCouponWithoutForecastCurve) {
}
}

IborCoupon iborCouponForFixingDate(const ext::shared_ptr<IborIndex>& index, Date fixingDate) {
Date startDate = index->valueDate(fixingDate);
Date endDate = index->maturityDate(fixingDate);

IborCoupon coupon(endDate, 100.0, startDate, endDate, index->fixingDays(), index);
coupon.setPricer(ext::make_shared<BlackIborCouponPricer>());

return coupon;
}

BOOST_AUTO_TEST_CASE(testIborCouponKnowsWhenitHasFixed) {
BOOST_TEST_MESSAGE("Testing that ibor coupon knows when it has fixed...");

Date today = Settings::instance().evaluationDate();

auto index = ext::make_shared<Euribor3M>();
auto calendar = index->fixingCalendar();

{
IborCoupon coupon = iborCouponForFixingDate(index, calendar.advance(today, -1, Days));
index->clearFixings();
// this should not throw an exception if the fixing is missing
BOOST_CHECK_EQUAL(coupon.hasFixed(), true);
// but this should
BOOST_CHECK_THROW(coupon.rate(), Error);
}

{
IborCoupon coupon = iborCouponForFixingDate(index, today);
QuantLib::Settings::instance().enforcesTodaysHistoricFixings() = false;
index->clearFixings();
BOOST_CHECK_EQUAL(coupon.hasFixed(), false);
}

{
IborCoupon coupon = iborCouponForFixingDate(index, today);
QuantLib::Settings::instance().enforcesTodaysHistoricFixings() = false;
index->addFixing(coupon.fixingDate(), 0.01);
BOOST_CHECK_EQUAL(coupon.hasFixed(), true);
}

{
IborCoupon coupon = iborCouponForFixingDate(index, today);
QuantLib::Settings::instance().enforcesTodaysHistoricFixings() = true;
index->clearFixings();
BOOST_CHECK_EQUAL(coupon.hasFixed(), true);
BOOST_CHECK_THROW(coupon.rate(), Error);
}

{
IborCoupon coupon = iborCouponForFixingDate(index, calendar.advance(today, 1, Days));
BOOST_CHECK_EQUAL(coupon.hasFixed(), false);
}
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 37c84ff

Please sign in to comment.