Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
SimmConfigurationCalibration Class Reference

#include <orea/simm/simmconfigurationcalibration.hpp>

+ Inheritance diagram for SimmConfigurationCalibration:
+ Collaboration diagram for SimmConfigurationCalibration:

Public Member Functions

 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")
 
std::string label2 (const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &irIndex) const override
 Return the SIMM Label2 value for the given interest rate index. More...
 
void addLabels2 (const CrifRecord::RiskType &rt, const std::string &label_2) override
 Add SIMM Label2 values under certain circumstances. More...
 
QuantLib::Real curvatureMarginScaling () const override
 
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 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
 
virtual bool isSimmConfigCalibration () const override
 
- Public Member Functions inherited from SimmConfigurationBase
const std::string & name () const override
 Returns the SIMM configuration name. More...
 
const std::string & version () const override
 Returns the SIMM configuration version. More...
 
const QuantLib::ext::shared_ptr< SimmBucketMapper > & bucketMapper () const override
 Returns the SIMM bucket mapper used by the configuration. More...
 
bool hasBuckets (const CrifRecord::RiskType &rt) const override
 Return true if the SIMM risk type rt has buckets. More...
 
std::string bucket (const CrifRecord::RiskType &rt, const std::string &qualifier) const override
 
const bool checkValue (const std::string &, const std::vector< std::string > &) const
 
std::vector< std::string > buckets (const CrifRecord::RiskType &rt) const override
 
std::vector< std::string > labels1 (const CrifRecord::RiskType &rt) const override
 
std::vector< std::string > labels2 (const CrifRecord::RiskType &rt) const override
 
void addLabels2 (const CrifRecord::RiskType &rt, const std::string &label_2) override
 Add SIMM Label2 values under certain circumstances. More...
 
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 curvatureWeight (const CrifRecord::RiskType &rt, const std::string &label_1) const override
 
QuantLib::Real historicalVolatilityRatio (const CrifRecord::RiskType &rt) const override
 
