Skip to content

Commit fd612e5

Browse files
pcaspersjenkins
authored andcommitted
QPR-12156 add support for spreaded curves in stress testing
1 parent 6517ca3 commit fd612e5

3 files changed

Lines changed: 60 additions & 16 deletions

File tree

OREAnalytics/orea/scenario/stressscenariodata.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ void StressTestScenarioData::fromXML(XMLNode* root) {
3232
XMLNode* node = XMLUtils::locateNode(root, "StressTesting");
3333
XMLUtils::checkNode(node, "StressTesting");
3434

35+
useSpreadedTermStructures_ = parseBool(XMLUtils::getChildValue(node, "UseSpreadedTermStructures", false, "false"));
36+
3537
for (XMLNode* testCase = XMLUtils::getChildNode(node, "StressTest"); testCase;
3638
testCase = XMLUtils::getNextSibling(testCase)) {
3739

OREAnalytics/orea/scenario/stressscenariodata.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class StressTestScenarioData : public XMLSerializable {
9696
//! \name Inspectors
9797
//@{
9898
const vector<StressTestData>& data() const { return data_; }
99-
99+
bool useSpreadedTermStructures() const { return useSpreadedTermStructures_; }
100100
//@}
101101

102102
//! \name Setters
@@ -118,6 +118,7 @@ class StressTestScenarioData : public XMLSerializable {
118118

119119
private:
120120
vector<StressTestData> data_;
121+
bool useSpreadedTermStructures_ = false;
121122
};
122123
} // namespace analytics
123124
} // namespace ore

OREAnalytics/orea/scenario/stressscenariogenerator.cpp

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,14 @@ void StressScenarioGenerator::addDiscountCurveShifts(StressTestScenarioData::Str
178178

179179
// store shifted discount curve in the scenario
180180
for (Size k = 0; k < n_ten; ++k) {
181+
RiskFactorKey key(RiskFactorKey::KeyType::DiscountCurve, ccy, k);
181182
Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
182-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::DiscountCurve, ccy, k), shiftedDiscount);
183+
if (stressData_->useSpreadedTermStructures()) {
184+
Real discount = exp(-zeros[k] * times[k]);
185+
scenario->add(key, shiftedDiscount / discount);
186+
} else {
187+
scenario->add(key, shiftedDiscount);
188+
}
183189
}
184190
}
185191
DLOG("Discount curve stress scenarios done");
@@ -232,9 +238,14 @@ void StressScenarioGenerator::addSurvivalProbabilityShifts(StressTestScenarioDat
232238

233239
// store shifted discount curve in the scenario
234240
for (Size k = 0; k < n_ten; ++k) {
241+
RiskFactorKey key(RiskFactorKey::KeyType::SurvivalProbability, name, k);
235242
Real shiftedSurvivalProbability = exp(-shiftedZeros[k] * times[k]);
236-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::SurvivalProbability, name, k),
237-
shiftedSurvivalProbability);
243+
if (stressData_->useSpreadedTermStructures()) {
244+
Real survivalProbability = exp(-zeros[k] * times[k]);
245+
scenario->add(key, shiftedSurvivalProbability / survivalProbability);
246+
} else {
247+
scenario->add(key, shiftedSurvivalProbability);
248+
}
238249
}
239250
}
240251
DLOG("Default Curve stress scenarios done");
@@ -288,8 +299,14 @@ void StressScenarioGenerator::addIndexCurveShifts(StressTestScenarioData::Stress
288299

289300
// store shifted discount curve for this index in the scenario
290301
for (Size k = 0; k < n_ten; ++k) {
302+
RiskFactorKey key(RiskFactorKey::KeyType::IndexCurve, indexName, k);
291303
Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
292-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::IndexCurve, indexName, k), shiftedDiscount);
304+
if (stressData_->useSpreadedTermStructures()) {
305+
Real discount = exp(-zeros[k] * times[k]);
306+
scenario->add(key, shiftedDiscount / discount);
307+
} else {
308+
scenario->add(key, shiftedDiscount);
309+
}
293310
}
294311
}
295312
DLOG("Index curve scenarios done");
@@ -347,10 +364,14 @@ void StressScenarioGenerator::addYieldCurveShifts(StressTestScenarioData::Stress
347364

348365
// store shifted discount curve in the scenario
349366
for (Size k = 0; k < n_ten; ++k) {
367+
RiskFactorKey key(RiskFactorKey::KeyType::YieldCurve, name, k);
350368
Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
351-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::YieldCurve, name, k), shiftedDiscount);
352-
// DLOG("yield scenario " << name << ", " << k << ", " << shiftedZeros[k] << " " << zeros[k] << " "
353-
// << shiftedZeros[k] - zeros[k]);
369+
if (stressData_->useSpreadedTermStructures()) {
370+
Real discount = exp(-zeros[k] * times[k]);
371+
scenario->add(key, shiftedDiscount / discount);
372+
} else {
373+
scenario->add(key, shiftedDiscount);
374+
}
354375
}
355376
} // end of shift curve tenors
356377
DLOG("Yield curve scenarios done");
@@ -406,8 +427,14 @@ void StressScenarioGenerator::addFxVolShifts(StressTestScenarioData::StressTestD
406427
applyShift(j, shifts[j], true, shiftType, shiftTimes, values, times, shiftedValues, j == 0 ? true : false);
407428
}
408429

