Skip to content

Commit f68745c

Browse files
pcaspersjenkins
authored andcommitted
Merge remote-tracking branch 'origin/master' into QPR-11968_Jerry
1 parent 5240ddb commit f68745c

12 files changed

Lines changed: 548 additions & 1 deletion

Docs/UserGuide/parameterisation/ore.tex

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,8 @@ \subsubsection{Analytics}\label{sec:analytics}
528528
<Parameter name="mcSamples">100000</Parameter>
529529
<Parameter name="mcSeed">42</Parameter>
530530
<Parameter name="outputFile">var.csv</Parameter>
531-
</Analytic> </Analytics>
531+
</Analytic>
532+
</Analytics>
532533
\end{minted}
533534
\caption{ORE analytic: VaR}
534535
\label{lst:ore_var}
@@ -547,4 +548,34 @@ \subsubsection{Analytics}\label{sec:analytics}
547548
\item {\tt mcSamples:} Number of Monte Carlo samples used when the {\em MonteCarlo} method is chosen
548549
\item {\tt mcSeed:} Random number generator seed when the {\em MonteCarlo} method is chosen
549550
\item {\tt outputFile:} Output file name
551+
\end{itemize}
552+
553+
\medskip The {\tt scenarioStatistics} 'analytics' provide the statistics and distribution of the scenarios generated through simulation. Listing \ref{lst:ore_scenarioStatistics}
554+
shows a typical configuration for sensitivity calculation.
555+
556+
\begin{listing}[H]
557+
%\hrule\medskip
558+
\begin{minted}[fontsize=\footnotesize]{xml}
559+
<Analytics>
560+
<Analytic type="scenarioStatistics">
561+
<Parameter name="active">Y</Parameter>
562+
<Parameter name="simulationConfigFile">simulation.xml</Parameter>
563+
<Parameter name="distributionBuckets">20</Parameter>
564+
<Parameter name="outputZeroRate">Y</Parameter>
565+
<Parameter name="scenariodump">scenariodump.csv</Parameter>
566+
</Analytic>
567+
</Analytics>
568+
\end{minted}
569+
\caption{ORE analytic: scenarioStatistics}
570+
\label{lst:ore_scenarioStatistics}
571+
\end{listing}
572+
573+
The parameters have the following interpretation:
574+
575+
\begin{itemize}
576+
\item {\tt simulationConfigFile:} Configuration file defining the simulation market under which sensitivities are computed,
577+
see \ref{sec:simulation}.
578+
\item {\tt distributionBuckets:} Number of buckets used for the distribution histogram.
579+
\item {\tt outputZeroRate:} Determine whether the statistics report and distribution report will use zero rate or discount factors. If set to Y, the reports will use zero rates. If set to N, they will use discount factors.
580+
\item {\tt scenariodump:} File containing all the scenarios generated through simulation market. If the node is not given, this file will not be outputted.
550581
\end{itemize}

