diff --git a/ql/cashflows/digitalcoupon.cpp b/ql/cashflows/digitalcoupon.cpp index 37d89ad439..61f7173a60 100644 --- a/ql/cashflows/digitalcoupon.cpp +++ b/ql/cashflows/digitalcoupon.cpp @@ -238,9 +238,7 @@ namespace QuantLib { rate_ = underlyingRate + callCsi_ * callPayoff() + putCsi_ * putPayoff(); } else if (fixingDate == today) { // might have been fixed - Rate pastFixing = - IndexManager::instance().getHistory((underlying_->index())->name())[fixingDate]; - if (pastFixing != Null()) { + if (underlying_->index()->hasHistoricalFixing(fixingDate)) { rate_ = underlyingRate + callCsi_ * callPayoff() + putCsi_ * putPayoff(); } else { rate_ = underlyingRate + callCsi_ * callOptionRate() + putCsi_ * putOptionRate(); diff --git a/ql/cashflows/overnightindexedcouponpricer.cpp b/ql/cashflows/overnightindexedcouponpricer.cpp index 98d78ff986..81f98b775f 100644 --- a/ql/cashflows/overnightindexedcouponpricer.cpp +++ b/ql/cashflows/overnightindexedcouponpricer.cpp @@ -56,7 +56,7 @@ namespace QuantLib { const ext::shared_ptr index = ext::dynamic_pointer_cast(coupon_->index()); - const auto& pastFixings = IndexManager::instance().getHistory(index->name()); + const auto& pastFixings = index->timeSeries(); const auto& fixingDates = coupon_->fixingDates(); const auto& valueDates = coupon_->valueDates(); @@ -194,11 +194,13 @@ namespace QuantLib { Real accumulatedRate = 0.0; + const auto& pastFixings = index->timeSeries(); + // already fixed part Date today = Settings::instance().evaluationDate(); while (i < n && fixingDates[i] < today) { // rate must have been fixed - Rate pastFixing = IndexManager::instance().getHistory(index->name())[fixingDates[i]]; + Rate pastFixing = pastFixings[fixingDates[i]]; QL_REQUIRE(pastFixing != Null(), "Missing " << index->name() << " fixing for " << fixingDates[i]); accumulatedRate += pastFixing * dt[i]; @@ -209,8 +211,7 @@ namespace QuantLib { if (i < n && fixingDates[i] == today) { // might have been fixed try { - Rate pastFixing = - IndexManager::instance().getHistory(index->name())[fixingDates[i]]; + Rate pastFixing = pastFixings[fixingDates[i]]; if (pastFixing != Null()) { accumulatedRate += pastFixing * dt[i]; ++i; diff --git a/ql/experimental/commodities/commodityindex.cpp b/ql/experimental/commodities/commodityindex.cpp index c89a30ddbb..06b1f11a75 100644 --- a/ql/experimental/commodities/commodityindex.cpp +++ b/ql/experimental/commodities/commodityindex.cpp @@ -38,7 +38,7 @@ namespace QuantLib { forwardCurve_(std::move(forwardCurve)), exchangeContracts_(std::move(exchangeContracts)), nearbyOffset_(nearbyOffset) { registerWith(Settings::instance().evaluationDate()); - registerWith(IndexManager::instance().notifier(name())); + registerWith(notifier()); if (forwardCurve_ != nullptr) // registerWith(forwardCurve_); diff --git a/ql/index.cpp b/ql/index.cpp index 967a806b2c..3a181837ba 100644 --- a/ql/index.cpp +++ b/ql/index.cpp @@ -42,7 +42,9 @@ namespace QuantLib { void Index::clearFixings() { checkNativeFixingsAllowed(); + QL_DEPRECATED_DISABLE_WARNING IndexManager::instance().clearHistory(name()); + QL_DEPRECATED_ENABLE_WARNING } void Index::checkNativeFixingsAllowed() { diff --git a/ql/index.hpp b/ql/index.hpp index 1bbe384caa..b7da8d98b9 100644 --- a/ql/index.hpp +++ b/ql/index.hpp @@ -69,7 +69,9 @@ namespace QuantLib { virtual Real pastFixing(const Date& fixingDate) const; //! returns the fixing TimeSeries const TimeSeries& timeSeries() const { + QL_DEPRECATED_DISABLE_WARNING return IndexManager::instance().getHistory(name()); + QL_DEPRECATED_ENABLE_WARNING } //! check if index allows for native fixings. /*! If this returns false, calls to addFixing and similar @@ -107,13 +109,23 @@ namespace QuantLib { //! clears all stored historical fixings void clearFixings(); + protected: + ext::shared_ptr notifier() const { + QL_DEPRECATED_DISABLE_WARNING + return IndexManager::instance().notifier(name()); + QL_DEPRECATED_ENABLE_WARNING + } + private: //! check if index allows for native fixings void checkNativeFixingsAllowed(); + }; inline bool Index::hasHistoricalFixing(const Date& fixingDate) const { + QL_DEPRECATED_DISABLE_WARNING return IndexManager::instance().hasHistoricalFixing(name(), fixingDate); + QL_DEPRECATED_ENABLE_WARNING } inline Real Index::pastFixing(const Date& fixingDate) const { diff --git a/ql/indexes/equityindex.cpp b/ql/indexes/equityindex.cpp index 1443539b9d..6f55a1a0ad 100644 --- a/ql/indexes/equityindex.cpp +++ b/ql/indexes/equityindex.cpp @@ -57,7 +57,7 @@ namespace QuantLib { registerWith(dividend_); registerWith(spot_); registerWith(Settings::instance().evaluationDate()); - registerWith(IndexManager::instance().notifier(EquityIndex::name())); + registerWith(notifier()); } Real EquityIndex::fixing(const Date& fixingDate, bool forecastTodaysFixing) const { @@ -107,4 +107,4 @@ namespace QuantLib { return ext::make_shared(name(), fixingCalendar(), currency(), interest, dividend, spot); } -} \ No newline at end of file +} diff --git a/ql/indexes/indexmanager.cpp b/ql/indexes/indexmanager.cpp index 3977b10def..a9c68ac832 100644 --- a/ql/indexes/indexmanager.cpp +++ b/ql/indexes/indexmanager.cpp @@ -30,7 +30,9 @@ namespace QuantLib { } void IndexManager::setHistory(const std::string& name, TimeSeries history) { + QL_DEPRECATED_DISABLE_WARNING notifier(name)->notifyObservers(); + QL_DEPRECATED_ENABLE_WARNING data_[name] = std::move(history); } @@ -59,13 +61,17 @@ namespace QuantLib { } void IndexManager::clearHistory(const std::string& name) { + QL_DEPRECATED_DISABLE_WARNING notifier(name)->notifyObservers(); + QL_DEPRECATED_ENABLE_WARNING data_.erase(name); } void IndexManager::clearHistories() { + QL_DEPRECATED_DISABLE_WARNING for (auto const& d : data_) notifier(d.first)->notifyObservers(); + QL_DEPRECATED_ENABLE_WARNING data_.clear(); } diff --git a/ql/indexes/indexmanager.hpp b/ql/indexes/indexmanager.hpp index 49ba0ad23e..d553eedc62 100644 --- a/ql/indexes/indexmanager.hpp +++ b/ql/indexes/indexmanager.hpp @@ -37,10 +37,67 @@ namespace QuantLib { /*! \note index names are case insensitive */ class IndexManager : public Singleton { friend class Singleton; + friend class Index; private: IndexManager() = default; - friend class Index; + + public: + //! returns all names of the indexes for which fixings were stored + std::vector histories() const; + //! clears all stored fixings + void clearHistories(); + + // deprecated in order to be moved into the private section + + /*! \deprecated Use Index::hasHistoricalFixing instead. + Deprecated in version 1.37. + */ + [[deprecated("Use Index::hasHistoricalFixing instead")]] + bool hasHistory(const std::string& name) const; + + /*! \deprecated Use Index::timeSeries instead. + Deprecated in version 1.37. + */ + [[deprecated("Use Index::timeSeries instead")]] + const TimeSeries& getHistory(const std::string& name) const; + + /*! \deprecated Use Index::clearFixings instead. + Deprecated in version 1.37. + */ + [[deprecated("Use Index::clearFixings instead")]] + void clearHistory(const std::string& name); + + /*! \deprecated Use Index::hasHistoricalFixing instead. + Deprecated in version 1.37. + */ + [[deprecated("Use Index::hasHistoricalFixing instead")]] + bool hasHistoricalFixing(const std::string& name, const Date& fixingDate) const; + + /*! \deprecated Use Index::addFixings instead. + Deprecated in version 1.37. + */ + [[deprecated("Use Index::addFixings instead")]] + void setHistory(const std::string& name, TimeSeries history); + + /*! \deprecated Register with the relevant index instead. + Deprecated in version 1.37. + */ + [[deprecated("Register with the relevant index instead")]] + ext::shared_ptr notifier(const std::string& name) const; + + private: + struct CaseInsensitiveCompare { + bool operator()(const std::string& s1, const std::string& s2) const { + return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), [](const auto& c1, const auto& c2) { + return std::toupper(static_cast(c1)) < std::toupper(static_cast(c2)); + }); + } + }; + + mutable std::map, CaseInsensitiveCompare> data_; + mutable std::map> notifiers_; + //! add a fixing void addFixing(const std::string& name, const Date& fixingDate, @@ -81,7 +138,9 @@ namespace QuantLib { invalidValue = *(vBegin++); } } + QL_DEPRECATED_DISABLE_WARNING notifier(name)->notifyObservers(); + QL_DEPRECATED_ENABLE_WARNING QL_REQUIRE(noInvalidFixing, "At least one invalid fixing provided: " << invalidDate.weekday() << " " << invalidDate << ", " << invalidValue); @@ -90,36 +149,6 @@ namespace QuantLib { << " while " << h[duplicatedDate] << " value is already present"); } - - public: - //! returns whether historical fixings were stored for the index - bool hasHistory(const std::string& name) const; - //! returns the (possibly empty) history of the index fixings - const TimeSeries& getHistory(const std::string& name) const; - //! stores the historical fixings of the index - void setHistory(const std::string& name, TimeSeries history); - //! observer notifying of changes in the index fixings_ - ext::shared_ptr notifier(const std::string& name) const; - //! returns all names of the indexes for which fixings were stored - std::vector histories() const; - //! clears the historical fixings of the index - void clearHistory(const std::string& name); - //! clears all stored fixings - void clearHistories(); - //! returns whether a specific historical fixing was stored for the index and date - bool hasHistoricalFixing(const std::string& name, const Date& fixingDate) const; - - private: - struct CaseInsensitiveCompare { - bool operator()(const std::string& s1, const std::string& s2) const { - return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), [](const auto& c1, const auto& c2) { - return std::toupper(static_cast(c1)) < std::toupper(static_cast(c2)); - }); - } - }; - - mutable std::map, CaseInsensitiveCompare> data_; - mutable std::map> notifiers_; }; } diff --git a/ql/indexes/inflationindex.cpp b/ql/indexes/inflationindex.cpp index 66d1c5c54a..5cb89e0206 100644 --- a/ql/indexes/inflationindex.cpp +++ b/ql/indexes/inflationindex.cpp @@ -126,7 +126,7 @@ namespace QuantLib { frequency_(frequency), availabilityLag_(availabilityLag), currency_(std::move(currency)) { name_ = region_.name() + " " + familyName_; registerWith(Settings::instance().evaluationDate()); - registerWith(IndexManager::instance().notifier(InflationIndex::name())); + registerWith(notifier()); } Calendar InflationIndex::fixingCalendar() const { diff --git a/ql/indexes/interestrateindex.cpp b/ql/indexes/interestrateindex.cpp index d4e9fab0d7..d98e26539c 100644 --- a/ql/indexes/interestrateindex.cpp +++ b/ql/indexes/interestrateindex.cpp @@ -57,7 +57,7 @@ namespace QuantLib { name_ = out.str(); registerWith(Settings::instance().evaluationDate()); - registerWith(IndexManager::instance().notifier(InterestRateIndex::name())); + registerWith(notifier()); } Rate InterestRateIndex::fixing(const Date& fixingDate, diff --git a/ql/instruments/overnightindexfuture.cpp b/ql/instruments/overnightindexfuture.cpp index 784e4811b0..7cb1bc9002 100644 --- a/ql/instruments/overnightindexfuture.cpp +++ b/ql/instruments/overnightindexfuture.cpp @@ -46,8 +46,7 @@ namespace QuantLib { Date d1 = valueDate_; // d1 could be a holiday Date fixingDate = calendar.adjust(d1, Preceding); - const TimeSeries& history = IndexManager::instance() - .getHistory(overnightIndex_->name()); + const auto& history = overnightIndex_->timeSeries(); Real fwd; while (d1 < maturityDate_) { Date d2 = calendar.advance(d1, 1, Days); @@ -86,8 +85,7 @@ namespace QuantLib { forwardDiscountStart = today; // for valuations inside the reference period, index quotes // must have been populated in the history - const TimeSeries& history = IndexManager::instance() - .getHistory(overnightIndex_->name()); + const auto& history = overnightIndex_->timeSeries(); Date d1 = valueDate_; // d1 could be a holiday Date fixingDate = calendar.adjust(d1, Preceding); diff --git a/test-suite/indexes.cpp b/test-suite/indexes.cpp index b094d1da64..6f14d223b2 100644 --- a/test-suite/indexes.cpp +++ b/test-suite/indexes.cpp @@ -96,39 +96,19 @@ BOOST_AUTO_TEST_CASE(testFixingHasHistoricalFixing) { name = euribor3M->name(); testCase(name, fixingNotFound, euribor3M->hasHistoricalFixing(today)); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_upper_copy(euribor3M->name()); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_lower_copy(euribor3M->name()); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); name = euribor6M->name(); testCase(name, fixingFound, euribor6M->hasHistoricalFixing(today)); testCase(name, fixingFound, euribor6M_a->hasHistoricalFixing(today)); - testCase(name, fixingFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_upper_copy(euribor6M->name()); - testCase(name, fixingFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_lower_copy(euribor6M->name()); - testCase(name, fixingFound, IndexManager::instance().hasHistoricalFixing(name, today)); IndexManager::instance().clearHistories(); name = euribor3M->name(); testCase(name, fixingNotFound, euribor3M->hasHistoricalFixing(today)); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_upper_copy(euribor3M->name()); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_lower_copy(euribor3M->name()); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); name = euribor6M->name(); testCase(name, fixingNotFound, euribor6M->hasHistoricalFixing(today)); testCase(name, fixingNotFound, euribor6M_a->hasHistoricalFixing(today)); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_upper_copy(euribor6M->name()); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); - name = boost::to_lower_copy(euribor6M->name()); - testCase(name, fixingNotFound, IndexManager::instance().hasHistoricalFixing(name, today)); } BOOST_AUTO_TEST_CASE(testTenorNormalization) { diff --git a/test-suite/shortratemodels.cpp b/test-suite/shortratemodels.cpp index 0265524e06..54ec8ff110 100644 --- a/test-suite/shortratemodels.cpp +++ b/test-suite/shortratemodels.cpp @@ -342,10 +342,7 @@ BOOST_AUTO_TEST_CASE(testSwaps) { Date startDate = calendar.advance(settlement,start[i],Months); if (startDate < today) { Date fixingDate = calendar.advance(startDate,-2,Days); - TimeSeries pastFixings; - pastFixings[fixingDate] = 0.03; - IndexManager::instance().setHistory(euribor->name(), - pastFixings); + euribor->addFixing(fixingDate, 0.03); } for (Size j=0; j