22#include <ql/math/comparison.hpp>
23#include <ql/math/matrixutilities/symmetricschurdecomposition.hpp>
25#include <boost/algorithm/string.hpp>
26#include <boost/assign.hpp>
27#include <boost/bimap.hpp>
34using boost::assign::list_of;
50 bool operator()(
const string& lhs,
const string& rhs)
const {
51 return ((boost::to_lower_copy(lhs)) < (boost::to_lower_copy(rhs)));
56template <
typename T>
using bm = boost::bimap<T, boost::bimaps::set_of<string, string_cmp>>;
60 list_of<bm<SimmConfiguration::RiskClass>::value_type>(SimmConfiguration::RiskClass::InterestRate,
"InterestRate")(
61 SimmConfiguration::RiskClass::CreditQualifying,
62 "CreditQualifying")(SimmConfiguration::RiskClass::CreditNonQualifying,
"CreditNonQualifying")(
63 SimmConfiguration::RiskClass::Equity,
"Equity")(SimmConfiguration::RiskClass::Commodity,
"Commodity")(
64 SimmConfiguration::RiskClass::FX,
"FX")(SimmConfiguration::RiskClass::All,
"All");
67 list_of<bm<SimmConfiguration::MarginType>::value_type>(SimmConfiguration::MarginType::Delta,
"Delta")(
68 SimmConfiguration::MarginType::Vega,
"Vega")(SimmConfiguration::MarginType::Curvature,
"Curvature")(
69 SimmConfiguration::MarginType::BaseCorr,
"BaseCorr")(SimmConfiguration::MarginType::AdditionalIM,
"AdditionalIM")(
70 SimmConfiguration::MarginType::All,
"All");
78 (SimmConfiguration::Regulation::CFTC,
"CFTC")(SimmConfiguration::Regulation::ESA,
"ESA")(SimmConfiguration::Regulation::FINMA,
"FINMA")
79 (SimmConfiguration::Regulation::KFSC,
"KFSC")(SimmConfiguration::Regulation::HKMA,
"HKMA")(SimmConfiguration::Regulation::JFSA,
"JFSA")
80 (SimmConfiguration::Regulation::MAS,
"MAS")(SimmConfiguration::Regulation::OSFI,
"OSFI")(SimmConfiguration::Regulation::RBI,
"RBI")
81 (SimmConfiguration::Regulation::SEC,
"SEC")(SimmConfiguration::Regulation::SEC_unseg,
"SEC-unseg")(SimmConfiguration::Regulation::USPR,
"USPR")
82 (SimmConfiguration::Regulation::NONREG,
"NONREG")(SimmConfiguration::Regulation::BACEN,
"BACEN")(SimmConfiguration::Regulation::SANT,
"SANT")
83 (SimmConfiguration::Regulation::SFC,
"SFC")(SimmConfiguration::Regulation::UK,
"UK")(SimmConfiguration::Regulation::AMFQ,
"AMFQ")
84 (SimmConfiguration::Regulation::Included,
"Included")(SimmConfiguration::Regulation::Unspecified,
"Unspecified")(SimmConfiguration::Regulation::Invalid,
"Invalid");
97 set<RiskClass> result;
98 for (Size i = 0; i < bound; ++i) {
106 static std::set<CrifRecord::RiskType> simmRiskTypes = {
108 CrifRecord::RiskType::Commodity,
109 CrifRecord::RiskType::CommodityVol,
110 CrifRecord::RiskType::CreditNonQ,
111 CrifRecord::RiskType::CreditQ,
112 CrifRecord::RiskType::CreditVol,
113 CrifRecord::RiskType::CreditVolNonQ,
114 CrifRecord::RiskType::Equity,
115 CrifRecord::RiskType::EquityVol,
116 CrifRecord::RiskType::FX,
117 CrifRecord::RiskType::FXVol,
118 CrifRecord::RiskType::Inflation,
119 CrifRecord::RiskType::IRCurve,
120 CrifRecord::RiskType::IRVol,
121 CrifRecord::RiskType::InflationVol,
122 CrifRecord::RiskType::BaseCorr,
123 CrifRecord::RiskType::XCcyBasis,
124 CrifRecord::RiskType::ProductClassMultiplier,
125 CrifRecord::RiskType::AddOnNotionalFactor,
126 CrifRecord::RiskType::Notional,
127 CrifRecord::RiskType::AddOnFixedAmount,
128 CrifRecord::RiskType::PV,
133 simmRiskTypes.insert(CrifRecord::RiskType::All);
135 return simmRiskTypes;
144 set<MarginType> result;
145 for (Size i = 0; i < bound; ++i) {
154 static std::set<CrifRecord::ProductClass> simmProductClasses = {
155 CrifRecord::ProductClass::RatesFX,
156 CrifRecord::ProductClass::Rates,
157 CrifRecord::ProductClass::FX,
158 CrifRecord::ProductClass::Credit,
159 CrifRecord::ProductClass::Equity,
160 CrifRecord::ProductClass::Commodity,
161 CrifRecord::ProductClass::Empty,
162 CrifRecord::ProductClass::Other,
163 CrifRecord::ProductClass::AddOnNotionalFactor,
164 CrifRecord::ProductClass::AddOnFixedAmount};
167 simmProductClasses.insert(CrifRecord::ProductClass::All);
169 return simmProductClasses;
172pair<CrifRecord::RiskType, CrifRecord::RiskType>
176 case RiskClass::InterestRate:
177 deltaRiskType = CrifRecord::RiskType::IRCurve;
178 vegaRiskType = CrifRecord::RiskType::IRVol;
180 case RiskClass::CreditQualifying:
181 deltaRiskType = CrifRecord::RiskType::CreditQ;
182 vegaRiskType = CrifRecord::RiskType::CreditVol;
184 case RiskClass::CreditNonQualifying:
185 deltaRiskType = CrifRecord::RiskType::CreditNonQ;
186 vegaRiskType = CrifRecord::RiskType::CreditVolNonQ;
188 case RiskClass::Equity:
189 deltaRiskType = CrifRecord::RiskType::Equity;
190 vegaRiskType = CrifRecord::RiskType::EquityVol;
192 case RiskClass::Commodity:
193 deltaRiskType = CrifRecord::RiskType::Commodity;
194 vegaRiskType = CrifRecord::RiskType::CommodityVol;
197 deltaRiskType = CrifRecord::RiskType::FX;
198 vegaRiskType = CrifRecord::RiskType::FXVol;
201 QL_FAIL(
"riskClassToRiskType: Unexpected risk class");
204 return std::make_pair(deltaRiskType, vegaRiskType);
209 case CrifRecord::RiskType::Commodity:
210 case CrifRecord::RiskType::CommodityVol:
211 return SimmConfiguration::RiskClass::Commodity;
212 case CrifRecord::RiskType::CreditQ:
213 case CrifRecord::RiskType::CreditVol:
214 case CrifRecord::RiskType::BaseCorr:
215 return SimmConfiguration::RiskClass::CreditQualifying;
216 case CrifRecord::RiskType::CreditNonQ:
217 case CrifRecord::RiskType::CreditVolNonQ:
218 return SimmConfiguration::RiskClass::CreditNonQualifying;
219 case CrifRecord::RiskType::Equity:
220 case CrifRecord::RiskType::EquityVol:
221 return SimmConfiguration::RiskClass::Equity;
222 case CrifRecord::RiskType::FX:
223 case CrifRecord::RiskType::FXVol:
224 return SimmConfiguration::RiskClass::FX;
225 case CrifRecord::RiskType::Inflation:
226 case CrifRecord::RiskType::InflationVol:
227 case CrifRecord::RiskType::IRCurve:
228 case CrifRecord::RiskType::IRVol:
229 case CrifRecord::RiskType::XCcyBasis:
230 return SimmConfiguration::RiskClass::InterestRate;
232 QL_FAIL(
"riskTypeToRiskClass: Invalid risk type");
237 string side = s == SimmConfiguration::SimmSide::Call ?
"Call" :
"Post";
243 "Risk class (" <<
static_cast<int>(rc) <<
") not a valid SimmConfiguration::RiskClass");
249 "Margin type (" <<
static_cast<int>(mt) <<
") not a valid SimmConfiguration::MarginType");
254 QL_REQUIRE(
imModelMap.left.count(model) > 0,
"Product class not a valid SimmConfiguration::IMModel");
256 return out <<
"SIMM";
262 QL_REQUIRE(
regulationsMap.left.count(regulation) > 0,
"Product class not a valid SimmConfiguration::Regulation");
267 if (side ==
"Call") {
268 return SimmConfiguration::SimmSide::Call;
269 }
else if (side ==
"Post") {
270 return SimmConfiguration::SimmSide::Post;
272 QL_FAIL(
"Could not parse the string '" << side <<
"' to a SimmSide");
278 "Risk class string " << rc <<
" does not correspond to a valid SimmConfiguration::RiskClass");
284 "Margin type string " << mt <<
" does not correspond to a valid SimmConfiguration::MarginType");
290 if (boost::to_lower_copy(model) == boost::to_lower_copy(it->first))
295 QL_FAIL(
"IM model string " << model <<
" does not correspond to a valid SimmConfiguration::IMModel");
300 return SimmConfiguration::Regulation::Invalid;
312 return regs1 +
',' + regs2;
316 set<string> uniqueRegNames;
319 vector<string> regNames;
320 boost::split(regNames, regsString, boost::is_any_of(
",[] "));
323 regNames.erase(std::remove(regNames.begin(), regNames.end(),
""), regNames.end());
326 for (
string& r : regNames)
331 std::sort(regNames.begin(), regNames.end());
333 uniqueRegNames = set<string>(regNames.begin(), regNames.end());
336 if (uniqueRegNames.empty())
339 return uniqueRegNames;
346 if (uniqueRegNames.size() == 0 ||
347 (uniqueRegNames.size() == 1 && uniqueRegNames.count(
"Unspecified") > 0)) {
350 return boost::algorithm::join(uniqueRegNames,
",");
357 for (
const string& r : regsToRemove) {
358 auto it = uniqueRegNames.find(r);
359 if (it != uniqueRegNames.end())
360 uniqueRegNames.erase(it);
363 if (!uniqueRegNames.empty())
364 return boost::algorithm::join(uniqueRegNames,
",");
371 set<string> filteredRegs;
373 for (
const string& r : uniqueRegNames) {
374 auto it = std::find(regsToFilter.begin(), regsToFilter.end(), r);
375 if (it != regsToFilter.end())
376 filteredRegs.insert(*it);
379 if (!filteredRegs.empty())
380 return boost::algorithm::join(filteredRegs,
",");
387 vector<SimmConfiguration::Regulation> mappedRegulations;
389 for (
const string& reg : winningRegulations)
393 for (
const auto& reg : mappedRegulations) {
394 if (reg < winningRegulation)
395 winningRegulation = reg;
398 return winningRegulation;
404 QL_REQUIRE(lhs != CrifRecord::ProductClass::All && rhs != CrifRecord::ProductClass::All,
405 "Cannot compare the \"All\" ProductClass.");
406 QL_REQUIRE(
static_cast<int>(CrifRecord::ProductClass::All) == 10,
407 "Number of SIMM Product classes is not 11. Some order comparisons are not handled.");
411 case CrifRecord::ProductClass::AddOnFixedAmount:
412 case CrifRecord::ProductClass::AddOnNotionalFactor:
413 case CrifRecord::ProductClass::Empty:
414 case CrifRecord::ProductClass::Other:
416 case CrifRecord::ProductClass::AddOnFixedAmount:
417 case CrifRecord::ProductClass::AddOnNotionalFactor:
418 case CrifRecord::ProductClass::Empty:
419 case CrifRecord::ProductClass::Other:
424 case CrifRecord::ProductClass::RatesFX:
425 case CrifRecord::ProductClass::Rates:
426 case CrifRecord::ProductClass::FX:
428 case CrifRecord::ProductClass::Empty:
429 case CrifRecord::ProductClass::Other:
430 case CrifRecord::ProductClass::RatesFX:
431 case CrifRecord::ProductClass::Rates:
432 case CrifRecord::ProductClass::FX:
437 case CrifRecord::ProductClass::Equity:
439 case CrifRecord::ProductClass::Empty:
440 case CrifRecord::ProductClass::Other:
441 case CrifRecord::ProductClass::RatesFX:
442 case CrifRecord::ProductClass::Rates:
443 case CrifRecord::ProductClass::FX:
444 case CrifRecord::ProductClass::Equity:
449 case CrifRecord::ProductClass::Commodity:
450 if (rhs != CrifRecord::ProductClass::Credit) {
455 case CrifRecord::ProductClass::Credit:
457 case CrifRecord::ProductClass::All:
461 QL_FAIL(
"Unhandled SIMM Product class in waterfall logic.");
static std::set< CrifRecord::RiskType > riskTypes(bool includeAll=false)
Give back a set containing the RiskType values optionally excluding 'All'.
static bool greater_than_or_equal_to(const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
static const QuantLib::Size numberOfRiskClasses
Number of risk classes including RiskClass::All.
static std::set< CrifRecord::ProductClass > productClasses(bool includeAll=false)
Give back a set containing the ProductClass values optionally excluding 'All'.
static std::set< MarginType > marginTypes(bool includeAll=false)
Give back a set containing the MarginType values optionally excluding 'All'.
SimmSide
Enum indicating the relevant side of the SIMM calculation.
static const QuantLib::Size numberOfMarginTypes
Number of margin types including MarginType::All.
static bool less_than(const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
Define ordering for ProductClass according to a waterfall:
static bool less_than_or_equal_to(const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
static std::set< RiskClass > riskClasses(bool includeAll=false)
Give back a set containing the RiskClass values optionally excluding 'All'.
static RiskClass riskTypeToRiskClass(const CrifRecord::RiskType &rt)
For a given rirsk type, return the corresponding risk class.
static const QuantLib::Size numberOfRegulations
Number of regulations.
Regulation
SIMM regulators.
static std::pair< CrifRecord::RiskType, CrifRecord::RiskType > riskClassToRiskType(const RiskClass &rc)
For a given risk class, return the corresponding risk types.
static bool greater_than(const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
string combineRegulations(const string ®s1, const string ®s2)
SimmConfiguration::Regulation parseRegulation(const string ®ulation)
SimmConfiguration::SimmSide parseSimmSide(const string &side)
SimmConfiguration::Regulation getWinningRegulation(const std::vector< string > &winningRegulations)
From a vector of regulations, determine the winning regulation based on order of priority.
set< string > parseRegulationString(const string ®sString, const set< string > &valueIfEmpty)
Reads a string containing regulations applicable for a given CRIF record.
SimmConfiguration::IMModel parseIMModel(const string &model)
const bm< SimmConfiguration::MarginType > marginTypeMap
SimmConfiguration::RiskClass parseSimmRiskClass(const string &rc)
string filterRegulations(const string ®sString, const vector< string > ®sToFilter)
string removeRegulations(const string ®sString, const vector< string > ®sToRemove)
Removes a given vector of regulations from a string of regulations and returns a string with the regu...
const bm< MarketRiskConfiguration::RiskClass > riskClassMap
boost::bimap< T, boost::bimaps::set_of< string, string_cmp > > bm
const bm< SimmConfiguration::IMModel > imModelMap
const bm< SimmConfiguration::Regulation > regulationsMap
SimmConfiguration::MarginType parseSimmMarginType(const string &mt)
string sortRegulationString(const string ®sString)
std::string to_string(const LocationInfo &l)
SIMM configuration interface.