Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
xvastressanalytic.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2024 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
20
24#include <orea/cube/cube_io.hpp>
30namespace ore {
31namespace analytics {
32
33void XvaStressAnalyticImpl::writeCubes(const std::string& label,
34 const QuantLib::ext::shared_ptr<XvaAnalytic>& xvaAnalytic) {
35 if (!inputs_->xvaStressWriteCubes() || xvaAnalytic == nullptr) {
36 return;
37 }
38
39 if (inputs_->rawCubeOutput()) {
40 DLOG("Write raw cube under scenario " << label);
41 // analytic()->reports()["XVA_STRESS"]["rawcube_" + label] = xvaAnalytic->reports()["XVA"]["rawcube"];
42 xvaAnalytic->reports()["XVA"]["rawcube"]->toFile(inputs_->resultsPath().string() + "/rawcube_" + label +
43 ".csv");
44 }
45
46 if (inputs_->netCubeOutput()) {
47 DLOG("Write raw cube under scenario " << label);
48 // analytic()->reports()["XVA_STRESS"]["netcube_" + label] = xvaAnalytic->reports()["XVA"]["netcube"];
49 xvaAnalytic->reports()["XVA"]["netcube"]->toFile(inputs_->resultsPath().string() + "/netcube_" + label +
50 ".csv");
51 }
52
53 if (inputs_->writeCube()) {
54 const auto& cubes = xvaAnalytic->npvCubes()["XVA"];
55 for (const auto& [name, cube] : cubes) {
56 DLOG("Write cube under scenario " << name << " for scenario" << label);
57 // analytic()->npvCubes()["XVA_STRESS"][name + "_" + label] = cube;
59 r.cube = cube;
60 if (name == "cube") {
61 // store meta data together with npv cube
62 r.scenarioGeneratorData = inputs_->scenarioGeneratorData();
63 r.storeFlows = inputs_->storeFlows();
64 r.storeCreditStateNPVs = inputs_->storeCreditStateNPVs();
65 }
66 saveCube(inputs_->resultsPath().string() + "/" + name + "_" + label + ".csv.gz", r);
67 }
68 }
69
70 if (inputs_->writeScenarios()) {
71 DLOG("Write scenario report under scenario " << label);
72 // analytic()->reports()["XVA_STRESS"]["scenario" + label] = xvaAnalytic->reports()["XVA"]["scenario"];
73 xvaAnalytic->reports()["XVA"]["scenario"]->toFile(inputs_->resultsPath().string() + "/scenario" + label +
74 ".csv");
75 }
76}
77
78XvaStressAnalyticImpl::XvaStressAnalyticImpl(const QuantLib::ext::shared_ptr<InputParameters>& inputs)
79 : Analytic::Impl(inputs) {
81}
82
83void XvaStressAnalyticImpl::runAnalytic(const QuantLib::ext::shared_ptr<ore::data::InMemoryLoader>& loader,
84 const std::set<std::string>& runTypes) {
85
86 // basic setup
87
88 LOG("Running XVA Stress analytic.");
89
90 Settings::instance().evaluationDate() = inputs_->asof();
91
92 QL_REQUIRE(inputs_->portfolio(), "XvaStressAnalytic::run: No portfolio loaded.");
93
94 Settings::instance().evaluationDate() = inputs_->asof();
95 std::string marketConfig = inputs_->marketConfig("pricing"); // FIXME
96
97 auto xvaAnalytic = dependentAnalytic<XvaAnalytic>("XVA");
98
99 // build t0, sim market, stress scenario generator
100
101 CONSOLEW("XVA_STRESS: Build T0 and Sim Markets and Stress Scenario Generator");
102
103 analytic()->buildMarket(loader);
104
105 QuantLib::ext::shared_ptr<StressTestScenarioData> scenarioData = inputs_->xvaStressScenarioData();
106 if (scenarioData != nullptr && scenarioData->hasScenarioWithParShifts()) {
107 try {
108 ParStressTestConverter converter(
109 inputs_->asof(), analytic()->configurations().todaysMarketParams,
110 analytic()->configurations().simMarketParams, analytic()->configurations().sensiScenarioData,
111 analytic()->configurations().curveConfig, analytic()->market(), inputs_->iborFallbackConfig());
112 scenarioData = converter.convertStressScenarioData(scenarioData);
113 analytic()->stressTests()[label()]["stress_ZeroStressData"] = scenarioData;
114 } catch (const std::exception& e) {
115 scenarioData = inputs_->xvaStressScenarioData();
116 StructuredAnalyticsErrorMessage(label(), "ParConversionFailed", e.what()).log();
117 }
118 }
119
120 LOG("XVA Stress: Build SimMarket and StressTestScenarioGenerator")
121 auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(
122 analytic()->market(), analytic()->configurations().simMarketParams, marketConfig,
123 *analytic()->configurations().curveConfig, *analytic()->configurations().todaysMarketParams,
124 inputs_->continueOnError(), scenarioData->useSpreadedTermStructures(), false, false,
125 *inputs_->iborFallbackConfig(), true);
126
127 auto baseScenario = simMarket->baseScenario();
128 auto scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
129 auto scenarioGenerator = QuantLib::ext::make_shared<StressScenarioGenerator>(
130 scenarioData, baseScenario, analytic()->configurations().simMarketParams, simMarket, scenarioFactory,
131 simMarket->baseScenarioAbsolute());
132 simMarket->scenarioGenerator() = scenarioGenerator;
133
134 CONSOLE("OK");
135
136 // generate the stress scenarios and run dependent xva analytic under each of them
137
138 CONSOLE("XVA_STRESS: Running stress scenarios");
139
140 // run stress test
141 LOG("Run XVA Stresstest")
142 runStressTest(scenarioGenerator, loader);
143
144 LOG("Running XVA Stress analytic finished.");
145}
146
147void XvaStressAnalyticImpl::runStressTest(const QuantLib::ext::shared_ptr<StressScenarioGenerator>& scenarioGenerator,
148 const QuantLib::ext::shared_ptr<ore::data::InMemoryLoader>& loader) {
149
150 std::map<std::string, std::vector<QuantLib::ext::shared_ptr<ore::data::InMemoryReport>>> xvaReports;
151 for (size_t i = 0; i < scenarioGenerator->samples(); ++i) {
152 auto scenario = scenarioGenerator->next(inputs_->asof());
153 const std::string& label = scenario != nullptr ? scenario->label() : std::string();
154 try {
155 DLOG("Calculate XVA for scenario " << label);
156 CONSOLE("XVA_STRESS: Apply scenario " << label);
157 auto newAnalytic = ext::make_shared<XvaAnalytic>(
158 inputs_, (label == "BASE" ? nullptr : scenario),
159 (label == "BASE" ? nullptr : analytic()->configurations().simMarketParams));
160 CONSOLE("XVA_STRESS: Calculate Exposure and XVA")
161 newAnalytic->runAnalytic(loader, {"EXPOSURE", "XVA"});
162 // Collect exposure and xva reports
163 for (auto& [name, rpt] : newAnalytic->reports()["XVA"]) {
164 // add scenario column to report and copy it, concat it later
165 if (boost::starts_with(name, "exposure") || boost::starts_with(name, "xva")) {
166 DLOG("Save and extend report " << name);
167 xvaReports[name].push_back(addColumnToExisitingReport("Scenario", label, rpt));
168 }
169 }
170 writeCubes(label, newAnalytic);
171 } catch (const std::exception& e) {
172 StructuredAnalyticsErrorMessage("XvaStress", "XVACalc",
173 "Error during XVA calc under scenario " + label + ", got " + e.what() +
174 ". Skip it")
175 .log();
176 }
177 }
178 concatReports(xvaReports);
179}
180
182 const std::map<std::string, std::vector<QuantLib::ext::shared_ptr<ore::data::InMemoryReport>>>& xvaReports) {
183 DLOG("Concat exposure and xva reports");
184 for (auto& [name, reports] : xvaReports) {
185 auto report = concatenateReports(reports);
186 if (report != nullptr) {
187 analytic()->reports()[label()][name] = report;
188 }
189 }
190}
191
193 analytic()->configurations().todaysMarketParams = inputs_->todaysMarketParams();
194 analytic()->configurations().simMarketParams = inputs_->xvaStressSimMarketParams();
195 analytic()->configurations().sensiScenarioData = inputs_->xvaStressSensitivityScenarioData();
196}
197
198XvaStressAnalytic::XvaStressAnalytic(const QuantLib::ext::shared_ptr<InputParameters>& inputs)
199 : Analytic(std::make_unique<XvaStressAnalyticImpl>(inputs), {"XVA_STRESS"}, inputs, true, false, false, false) {
200 impl()->addDependentAnalytic("XVA", QuantLib::ext::make_shared<XvaAnalytic>(inputs));
201}
202
203} // namespace analytics
204} // namespace ore
Analytic * analytic() const
Definition: analytic.hpp:193
void setLabel(const string &label)
Definition: analytic.hpp:189
const std::string & label() const
Definition: analytic.hpp:190
QuantLib::ext::shared_ptr< InputParameters > inputs_
Definition: analytic.hpp:216
analytic_reports & reports()
Result reports.
Definition: analytic.hpp:131
Configurations & configurations()
Definition: analytic.hpp:128
analytic_stresstests & stressTests()
Definition: analytic.hpp:134
virtual void buildMarket(const QuantLib::ext::shared_ptr< ore::data::InMemoryLoader > &loader, const bool marketRequired=true)
Definition: analytic.cpp:178
QuantLib::ext::shared_ptr< ore::analytics::StressTestScenarioData > convertStressScenarioData(const QuantLib::ext::shared_ptr< ore::analytics::StressTestScenarioData > &scenarioData) const
Convert all par shifts to zero shifts for all scenarios defined in the stresstest.
XvaStressAnalytic(const QuantLib::ext::shared_ptr< InputParameters > &inputs)
void runStressTest(const QuantLib::ext::shared_ptr< ore::analytics::StressScenarioGenerator > &scenarioGenerator, const QuantLib::ext::shared_ptr< ore::data::InMemoryLoader > &loader)
void runAnalytic(const QuantLib::ext::shared_ptr< ore::data::InMemoryLoader > &loader, const std::set< std::string > &runTypes={}) override
void writeCubes(const std::string &label, const QuantLib::ext::shared_ptr< XvaAnalytic > &xvaAnalytic)
void concatReports(const std::map< std::string, std::vector< QuantLib::ext::shared_ptr< ore::data::InMemoryReport > > > &xvaReports)
XvaStressAnalyticImpl(const QuantLib::ext::shared_ptr< InputParameters > &inputs)
static constexpr const char * LABEL
factory class for cloning a cached scenario
load / save cubes and agg scen data from / to disk
#define LOG(text)
#define DLOG(text)
#define CONSOLEW(text)
#define CONSOLE(text)
void saveCube(const std::string &filename, const NPVCubeWithMetaData &cube, const bool doublePrecision)
Definition: cube_io.cpp:167
QuantLib::ext::shared_ptr< ore::data::InMemoryReport > addColumnToExisitingReport(const std::string &columnName, const std::string &value, const QuantLib::ext::shared_ptr< ore::data::InMemoryReport > &report)
QuantLib::ext::shared_ptr< ore::data::InMemoryReport > concatenateReports(const std::vector< QuantLib::ext::shared_ptr< ore::data::InMemoryReport > > &reports)
Convert all par shifts in a stress test to a zero shifts.
A Market class that can be updated by Scenarios.
Stress scenario generation.
QuantLib::ext::shared_ptr< ore::analytics::SensitivityScenarioData > sensiScenarioData
Definition: analytic.hpp:70
QuantLib::ext::shared_ptr< ore::data::TodaysMarketParameters > todaysMarketParams
Definition: analytic.hpp:68
QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > simMarketParams
Definition: analytic.hpp:69
QuantLib::ext::shared_ptr< NPVCube > cube
Definition: cube_io.hpp:39
QuantLib::ext::shared_ptr< ScenarioGeneratorData > scenarioGeneratorData
Definition: cube_io.hpp:41
boost::optional< Size > storeCreditStateNPVs
Definition: cube_io.hpp:43
boost::optional< bool > storeFlows
Definition: cube_io.hpp:42
Structured analytics error.
Class for structured analytics warnings.
string name
xva stress analytic