QuantLib::Real sigma (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 curvatureMarginScaling () const override
 
QuantLib::Real concentrationThreshold (const CrifRecord::RiskType &rt, const std::string &qualifier) const override
 
bool isValidRiskType (const CrifRecord::RiskType &rt) const override
 
QuantLib::Real correlationRiskClasses (const RiskClass &rc_1, const RiskClass &rc_2) const override
 Return the correlation between SIMM risk classes rc_1 and rc_2. More...
 
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
 
QuantLib::Size mporDays () const
 MPOR in days. More...
 
- Public Member Functions inherited from SimmConfiguration
virtual ~SimmConfiguration ()
 
virtual std::vector< std::string > buckets (const CrifRecord::RiskType &rt) const =0
 
virtual bool hasBuckets (const CrifRecord::RiskType &rt) const =0
 Return true if the SIMM risk type rt has buckets. More...
 
bool hasBucketMapping (const CrifRecord::RiskType &rt, const std::string &qualifier) const override
 Return true if the SIMM risk type rt has buckets. More...
 
virtual std::vector< std::string > labels1 (const CrifRecord::RiskType &rt) const =0
 
virtual std::vector< std::string > labels2 (const CrifRecord::RiskType &rt) const =0
 
virtual void addLabels2 (const CrifRecord::RiskType &rt, const std::string &label_2)=0
 
virtual 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 =0
 
virtual QuantLib::Real curvatureWeight (const CrifRecord::RiskType &rt, const std::string &label_1) const =0
 
virtual QuantLib::Real historicalVolatilityRatio (const CrifRecord::RiskType &rt) const =0
 
virtual QuantLib::Real sigma (const CrifRecord::RiskType &rt, boost::optional< std::string > qualifier=boost::none, boost::optional< std::string > label_1=boost::none, const std::string &calculationCurrency="") const =0
 
virtual QuantLib::Real curvatureMarginScaling () const =0
 
virtual QuantLib::Real concentrationThreshold (const CrifRecord::RiskType &rt, const std::string &qualifier) const =0
 
virtual bool isValidRiskType (const CrifRecord::RiskType &rt) const =0
 
virtual QuantLib::Real correlationRiskClasses (const RiskClass &rc_1, const RiskClass &rc_2) const =0
 Return the correlation between SIMM risk classes rc_1 and rc_2. More...
 
virtual 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 =0
 
virtual bool isSimmConfigCalibration () const
 
- Public Member Functions inherited from CrifConfiguration
virtual ~CrifConfiguration ()
 
virtual const std::string & name () const =0
 Returns the SIMM configuration name. More...
 
virtual const std::string & version () const =0
 Returns the SIMM configuration version. More...
 
virtual std::string bucket (const ore::analytics::CrifRecord::RiskType &rt, const std::string &qualifier) const =0
 
virtual bool hasBucketMapping (const ore::analytics::CrifRecord::RiskType &rt, const std::string &qualifier) const =0
 
virtual const QuantLib::ext::shared_ptr< SimmBucketMapper > & bucketMapper () const =0
 Returns the SIMM bucket mapper used by the configuration. More...
 
virtual std::string label2 (const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &irIndex) const
 
virtual std::string label2 (const QuantLib::Period &p) const
 

Private Member Functions

std::string group (const std::string &qualifier, const std::map< std::string, std::set< std::string > > &groups) const
 Find the group of the qualifier. More...
 

Private Attributes

std::map< std::string, std::set< std::string > > ccyGroups_
 
QuantLib::Real hvr_ir_
 IR Historical volatility ratio. More...
 

Additional Inherited Members

- Public Types inherited from SimmConfigurationBase
typedef std::map< std::tuple< std::string, std::string, std::string >, QuantLib::Real > Amounts
 
- Public Types inherited from SimmConfiguration
enum class  SimmSide { Call , Post }
 Enum indicating the relevant side of the SIMM calculation. More...
 
enum class  RiskClass {
  InterestRate , CreditQualifying , CreditNonQualifying , Equity ,
  Commodity , FX , All
}
 
enum class  MarginType {
  Delta , Vega , Curvature , BaseCorr ,
  AdditionalIM , All
}
 
enum class  IMModel { Schedule , SIMM , SIMM_R , SIMM_P }
 
enum  Regulation {
  APRA , CFTC , ESA , FINMA ,
  KFSC , HKMA , JFSA , MAS ,
  OSFI , RBI , SEC , SEC_unseg ,
  USPR , NONREG , BACEN , SANT ,
  SFC , UK , AMFQ , Included ,
  Unspecified , Invalid
}
 SIMM regulators. More...
 
- Static Public Member Functions inherited from SimmConfiguration
static std::set< RiskClassriskClasses (bool includeAll=false)
 Give back a set containing the RiskClass values optionally excluding 'All'. More...
 
static std::set< CrifRecord::RiskTyperiskTypes (bool includeAll=false)
 Give back a set containing the RiskType values optionally excluding 'All'. More...
 
static std::set< MarginTypemarginTypes (bool includeAll=false)
 Give back a set containing the MarginType values optionally excluding 'All'. More...
 
static std::set< CrifRecord::ProductClassproductClasses (bool includeAll=false)
 Give back a set containing the ProductClass values optionally excluding 'All'. More...
 
static std::pair< CrifRecord::RiskType, CrifRecord::RiskTyperiskClassToRiskType (const RiskClass &rc)
 For a given risk class, return the corresponding risk types. More...
 
static RiskClass riskTypeToRiskClass (const CrifRecord::RiskType &rt)
 For a given rirsk type, return the corresponding risk class. More...
 
static bool less_than (const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
 Define ordering for ProductClass according to a waterfall: More...
 
static bool greater_than (const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
 
static bool less_than_or_equal_to (const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
 
static bool greater_than_or_equal_to (const CrifRecord::ProductClass &lhs, const CrifRecord::ProductClass &rhs)
 
static CrifRecord::ProductClass maxProductClass (CrifRecord::ProductClass pc1, CrifRecord::ProductClass pc2)
 Return the "worse" ProductClass using a waterfall logic: More...
 
- Protected Member Functions inherited from SimmConfigurationBase
 SimmConfigurationBase (const QuantLib::ext::shared_ptr< SimmBucketMapper > &simmBucketMapper, const std::string &name, const std::string version, QuantLib::Size mporDays=10)
 Constructor taking the SIMM configuration name and version. More...
 
const std::tuple< std::string, std::string, std::string > makeKey (const std::string &, const std::string &, const std::string &) const
 
QuantLib::Size labelIndex (const std::string &label, const std::vector< std::string > &labels) const
 Helper method to find the index of the label in labels. More...
 
void addLabels2Impl (const CrifRecord::RiskType &rt, const std::string &label_2)
 A base implementation of addLabels2 that can be shared by derived classes. More...
 
- Protected Attributes inherited from SimmConfigurationBase
std::string version_
 SIMM configuration version. More...
 
QuantLib::ext::shared_ptr< SimmBucketMappersimmBucketMapper_
 Used to map SIMM Qualifier names to SIMM bucket values. More...
 
QuantLib::ext::shared_ptr< SimmConcentrationsimmConcentration_
 Used to get the concentration thresholds for a given risk type and qualifier. More...
 
std::map< CrifRecord::RiskType, std::vector< std::string > > mapBuckets_
 
std::map< CrifRecord::RiskType, std::vector< std::string > > mapLabels_1_
 
std::map< CrifRecord::RiskType, std::vector< std::string > > mapLabels_2_
 
std::map< CrifRecord::RiskType, QuantLib::Real > rwRiskType_
 
std::map< CrifRecord::RiskType, AmountsrwBucket_
 
std::map< CrifRecord::RiskType, AmountsrwLabel_1_
 
std::map< CrifRecord::RiskType, std::vector< QuantLib::Real > > curvatureWeights_
 
std::map< CrifRecord::RiskType, QuantLib::Real > historicalVolatilityRatios_
 Map from risk type to a historical volatility ratio. More...
 
std::set< CrifRecord::RiskTypevalidRiskTypes_
 Set of valid risk types for the current configuration. More...
 
Amounts riskClassCorrelation_
 Risk class correlation matrix. More...
 
std::map< CrifRecord::RiskType, AmountsinterBucketCorrelation_
 
std::map< CrifRecord::RiskType, AmountsintraBucketCorrelation_
 
QuantLib::Size mporDays_
 
QuantLib::Real xccyCorr_
 
QuantLib::Real infCorr_
 Correlation between any yield and inflation in same currency. More...
 
QuantLib::Real infVolCorr_
 Correlation between any yield volatility and inflation volatility in same currency. More...
 
QuantLib::Real irSubCurveCorr_
 IR Label2 level i.e. sub-curve correlation. More...
 
QuantLib::Real irInterCurrencyCorr_
 IR correlation across currencies. More...
 
QuantLib::Real crqResidualIntraCorr_
 Credit-Q residual intra correlation. More...
 
QuantLib::Real crqSameIntraCorr_
 Credit-Q non-residual intra correlation when same qualifier but different vertex/source. More...
 
QuantLib::Real crqDiffIntraCorr_
 Credit-Q non-residual intra correlation when different qualifier. More...
 
QuantLib::Real crnqResidualIntraCorr_
 Credit-NonQ residual intra correlation. More...
 
QuantLib::Real crnqSameIntraCorr_
 Credit-NonQ non-residual intra correlation when same underlying names. More...
 
QuantLib::Real crnqDiffIntraCorr_
 Credit-NonQ non-residual intra correlation when different underlying names. More...
 
QuantLib::Real crnqInterCorr_
 Credit-NonQ non-residual inter bucket correlation. More...
 
QuantLib::Real fxCorr_
 FX correlation. More...
 
QuantLib::Real basecorrCorr_
 Base correlation risk factor correlation. More...
 
- Static Protected Attributes inherited from SimmConfiguration
static const QuantLib::Size numberOfRiskClasses = riskClassMap.size()
 Number of risk classes including RiskClass::All. More...
 
static const QuantLib::Size numberOfMarginTypes = marginTypeMap.size()
 Number of margin types including MarginType::All. More...
 
static const QuantLib::Size numberOfRegulations = regulationsMap.size()
 Number of regulations. More...
 

Detailed Description

Class giving the SIMM configuration as outlined in the document ISDA SIMM Methodology, version 2.6. Effective Date: December 2, 2023.

Definition at line 35 of file simmconfigurationcalibration.hpp.

Constructor & Destructor Documentation

◆ SimmConfigurationCalibration()

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" 
)

Definition at line 86 of file simmconfigurationcalibration.cpp.

89 : SimmConfigurationBase(simmBucketMapper, name, "", mporDays) {
90
91 version_ = simmCalibration->version();
92
93 // The differences in methodology for 1 Day horizon is described in
94 // Standard Initial Margin Model: Technical Paper, ISDA SIMM Governance Forum, Version 10:
95 // Section I - Calibration with one-day horizon
96 QL_REQUIRE(mporDays_ == 10 || mporDays_ == 1, "SIMM only supports MPOR 10-day or 1-day");
97
98 // Set up the correct concentration threshold getter
99 if (mporDays == 10) {
100 simmConcentration_ = QuantLib::ext::make_shared<SimmConcentrationCalibration>(simmCalibration, simmBucketMapper_);
101 } else {
102 // SIMM:Technical Paper, Section I.4: "The Concentration Risk feature is disabled"
103 simmConcentration_ = QuantLib::ext::make_shared<SimmConcentrationBase>();
104 }
105
106 for (const auto& [riskClass, rcData] : simmCalibration->riskClassData()) {
107
108 // Risk weights
109 const auto& riskWeights = rcData->riskWeights();
110
111 // Currency lists for FX
112 // Populate CCY groups that are used for FX correlations and risk weights
113 // The groups consists of High Vol Currencies & regular vol currencies
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();
118
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") {
123 ccyGroups_[bucket].clear();
124 } else {
125 ccyGroups_[bucket].insert(ccy);
126 }
127 }
128 }
129 }
130
131 const auto& [deltaRiskType, vegaRiskType] = SimmConfiguration::riskClassToRiskType(riskClass);
132
133 // Risk weights unique to each risk class
134 auto singleRiskWeights = riskWeights->uniqueRiskWeights();
135 for (const auto& [riskType, rw] : singleRiskWeights) {
136 rwRiskType_[riskType] = ore::data::parseReal(rw.at(mporDays_)->value());
137 }
138
139 // Delta risk weights
140 const auto& deltaRiskWeights = riskWeights->delta().at(mporDays_);
141 const auto& vegaRiskWeights = riskWeights->vega().at(mporDays_);
142
143 if (deltaRiskWeights.size() == 1) {
144 rwRiskType_[deltaRiskType] = ore::data::parseReal(deltaRiskWeights.begin()->second);
145 } else {
146 // IR risk weights
147 if (riskClass == RiskClass::InterestRate) {
148 for (const auto& [rwKey, weight] : deltaRiskWeights) {
149 rwLabel_1_[deltaRiskType][rwKey] = ore::data::parseReal(weight);
150 }
151 } else {
152 for (const auto& [rwKey, weight] : deltaRiskWeights) {
153 rwBucket_[deltaRiskType][rwKey] = ore::data::parseReal(weight);
154 }
155 }
156 }
157
158 // Vega risk weights
159 if (vegaRiskWeights.size() == 1) {
160 rwRiskType_[vegaRiskType] = ore::data::parseReal(vegaRiskWeights.begin()->second);
161 if (vegaRiskType == RiskType::IRVol)
162 rwRiskType_[RiskType::InflationVol] = rwRiskType_[RiskType::IRVol];
163 } else {
164 for (const auto& [rwKey, weight] : vegaRiskWeights) {
165 rwBucket_[vegaRiskType][rwKey] = ore::data::parseReal(weight);
166 }
167 }
168
169 // Historical volatility ratio
170 // IR
171 if (riskClass == RiskClass::InterestRate) {
172 hvr_ir_ = ore::data::parseReal(riskWeights->historicalVolatilityRatio().at(mporDays)->value());
173 }
174 // EQ, COMM, FX
175 if (riskClass == RiskClass::Equity || riskClass == RiskClass::Commodity || riskClass == RiskClass::FX)
176 historicalVolatilityRatios_[vegaRiskType] =
177 ore::data::parseReal(riskWeights->historicalVolatilityRatio().at(mporDays_)->value());
178
179 // Correlations
180 const auto& correlations = rcData->correlations();
181
182 // Interbucket and Intrabucket 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);
188
189 if (riskClass == RiskClass::CreditQualifying) {
190 if (label1 == "aggregate") {
191 if (label2 == "same") {
193 } else {
195 }
196 } else {
198 }
199 } else {
200 if (label1 == "aggregate") {
201 if (label2 == "same") {
203 } else {
205 }
206 } else {
208 }
209 }
210 } else {
211 intraBucketCorrelation_[deltaRiskType][corrKey] = ore::data::parseReal(corr);
212 }
213 }
214 for (const auto& [corrKey, corr] : rcData->correlations()->interBucketCorrelations()) {
215 interBucketCorrelation_[deltaRiskType][corrKey] = ore::data::parseReal(corr);
216 }
217
218 // Correlations unique to other risk class
219 if (riskClass == RiskClass::InterestRate) {
220 const auto& irCorrelations = QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::IRCorrelations>(correlations);
221 irSubCurveCorr_ = ore::data::parseReal(irCorrelations->subCurves()->value());
222 infCorr_ = ore::data::parseReal(irCorrelations->inflation()->value());
223 infVolCorr_ = ore::data::parseReal(irCorrelations->inflation()->value());
224 xccyCorr_ = ore::data::parseReal(irCorrelations->xCcyBasis()->value());
225 irInterCurrencyCorr_ = ore::data::parseReal(irCorrelations->outer()->value());
226 } else if (riskClass == RiskClass::FX) {
227 const auto& fxCorrelations =
228 QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::FXCorrelations>(correlations);
229 fxCorr_ = ore::data::parseReal(fxCorrelations->volatility()->value());
230 } else if (riskClass == RiskClass::CreditQualifying) {
231 const auto& creditQCorrelations =
232 QuantLib::ext::dynamic_pointer_cast<SimmCalibration::RiskClassData::CreditQCorrelations>(correlations);
233 basecorrCorr_ = ore::data::parseReal(creditQCorrelations->baseCorrelation()->value());
234 } else if (riskClass == RiskClass::CreditNonQualifying) {
235 crnqInterCorr_ = ore::data::parseReal(correlations->interBucketCorrelations().begin()->second);
236 }
237 }
238
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"}}};
250
251 mapLabels_1_ = {
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"}}};
262
263 mapLabels_2_ = {{RiskType::IRCurve, {"OIS", "Libor1m", "Libor3m", "Libor6m", "Libor12m", "Prime", "Municipal"}},
264 {RiskType::CreditQ, {"", "Sec"}}};
265
266 // Valid risk types
267 validRiskTypes_ = {RiskType::Commodity,
268 RiskType::CommodityVol,
269 RiskType::CreditNonQ,
270 RiskType::CreditQ,
271 RiskType::CreditVol,
272 RiskType::CreditVolNonQ,
273 RiskType::Equity,
274 RiskType::EquityVol,
275 RiskType::FX,
276 RiskType::FXVol,
277 RiskType::Inflation,
278 RiskType::IRCurve,
279 RiskType::IRVol,
280 RiskType::InflationVol,
281 RiskType::BaseCorr,
282 RiskType::XCcyBasis,
283 RiskType::ProductClassMultiplier,
284 RiskType::AddOnNotionalFactor,
285 RiskType::PV,
286 RiskType::Notional,
287 RiskType::AddOnFixedAmount};
288
289 // Curvature weights
290 // Hardcoded weights - doesn't seem to change much across versions
291 // clang-format off
292 if (mporDays_ == 10) {
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),
298 0.5 * 14.0 / 365.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) }
306 },
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) }
312 }
313 };
314 } else {
315 //SIMM:Technical Paper, Section I.3, this 10-day formula for curvature weights is modified
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),
321 0.5 * 1.40 / 365.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) }
329 },
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) }
335 }
336 };
337 }
338 // clang-format on
339 curvatureWeights_[RiskType::InflationVol] = curvatureWeights_[RiskType::IRVol];
340 curvatureWeights_[RiskType::EquityVol] = curvatureWeights_[RiskType::IRVol];
341 curvatureWeights_[RiskType::CommodityVol] = curvatureWeights_[RiskType::IRVol];
342 curvatureWeights_[RiskType::FXVol] = curvatureWeights_[RiskType::IRVol];
343 curvatureWeights_[RiskType::CreditVolNonQ] = curvatureWeights_[RiskType::CreditVol];
344
345 // Risk class correlation matrix
346 const auto& rcCorrelations = simmCalibration->riskClassCorrelations();
347 for (const auto& [rcCorrKey, rcCorr] : rcCorrelations) {
348 riskClassCorrelation_[rcCorrKey] = ore::data::parseReal(rcCorr);
349 }
350}
QuantLib::Real crqResidualIntraCorr_
Credit-Q residual intra correlation.
SimmConfigurationBase(const QuantLib::ext::shared_ptr< SimmBucketMapper > &simmBucketMapper, const std::string &name, const std::string version, QuantLib::Size mporDays=10)
Constructor taking the SIMM configuration name and version.
QuantLib::Real basecorrCorr_
Base correlation risk factor correlation.
std::map< CrifRecord::RiskType, QuantLib::Real > rwRiskType_
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.
const std::string & name() const override
Returns the SIMM configuration name.
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 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.
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
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_
std::string label2(const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &irIndex) const override
Return the SIMM Label2 value for the given interest rate index.
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)
+ Here is the call graph for this function:

