Skip to content

Commit 4b10c79

Browse files
author
Sebastien Bouvard
committed
Merge branch 'bugfix/QPR-13667' into 'master'
QPR-13667 use bucket for correlation if available Closes QPR-13667 See merge request qs/oreplus!3040
2 parents 6e0c167 + 97cf5ac commit 4b10c79

25 files changed

Lines changed: 201 additions & 161 deletions

OREAnalytics/orea/engine/simpledynamicsimm.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,15 @@ SimpleDynamicSimm::SimpleDynamicSimm(const std::size_t n, const std::vector<std:
5555
for (std::size_t j = 0; j < i; ++j) {
5656
auto p2 = ore::data::to_string(irDeltaTerms[j]);
5757
boost::algorithm::to_lower(p2);
58-
irDeltaCorrelations_(i, j) = irDeltaCorrelations_(j, i) =
59-
simmConfiguration_->correlation(CrifRecord::RiskType::IRCurve, "USD", p1, std::string(),
60-
CrifRecord::RiskType::IRCurve, "USD", p2, std::string());
58+
irDeltaCorrelations_(i, j) = irDeltaCorrelations_(j, i) = simmConfiguration_->correlation(
59+
CrifRecord::RiskType::IRCurve, "USD", std::string(), p1, std::string(), CrifRecord::RiskType::IRCurve,
60+
"USD", std::string(), p2, std::string(), std::string());
6161
}
6262
}
6363

6464
irGamma_ = simmConfiguration_->correlation(CrifRecord::RiskType::IRCurve, "USD", std::string(), std::string(),
65-
CrifRecord::RiskType::IRCurve, "GBP", std::string(), std::string());
65+
std::string(), CrifRecord::RiskType::IRCurve, "GBP", std::string(),
66+
std::string(), std::string(), std::string());
6667

6768
irVegaRw_ = simmConfiguration_->weight(CrifRecord::RiskType::IRVol, std::string("USD"));
6869

@@ -76,9 +77,9 @@ SimpleDynamicSimm::SimpleDynamicSimm(const std::size_t n, const std::vector<std:
7677
for (std::size_t j = 0; j < i; ++j) {
7778
auto p2 = ore::data::to_string(irVegaTerms[j]);
7879
boost::algorithm::to_lower(p2);
79-
irVegaCorrelations_(i, j) = irVegaCorrelations_(j, i) =
80-
simmConfiguration_->correlation(CrifRecord::RiskType::IRVol, "USD", p1, std::string(),
81-
CrifRecord::RiskType::IRVol, "USD", p2, std::string());
80+
irVegaCorrelations_(i, j) = irVegaCorrelations_(j, i) = simmConfiguration_->correlation(
81+
CrifRecord::RiskType::IRVol, "USD", std::string(), p1, std::string(), CrifRecord::RiskType::IRVol,
82+
"USD", std::string(), p2, std::string(), std::string());
8283
}
8384
}
8485

@@ -101,8 +102,8 @@ SimpleDynamicSimm::SimpleDynamicSimm(const std::size_t n, const std::vector<std:
101102
fxHvr_ = simmConfiguration_->historicalVolatilityRatio(CrifRecord::RiskType::FXVol);
102103

103104
fxCorr_ = simmConfiguration_->correlation(CrifRecord::RiskType::FX, "GBP", std::string(), std::string(),
104-
CrifRecord::RiskType::FX, "GBP", std::string(), std::string(),
105-
std::string("USD"));
105+
std::string(), CrifRecord::RiskType::FX, "GBP", std::string(),
106+
std::string(), std::string(), std::string("USD"));
106107