409-
for (Size k = 0; k < n_fxvol_exp; ++k)
410-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::FXVolatility, ccypair, k), shiftedValues[k]);
430+
for (Size k = 0; k < n_fxvol_exp; ++k) {
431+
RiskFactorKey key(RiskFactorKey::KeyType::FXVolatility, ccypair, k);
432+
if (stressData_->useSpreadedTermStructures()) {
433+
scenario->add(key, shiftedValues[k] - values[k]);
434+
} else {
435+
scenario->add(key, shiftedValues[k]);
436+
}
437+
}
411438
}
412439
DLOG("FX vol scenarios done");
413440
}
@@ -461,8 +488,14 @@ void StressScenarioGenerator::addEquityVolShifts(StressTestScenarioData::StressT
461488
applyShift(j, shifts[j], true, shiftType, shiftTimes, values, times, shiftedValues, j == 0 ? true : false);
462489
}
463490

464-
for (Size k = 0; k < n_eqvol_exp; ++k)
465-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::EquityVolatility, equity, k), shiftedValues[k]);
491+
for (Size k = 0; k < n_eqvol_exp; ++k) {
492+
RiskFactorKey key(RiskFactorKey::KeyType::EquityVolatility, equity, k);
493+
if (stressData_->useSpreadedTermStructures()) {
494+
scenario->add(key, shiftedValues[k] - values[k]);
495+
} else {
496+
scenario->add(key, shiftedValues[k]);
497+
}
498+
}
466499
}
467500
DLOG("Equity vol scenarios done");
468501
}
@@ -545,8 +578,12 @@ void StressScenarioGenerator::addSwaptionVolShifts(StressTestScenarioData::Stres
545578
for (Size jj = 0; jj < n_swvol_exp; ++jj) {
546579
for (Size kk = 0; kk < n_swvol_term; ++kk) {
547580
Size idx = jj * n_swvol_term + kk;
548-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::SwaptionVolatility, key, idx),
549-
shiftedVolData[jj][kk]);
581+
RiskFactorKey rfkey(RiskFactorKey::KeyType::SwaptionVolatility, key, idx);
582+
if (stressData_->useSpreadedTermStructures()) {
583+
scenario->add(rfkey, shiftedVolData[jj][kk] - volData[jj][kk]);
584+
} else {
585+
scenario->add(rfkey, shiftedVolData[jj][kk]);
586+
}
550587
}
551588
}
552589
}
@@ -615,8 +652,12 @@ void StressScenarioGenerator::addCapFloorVolShifts(StressTestScenarioData::Stres
615652
for (Size jj = 0; jj < n_cfvol_exp; ++jj) {
616653
for (Size kk = 0; kk < n_cfvol_strikes; ++kk) {
617654
Size idx = jj * n_cfvol_strikes + kk;
618-
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::OptionletVolatility, key, idx),
619-
shiftedVolData[jj][kk]);
655+
RiskFactorKey rfkey(RiskFactorKey::KeyType::OptionletVolatility, key, idx);
656+
if (stressData_->useSpreadedTermStructures()) {
657+
scenario->add(rfkey, shiftedVolData[jj][kk] - volData[jj][kk]);
658+
} else {
659+
scenario->add(rfkey, shiftedVolData[jj][kk]);
660+
}
620661
}
621662
}
622663
}

0 commit comments

Comments
 (0)