Skip to content

Commit f7da9a7

Browse files
pcaspersjenkins
authored andcommitted
QPR-12216 fix stress scenario generation with spreaded term structures
1 parent 9ef3023 commit f7da9a7

3 files changed

Lines changed: 21 additions & 17 deletions

File tree

OREAnalytics/orea/engine/stresstest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ StressTest::StressTest(const boost::shared_ptr<ore::data::Portfolio>& portfolio,
5656
Date asof = market->asofDate();
5757
boost::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
5858
scenarioFactory = scenarioFactory ? scenarioFactory : boost::make_shared<CloneScenarioFactory>(baseScenario);
59-
boost::shared_ptr<StressScenarioGenerator> scenarioGenerator =
60-
boost::make_shared<StressScenarioGenerator>(stressData, baseScenario, simMarketData, simMarket, scenarioFactory);
59+
boost::shared_ptr<StressScenarioGenerator> scenarioGenerator = boost::make_shared<StressScenarioGenerator>(
60+
stressData, baseScenario, simMarketData, simMarket, scenarioFactory, simMarket->baseScenarioAbsolute());
6161
simMarket->scenarioGenerator() = scenarioGenerator;
6262

6363
DLOG("Build Engine Factory");

OREAnalytics/orea/scenario/stressscenariogenerator.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ StressScenarioGenerator::StressScenarioGenerator(const boost::shared_ptr<StressT
3131
const boost::shared_ptr<Scenario>& baseScenario,
3232
const boost::shared_ptr<ScenarioSimMarketParameters>& simMarketData,
3333
const boost::shared_ptr<ScenarioSimMarket>& simMarket,
34-
const boost::shared_ptr<ScenarioFactory>& stressScenarioFactory)
34+
const boost::shared_ptr<ScenarioFactory>& stressScenarioFactory,
35+
const boost::shared_ptr<Scenario>& baseScenarioAbsolute)
3536
: ShiftScenarioGenerator(baseScenario, simMarketData, simMarket), stressData_(stressData),
36-
stressScenarioFactory_(stressScenarioFactory) {
37+
stressScenarioFactory_(stressScenarioFactory),
38+
baseScenarioAbsolute_(baseScenarioAbsolute == nullptr ? baseScenario : baseScenarioAbsolute) {
3739

3840
QL_REQUIRE(stressData_, "StressScenarioGenerator: stressData is null");
3941

@@ -123,7 +125,7 @@ void StressScenarioGenerator::addEquityShifts(StressTestScenarioData::StressTest
123125
Real size = data.shiftSize;
124126

125127
RiskFactorKey key(RiskFactorKey::KeyType::EquitySpot, equity);
126-
Real rate = baseScenario_->get(key);
128+
Real rate = baseScenarioAbsolute_->get(key);
127129

128130
Real newRate = relShift ? rate * (1.0 + size) : (rate + size);
129131
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::EquitySpot, equity), newRate);
@@ -160,7 +162,7 @@ void StressScenarioGenerator::addDiscountCurveShifts(StressTestScenarioData::Str
160162
Date d = asof + simMarketData_->yieldCurveTenors(ccy)[j];
161163
times[j] = dc.yearFraction(asof, d);
162164
RiskFactorKey key(RiskFactorKey::KeyType::DiscountCurve, ccy, j);
163-
Real quote = baseScenario_->get(key);
165+
Real quote = baseScenarioAbsolute_->get(key);
164166
zeros[j] = -std::log(quote) / times[j];
165167
}
166168

@@ -220,7 +222,7 @@ void StressScenarioGenerator::addSurvivalProbabilityShifts(StressTestScenarioDat
220222
Date d = asof + simMarketData_->defaultTenors(name)[j];
221223
times[j] = dc.yearFraction(asof, d);
222224
RiskFactorKey key(RiskFactorKey::KeyType::SurvivalProbability, name, j);
223-
Real quote = baseScenario_->get(key);
225+
Real quote = baseScenarioAbsolute_->get(key);
224226
zeros[j] = -std::log(quote) / times[j];
225227
}
226228

@@ -282,7 +284,7 @@ void StressScenarioGenerator::addIndexCurveShifts(StressTestScenarioData::Stress
282284
Date d = asof + simMarketData_->yieldCurveTenors(indexName)[j];
283285
times[j] = dc.yearFraction(asof, d);
284286
RiskFactorKey key(RiskFactorKey::KeyType::IndexCurve, indexName, j);
285-
Real quote = baseScenario_->get(key);
287+
Real quote = baseScenarioAbsolute_->get(key);
286288
zeros[j] = -std::log(quote) / times[j];
287289
}
288290

@@ -343,7 +345,7 @@ void StressScenarioGenerator::addYieldCurveShifts(StressTestScenarioData::Stress
343345
Date d = asof + simMarketData_->yieldCurveTenors(name)[j];
344346
times[j] = dc.yearFraction(asof, d);
345347
RiskFactorKey key(RiskFactorKey::KeyType::YieldCurve, name, j);
346-
Real quote = baseScenario_->get(key);
348+
Real quote = baseScenarioAbsolute_->get(key);
347349
zeros[j] = -std::log(quote) / times[j];
348350
}
349351

@@ -406,7 +408,7 @@ void StressScenarioGenerator::addFxVolShifts(StressTestScenarioData::StressTestD
406408
Date d = asof + simMarketData_->fxVolExpiries(ccypair)[j];
407409

408410
RiskFactorKey key(RiskFactorKey::KeyType::FXVolatility, ccypair, j);
409-
values[j] = baseScenario_->get(key);
411+
values[j] = baseScenarioAbsolute_->get(key);
410412

411413
times[j] = dc.yearFraction(asof, d);
412414
}
@@ -467,7 +469,7 @@ void StressScenarioGenerator::addEquityVolShifts(StressTestScenarioData::StressT
467469
Date d = asof + simMarketData_->equityVolExpiries(equity)[j];
468470

469471
RiskFactorKey key(RiskFactorKey::KeyType::EquityVolatility, equity, j);
470-
values[j] = baseScenario_->get(key);
472+
values[j] = baseScenarioAbsolute_->get(key);
471473

472474
times[j] = dc.yearFraction(asof, d);
473475
}
@@ -544,7 +546,7 @@ void StressScenarioGenerator::addSwaptionVolShifts(StressTestScenarioData::Stres
544546
Size idx = j * n_swvol_term + k;
545547

546548
RiskFactorKey rf(RiskFactorKey::KeyType::SwaptionVolatility, key, idx);
547-
volData[j][k] = baseScenario_->get(rf);
549+
volData[j][k] = baseScenarioAbsolute_->get(rf);
548550
}
549551
}
550552

