diff --git a/ql/index.cpp b/ql/index.cpp index c5bb900a15..967a806b2c 100644 --- a/ql/index.cpp +++ b/ql/index.cpp @@ -25,9 +25,7 @@ namespace QuantLib { Real fixing, bool forceOverwrite) { checkNativeFixingsAllowed(); - addFixings(&fixingDate, (&fixingDate)+1, - &fixing, - forceOverwrite); + addFixings(&fixingDate, (&fixingDate) + 1, &fixing, forceOverwrite); } void Index::addFixings(const TimeSeries& t, diff --git a/ql/index.hpp b/ql/index.hpp index 6419700ff6..1bbe384caa 100644 --- a/ql/index.hpp +++ b/ql/index.hpp @@ -100,42 +100,9 @@ namespace QuantLib { ValueIterator vBegin, bool forceOverwrite = false) { checkNativeFixingsAllowed(); - std::string tag = name(); - TimeSeries h = IndexManager::instance().getHistory(tag); - bool noInvalidFixing = true, noDuplicatedFixing = true; - Date invalidDate, duplicatedDate; - Real nullValue = Null(); - Real invalidValue = Null(); - Real duplicatedValue = Null(); - while (dBegin != dEnd) { - bool validFixing = isValidFixingDate(*dBegin); - Real currentValue = h[*dBegin]; - bool missingFixing = forceOverwrite || currentValue == nullValue; - if (validFixing) { - if (missingFixing) - h[*(dBegin++)] = *(vBegin++); - else if (close(currentValue, *(vBegin))) { - ++dBegin; - ++vBegin; - } else { - noDuplicatedFixing = false; - duplicatedDate = *(dBegin++); - duplicatedValue = *(vBegin++); - } - } else { - noInvalidFixing = false; - invalidDate = *(dBegin++); - invalidValue = *(vBegin++); - } - } - IndexManager::instance().setHistory(tag, h); - QL_REQUIRE(noInvalidFixing, "At least one invalid fixing provided: " - << invalidDate.weekday() << " " << invalidDate << ", " - << invalidValue); - QL_REQUIRE(noDuplicatedFixing, "At least one duplicated fixing provided: " - << duplicatedDate << ", " << duplicatedValue - << " while " << h[duplicatedDate] - << " value is already present"); + IndexManager::instance().addFixings( + name(), dBegin, dEnd, vBegin, forceOverwrite, + [this](const Date& d) { return isValidFixingDate(d); }); } //! clears all stored historical fixings void clearFixings(); diff --git a/ql/indexes/indexmanager.cpp b/ql/indexes/indexmanager.cpp index 19f4c4f77d..3977b10def 100644 --- a/ql/indexes/indexmanager.cpp +++ b/ql/indexes/indexmanager.cpp @@ -26,15 +26,28 @@ namespace QuantLib { } const TimeSeries& IndexManager::getHistory(const std::string& name) const { - return data_[name].value(); + return data_[name]; } void IndexManager::setHistory(const std::string& name, TimeSeries history) { + notifier(name)->notifyObservers(); data_[name] = std::move(history); } + void IndexManager::addFixing(const std::string& name, + const Date& fixingDate, + Real fixing, + bool forceOverwrite) { + addFixings(name, &fixingDate, (&fixingDate) + 1, &fixing, forceOverwrite); + } + ext::shared_ptr IndexManager::notifier(const std::string& name) const { - return data_[name]; + auto n = notifiers_.find(name); + if(n != notifiers_.end()) + return n->second; + auto o = ext::make_shared(); + notifiers_[name] = o; + return o; } std::vector IndexManager::histories() const { @@ -45,14 +58,21 @@ namespace QuantLib { return temp; } - void IndexManager::clearHistory(const std::string& name) { data_.erase(name); } + void IndexManager::clearHistory(const std::string& name) { + notifier(name)->notifyObservers(); + data_.erase(name); + } - void IndexManager::clearHistories() { data_.clear(); } + void IndexManager::clearHistories() { + for (auto const& d : data_) + notifier(d.first)->notifyObservers(); + data_.clear(); + } bool IndexManager::hasHistoricalFixing(const std::string& name, const Date& fixingDate) const { auto const& indexIter = data_.find(name); return (indexIter != data_.end()) && - ((*indexIter).second.value()[fixingDate] != Null()); + ((*indexIter).second[fixingDate] != Null()); } } diff --git a/ql/indexes/indexmanager.hpp b/ql/indexes/indexmanager.hpp index 0115aabfe9..49ba0ad23e 100644 --- a/ql/indexes/indexmanager.hpp +++ b/ql/indexes/indexmanager.hpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,56 @@ namespace QuantLib { private: IndexManager() = default; + friend class Index; + //! add a fixing + void addFixing(const std::string& name, + const Date& fixingDate, + Real fixing, + bool forceOverwrite = false); + //! add fixings + template + void addFixings(const std::string& name, + DateIterator dBegin, + DateIterator dEnd, + ValueIterator vBegin, + bool forceOverwrite = false, + const std::function& isValidFixingDate = {}) { + auto& h = data_[name]; + bool noInvalidFixing = true, noDuplicatedFixing = true; + Date invalidDate, duplicatedDate; + Real nullValue = Null(); + Real invalidValue = Null(); + Real duplicatedValue = Null(); + while (dBegin != dEnd) { + bool validFixing = isValidFixingDate ? isValidFixingDate(*dBegin) : true; + Real currentValue = h[*dBegin]; + bool missingFixing = forceOverwrite || currentValue == nullValue; + if (validFixing) { + if (missingFixing) + h[*(dBegin++)] = *(vBegin++); + else if (close(currentValue, *(vBegin))) { + ++dBegin; + ++vBegin; + } else { + noDuplicatedFixing = false; + duplicatedDate = *(dBegin++); + duplicatedValue = *(vBegin++); + } + } else { + noInvalidFixing = false; + invalidDate = *(dBegin++); + invalidValue = *(vBegin++); + } + } + notifier(name)->notifyObservers(); + QL_REQUIRE(noInvalidFixing, "At least one invalid fixing provided: " + << invalidDate.weekday() << " " << invalidDate << ", " + << invalidValue); + QL_REQUIRE(noDuplicatedFixing, "At least one duplicated fixing provided: " + << duplicatedDate << ", " << duplicatedValue + << " while " << h[duplicatedDate] + << " value is already present"); + } public: //! returns whether historical fixings were stored for the index @@ -47,7 +98,7 @@ namespace QuantLib { 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 + //! 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; @@ -67,7 +118,8 @@ namespace QuantLib { } }; - mutable std::map>, CaseInsensitiveCompare> data_; + mutable std::map, CaseInsensitiveCompare> data_; + mutable std::map> notifiers_; }; }