Member Function Documentation

◆ label2()

string label2 ( const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &  irIndex) const
overridevirtual

Return the SIMM Label2 value for the given interest rate index.

Reimplemented from CrifConfiguration.

Definition at line 363 of file simmconfigurationcalibration.cpp.

363 {
364 // Special for BMA
365 if (boost::algorithm::starts_with(irIndex->name(), "BMA")) {
366 return "Municipal";
367 }
368
369 // Otherwise pass off to base class
370 return SimmConfigurationBase::label2(irIndex);
371}
virtual std::string label2(const QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > &irIndex) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ addLabels2()

void addLabels2 ( const CrifRecord::RiskType rt,
const std::string &  label_2 
)
overridevirtual

Add SIMM Label2 values under certain circumstances.

Reimplemented from SimmConfigurationBase.

Definition at line 358 of file simmconfigurationcalibration.cpp.

358 {
359 // Call the shared implementation
361}
void addLabels2Impl(const CrifRecord::RiskType &rt, const std::string &label_2)
A base implementation of addLabels2 that can be shared by derived classes.
+ Here is the call graph for this function:

◆ curvatureMarginScaling()

QuantLib::Real curvatureMarginScaling ( ) const
overridevirtual

Give back the scaling factor for the Interest Rate curvature margin