OREAnalytics/orea/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ aggregation/xvacalculator.cpp
1818
app/analytic.cpp
1919
app/analytics/parconversionanalytic.cpp
2020
app/analytics/pricinganalytic.cpp
21+
app/analytics/scenariostatisticsanalytic.cpp
2122
app/analytics/simmanalytic.cpp
2223
app/analytics/varanalytic.cpp
2324
app/analytics/xvaanalytic.cpp
@@ -80,6 +81,7 @@ scenario/lgmscenariogenerator.cpp
8081
scenario/scenario.cpp
8182
scenario/scenariogeneratorbuilder.cpp
8283
scenario/scenariogeneratordata.cpp
84+
scenario/scenariogeneratortransform.cpp
8385
scenario/scenarioshiftcalculator.cpp
8486
scenario/scenariosimmarket.cpp
8587
scenario/scenariosimmarketparameters.cpp
@@ -145,6 +147,7 @@ aggregation/xvacalculator.hpp
145147
app/analytic.hpp
146148
app/analytics/parconversionanalytic.hpp
147149
app/analytics/pricinganalytic.hpp
150+
app/analytics/scenariostatisticsanalytic.hpp
148151
app/analytics/simmanalytic.hpp
149152
app/analytics/varanalytic.hpp
150153
app/analytics/xvaanalytic.hpp
@@ -223,6 +226,7 @@ scenario/scenariofilter.hpp
223226
scenario/scenariogenerator.hpp
224227
scenario/scenariogeneratorbuilder.hpp
225228
scenario/scenariogeneratordata.hpp
229+
scenario/scenariogeneratortransform.hpp
226230
scenario/scenarioshiftcalculator.hpp
227231
scenario/scenariosimmarket.hpp
228232
scenario/scenariosimmarketparameters.hpp
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
Copyright (C) 2022 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+
19+
#include <orea/app/analytics/scenariostatisticsanalytic.hpp>
20+
#include <orea/app/reportwriter.hpp>
21+
#include <orea/app/structuredanalyticserror.hpp>
22+
#include <orea/app/structuredanalyticswarning.hpp>
23+
#include <orea/scenario/scenariowriter.hpp>
24+
#include <orea/scenario/simplescenariofactory.hpp>
25+
#include <orea/scenario/crossassetmodelscenariogenerator.hpp>
26+
#include <orea/scenario/scenariogeneratortransform.hpp>
27+
28+
#include <ored/model/crossassetmodelbuilder.hpp>
29+
#include <ored/portfolio/structuredtradeerror.hpp>
30+
31+
using namespace ore::data;
32+
using namespace boost::filesystem;
33+
34+
namespace ore {
35+
namespace analytics {
36+
37+
/******************************************************************************
38+
* ScenarioStatistics Analytic: Scenario_Statistics
39+
******************************************************************************/
40+
41+
void ScenarioStatisticsAnalyticImpl::setUpConfigurations() {
42+
LOG("ScenarioStatisticsAnalytic::setUpConfigurations() called");
43+
analytic()->configurations().todaysMarketParams = inputs_->todaysMarketParams();
44+
analytic()->configurations().simMarketParams = inputs_->exposureSimMarketParams();
45+
analytic()->configurations().scenarioGeneratorData = inputs_->scenarioGeneratorData();
46+
analytic()->configurations().crossAssetModelData = inputs_->crossAssetModelData();
47+
}
48+
49+
void ScenarioStatisticsAnalyticImpl::buildScenarioSimMarket() {
50+
51+
std::string configuration = inputs_->marketConfig("simulation");
52+
simMarket_ = boost::make_shared<ScenarioSimMarket>(
53+
analytic()->market(),
54+
analytic()->configurations().simMarketParams,
55+
boost::make_shared<FixingManager>(inputs_->asof()),
56+
configuration,
57+
*inputs_->curveConfigs().get(),
58+
*analytic()->configurations().todaysMarketParams,
59+
inputs_->continueOnError(),
60+
false, true, false,
61+
*inputs_->iborFallbackConfig(),
62+
false);
63+
}
64+
65+
void ScenarioStatisticsAnalyticImpl::buildScenarioGenerator(const bool continueOnCalibrationError) {
66+
if (!model_)
67+
buildCrossAssetModel(continueOnCalibrationError);
68+
ScenarioGeneratorBuilder sgb(analytic()->configurations().scenarioGeneratorData);
69+
boost::shared_ptr<ScenarioFactory> sf = boost::make_shared<SimpleScenarioFactory>();
70+
string config = inputs_->marketConfig("simulation");
71+
scenarioGenerator_ = sgb.build(model_, sf, analytic()->configurations().simMarketParams, inputs_->asof(), analytic()->market(), config);
72+
QL_REQUIRE(scenarioGenerator_, "failed to build the scenario generator");
73+
samples_ = analytic()->configurations().scenarioGeneratorData->samples();
74+
LOG("simulation grid size " << grid_->size());
75+
LOG("simulation grid valuation dates " << grid_->valuationDates().size());
76+
LOG("simulation grid close-out dates " << grid_->closeOutDates().size());
77+
LOG("simulation grid front date " << io::iso_date(grid_->dates().front()));
78+
LOG("simulation grid back date " << io::iso_date(grid_->dates().back()));
79+
80+
if (inputs_->writeScenarios()) {
81+
auto report = boost::make_shared<InMemoryReport>();
82+
analytic()->reports()["SCENARIO_STATISTICS"]["scenario"] = report;
83+
scenarioGenerator_ = boost::make_shared<ScenarioWriter>(scenarioGenerator_, report);
84+
}
85+
}
86+
87+
void ScenarioStatisticsAnalyticImpl::buildCrossAssetModel(const bool continueOnCalibrationError) {
88+
LOG("SCENARIO_STATISTICS: Build Simulation Model (continueOnCalibrationError = "
89+
<< std::boolalpha << continueOnCalibrationError << ")");
90+
CrossAssetModelBuilder modelBuilder(
91+
analytic()->market(), analytic()->configurations().crossAssetModelData, inputs_->marketConfig("lgmcalibration"),
92+
inputs_->marketConfig("fxcalibration"), inputs_->marketConfig("eqcalibration"),
93+
inputs_->marketConfig("infcalibration"), inputs_->marketConfig("crcalibration"),
94+
inputs_->marketConfig("simulation"), false, continueOnCalibrationError, "",
95+
inputs_->salvageCorrelationMatrix() ? SalvagingAlgorithm::Spectral : SalvagingAlgorithm::None,
96+
"xva cam building");
97+
model_ = *modelBuilder.model();
98+
}
99+
100+
void ScenarioStatisticsAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLoader>& loader,
101+
const std::set<std::string>& runTypes) {
102+
103+
LOG("Scenario analytic called with asof " << io::iso_date(inputs_->asof()));
104+
105+
Settings::instance().evaluationDate() = inputs_->asof();
106+
//ObservationMode::instance().setMode(inputs_->exposureObservationModel());
107+
108+
LOG("SCENARIO_STATISTICS: Build Today's Market");
109+
CONSOLEW("SCENARIO_STATISTICS: Build Market");
110+
analytic()->buildMarket(loader);
111+
CONSOLE("OK");
112+
113+
grid_ = analytic()->configurations().scenarioGeneratorData->getGrid();
114+
115+
LOG("SCENARIO_STATISTICS: Build simulation market");
116+
buildScenarioSimMarket();
117+
118+
LOG("SCENARIO_STATISTICS: Build Scenario Generator");
119+
auto globalParams = inputs_->simulationPricingEngine()->globalParameters();
120+
auto continueOnCalErr = globalParams.find("ContinueOnCalibrationError");
121+
bool continueOnErr = (continueOnCalErr != globalParams.end()) && parseBool(continueOnCalErr->second);
122+
buildScenarioGenerator(continueOnErr);
123+
124+
LOG("SCENARIO_STATISTICS: Attach Scenario Generator to ScenarioSimMarket");
125+
simMarket_->scenarioGenerator() = scenarioGenerator_;
126+
127+
MEM_LOG;
128+
129+
// Output scenario statistics and distribution reports
130+
const vector<RiskFactorKey>& keys = simMarket_->baseScenario()->keys();
131+
boost::shared_ptr<ScenarioGenerator> scenarioGenerator =
132+
inputs_->scenarioOutputZeroRate()
133+
? boost::make_shared<ScenarioGeneratorTransform>(scenarioGenerator_, simMarket_,
134+
analytic()->configurations().simMarketParams)
135+
: scenarioGenerator_;
136+
137+
auto statsReport = boost::make_shared<InMemoryReport>();
138+
scenarioGenerator->reset();
139+
ReportWriter().writeScenarioStatistics(scenarioGenerator, keys, samples_, grid_->valuationDates(),
140+
*statsReport);
141+
analytic()->reports()["SCENARIO_STATISTICS"]["scenario_statistics"] = statsReport;
142+
143+
auto distributionReport = boost::make_shared<InMemoryReport>();
144+
scenarioGenerator->reset();
145+
ReportWriter().writeScenarioDistributions(scenarioGenerator, keys, samples_, grid_->valuationDates(),
146+
inputs_->scenarioDistributionSteps(), *distributionReport);
147+
analytic()->reports()["SCENARIO_STATISTICS"]["scenario_distribution"] = distributionReport;
148+
}
149+
150+
} // namespace analytics
151+
} // namespace ore
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright (C) 2022 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+
19+
/*! \file orea/app/scenarioanalytic.hpp
20+
\brief ORE Scenario Statistics Analytics
21+
*/
22+
23+
#pragma once
24+
25+
#include <orea/app/analytic.hpp>
26+
27+
namespace ore {
28+
namespace analytics {
29+
30+
class ScenarioStatisticsAnalyticImpl : public Analytic::Impl {
31+
public:
32+
static constexpr const char* LABEL = "SCENARIO_STATISTICS";
33+
34+
ScenarioStatisticsAnalyticImpl(const boost::shared_ptr<InputParameters>& inputs) : Analytic::Impl(inputs) { setLabel(LABEL); }
35+
virtual void runAnalytic(const boost::shared_ptr<ore::data::InMemoryLoader>& loader,
36+
const std::set<std::string>& runTypes = {}) override;
37+
void setUpConfigurations() override;
38+
39+
boost::shared_ptr<ScenarioGenerator> scenarioGenerator() { return scenarioGenerator_; }
40+
41+
protected:
42+
void buildScenarioSimMarket();
43+
void buildCrossAssetModel(bool continueOnError);
44+
void buildScenarioGenerator(bool continueOnError);
45+
46+
boost::shared_ptr<ScenarioSimMarket> simMarket_;
47+
boost::shared_ptr<CrossAssetModel> model_;
48+
boost::shared_ptr<ScenarioGenerator> scenarioGenerator_;
49+
50+
boost::shared_ptr<DateGrid> grid_;
51+
Size samples_ = 0;
52+
};
53+
54+
class ScenarioStatisticsAnalytic : public Analytic {
55+
public:
56+
ScenarioStatisticsAnalytic(const boost::shared_ptr<InputParameters>& inputs)
57+
: Analytic(std::make_unique<ScenarioStatisticsAnalyticImpl>(inputs), {"SCENARIO_STATISTICS"}, inputs, true, false, true, true) {}
58+
};
59+
60+
} // namespace analytics
61+
} // namespace oreplus

