2020 \brief Struct for holding CRIF records
2121*/
2222
23+ #include < boost/range/adaptor/filtered.hpp>
24+ #include < boost/range/adaptor/transformed.hpp>
25+ #include < boost/range/algorithm_ext.hpp>
26+ #include < boost/range/algorithm_ext/erase.hpp>
27+ #include < orea/app/structuredanalyticswarning.hpp>
2328#include < orea/simm/crif.hpp>
2429#include < ored/portfolio/structuredtradeerror.hpp>
2530#include < ored/portfolio/structuredtradewarning.hpp>
26- #include < orea/app/structuredanalyticswarning.hpp>
27- #include < ored/utilities/parsers.hpp>
2831#include < ored/utilities/log.hpp>
32+ #include < ored/utilities/parsers.hpp>
2933#include < ored/utilities/to_string.hpp>
30- #include < boost/range/algorithm_ext/erase.hpp>
31- #include < boost/range/adaptor/filtered.hpp>
32- #include < boost/range/adaptor/transformed.hpp>
33- #include < boost/range/algorithm_ext.hpp>
3434
3535namespace ore {
3636namespace analytics {
@@ -48,18 +48,18 @@ void Crif::addRecord(const CrifRecord& record, bool aggregateDifferentAmountCurr
4848 }
4949}
5050
51- void Crif::addFrtbCrifRecord (const CrifRecord& record, bool aggregateDifferentAmountCurrencies, bool sortFxVolQualifer) {
52- QL_REQUIRE (type_ == CrifType::Empty || type_ == CrifType::Frtb,
53- " Can not add a FRTB crif record to a SIMM Crif" );
51+ void Crif::addFrtbCrifRecord (const CrifRecord& record, bool aggregateDifferentAmountCurrencies,
52+ bool sortFxVolQualifer) {
53+ QL_REQUIRE (type_ == CrifType::Empty || type_ == CrifType::Frtb, " Can not add a FRTB crif record to a SIMM Crif" );
5454 if (type_ == CrifType::Empty) {
5555 type_ = CrifType::Frtb;
5656 }
5757 insertCrifRecord (record, aggregateDifferentAmountCurrencies);
5858}
5959
60- void Crif::addSimmCrifRecord (const CrifRecord& record, bool aggregateDifferentAmountCurrencies, bool sortFxVolQualifer) {
61- QL_REQUIRE (type_ == CrifType::Empty || type_ == CrifType::Simm,
62- " Can not add a Simm crif record to a Frtb Crif" );
60+ void Crif::addSimmCrifRecord (const CrifRecord& record, bool aggregateDifferentAmountCurrencies,
61+ bool sortFxVolQualifer) {
62+ QL_REQUIRE (type_ == CrifType::Empty || type_ == CrifType::Simm, " Can not add a Simm crif record to a Frtb Crif" );
6363 if (type_ == CrifType::Empty) {
6464 type_ = CrifType::Simm;
6565 }
@@ -111,20 +111,20 @@ void Crif::addSimmParameterRecord(const CrifRecord& record) {
111111
112112void Crif::updateAmountExistingRecord (std::set<CrifRecord>::iterator& it, const CrifRecord& record) {
113113 bool updated = false ;
114- if (record.hasAmountUsd ()) {
115- it->amountUsd += record.amountUsd ;
116- updated = true ;
117- }
118- if (record.hasAmount () && record.hasAmountCcy () && it->amountCurrency == record.amountCurrency ) {
119- it->amount += record.amount ;
120- updated = true ;
121- }
122- if (record.hasAmountResultCcy () && record.hasResultCcy () && it->resultCurrency == record.resultCurrency ) {
123- it->amountResultCcy += record.amountResultCcy ;
124- updated = true ;
125- }
126- if (updated)
127- DLOG (" Updated net CRIF records: " << *it)
114+ if (record.hasAmountUsd ()) {
115+ it->amountUsd += record.amountUsd ;
116+ updated = true ;
117+ }
118+ if (record.hasAmount () && record.hasAmountCcy () && it->amountCurrency == record.amountCurrency ) {
119+ it->amount += record.amount ;
120+ updated = true ;
121+ }
122+ if (record.hasAmountResultCcy () && record.hasResultCcy () && it->resultCurrency == record.resultCurrency ) {
123+ it->amountResultCcy += record.amountResultCcy ;
124+ updated = true ;
125+ }
126+ if (updated)
127+ DLOG (" Updated net CRIF records: " << *it)
128128}
129129
130130void Crif::addRecords (const Crif& crif, bool aggregateDifferentAmountCurrencies, bool sortFxVolQualifer) {
@@ -147,19 +147,18 @@ Crif Crif::aggregate() const {
147147 return result;
148148}
149149
150-
151- const bool Crif::hasCrifRecords () const {
152- auto it= std::find_if (records_.begin (), records_.end (), isNotSimmParameter);
150+ const bool Crif::hasCrifRecords () const {
151+ auto it = std::find_if (records_.begin (), records_.end (), isNotSimmParameter);
153152 return it != records_.end ();
154153}
155154
156155// ! check if the Crif contains simmParameters
157156const bool Crif::hasSimmParameters () const {
158- auto it= std::find_if (records_.begin (), records_.end (), isSimmParameter);
157+ auto it = std::find_if (records_.begin (), records_.end (), isSimmParameter);
159158 return it != records_.end ();
160159}
161160
162- // ! returns a Crif containing only simmParameter entries
161+ // ! returns a Crif containing only simmParameter entries
163162Crif Crif::simmParameters () const {
164163 Crif results;
165164 for (const auto & record : records_) {
@@ -169,7 +168,100 @@ Crif Crif::simmParameters() const {
169168 }
170169 return results;
171170}
172-
171+ // ! Find first element
172+ std::set<CrifRecord>::const_iterator Crif::findBy (const NettingSetDetails nsd, CrifRecord::ProductClass pc,
173+ const CrifRecord::RiskType rt, const std::string& qualifier) const {
174+ return std::find_if (records_.begin (), records_.end (), [&nsd, &pc, &rt, &qualifier](const CrifRecord& record) {
175+ return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
176+ record.qualifier == qualifier;
177+ });
178+ };
179+
180+ Crif Crif::filterNonZeroAmount (double threshold = 0.0 , std::string alwaysIncludeFxRiskCcy) const {
181+ Crif results;
182+ for (auto record : records_) {
183+ QL_REQUIRE (record.amount != QuantLib::Null<QuantLib::Real>() || record.amountUsd != QuantLib::Null<double >(),
184+ " Internal Error, amount and amountUsd are empty" );
185+ double absAmount = 0.0 ;
186+ if ((record.amount != QuantLib::Null<double >()) && (record.amountUsd != QuantLib::Null<double >())) {
187+ absAmount = std::max (std::fabs (record.amount ), std::fabs (record.amountUsd ));
188+ } else if (record.amount != QuantLib::Null<double >()) {
189+ absAmount = std::fabs (record.amount );
190+ } else if (record.amountUsd != QuantLib::Null<double >()) {
191+ absAmount = std::fabs (record.amountUsd );
192+ }
193+ bool add = (absAmount > threshold && !QuantLib::close_enough (absAmount, threshold));
194+ if (!alwaysIncludeFxRiskCcy.empty ())
195+ add = add || (record.riskType == CrifRecord::RiskType::FX && record.qualifier == alwaysIncludeFxRiskCcy);
196+ if (add) {
197+ results.addRecord (record);
198+ }
199+ }
200+ return results;
201+ }
202+
203+ std::set<std::string> Crif::qualifiersBy (const NettingSetDetails nsd, CrifRecord::ProductClass pc,
204+ const CrifRecord::RiskType rt) const {
205+ auto res = records_ | boost::adaptors::filtered ([&nsd, &pc, &rt](const CrifRecord& record) {
206+ return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt;
207+ }) |
208+ boost::adaptors::transformed ([](const CrifRecord& record) { return record.qualifier ; });
209+ return boost::copy_range<std::set<std::string>>(res);
210+ }
211+
212+ std::vector<CrifRecord> Crif::filterByQualifierAndBucket (const NettingSetDetails& nsd,
213+ const CrifRecord::ProductClass pc,
214+ const CrifRecord::RiskType rt, const std::string& qualifier,
215+ const std::string& bucket) const {
216+ return boost::copy_range<std::vector<CrifRecord>>(
217+ records_ | boost::adaptors::filtered ([&nsd, &pc, &rt, &qualifier, &bucket](const CrifRecord& record) {
218+ return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
219+ record.qualifier == qualifier && record.bucket == bucket;
220+ }));
221+ }
222+
223+ std::vector<CrifRecord> Crif::filterByQualifier (const NettingSetDetails& nsd, const CrifRecord::ProductClass pc,
224+ const CrifRecord::RiskType rt, const std::string& qualifier) const {
225+
226+ return boost::copy_range<std::vector<CrifRecord>>(
227+ records_ | boost::adaptors::filtered ([&nsd, &pc, &rt, &qualifier](const CrifRecord& record) {
228+ return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
229+ record.qualifier == qualifier;
230+ }));
231+ }
232+
233+ std::vector<CrifRecord> Crif::filterByBucket (const NettingSetDetails& nsd, const CrifRecord::ProductClass pc,
234+ const CrifRecord::RiskType rt, const std::string& bucket) const {
235+ return boost::copy_range<std::vector<CrifRecord>>(
236+ records_ | boost::adaptors::filtered ([&nsd, &pc, &rt, &bucket](const CrifRecord& record) {
237+ return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
238+ record.bucket == bucket;
239+ }));
240+ }
241+
242+ std::vector<CrifRecord> Crif::filterBy (const NettingSetDetails& nsd, const CrifRecord::ProductClass pc,
243+ const CrifRecord::RiskType rt) const {
244+ return boost::copy_range<std::vector<CrifRecord>>(
245+ records_ | boost::adaptors::filtered ([&nsd, &pc, &rt](const CrifRecord& record) {
246+ return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt;
247+ }));
248+ }
249+
250+ std::vector<CrifRecord> Crif::filterBy (const CrifRecord::RiskType rt) const {
251+ return boost::copy_range<std::vector<CrifRecord>>(
252+ records_ | boost::adaptors::filtered ([&rt](const CrifRecord& record) { return record.riskType == rt; }));
253+ }
254+
255+ std::vector<CrifRecord> Crif::filterByTradeId (const std::string& id) const {
256+ return boost::copy_range<std::vector<CrifRecord>>(
257+ records_ | boost::adaptors::filtered ([&id](const CrifRecord& record) { return record.tradeId == id; }));
258+ }
259+
260+ std::set<std::string> Crif::tradeIds () const {
261+ return boost::copy_range<std::set<std::string>>(
262+ records_ | boost::adaptors::transformed ([](const CrifRecord& r) { return r.tradeId ; }));
263+ }
264+
173265// ! deletes all existing simmParameter and replaces them with the new one
174266void Crif::setSimmParameters (const Crif& crif) {
175267 auto backup = records_;
@@ -186,7 +278,6 @@ void Crif::setSimmParameters(const Crif& crif) {
186278 }
187279}
188280
189-
190281void Crif::setCrifRecords (const Crif& crif) {
191282 auto backup = records_;
192283 records_.clear ();
@@ -216,15 +307,14 @@ std::set<CrifRecord::ProductClass> Crif::ProductClassesByNettingSetDetails(const
216307 return keys;
217308}
218309
219- size_t Crif::countMatching (const NettingSetDetails& nsd, const CrifRecord::ProductClass pc, const CrifRecord::RiskType rt,
220- const std::string& qualifier) const {
310+ size_t Crif::countMatching (const NettingSetDetails& nsd, const CrifRecord::ProductClass pc,
311+ const CrifRecord::RiskType rt, const std::string& qualifier) const {
221312 return std::count_if (records_.begin (), records_.end (), [&nsd, &pc, &rt, &qualifier](const CrifRecord& record) {
222313 return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
223314 record.qualifier == qualifier;
224315 });
225316}
226317
227-
228318bool Crif::hasNettingSetDetails () const {
229319 bool hasNettingSetDetails = false ;
230320 for (const auto & nsd : nettingSetDetails_) {
0 commit comments