Reimplemented from SimmConfigurationBase.

Definition at line 356 of file simmconfigurationcalibration.cpp.

356{ return pow(hvr_ir_, -2.0); }
RandomVariable pow(RandomVariable x, const RandomVariable &y)
+ Here is the call graph for this function:

◆ weight()

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
overridevirtual

Return the SIMM risk weight for the given risk type rt with the given qualifier and the given label_1. Three possibilities:

  1. there is a flat risk weight for the risk factor's RiskType so only need rt
  2. there is a qualifier-dependent risk weight for the risk factor's RiskType so need rt and qualifier
  3. there is a qualifier-dependent and label1-dependent risk weight for the risk factor's RiskType so need all three parameters

Reimplemented from SimmConfigurationBase.

Definition at line 43 of file simmconfigurationcalibration.cpp.

45 {
46
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");
50
51 const string label1 = group(calculationCurrency, ccyGroups_);
52 const string label2 = group(*qualifier, ccyGroups_);
53 auto label12Key = makeKey("", label1, label2);
54 return rwBucket_.at(RiskType::FX).at(label12Key);
55 }
56
57 return SimmConfigurationBase::weight(rt, qualifier, label_1);
58}
const std::tuple< std::string, std::string, std::string > makeKey(const std::string &, const std::string &, const std::string &) const
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::string group(const std::string &qualifier, const std::map< std::string, std::set< std::string > > &groups) const
Find the group of the qualifier.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ correlation()

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
overridevirtual

