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>
52 bool sortFxVolQualifer) {
61 bool sortFxVolQualifer) {
66 auto recordToAdd = record;
67 if (sortFxVolQualifer && recordToAdd.riskType == CrifRecord::RiskType::FXVol) {
68 auto ccy_1 = recordToAdd.
qualifier.substr(0, 3);
69 auto ccy_2 = recordToAdd.qualifier.substr(3);
72 recordToAdd.qualifier = ccy_1 + ccy_2;
79 auto it = aggregateDifferentAmountCurrencies ?
records_.end() :
records_.find(record);
80 auto itDiffAmountCcy = aggregateDifferentAmountCurrencies
85 auto recordIt =
records_.insert(record);
102 }
else if (it->riskType == CrifRecord::RiskType::AddOnFixedAmount) {
104 }
else if (it->riskType == CrifRecord::RiskType::AddOnNotionalFactor ||
105 it->riskType == CrifRecord::RiskType::ProductClassMultiplier) {
107 if (record.
amount != it->amount) {
108 string errMsg =
"Found more than one instance of risk type " +
ore::data::to_string(it->riskType) +
109 ". Please check the SIMM parameters input. If enforceIMRegulations=False, then it "
110 "is possible that multiple entries for different regulations now belong under the same "
111 "'Unspecified' regulation.";
118 bool updated =
false;
124 it->amount += record.
amount;
132 DLOG(
"Updated net CRIF records: " << *it)
137 bool updated =
false;
139 it->second->amountUsd += record.
amountUsd;
143 it->second->amount += record.
amount;
151 DLOG(
"Updated net CRIF records: " << *(it->second))
155 for (
const auto& r : crif.
records_) {
156 addRecord(r, aggregateDifferentAmountCurrencies, sortFxVolQualifer);
166 if (cr.imModel !=
"Schedule") {
188 for (
const auto& record :
records_) {
189 if (record.isSimmParameter()) {
199 return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
200 record.qualifier == qualifier;
207 QL_REQUIRE(record.amount != QuantLib::Null<QuantLib::Real>() || record.amountUsd != QuantLib::Null<double>(),
208 "Internal Error, amount and amountUsd are empty");
209 double absAmount = 0.0;
210 if ((record.amount != QuantLib::Null<double>()) && (record.amountUsd != QuantLib::Null<double>())) {
211 absAmount = std::max(std::fabs(record.amount), std::fabs(record.amountUsd));
212 }
else if (record.amount != QuantLib::Null<double>()) {
213 absAmount = std::fabs(record.amount);
214 }
else if (record.amountUsd != QuantLib::Null<double>()) {
215 absAmount = std::fabs(record.amountUsd);
217 bool add = (absAmount > threshold && !QuantLib::close_enough(absAmount, threshold));
218 if (!alwaysIncludeFxRiskCcy.empty())
219 add = add || (record.riskType == CrifRecord::RiskType::FX && record.qualifier == alwaysIncludeFxRiskCcy);
229 auto res =
records_ | boost::adaptors::filtered([&nsd, &pc, &rt](
const CrifRecord& record) {
233 return boost::copy_range<std::set<std::string>>(res);
239 const std::string& bucket)
const {
240 return boost::copy_range<std::vector<CrifRecord>>(
241 records_ | boost::adaptors::filtered([&nsd, &pc, &rt, &qualifier, &bucket](
const CrifRecord& record) {
250 return boost::copy_range<std::vector<CrifRecord>>(
251 records_ | boost::adaptors::filtered([&nsd, &pc, &rt, &qualifier](
const CrifRecord& record) {
259 return boost::copy_range<std::vector<CrifRecord>>(
260 records_ | boost::adaptors::filtered([&nsd, &pc, &rt, &bucket](
const CrifRecord& record) {
268 return boost::copy_range<std::vector<CrifRecord>>(
275 return boost::copy_range<std::vector<CrifRecord>>(
280 return boost::copy_range<std::vector<CrifRecord>>(
285 return boost::copy_range<std::set<std::string>>(
293 for (
auto& r : backup) {
294 if (!r.isSimmParameter()) {
298 for (
const auto& r : crif) {
299 if (r.isSimmParameter()) {
308 for (
auto& r : backup) {
309 if (r.isSimmParameter()) {
313 for (
const auto& r : crif) {
314 if (!r.isSimmParameter()) {
325 std::set<CrifRecord::ProductClass> keys;
326 for (
const auto& record :
records_) {
327 if (record.nettingSetDetails == nsd) {
328 keys.insert(record.productClass);
337 return record.nettingSetDetails == nsd && record.productClass == pc && record.riskType == rt &&
338 record.qualifier == qualifier;
345 if (!nsd.emptyOptionalFields())
353 WLOG(
"CrifLoader::fillAmountUsd() was called, but market object is empty.")
356 std::set<CrifRecord> results;
362 if (cr.requiresAmountUsd() && !cr.hasAmountUsd()) {
363 if (!cr.hasAmount() || !cr.hasAmountCcy()) {
365 cr.tradeId, cr.tradeType,
"Populating CRIF amount USD",
366 "CRIF record is missing one of Amount and AmountCurrency, and there is no amountUsd value to "
371 double usdSpot = market->fxRate(cr.amountCurrency +
"USD")->value();
372 cr.amountUsd = cr.amount * usdSpot;
Crif aggregate() const
Aggregate all existing records.
void setCrifRecords(const Crif &crif)
deletes all existing simmParameter and replaces them with the new one
void updateAmountExistingRecord(std::set< CrifRecord >::iterator &it, const CrifRecord &record)
std::set< std::string > qualifiersBy(const NettingSetDetails nsd, CrifRecord::ProductClass pc, const CrifRecord::RiskType rt) const
std::set< ore::data::NettingSetDetails > nettingSetDetails_
std::vector< CrifRecord > filterByQualifier(const NettingSetDetails &nsd, const CrifRecord::ProductClass pc, const CrifRecord::RiskType rt, const std::string &qualifier) const
std::set< std::string > tradeIds() const
const std::set< ore::data::NettingSetDetails > & nettingSetDetails() const
Crif filterNonZeroAmount(double threshold=0.0, std::string alwaysIncludeFxRiskCcy="") const
returns a crif without zero amount records, FXRisk entries in currency alwaysIncludeFxRiskCcy are alw...
void addFrtbCrifRecord(const CrifRecord &record, bool aggregateDifferentAmountCurrencies=false, bool sortFxVolQualifer=true)
std::vector< CrifRecord > filterByBucket(const NettingSetDetails &nsd, const CrifRecord::ProductClass pc, const CrifRecord::RiskType rt, const std::string &bucket) const
std::vector< CrifRecord > filterByQualifierAndBucket(const NettingSetDetails &nsd, const CrifRecord::ProductClass pc, const CrifRecord::RiskType rt, const std::string &qualifier, const std::string &bucket) const
std::set< CrifRecord::ProductClass > ProductClassesByNettingSetDetails(const NettingSetDetails nsd) const
std::vector< CrifRecord > filterByTradeId(const std::string &id) const
void addRecords(const Crif &crif, bool aggregateDifferentAmountCurrencies=false, bool sortFxVolQualfier=true)
Crif simmParameters() const
returns a Crif containing only simmParameter entries
const std::set< std::string > & portfolioIds() const
Give back the set of portfolio IDs that have been loaded.
void addRecord(const CrifRecord &record, bool aggregateDifferentAmountCurrencies=false, bool sortFxVolQualifer=true)
size_t countMatching(const NettingSetDetails &nsd, const CrifRecord::ProductClass pc, const CrifRecord::RiskType rt, const std::string &qualifier) const
bool hasNettingSetDetails() const
Check if netting set details are used anywhere, instead of just the netting set ID.
const bool hasCrifRecords() const
check if there are crif records beside simmParameters
std::set< std::string > portfolioIds_
Set of portfolio IDs that have been loaded.
std::set< CrifRecord > records_
void insertCrifRecord(const CrifRecord &record, bool aggregateDifferentAmountCurrencies=false)
void fillAmountUsd(const QuantLib::ext::shared_ptr< ore::data::Market > market)
const bool hasSimmParameters() const
check if the Crif contains simmParameters
std::set< CrifRecord >::const_iterator findBy(const NettingSetDetails nsd, CrifRecord::ProductClass pc, const CrifRecord::RiskType rt, const std::string &qualifier) const
Find first element.
std::map< CrifRecord::SimmAmountCcyKey, const CrifRecord * > diffAmountCurrenciesIndex_
std::vector< CrifRecord > filterBy(const NettingSetDetails &nsd, const CrifRecord::ProductClass pc, const CrifRecord::RiskType rt) const
void addSimmParameterRecord(const CrifRecord &record)
void setSimmParameters(const Crif &crif)
deletes all existing simmParameter and replaces them with the new one
void addSimmCrifRecord(const CrifRecord &record, bool aggregateDifferentAmountCurrencies=false, bool sortFxVolQualifer=true)
Struct for holding CRIF records.
std::string to_string(const LocationInfo &l)
std::string amountCurrency
bool hasAmountCcy() const
std::string resultCurrency
ProductClass productClass
const SimmAmountCcyKey getSimmAmountCcyKey() const
QuantLib::Real amountResultCcy
NettingSetDetails nettingSetDetails
bool hasAmountUsd() const
bool isSimmParameter() const
bool hasAmountResultCcy() const
bool hasResultCcy() const
Class for structured analytics warnings.