OREAnalytics/orea/app/analyticsmanager.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <orea/app/analytics/parconversionanalytic.hpp>
2020
#include <orea/app/analytics/pricinganalytic.hpp>
21+
#include <orea/app/analytics/scenariostatisticsanalytic.hpp>
2122
#include <orea/app/analytics/simmanalytic.hpp>
2223
#include <orea/app/analytics/varanalytic.hpp>
2324
#include <orea/app/analytics/xvaanalytic.hpp>
@@ -56,6 +57,7 @@ AnalyticsManager::AnalyticsManager(const boost::shared_ptr<InputParameters>& inp
5657
addAnalytic("XVA", boost::make_shared<XvaAnalytic>(inputs_));
5758
addAnalytic("SIMM", boost::make_shared<SimmAnalytic>(inputs_));
5859
addAnalytic("PARCONVERSION", boost::make_shared<ParConversionAnalytic>(inputs_));
60+
addAnalytic("SCENARIO_STATISTICS", boost::make_shared<ScenarioStatisticsAnalytic>(inputs_));
5961
}
6062

6163
void AnalyticsManager::clear() {

OREAnalytics/orea/app/inputparameters.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,10 @@ class InputParameters {
306306
void setParConversionInputBaseNpvColumn(const std::string& s) { parConversionInputBaseNpvColumn_ = s; }
307307
void setParConversionInputShiftSizeColumn(const std::string& s) { parConversionInputShiftSizeColumn_ = s; }
308308

309+
// Setters for ScenarioStatistics
310+
void setScenarioDistributionSteps(const Size s) { scenarioDistributionSteps_ = s; }
311+
void setScenarioOutputZeroRate(const bool b) { scenarioOutputZeroRate_ = b; }
312+
309313

310314
// Set list of analytics that shall be run
311315
void setAnalytics(const std::string& s); // parse to set<string>
@@ -552,6 +556,9 @@ class InputParameters {
552556
const std::string& parConversionInputBaseNpvColumn() { return parConversionInputBaseNpvColumn_; }
553557
const std::string& parConversionInputShiftSizeColumn() { return parConversionInputShiftSizeColumn_; }
554558

559+
// Getters for ScenarioStatistics
560+
const Size& scenarioDistributionSteps() { return scenarioDistributionSteps_; }
561+
const bool& scenarioOutputZeroRate() { return scenarioOutputZeroRate_; }
555562

556563
/*************************************
557564
* List of analytics that shall be run
@@ -785,6 +792,12 @@ class InputParameters {
785792
std::string parConversionInputCurrencyColumn_ = "Currency";
786793
std::string parConversionInputBaseNpvColumn_ = "Base NPV";
787794
std::string parConversionInputShiftSizeColumn_ = "ShiftSize_1";
795+
796+
/***************
797+
* Scenario Statistics analytic
798+
***************/
799+
Size scenarioDistributionSteps_ = 20;
800+
bool scenarioOutputZeroRate_ = false;
788801
};
789802

790803
inline const std::string& InputParameters::marketConfig(const std::string& context) {

OREAnalytics/orea/app/oreapp.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,41 @@ void OREApp::buildInputParameters(boost::shared_ptr<InputParameters> inputs,
13011301

13021302
}
13031303

1304+
/**********************
1305+
* Scenario_Statistics
1306+
**********************/
1307+
1308+
tmp = params_->get("scenarioStatistics", "active", false);
1309+
if (!tmp.empty() && parseBool(tmp)) {
1310+
inputs->insertAnalytic("SCENARIO_STATISTICS");
1311+
tmp = params_->get("scenarioStatistics", "distributionBuckets", false);
1312+
if (tmp != "")
1313+
inputs->setScenarioDistributionSteps(parseInteger(tmp));
1314+
1315+
tmp = params_->get("scenarioStatistics", "outputZeroRate", false);
1316+
if (tmp != "")
1317+
inputs->setScenarioOutputZeroRate(parseBool(tmp));
1318+
1319+
tmp = params_->get("scenarioStatistics", "simulationConfigFile", false);
1320+
if (tmp != "") {
1321+
string simulationConfigFile = inputPath + "/" + tmp;
1322+
LOG("Loading simulation config from file" << simulationConfigFile);
1323+
inputs->setExposureSimMarketParamsFromFile(simulationConfigFile);
1324+
inputs->setCrossAssetModelDataFromFile(simulationConfigFile);
1325+
inputs->setScenarioGeneratorDataFromFile(simulationConfigFile);
1326+
auto grid = inputs->scenarioGeneratorData()->getGrid();
1327+
DLOG("grid size=" << grid->size() << ", dates=" << grid->dates().size()
1328+
<< ", valuationDates=" << grid->valuationDates().size()
1329+
<< ", closeOutDates=" << grid->closeOutDates().size());
1330+
} else {
1331+
ALOG("Simulation market, model and scenario generator data not loaded");
1332+
}
1333+
1334+
tmp = params_->get("scenarioStatistics", "scenariodump", false);
1335+
if (tmp != "")
1336+
inputs->setWriteScenarios(true);
1337+
}
1338+
13041339
if (inputs->analytics().size() == 0) {
13051340
inputs->insertAnalytic("MARKETDATA");
13061341
inputs->setOutputTodaysMarketCalibration(true);

0 commit comments

Comments
 (0)