Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
stresstest.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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
24
26
27#include <ql/errors.hpp>
28
29#include <boost/lexical_cast.hpp>
30
31using namespace QuantLib;
32using namespace QuantExt;
33using namespace std;
34using namespace ore::data;
35
36namespace ore {
37namespace analytics {
38
39StressTest::StressTest(const QuantLib::ext::shared_ptr<ore::data::Portfolio>& portfolio,
40 const QuantLib::ext::shared_ptr<ore::data::Market>& market, const string& marketConfiguration,
41 const QuantLib::ext::shared_ptr<ore::data::EngineData>& engineData,
42 const QuantLib::ext::shared_ptr<ScenarioSimMarketParameters>& simMarketData,
43 const QuantLib::ext::shared_ptr<StressTestScenarioData>& stressData,
44 const CurveConfigurations& curveConfigs, const TodaysMarketParameters& todaysMarketParams,
45 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory,
46 const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceData,
47 const IborFallbackConfig& iborFallbackConfig, bool continueOnError) {
48
49 LOG("Run Stress Test");
50 DLOG("Build Simulation Market");
51 QuantLib::ext::shared_ptr<ScenarioSimMarket> simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(
52 market, simMarketData, marketConfiguration, curveConfigs, todaysMarketParams, continueOnError,
53 stressData->useSpreadedTermStructures(), false, false, iborFallbackConfig, true);
54
55 DLOG("Build Stress Scenario Generator");
56 Date asof = market->asofDate();
57 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
58 scenarioFactory = scenarioFactory ? scenarioFactory : QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
59 QuantLib::ext::shared_ptr<StressScenarioGenerator> scenarioGenerator = QuantLib::ext::make_shared<StressScenarioGenerator>(
60 stressData, baseScenario, simMarketData, simMarket, scenarioFactory, simMarket->baseScenarioAbsolute());
61 simMarket->scenarioGenerator() = scenarioGenerator;
62
63 DLOG("Build Engine Factory");
64 map<MarketContext, string> configurations;
65 configurations[MarketContext::pricing] = marketConfiguration;
66 auto ed = QuantLib::ext::make_shared<EngineData>(*engineData);
67 ed->globalParameters()["RunType"] = "Stress";
68 QuantLib::ext::shared_ptr<EngineFactory> factory =
69 QuantLib::ext::make_shared<EngineFactory>(ed, simMarket, configurations, referenceData, iborFallbackConfig);
70
71 DLOG("Reset and Build Portfolio");
72 portfolio->reset();
73 portfolio->build(factory, "stress analysis");
74
75 DLOG("Build the cube object to store sensitivities");
76 QuantLib::ext::shared_ptr<NPVCube> cube = QuantLib::ext::make_shared<DoublePrecisionInMemoryCube>(
77 asof, portfolio->ids(), vector<Date>(1, asof), scenarioGenerator->samples());
78
79 DLOG("Run Stress Scenarios");
80 QuantLib::ext::shared_ptr<DateGrid> dg = QuantLib::ext::make_shared<DateGrid>("1,0W", NullCalendar());
81 vector<QuantLib::ext::shared_ptr<ValuationCalculator>> calculators;
82 calculators.push_back(QuantLib::ext::make_shared<NPVCalculator>(simMarketData->baseCcy()));
83 ValuationEngine engine(asof, dg, simMarket, factory->modelBuilders());
84
85 engine.registerProgressIndicator(QuantLib::ext::make_shared<ProgressLog>("stress scenarios", 100, oreSeverity::notice));
86 engine.buildCube(portfolio, cube, calculators);
87
88 /*****************
89 * Collect results
90 */
91 baseNPV_.clear();
92 shiftedNPV_.clear();
93 delta_.clear();
94 labels_.clear();
95 trades_.clear();
96 for (auto const& [tradeId, trade] : portfolio->trades()) {
97 auto index = cube->idsAndIndexes().find(tradeId);
98 if (index == cube->idsAndIndexes().end()) {
99 ALOG("cube does not contain tradeId '" << tradeId << "'");
100 continue;
101 }
102 Real npv0 = cube->getT0(index->second, 0);
103 trades_.insert(tradeId);
104 baseNPV_[tradeId] = npv0;
105 for (Size j = 0; j < scenarioGenerator->samples(); ++j) {
106 const string& label = scenarioGenerator->scenarios()[j]->label();
107 TLOG("Adding stress test result for trade '" << tradeId << "' and scenario #" << j << " '" << label << "'");
108 Real npv = cube->get(index->second, 0, j, 0);
109 pair<string, string> p(tradeId, label);
110 shiftedNPV_[p] = npv;
111 delta_[p] = npv - npv0;
112 labels_.insert(label);
113 }
114 }
115 LOG("Stress testing done");
116}
117
118void StressTest::writeReport(const QuantLib::ext::shared_ptr<ore::data::Report>& report, Real outputThreshold) {
119
120 report->addColumn("TradeId", string());
121 report->addColumn("ScenarioLabel", string());
122 report->addColumn("Base NPV", double(), 2);
123 report->addColumn("Scenario NPV", double(), 2);
124 report->addColumn("Sensitivity", double(), 2);
125
126 for (auto const& [id, npv] : shiftedNPV_) {
127 string tradeId = id.first;
128 string factor = id.second;
129 Real base = baseNPV_[tradeId];
130 Real sensi = npv - base;
131 TLOG("Adding stress report result for tradeId '" << tradeId << "' and scenario '" << factor << ": sensi = "
132 << sensi << ", threshold = " << outputThreshold);
133 if (fabs(sensi) > outputThreshold || QuantLib::close_enough(sensi, outputThreshold)) {
134 report->next();
135 report->add(tradeId);
136 report->add(factor);
137 report->add(base);
138 report->add(npv);
139 report->add(sensi);
140 }
141 }
142
143 report->end();
144}
145} // namespace analytics
146} // namespace ore
std::map< std::pair< string, string >, Real > delta_
Definition: stresstest.hpp:92
void writeReport(const QuantLib::ext::shared_ptr< ore::data::Report > &report, Real outputThreshold=0.0)
Write NPV by trade/scenario to a file (base and shifted NPVs, delta)
Definition: stresstest.cpp:118
std::map< std::pair< string, string >, Real > shiftedNPV_
Definition: stresstest.hpp:92
std::set< std::string > labels_
Definition: stresstest.hpp:94
StressTest(const QuantLib::ext::shared_ptr< ore::data::Portfolio > &portfolio, const QuantLib::ext::shared_ptr< ore::data::Market > &market, const string &marketConfiguration, const QuantLib::ext::shared_ptr< ore::data::EngineData > &engineData, const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > &simMarketData, const QuantLib::ext::shared_ptr< StressTestScenarioData > &stressData, const ore::data::CurveConfigurations &curveConfigs=ore::data::CurveConfigurations(), const ore::data::TodaysMarketParameters &todaysMarketParams=ore::data::TodaysMarketParameters(), QuantLib::ext::shared_ptr< ScenarioFactory > scenarioFactory={}, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceData=nullptr, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), bool continueOnError=false)
Constructor.
Definition: stresstest.cpp:39
std::map< std::string, Real > baseNPV_
Definition: stresstest.hpp:90
std::set< std::string > trades_
Definition: stresstest.hpp:94
void buildCube(const QuantLib::ext::shared_ptr< data::Portfolio > &portfolio, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCube, std::vector< QuantLib::ext::shared_ptr< ValuationCalculator > > calculators, bool mporStickyDate=true, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCubeNettingSet=nullptr, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCptyCube=nullptr, std::vector< QuantLib::ext::shared_ptr< CounterpartyCalculator > > cptyCalculators={}, bool dryRun=false)
Build NPV cube.
void registerProgressIndicator(const QuantLib::ext::shared_ptr< ProgressIndicator > &indicator)
factory class for cloning a cached scenario
A cube implementation that stores the cube in memory.
#define LOG(text)
#define DLOG(text)
#define ALOG(text)
#define TLOG(text)
perform a stress testing analysis for a given portfolio.
vector< string > curveConfigs
Date asof(14, Jun, 2018)
The counterparty cube calculator interface.
The cube valuation core.