107108
fxVegaCorrelations_ = Matrix(fxVegaTerms.size(), fxVegaTerms.size(), 0.0);
108109
for (std::size_t i = 0; i < fxVegaTerms.size(); ++i) {
@@ -112,9 +113,9 @@ SimpleDynamicSimm::SimpleDynamicSimm(const std::size_t n, const std::vector<std:
112113
for (std::size_t j = 0; j < i; ++j) {
113114
auto p2 = ore::data::to_string(fxVegaTerms[j]);
114115
boost::algorithm::to_lower(p2);
115-
fxVegaCorrelations_(i, j) = fxVegaCorrelations_(j, i) =
116-
simmConfiguration_->correlation(CrifRecord::RiskType::FXVol, "USD", p1, std::string(),
117-
CrifRecord::RiskType::FXVol, "USD", p2, std::string());
116+
fxVegaCorrelations_(i, j) = fxVegaCorrelations_(j, i) = simmConfiguration_->correlation(
117+
CrifRecord::RiskType::FXVol, "USD", std::string(), p1, std::string(), CrifRecord::RiskType::FXVol,
118+
"USD", std::string(), p2, std::string(), std::string());
118119
}
119120
}
120121

OREAnalytics/orea/simm/simmcalculator.cpp

Lines changed: 41 additions & 38 deletions
Large diffs are not rendered by default.

OREAnalytics/orea/simm/simmconfiguration.hpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,20 +180,23 @@ class SimmConfiguration : public CrifConfiguration {
180180
//! Return the correlation between SIMM risk classes \p rc_1 and \p rc_2
181181
virtual QuantLib::Real correlationRiskClasses(const RiskClass& rc_1, const RiskClass& rc_2) const = 0;
182182

183-
/*! Return the correlation between the \p firstQualifier with risk type \p firstRt,
184-
Label1 value of \p firstLabel_1 and Label2 value of \p firstLabel_2 *and* the
185-
\p secondQualifier with risk type \p secondRt, Label1 value of \p secondLabel_1
186-
and Label2 value of \p secondLabel_2
183+
/*! Return the correlation between the \p firstQualifier and \p firstBucket with risk type \p firstRt, Label1 value
184+
of \p firstLabel_1 and Label2 value of \p firstLabel_2 *and* the \p secondQualifier and \p secondBucket with
185+
risk type \p secondRt, Label1 value of \p secondLabel_1 and Label2 value of \p secondLabel_2
186+
187+
firstBucket and secondBucket are derived from firstQualifier and secondQualifier
188+
if they are not given (empty string)
187189
188190
\warning Returns 0 if no correlation found
189191
190192
\todo test if the default return value of 0 makes sense
191193
*/
192194
virtual QuantLib::Real correlation(const CrifRecord::RiskType& firstRt, const std::string& firstQualifier,
193-
const std::string& firstLabel_1, const std::string& firstLabel_2,
194-
const CrifRecord::RiskType& secondRt, const std::string& secondQualifier,
195+
const std::string& firstBucket, const std::string& firstLabel_1,
196+
const std::string& firstLabel_2, const CrifRecord::RiskType& secondRt,
197+
const std::string& secondQualifier, const std::string& secondBucket,
195198
const std::string& secondLabel_1, const std::string& secondLabel_2,
196-
const std::string& calculationCurrency = "") const = 0;
199+
const std::string& calculationCurrency) const = 0;
197200

198201
virtual bool isSimmConfigCalibration() const { return false; }
199202

OREAnalytics/orea/simm/simmconfigurationbase.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,9 @@ Real SimmConfigurationBase::sigma(const RiskType& rt, QuantLib::ext::optional<st
214214
}
215215

216216
QuantLib::Real SimmConfigurationBase::correlation(const RiskType& firstRt, const string& firstQualifier,
217-
const string& firstLabel_1, const string& firstLabel_2,
218-
const RiskType& secondRt, const string& secondQualifier,
217+
const string& firstBucket, const string& firstLabel_1,
218+
const string& firstLabel_2, const RiskType& secondRt,
219+
const string& secondQualifier, const string& secondBucket,
219220
const string& secondLabel_1, const string& secondLabel_2,
220221
const std::string&) const {
221222

@@ -226,8 +227,8 @@ QuantLib::Real SimmConfigurationBase::correlation(const RiskType& firstRt, const
226227
"The risk type " << secondRt << " is not valid for SIMM configuration with name" << name());
227228

228229
// Deal with trivial case of everything equal
229-
if (firstRt == secondRt && firstQualifier == secondQualifier && firstLabel_1 == secondLabel_1 &&
230-
firstLabel_2 == secondLabel_2) {
230+
if (firstRt == secondRt && firstQualifier == secondQualifier && firstBucket == secondBucket &&
231+
firstLabel_1 == secondLabel_1 && firstLabel_2 == secondLabel_2) {
231232
return 1.0;
232233
}
233234

@@ -236,8 +237,8 @@ QuantLib::Real SimmConfigurationBase::correlation(const RiskType& firstRt, const
236237
(firstRt == RiskType::EquityVol && secondRt == RiskType::EquityVol)) {
237238

238239
// Get the bucket of each qualifier
239-
string bucket_1 = simmBucketMapper_->bucket(firstRt, firstQualifier);
240-
string bucket_2 = simmBucketMapper_->bucket(secondRt, secondQualifier);
240+
string bucket_1 = firstBucket.empty() ? simmBucketMapper_->bucket(firstRt, firstQualifier) : firstBucket;
241+
string bucket_2 = secondBucket.empty() ? simmBucketMapper_->bucket(secondRt, secondQualifier) : secondBucket;
241242

242243
// Residual is special, 0 correlation inter and intra except if same qualifier
243244
if (bucket_1 == "Residual" || bucket_2 == "Residual") {
@@ -262,8 +263,8 @@ QuantLib::Real SimmConfigurationBase::correlation(const RiskType& firstRt, const
262263
(firstRt == RiskType::CreditVol && secondRt == RiskType::CreditVol)) {
263264

264265
// Get the bucket of each qualifier
265-
string bucket_1 = simmBucketMapper_->bucket(firstRt, firstQualifier);
266-
string bucket_2 = simmBucketMapper_->bucket(secondRt, secondQualifier);
266+
string bucket_1 = firstBucket.empty() ? simmBucketMapper_->bucket(firstRt, firstQualifier) : firstBucket;
267+
string bucket_2 = secondBucket.empty() ? simmBucketMapper_->bucket(secondRt, secondQualifier) : secondBucket;
267268

268269
// Residual is special
269270
if (bucket_1 == "Residual" || bucket_2 == "Residual") {
@@ -302,8 +303,8 @@ QuantLib::Real SimmConfigurationBase::correlation(const RiskType& firstRt, const
302303
(firstRt == RiskType::CreditVolNonQ && secondRt == RiskType::CreditVolNonQ)) {
303304

304305
// Get the bucket of each qualifier
305-
string bucket_1 = simmBucketMapper_->bucket(firstRt, firstQualifier);
306-
string bucket_2 = simmBucketMapper_->bucket(secondRt, secondQualifier);
306+
string bucket_1 = firstBucket.empty() ? simmBucketMapper_->bucket(firstRt, firstQualifier) : firstBucket;
307+
string bucket_2 = secondBucket.empty() ? simmBucketMapper_->bucket(secondRt, secondQualifier) : secondBucket;
307308

308309
// Residual is special
309310
if (bucket_1 == "Residual" || bucket_2 == "Residual") {
@@ -342,8 +343,8 @@ QuantLib::Real SimmConfigurationBase::correlation(const RiskType& firstRt, const
342343
(firstRt == RiskType::CommodityVol && secondRt == RiskType::CommodityVol)) {
343344

344345
// Get the bucket index of each qualifier
345-
const string& bucket_1 = simmBucketMapper_->bucket(firstRt, firstQualifier);
346-
const string& bucket_2 = simmBucketMapper_->bucket(secondRt, secondQualifier);
346+
string bucket_1 = firstBucket.empty() ? simmBucketMapper_->bucket(firstRt, firstQualifier) : firstBucket;
347+
string bucket_2 = secondBucket.empty() ? simmBucketMapper_->bucket(secondRt, secondQualifier) : secondBucket;
347348

348349
if (bucket_1 == bucket_2) {
349350
auto bucketKey = makeKey(bucket_1, "", "");

OREAnalytics/orea/simm/simmconfigurationbase.hpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,23 +134,23 @@ class SimmConfigurationBase : public SimmConfiguration {
134134
//! Return the correlation between SIMM risk classes \p rc_1 and \p rc_2
135135
QuantLib::Real correlationRiskClasses(const RiskClass& rc_1, const RiskClass& rc_2) const override;
136136

137-
/*! Return the correlation between the \p firstQualifier with risk type \p firstRt,
138-
Label1 value of \p firstLabel_1 and Label2 value of \p firstLabel_2 *and* the
139-
\p secondQualifier with risk type \p secondRt, Label1 value of \p secondLabel_1
140-
and Label2 value of \p secondLabel_2
137+
/*! Return the correlation between the \p firstQualifier and \p firstBucket with risk type \p firstRt, Label1 value
138+
of \p firstLabel_1 and Label2 value of \p firstLabel_2 *and* the \p secondQualifier and \p secondBucket with
139+
risk type \p secondRt, Label1 value of \p secondLabel_1 and Label2 value of \p secondLabel_2
141140
142-
\remark if not using \p firstLabel_1 and \p secondLabel_1, just enter an empty
143-
string for both. Similarly for \p firstLabel_2 and \p secondLabel_2.
141+
firstBucket and secondBucket are derived from firstQualifier and secondQualifier
142+
if they are not given (empty string)
144143
145144
\warning Returns 0 if no correlation found
146145
147146
\todo test if the default return value of 0 makes sense
148147
*/
149148
QuantLib::Real correlation(const CrifRecord::RiskType& firstRt, const std::string& firstQualifier,
150-
const std::string& firstLabel_1, const std::string& firstLabel_2,
151-
const CrifRecord::RiskType& secondRt, const std::string& secondQualifier,
149+
const std::string& firstBucket, const std::string& firstLabel_1,
150+
const std::string& firstLabel_2, const CrifRecord::RiskType& secondRt,
151+
const std::string& secondQualifier, const std::string& secondBucket,
152152
const std::string& secondLabel_1, const std::string& secondLabel_2,
153-
const std::string& calculationCurrency = "") const override;
153+
const std::string& calculationCurrency) const override;
154154

155155
//! MPOR in days
156156
QuantLib::Size mporDays() const { return mporDays_; }

OREAnalytics/orea/simm/simmconfigurationcalibration.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,11 @@ QuantLib::Real SimmConfigurationCalibration::weight(const RiskType& rt, QuantLib
5858
}
5959

6060
QuantLib::Real SimmConfigurationCalibration::correlation(const RiskType& firstRt, const string& firstQualifier,
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 {
61+
const string& firstBucket, const string& firstLabel_1,
62+
const string& firstLabel_2, const RiskType& secondRt,
63+
const string& secondQualifier, const string& secondBucket,
64+
const string& secondLabel_1, const string& secondLabel_2,
65+
const string& calculationCurrency) const {
6566

6667
if (firstRt == RiskType::FX && secondRt == RiskType::FX) {
6768
QL_REQUIRE(calculationCurrency != "", "no calculation currency provided corr");
@@ -79,8 +80,9 @@ QuantLib::Real SimmConfigurationCalibration::correlation(const RiskType& firstRt
7980
}
8081
}
8182

82-
return SimmConfigurationBase::correlation(firstRt, firstQualifier, firstLabel_1, firstLabel_2, secondRt,
83-
secondQualifier, secondLabel_1, secondLabel_2);
83+
return SimmConfigurationBase::correlation(firstRt, firstQualifier, firstBucket, firstLabel_1, firstLabel_2,
84+
secondRt, secondQualifier, secondBucket, secondLabel_1, secondLabel_2,
85+
calculationCurrency);
8486
}
8587

8688
SimmConfigurationCalibration::SimmConfigurationCalibration(const QuantLib::ext::shared_ptr<SimmBucketMapper>& simmBucketMapper,

OREAnalytics/orea/simm/simmconfigurationcalibration.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ class SimmConfigurationCalibration : public SimmConfigurationBase {
5252
const std::string& calculationCurrency = "") const override;
5353

5454
QuantLib::Real correlation(const CrifRecord::RiskType& firstRt, const std::string& firstQualifier,
55-
const std::string& firstLabel_1, const std::string& firstLabel_2,
56-
const CrifRecord::RiskType& secondRt, const std::string& secondQualifier,
55+
const std::string& firstBucket, const std::string& firstLabel_1,
56+
const std::string& firstLabel_2, const CrifRecord::RiskType& secondRt,
57+
const std::string& secondQualifier, const std::string& secondBucket,
5758
const std::string& secondLabel_1, const std::string& secondLabel_2,
58-
const std::string& calculationCurrency = "") const override;
59-
59+
const std::string& calculationCurrency) const override;
60+
6061
virtual bool isSimmConfigCalibration() const override { return true; }
6162

6263
private:

OREAnalytics/orea/simm/simmconfigurationisdav2_2.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ QuantLib::Real SimmConfiguration_ISDA_V2_2::weight(const RiskType& rt, QuantLib:
7171
}
7272

7373
QuantLib::Real SimmConfiguration_ISDA_V2_2::correlation(const RiskType& firstRt, const string& firstQualifier,
74-
const string& firstLabel_1, const string& firstLabel_2,
75-
const RiskType& secondRt, const string& secondQualifier,
74+
const string& firstBucket, const string& firstLabel_1,
75+
const string& firstLabel_2, const RiskType& secondRt,
76+
const string& secondQualifier, const string& secondBucket,
7677
const string& secondLabel_1, const string& secondLabel_2,
7778
const std::string& calculationCurrency) const {
7879

@@ -90,8 +91,9 @@ QuantLib::Real SimmConfiguration_ISDA_V2_2::correlation(const RiskType& firstRt,
9091
}
9192
}
9293

93-
return SimmConfigurationBase::correlation(firstRt, firstQualifier, firstLabel_1, firstLabel_2, secondRt,
94-
secondQualifier, secondLabel_1, secondLabel_2);
94+
return SimmConfigurationBase::correlation(firstRt, firstQualifier, firstBucket, firstLabel_1, firstLabel_2,
95+
secondRt, secondQualifier, secondBucket, secondLabel_1, secondLabel_2,
96+
calculationCurrency);
9597
}
9698

9799
SimmConfiguration_ISDA_V2_2::SimmConfiguration_ISDA_V2_2(const QuantLib::ext::shared_ptr<SimmBucketMapper>& simmBucketMapper,

OREAnalytics/orea/simm/simmconfigurationisdav2_2.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ class SimmConfiguration_ISDA_V2_2 : public SimmConfigurationBase {
5151
const std::string& calculationCurrency = "") const override;
5252

5353
QuantLib::Real correlation(const CrifRecord::RiskType& firstRt, const std::string& firstQualifier,
54-
const std::string& firstLabel_1, const std::string& firstLabel_2,
55-
const CrifRecord::RiskType& secondRt, const std::string& secondQualifier,
54+
const string& firstBucket, const std::string& firstLabel_1,
55+
const std::string& firstLabel_2, const CrifRecord::RiskType& secondRt,
56+
const std::string& secondQualifier, const std::string& secondBucket,
5657
const std::string& secondLabel_1, const std::string& secondLabel_2,
57-
const std::string& calculationCurrency = "") const override;
58+
const std::string& calculationCurrency) const override;
5859

5960
private:
6061
//! Find the group of the \p qualifier

0 commit comments

Comments
 (0)