9#include <ql/math/matrix.hpp>
11#include <boost/algorithm/string/predicate.hpp>
12#include <boost/make_shared.hpp>
14using QuantLib::InterestRateIndex;
15using QuantLib::Matrix;
26 const std::map<
string, std::set<string>>& categories)
const {
28 for (
const auto& kv : categories) {
29 if (kv.second.empty()) {
32 if (kv.second.count(qualifier) > 0) {
44 boost::optional<string> label_1,
45 const string& calculationCurrency)
const {
47 if (rt == RiskType::FX) {
48 QL_REQUIRE(calculationCurrency !=
"",
"no calculation currency provided weight");
49 QL_REQUIRE(qualifier,
"need a qualifier to return a risk weight for the risk type FX");
54 return rwBucket_.at(RiskType::FX).at(label12Key);
61 const string& firstLabel_1,
const string& firstLabel_2,
62 const RiskType& secondRt,
const string& secondQualifier,
63 const string& secondLabel_1,
const string& secondLabel_2,
64 const string& calculationCurrency)
const {
66 if (firstRt == RiskType::FX && secondRt == RiskType::FX) {
67 QL_REQUIRE(calculationCurrency !=
"",
"no calculation currency provided corr");
76 QL_FAIL(
"Could not find FX intrabucket correlation, calculation currency '"
77 << calculationCurrency <<
"', firstQualifier '" << firstQualifier <<
"', secondQualifier '"
78 << secondQualifier <<
"'.");
83 secondQualifier, secondLabel_1, secondLabel_2);
87 const QuantLib::ext::shared_ptr<SimmCalibration>& simmCalibration,
88 const QuantLib::Size& mporDays,
const string& name)
91 version_ = simmCalibration->version();
96 QL_REQUIRE(
mporDays_ == 10 ||
mporDays_ == 1,
"SIMM only supports MPOR 10-day or 1-day");
106 for (
const auto& [riskClass, rcData] : simmCalibration->riskClassData()) {
109 const auto& riskWeights = rcData->riskWeights();
114 if (riskClass == RiskClass::FX) {
115 const auto& fxRiskWeights = QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::FXRiskWeights>(riskWeights);
116 QL_REQUIRE(fxRiskWeights,
"Cannot cast RiskWeights to FXRiskWeights");
117 const auto& ccyLists = fxRiskWeights->currencyLists();
119 for (
const auto& [ccyKey, ccyList] : ccyLists) {
120 const string&
bucket = std::get<0>(ccyKey);
121 for (
const string& ccy : ccyList) {
122 if (ccy ==
"Other") {
134 auto singleRiskWeights = riskWeights->uniqueRiskWeights();
135 for (
const auto& [riskType, rw] : singleRiskWeights) {
140 const auto& deltaRiskWeights = riskWeights->delta().at(
mporDays_);
141 const auto& vegaRiskWeights = riskWeights->vega().at(
mporDays_);
143 if (deltaRiskWeights.size() == 1) {
147 if (riskClass == RiskClass::InterestRate) {
148 for (
const auto& [rwKey,
weight] : deltaRiskWeights) {
152 for (
const auto& [rwKey,
weight] : deltaRiskWeights) {
159 if (vegaRiskWeights.size() == 1) {
161 if (vegaRiskType == RiskType::IRVol)
164 for (
const auto& [rwKey,
weight] : vegaRiskWeights) {
171 if (riskClass == RiskClass::InterestRate) {
175 if (riskClass == RiskClass::Equity || riskClass == RiskClass::Commodity || riskClass == RiskClass::FX)
180 const auto& correlations = rcData->correlations();
183 for (
const auto& [corrKey, corr] : rcData->correlations()->intraBucketCorrelations()) {
184 if (riskClass == RiskClass::CreditQualifying || riskClass == RiskClass::CreditNonQualifying) {
185 const string& label1 = std::get<1>(corrKey);
186 const string&
label2 = std::get<2>(corrKey);
189 if (riskClass == RiskClass::CreditQualifying) {
190 if (label1 ==
"aggregate") {
200 if (label1 ==
"aggregate") {
214 for (
const auto& [corrKey, corr] : rcData->correlations()->interBucketCorrelations()) {
219 if (riskClass == RiskClass::InterestRate) {
220 const auto& irCorrelations = QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::IRCorrelations>(correlations);
226 }
else if (riskClass == RiskClass::FX) {
227 const auto& fxCorrelations =
228 QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::FXCorrelations>(correlations);
230 }
else if (riskClass == RiskClass::CreditQualifying) {
231 const auto& creditQCorrelations =
232 QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::CreditQCorrelations>(correlations);
234 }
else if (riskClass == RiskClass::CreditNonQualifying) {
239 mapBuckets_ = {{RiskType::IRCurve, {
"1",
"2",
"3"}},
240 {RiskType::CreditQ, {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"Residual"}},
241 {RiskType::CreditVol, {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"Residual"}},
242 {RiskType::CreditNonQ, {
"1",
"2",
"Residual"}},
243 {RiskType::CreditVolNonQ, {
"1",
"2",
"Residual"}},
244 {RiskType::Equity, {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"Residual"}},
245 {RiskType::EquityVol, {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"Residual"}},
246 {RiskType::Commodity,
247 {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17"}},
248 {RiskType::CommodityVol,
249 {
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17"}}};
252 {RiskType::IRCurve, {
"2w",
"1m",
"3m",
"6m",
"1y",
"2y",
"3y",
"5y",
"10y",
"15y",
"20y",
"30y"}},
253 {RiskType::CreditQ, {
"1y",
"2y",
"3y",
"5y",
"10y"}},
254 {RiskType::CreditNonQ, {
"1y",
"2y",
"3y",
"5y",
"10y"}},
255 {RiskType::IRVol, {
"2w",
"1m",
"3m",
"6m",
"1y",
"2y",
"3y",
"5y",
"10y",
"15y",
"20y",
"30y"}},
256 {RiskType::InflationVol, {
"2w",
"1m",
"3m",
"6m",
"1y",
"2y",
"3y",
"5y",
"10y",
"15y",
"20y",
"30y"}},
257 {RiskType::CreditVol, {
"1y",
"2y",
"3y",
"5y",
"10y"}},
258 {RiskType::CreditVolNonQ, {
"1y",
"2y",
"3y",
"5y",
"10y"}},
259 {RiskType::EquityVol, {
"2w",
"1m",
"3m",
"6m",
"1y",
"2y",
"3y",
"5y",
"10y",
"15y",
"20y",
"30y"}},
260 {RiskType::CommodityVol, {
"2w",
"1m",
"3m",
"6m",
"1y",
"2y",
"3y",
"5y",
"10y",
"15y",
"20y",
"30y"}},
261 {RiskType::FXVol, {
"2w",
"1m",
"3m",
"6m",
"1y",
"2y",
"3y",
"5y",
"10y",
"15y",
"20y",
"30y"}}};
263 mapLabels_2_ = {{RiskType::IRCurve, {
"OIS",
"Libor1m",
"Libor3m",
"Libor6m",
"Libor12m",
"Prime",
"Municipal"}},
264 {RiskType::CreditQ, {
"",
"Sec"}}};
268 RiskType::CommodityVol,
269 RiskType::CreditNonQ,
272 RiskType::CreditVolNonQ,
280 RiskType::InflationVol,
283 RiskType::ProductClassMultiplier,
284 RiskType::AddOnNotionalFactor,
287 RiskType::AddOnFixedAmount};
294 { RiskType::IRVol, { 0.5,
295 0.5 * 14.0 / (365.0 / 12.0),
296 0.5 * 14.0 / (3.0 * 365.0 / 12.0),
297 0.5 * 14.0 / (6.0 * 365.0 / 12.0),
299 0.5 * 14.0 / (2.0 * 365.0),
300 0.5 * 14.0 / (3.0 * 365.0),
301 0.5 * 14.0 / (5.0 * 365.0),
302 0.5 * 14.0 / (10.0 * 365.0),
303 0.5 * 14.0 / (15.0 * 365.0),
304 0.5 * 14.0 / (20.0 * 365.0),
305 0.5 * 14.0 / (30.0 * 365.0) }
307 { RiskType::CreditVol, { 0.5 * 14.0 / 365.0,
308 0.5 * 14.0 / (2.0 * 365.0),
309 0.5 * 14.0 / (3.0 * 365.0),
310 0.5 * 14.0 / (5.0 * 365.0),
311 0.5 * 14.0 / (10.0 * 365.0) }
317 { RiskType::IRVol, { 0.5 / 10.0,
318 0.5 * 1.40 / (365.0 / 12.0),
319 0.5 * 1.40 / (3.0 * 365.0 / 12.0),
320 0.5 * 1.40 / (6.0 * 365.0 / 12.0),
322 0.5 * 1.40 / (2.0 * 365.0),
323 0.5 * 1.40 / (3.0 * 365.0),
324 0.5 * 1.40 / (5.0 * 365.0),
325 0.5 * 1.40 / (10.0 * 365.0),
326 0.5 * 1.40 / (15.0 * 365.0),
327 0.5 * 1.40 / (20.0 * 365.0),
328 0.5 * 1.40 / (30.0 * 365.0) }
330 { RiskType::CreditVol, { 0.5 * 1.40 / 365.0,
331 0.5 * 1.40 / (2.0 * 365.0),
332 0.5 * 1.40 / (3.0 * 365.0),
333 0.5 * 1.40 / (5.0 * 365.0),
334 0.5 * 1.40 / (10.0 * 365.0) }
346 const auto& rcCorrelations = simmCalibration->riskClassCorrelations();
347 for (
const auto& [rcCorrKey, rcCorr] : rcCorrelations) {
365 if (boost::algorithm::starts_with(irIndex->name(),
"BMA")) {
virtual std::string label2(const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &irIndex) const
QuantLib::Real correlation(const CrifRecord::RiskType &firstRt, const std::string &firstQualifier, const std::string &firstLabel_1, const std::string &firstLabel_2, const CrifRecord::RiskType &secondRt, const std::string &secondQualifier, const std::string &secondLabel_1, const std::string &secondLabel_2, const std::string &calculationCurrency="") const override
const std::tuple< std::string, std::string, std::string > makeKey(const std::string &, const std::string &, const std::string &) const
QuantLib::Real crqResidualIntraCorr_
Credit-Q residual intra correlation.
QuantLib::Real basecorrCorr_
Base correlation risk factor correlation.
std::map< CrifRecord::RiskType, QuantLib::Real > rwRiskType_
QuantLib::Real weight(const CrifRecord::RiskType &rt, boost::optional< std::string > qualifier=boost::none, boost::optional< std::string > label_1=boost::none, const std::string &calculationCurrency="") const override
QuantLib::Real crnqResidualIntraCorr_
Credit-NonQ residual intra correlation.
std::string version_
SIMM configuration version.
QuantLib::Size mporDays() const
MPOR in days.
std::map< CrifRecord::RiskType, std::vector< std::string > > mapLabels_2_
QuantLib::Real irInterCurrencyCorr_
IR correlation across currencies.
std::map< CrifRecord::RiskType, Amounts > rwLabel_1_
std::map< CrifRecord::RiskType, Amounts > intraBucketCorrelation_
std::map< CrifRecord::RiskType, std::vector< std::string > > mapBuckets_
QuantLib::Real crnqDiffIntraCorr_
Credit-NonQ non-residual intra correlation when different underlying names.
QuantLib::Real crqSameIntraCorr_
Credit-Q non-residual intra correlation when same qualifier but different vertex/source.
QuantLib::Real crnqSameIntraCorr_
Credit-NonQ non-residual intra correlation when same underlying names.
std::set< CrifRecord::RiskType > validRiskTypes_
Set of valid risk types for the current configuration.
QuantLib::ext::shared_ptr< SimmConcentration > simmConcentration_
Used to get the concentration thresholds for a given risk type and qualifier.
QuantLib::Real fxCorr_
FX correlation.
QuantLib::Real infCorr_
Correlation between any yield and inflation in same currency.
Amounts riskClassCorrelation_
Risk class correlation matrix.
QuantLib::Real crnqInterCorr_
Credit-NonQ non-residual inter bucket correlation.
std::map< CrifRecord::RiskType, QuantLib::Real > historicalVolatilityRatios_
Map from risk type to a historical volatility ratio.
std::map< CrifRecord::RiskType, Amounts > interBucketCorrelation_
std::map< CrifRecord::RiskType, std::vector< std::string > > mapLabels_1_
QuantLib::Real infVolCorr_
Correlation between any yield volatility and inflation volatility in same currency.
QuantLib::Real crqDiffIntraCorr_
Credit-Q non-residual intra correlation when different qualifier.
QuantLib::Real irSubCurveCorr_
IR Label2 level i.e. sub-curve correlation.
void addLabels2Impl(const CrifRecord::RiskType &rt, const std::string &label_2)
A base implementation of addLabels2 that can be shared by derived classes.
std::map< CrifRecord::RiskType, std::vector< QuantLib::Real > > curvatureWeights_
QuantLib::ext::shared_ptr< SimmBucketMapper > simmBucketMapper_
Used to map SIMM Qualifier names to SIMM bucket values.
std::string bucket(const CrifRecord::RiskType &rt, const std::string &qualifier) const override
std::map< CrifRecord::RiskType, Amounts > rwBucket_
QuantLib::Real correlation(const CrifRecord::RiskType &firstRt, const std::string &firstQualifier, const std::string &firstLabel_1, const std::string &firstLabel_2, const CrifRecord::RiskType &secondRt, const std::string &secondQualifier, const std::string &secondLabel_1, const std::string &secondLabel_2, const std::string &calculationCurrency="") const override
SimmConfigurationCalibration(const QuantLib::ext::shared_ptr< SimmBucketMapper > &simmBucketMapper, const QuantLib::ext::shared_ptr< SimmCalibration > &simmCalibration, const QuantLib::Size &mporDays=10, const std::string &name="SIMM Calibration")
QuantLib::Real weight(const CrifRecord::RiskType &rt, boost::optional< std::string > qualifier=boost::none, boost::optional< std::string > label_1=boost::none, const std::string &calculationCurrency="") const override
std::map< std::string, std::set< std::string > > ccyGroups_
QuantLib::Real curvatureMarginScaling() const override
std::string label2(const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &irIndex) const override
Return the SIMM Label2 value for the given interest rate index.
void addLabels2(const CrifRecord::RiskType &rt, const std::string &label_2) override
Add SIMM Label2 values under certain circumstances.
std::string group(const std::string &qualifier, const std::map< std::string, std::set< std::string > > &groups) const
Find the group of the qualifier.
QuantLib::Real hvr_ir_
IR Historical volatility ratio.
static std::pair< CrifRecord::RiskType, CrifRecord::RiskType > riskClassToRiskType(const RiskClass &rc)
For a given risk class, return the corresponding risk types.
Real parseReal(const string &s)
RandomVariable pow(RandomVariable x, const RandomVariable &y)
CrifRecord::RiskType RiskType
SIMM concentration thresholds built from SIMM calibration.
SIMM configuration built for SIMM calibration.