Return the correlation between the firstQualifier with risk type firstRt, Label1 value of firstLabel_1 and Label2 value of firstLabel_2 and the secondQualifier with risk type secondRt, Label1 value of secondLabel_1 and Label2 value of secondLabel_2

Remarks
if not using firstLabel_1 and secondLabel_1, just enter an empty string for both. Similarly for firstLabel_2 and secondLabel_2.
Warning:
Returns 0 if no correlation found

Reimplemented from SimmConfigurationBase.

Definition at line 60 of file simmconfigurationcalibration.cpp.

64 {
65
66 if (firstRt == RiskType::FX && secondRt == RiskType::FX) {
67 QL_REQUIRE(calculationCurrency != "", "no calculation currency provided corr");
68 const string bucket = group(calculationCurrency, ccyGroups_);
69 const string label1 = group(firstQualifier, ccyGroups_);
70 const string label2 = group(secondQualifier, ccyGroups_);
71 auto key = makeKey(bucket, label1, label2);
72
73 if (intraBucketCorrelation_.at(RiskType::FX).find(key) != intraBucketCorrelation_.at(RiskType::FX).end()) {
74 return intraBucketCorrelation_.at(RiskType::FX).at(key);
75 } else {
76 QL_FAIL("Could not find FX intrabucket correlation, calculation currency '"
77 << calculationCurrency << "', firstQualifier '" << firstQualifier << "', secondQualifier '"
78 << secondQualifier << "'.");
79 }
80 }
81
82 return SimmConfigurationBase::correlation(firstRt, firstQualifier, firstLabel_1, firstLabel_2, secondRt,
83 secondQualifier, secondLabel_1, secondLabel_2);
84}
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ isSimmConfigCalibration()

