Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
simmconcentration.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2018 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
23#include <ql/errors.hpp>
24
26using QuantLib::Real;
27using std::map;
28using std::set;
29using std::string;
30
31namespace ore {
32namespace analytics {
33
34// Ease syntax
38
39Real SimmConcentrationBase::thresholdImpl(const QuantLib::ext::shared_ptr<SimmBucketMapper>& simmBucketMapper,
40 const RiskType& riskType, const string& qualifier) const {
41
42 // Deal with some specific cases first
43 if (riskType == RiskType::IRCurve || riskType == RiskType::IRVol || riskType == RiskType::FX) {
44
45 QL_REQUIRE(qualifier.size() == 3, "Expect the qualifier, " << qualifier << ", to be a valid currency code");
46 QL_REQUIRE(checkCurrency(qualifier),
47 "The qualifier, " << qualifier << ", is not a supported currency code");
48 auto cat = riskType == RiskType::FX ? category(qualifier, fxCategories_) : category(qualifier, irCategories_);
49
50 return bucketedThresholds_.at(riskType).at(cat) * units_;
51 }
52
53 if (riskType == RiskType::FXVol) {
54 return fxVolThreshold(qualifier) * units_;
55 }
56
57 // Check if the risk type's threshold is not bucket dependent and if so return the threshold
58 if (flatThresholds_.count(riskType) > 0) {
59 return flatThresholds_.at(riskType) * units_;
60 }
61
62 // Check if the risk type's threshold is bucket dependent and if so, find the bucket and return the threshold
63 if (bucketedThresholds_.count(riskType) > 0) {
64 string bucket = simmBucketMapper->bucket(riskType, qualifier);
65 bucket = bucket == "residual" ? "Residual" : bucket;
66 auto const& m = bucketedThresholds_.at(riskType);
67 auto const& t = m.find(bucket);
68 QL_REQUIRE(t != m.end(), "SimmConcentrationBase::thresholdImpl(): bucket '"
69 << bucket << "' not found in bucketedThresholds for qualifier '" << qualifier
70 << "' and risk type '" << riskType << "'");
71 return t->second * units_;
72 }
73
74 // If we get to here, no threshold
75 return QL_MAX_REAL;
76}
77
78string SimmConcentrationBase::category(const string& qualifier, const map<string, set<string>>& categories) const {
79 string result;
80 for (const auto& kv : categories) {
81 if (kv.second.empty()) {
82 result = kv.first;
83 } else {
84 if (kv.second.count(qualifier) > 0) {
85 // Found qualifier in category so return it
86 return kv.first;
87 }
88 }
89 }
90
91 // If we get here, result should hold category with empty set
92 return result;
93}
94
95Real SimmConcentrationBase::fxVolThreshold(const string& fxPair) const {
96
97 QL_REQUIRE(fxPair.size() == 6, "Expected '" << fxPair << "' to be a currency pair so it should be of length 6.");
98
99 string ccy_1 = fxPair.substr(0, 3);
100 QL_REQUIRE(checkCurrency(ccy_1),
101 "First currency in pair " << fxPair << " (" << ccy_1 << ") is not a supported currency code");
102 string ccy_2 = fxPair.substr(3);
103 QL_REQUIRE(checkCurrency(ccy_2),
104 "Second currency in pair " << fxPair << " (" << ccy_2 << ") is not a supported currency code");
105
106 // Find category of currency 1 and currency 2
107 string category_1 = category(ccy_1, fxCategories_);
108 string category_2 = category(ccy_2, fxCategories_);
109
110 if (category_1 == "1" && category_2 == "1") {
111 // Both currencies in FX category 1
112 return bucketedThresholds_.at(RiskType::FXVol).at("1");
113 } else if ((category_1 == "1" && category_2 == "2") || (category_1 == "2" && category_2 == "1")) {
114 // One currency in FX category 1 and the other in FX category 2
115 return bucketedThresholds_.at(RiskType::FXVol).at("2");
116 } else if ((category_1 == "1" && category_2 == "3") || (category_1 == "3" && category_2 == "1")) {
117 // One currency in FX category 1 and the other in FX category 3
118 return bucketedThresholds_.at(RiskType::FXVol).at("3");
119 } else if (category_1 == "2" && category_2 == "2") {
120 // Both currencies in FX category 2
121 return bucketedThresholds_.at(RiskType::FXVol).at("4");
122 } else if ((category_1 == "2" && category_2 == "3") || (category_1 == "3" && category_2 == "2")) {
123 // One currency in FX category 2 and the other in FX category 3
124 return bucketedThresholds_.at(RiskType::FXVol).at("5");
125 } else {
126 // Both currencies in FX category 3
127 return bucketedThresholds_.at(RiskType::FXVol).at("6");
128 }
129}
130
131} // namespace analytics
132} // namespace ore
QuantLib::Real units_
The units of quotation of the threshold amount e.g. $1MM.
QuantLib::Real fxVolThreshold(const std::string &fxPair) const
Return concentration threshold for Risk_FXVol given the fxPair.
std::map< std::string, std::set< std::string > > fxCategories_
std::map< std::string, std::set< std::string > > irCategories_
std::map< CrifRecord::RiskType, std::map< std::string, QuantLib::Real > > bucketedThresholds_
QuantLib::Real thresholdImpl(const QuantLib::ext::shared_ptr< SimmBucketMapper > &simmBucketMapper, const CrifRecord::RiskType &riskType, const std::string &qualifier) const
std::string category(const std::string &qualifier, const std::map< std::string, std::set< std::string > > &categories) const
Find the concentration threshold category of the qualifier.
std::map< CrifRecord::RiskType, QuantLib::Real > flatThresholds_
bool checkCurrency(const string &code)
SimmConfiguration::RiskClass RiskClass
CrifRecord::RiskType RiskType
Definition: crifloader.cpp:92
Abstract base class for classes that map SIMM qualifiers to buckets.
Abstract base class for retrieving SIMM concentration thresholds.