24#include <ql/errors.hpp>
46 {RiskType::InflationVol, RiskType::IRCurve},
47 {RiskType::CreditVol, RiskType::CreditQ},
48 {RiskType::CreditVolNonQ, RiskType::CreditNonQ},
49 {RiskType::EquityVol, RiskType::Equity},
50 {RiskType::CommodityVol, RiskType::Commodity}};
53 const QuantLib::ext::shared_ptr<ore::data::ReferenceDataManager>& refDataManager,
54 const QuantLib::ext::shared_ptr<SimmBasicNameMapper>& nameMapper) :
55 refDataManager_(refDataManager), nameMapper_(nameMapper){
58 rtWithBuckets_ = {RiskType::IRCurve, RiskType::CreditQ, RiskType::CreditNonQ, RiskType::Equity,
59 RiskType::Commodity, RiskType::IRVol, RiskType::InflationVol, RiskType::CreditVol,
60 RiskType::CreditVolNonQ, RiskType::EquityVol, RiskType::CommodityVol};
75 return Date::maxDate();
82 return Date::minDate();
89 auto key = std::make_pair(riskType, qualifier);
93 QL_REQUIRE(
hasBuckets(riskType),
"The risk type " << riskType <<
" does not have buckets");
96 auto lookupRiskType = riskType;
99 lookupRiskType = nv->second;
103 if (lookupRiskType == RiskType::IRCurve || lookupRiskType == RiskType::GIRR_DELTA) {
110 string lookupName = qualifier;
112 bool haveMapping =
has(lookupRiskType, lookupName,
false);
113 bool haveFallback =
has(lookupRiskType, lookupName,
true);
114 bool noBucket = !haveMapping && !haveFallback;
117 (lookupRiskType == RiskType::Equity || lookupRiskType == RiskType::EQ_DELTA)) {
120 haveMapping =
has(lookupRiskType, lookupName,
false);
121 noBucket = !haveMapping && !haveFallback;
126 if (lookupRiskType == RiskType::Commodity) {
127 bool commIndex =
false;
130 auto refData = QuantLib::ext::dynamic_pointer_cast<ore::data::EquityReferenceDatum>(
132 if (refData->equityData().isIndex)
139 bucket = commIndex ?
"17" :
"16";
140 TLOG(
"Don't have any bucket mappings for the "
141 <<
"combination of risk type " << riskType <<
" and qualifier " << lookupName
142 <<
" - assigning to bucket " <<
bucket);
144 }
else if (lookupRiskType == RiskType::Equity) {
147 auto refData = QuantLib::ext::dynamic_pointer_cast<ore::data::EquityReferenceDatum>(
refDataManager_->getData(
"Equity", lookupName));
149 if (refData->equityData().isIndex) {
150 TLOG(
"Don't have any bucket mappings for the "
151 <<
"combination of risk type " << riskType <<
" and qualifier " << lookupName
152 <<
" - assigning to bucket 11");
159 TLOG(
"Don't have any bucket mappings for the "
160 <<
"combination of risk type " << riskType <<
" and qualifier " << lookupName
161 <<
" - assigning to Residual/Other bucket");
174 Date today = Settings::instance().evaluationDate();
176 if (m.validToDate() >= today && m.validFromDate() <= today && m.fallback() == !haveMapping) {
182 TLOG(
"bucket mapping for risk type " << riskType <<
" and qualifier " << qualifier <<
" inactive, return Residual");
193 boost::optional<bool> fallback)
const {
196 auto lookupRiskType = riskType;
199 lookupRiskType = nv->second;
202 if (lookupRiskType == RiskType::IRCurve || lookupRiskType == RiskType::GIRR_DELTA)
209 auto q =
bm->second.find(qualifier);
210 if (q ==
bm->second.end())
213 Date today = Settings::instance().evaluationDate();
218 for (
const auto& m : q->second) {
219 Date validTo = m.validToDate();
220 Date validFrom = m.validFromDate();
221 if (validTo >= today && validFrom <= today && (fallback ? *fallback == m.fallback() :
true))
233 LOG(
"Start parsing SIMMBucketMappings");
243 "Can only have one node for each risk type. " << strRiskType <<
" appears more than once.");
254 if (
bucket ==
"" || qualifier ==
"") {
255 ALOG(
"skip bucket mapping for quaifier '" << qualifier <<
"' and bucket '" <<
bucket <<
"'");
259 bool fallback =
false;
260 if (fallbackString !=
"")
267 }
catch(std::exception&) {
268 ALOG(
"Cannot parse bucket mapping validTo " << validTo <<
" for qualifier " << qualifier <<
", ignore");
272 if (validFrom !=
"") {
276 }
catch(std::exception&) {
277 ALOG(
"Cannot parse bucket mapping validFrom " << validFrom <<
" for qualifier " << qualifier <<
", ignore");
287 TLOG(
"Added SIMM bucket mapping: {" << riskType <<
": {" << qualifier <<
", " <<
bucket <<
", " << validFrom <<
", " << validTo <<
", " << fallback <<
"}}");
288 if (
bucket !=
"Residual") {
290 QL_REQUIRE(bucketInt >= 1,
"found bucket " <<
bucket <<
", expected >= 1");
295 LOG(
"Finished parsing SIMMBucketMappings");
303 for (
auto const& bms : b.second) {
304 for (
auto const&
bm : bms.second) {
307 if (!bms.first.empty())
309 if (!
bm.validTo().empty())
311 if (!
bm.validFrom().empty())
313 if (!
bm.bucket().empty())
324 const string& validFrom,
const string& validTo,
bool fallback) {
334 if (rt == RiskType::IRCurve) {
341 "Tried to add a bucket mapping for risk type " << riskType <<
" but it does not have buckets.");
346 std::string vf = validFrom, vt = validTo;
350 }
catch(std::exception& e) {
351 ALOG(
"Error parsing validFrom date, ignore: " << e.what());
358 }
catch(std::exception& e) {
359 ALOG(
"Error parsing validTo date, ignore: " << e.what());
368 if (qualifier ==
"USD" || qualifier ==
"EUR" || qualifier ==
"GBP" || qualifier ==
"AUD" || qualifier ==
"CAD" ||
369 qualifier ==
"CHF" || qualifier ==
"DKK" || qualifier ==
"HKD" || qualifier ==
"KRW" || qualifier ==
"NOK" ||
370 qualifier ==
"NZD" || qualifier ==
"SEK" || qualifier ==
"SGD" || qualifier ==
"TWD")
372 if (qualifier ==
"JPY")
378 QL_REQUIRE(riskType != RiskType::IRCurve,
"Risk type " << RiskType::IRCurve <<
" is mapped to buckets internally.");
380 QL_REQUIRE(
hasBuckets(riskType),
"The risk type " << riskType <<
" does not have buckets.");
383 <<
"mappings are stored in their non-vol counterparts. Use "
QuantLib::Date validFromDate() const
QuantLib::Date validToDate() const
bool hasBuckets(const CrifRecord::RiskType &riskType) const override
Check if the given SIMM RiskType has a bucket structure.
std::string bucket(const CrifRecord::RiskType &riskType, const std::string &qualifier) const override
ore::data::XMLNode * toXML(ore::data::XMLDocument &) const override
SimmBucketMapperBase(const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &refDataManager=nullptr, const QuantLib::ext::shared_ptr< SimmBasicNameMapper > &nameMapper=nullptr)
Default constructor that adds fixed known mappings.
void addMapping(const CrifRecord::RiskType &riskType, const std::string &qualifier, const std::string &bucket, const std::string &validFrom="", const std::string &validTo="", bool fallback=false) override
Add a single bucket mapping for qualifier with risk type riskType.
void fromXML(ore::data::XMLNode *node) override
bool has(const CrifRecord::RiskType &riskType, const std::string &qualifier, boost::optional< bool > fallback=boost::none) const override
Check if the given riskType and qualifier has a valid mapping.
virtual std::string irBucket(const std::string &qualifier) const
void checkRiskType(const CrifRecord::RiskType &riskType) const
Check the risk type before adding a mapping entry.
std::set< FailedMapping > failedMappings_
std::map< CrifRecord::RiskType, std::map< std::string, std::set< BucketMapping > > > bucketMapping_
QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > refDataManager_
Reference data manager.
void reset()
Reset the SIMM bucket mapper i.e. clears all mappings and adds the initial hard-coded commodity mappi...
std::set< CrifRecord::RiskType > rtWithBuckets_
Set of SIMM risk types that have buckets.
QuantLib::ext::shared_ptr< SimmBasicNameMapper > nameMapper_
Simm Name Mapper.
std::map< std::pair< CrifRecord::RiskType, std::string >, std::string > cache_
XMLNode * allocNode(const string &nodeName)
static void checkNode(XMLNode *n, const string &expectedName)
static string getNodeName(XMLNode *n)
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static XMLNode * getNextSibling(XMLNode *node, const string &name="")
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
Date parseDate(const string &s)
bool parseBool(const string &s)
bool checkCurrency(const string &code)
Integer parseInteger(const string &s)
bool operator<(const Dividend &d1, const Dividend &d2)
CrifRecord::RiskType RiskType
boost::bimap< T, boost::bimaps::set_of< string, string_cmp > > bm
const map< RiskType, RiskType > nonVolRiskTypeMap
CrifRecord::RiskType parseRiskType(const string &rt)
std::string to_string(const LocationInfo &l)
Base SIMM class for mapping qualifiers to buckets.
CrifRecord::RiskType riskType
CrifRecord::RiskType lookupRiskType