@@ -633,7 +635,7 @@ void StressScenarioGenerator::addCapFloorVolShifts(StressTestScenarioData::Stres
633635
for (Size k = 0; k < n_cfvol_strikes; ++k) {
634636
Size idx = j * n_cfvol_strikes + k;
635637
volData[j][k] =
636-
baseScenario_->get(RiskFactorKey(RiskFactorKey::KeyType::OptionletVolatility, key, idx));
638+
baseScenarioAbsolute_->get(RiskFactorKey(RiskFactorKey::KeyType::OptionletVolatility, key, idx));
637639
}
638640
}
639641

@@ -675,7 +677,7 @@ void StressScenarioGenerator::addSecuritySpreadShifts(StressTestScenarioData::St
675677
Real size = data.shiftSize;
676678

677679
RiskFactorKey key(RiskFactorKey::KeyType::SecuritySpread, bond);
678-
Real base_spread = baseScenario_->get(key);
680+
Real base_spread = baseScenarioAbsolute_->get(key);
679681

680682
Real newSpread = relShift ? base_spread * (1.0 + size) : (base_spread + size);
681683
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::SecuritySpread, bond), newSpread);
@@ -694,7 +696,7 @@ void StressScenarioGenerator::addRecoveryRateShifts(StressTestScenarioData::Stre
694696
Real size = data.shiftSize;
695697

696698
RiskFactorKey key(RiskFactorKey::KeyType::RecoveryRate, isin);
697-
Real base_recoveryRate = baseScenario_->get(key);
699+
Real base_recoveryRate = baseScenarioAbsolute_->get(key);
698700
Real new_recoveryRate = relShift ? base_recoveryRate * (1.0 + size) : (base_recoveryRate + size);
699701
scenario->add(RiskFactorKey(RiskFactorKey::KeyType::RecoveryRate, isin), new_recoveryRate);
700702
}

OREAnalytics/orea/scenario/stressscenariogenerator.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ class StressScenarioGenerator : public ShiftScenarioGenerator {
7272
StressScenarioGenerator(const boost::shared_ptr<StressTestScenarioData>& stressData,
7373
const boost::shared_ptr<Scenario>& baseScenario,
7474
const boost::shared_ptr<ScenarioSimMarketParameters>& simMarketData,
75-
const boost::shared_ptr<ScenarioSimMarket>& simMarket,
76-
const boost::shared_ptr<ScenarioFactory>& stressScenarioFactory);
75+
const boost::shared_ptr<ScenarioSimMarket>& simMarket,
76+
const boost::shared_ptr<ScenarioFactory>& stressScenarioFactory,
77+
const boost::shared_ptr<Scenario>& baseScenarioAbsolute = nullptr);
7778
//! Default destructor
7879
~StressScenarioGenerator() {}
7980

@@ -96,6 +97,7 @@ class StressScenarioGenerator : public ShiftScenarioGenerator {
9697

9798
boost::shared_ptr<StressTestScenarioData> stressData_;
9899
boost::shared_ptr<ScenarioFactory> stressScenarioFactory_;
100+
boost::shared_ptr<Scenario> baseScenarioAbsolute_;
99101
};
100102
} // namespace analytics
101103
} // namespace ore

0 commit comments

Comments
 (0)