virtual bool isSimmConfigCalibration ( ) const
overridevirtual

Reimplemented from SimmConfiguration.

Definition at line 60 of file simmconfigurationcalibration.hpp.

60{ return true; }

◆ group()

string group ( const std::string &  qualifier,
const std::map< std::string, std::set< std::string > > &  groups 
) const
private

Find the group of the qualifier.

Definition at line 25 of file simmconfigurationcalibration.cpp.

26 {
27 string result;
28 for (const auto& kv : categories) {
29 if (kv.second.empty()) {
30 result = kv.first;
31 } else {
32 if (kv.second.count(qualifier) > 0) {
33 // Found qualifier in category so return it
34 return kv.first;
35 }
36 }
37 }
38
39 // If we get here, result should hold category with empty set
40 return result;
41}
+ Here is the caller graph for this function:

Member Data Documentation

◆ ccyGroups_

std::map<std::string, std::set<std::string> > ccyGroups_
private

Map giving a currency's FX Volatility group (High or Regular). This concept was introduced in ISDA Simm 2.2

Definition at line 69 of file simmconfigurationcalibration.hpp.

◆ hvr_ir_

QuantLib::Real hvr_ir_
private

IR Historical volatility ratio.

Definition at line 72 of file simmconfigurationcalibration.hpp.