Skip to content

Commit 3947c18

Browse files
damienbarkerjenkins
authored andcommitted
Merge branch 'QPR-11853' into 'master'
QPR-11853 RAG threshold dynamic implementation (needs to be synced with PPR-586) Closes QPR-11853 See merge request qs/oreplus!2565
1 parent 1b25192 commit 3947c18

17 files changed

Lines changed: 317 additions & 105 deletions

OREAnalytics/orea/app/inputparameters.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ void InputParameters::setRefDataManagerFromFile(const std::string& fileName) {
9191
refDataManager_ = QuantLib::ext::make_shared<BasicReferenceDataManager>(fileName);
9292
}
9393

94+
void InputParameters::setBaselTrafficLightConfig(const std::string& xml) {
95+
baselTrafficLightConfig_ = QuantLib::ext::make_shared<BaselTrafficLightData>();
96+
baselTrafficLightConfig_->fromXMLString(xml);
97+
}
98+
99+
void InputParameters::setBaselTrafficLightFromFile(const std::string& fileName) {
100+
baselTrafficLightConfig_ = QuantLib::ext::make_shared<BaselTrafficLightData>(fileName);
101+
}
102+
94103
void InputParameters::setScriptLibrary(const std::string& xml) {
95104
ScriptLibraryData data;
96105
data.fromXMLString(xml);

OREAnalytics/orea/app/inputparameters.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <orea/simm/simmconfiguration.hpp>
4848
#include <ored/configuration/curveconfigurations.hpp>
4949
#include <ored/configuration/iborfallbackconfig.hpp>
50+
#include <ored/configuration/baseltrafficlightconfig.hpp>
5051
#include <ored/marketdata/csvloader.hpp>
5152
#include <ored/marketdata/todaysmarketparameters.hpp>
5253
#include <ored/model/crossassetmodeldata.hpp>
@@ -101,6 +102,8 @@ class InputParameters {
101102
void setConventionsFromFile(const std::string& fileName);
102103
void setIborFallbackConfig(const std::string& xml);
103104
void setIborFallbackConfigFromFile(const std::string& fileName);
105+
void setBaselTrafficLightConfig(const std::string& xml);
106+
void setBaselTrafficLightFromFile(const std::string& fileName);
104107
void setCurveConfigs(const std::string& xml);
105108
void setCurveConfigsFromFile(const std::string& fileName, std::string id = "");
106109
void setPricingEngine(const std::string& xml);
@@ -529,6 +532,7 @@ class InputParameters {
529532
const QuantLib::ext::shared_ptr<ore::data::BasicReferenceDataManager>& refDataManager() const { return refDataManager_; }
530533
const QuantLib::ext::shared_ptr<ore::data::Conventions>& conventions() const { return conventions_; }
531534
const QuantLib::ext::shared_ptr<ore::data::IborFallbackConfig>& iborFallbackConfig() const { return iborFallbackConfig_; }
535+
const QuantLib::ext::shared_ptr<ore::data::BaselTrafficLightData>& baselTrafficLightConfig() const { return baselTrafficLightConfig_; }
532536
CurveConfigurationsManager& curveConfigs() { return curveConfigs_; }
533537
const QuantLib::ext::shared_ptr<ore::data::EngineData>& pricingEngine() const { return pricingEngine_; }
534538
const QuantLib::ext::shared_ptr<ore::data::TodaysMarketParameters>& todaysMarketParams() const { return todaysMarketParams_; }
@@ -966,6 +970,7 @@ class InputParameters {
966970

967971
std::map<std::string, std::string> marketConfigs_;
968972
QuantLib::ext::shared_ptr<ore::data::BasicReferenceDataManager> refDataManager_;
973+
QuantLib::ext::shared_ptr<ore::data::BaselTrafficLightData> baselTrafficLightConfig_;
969974
QuantLib::ext::shared_ptr<ore::data::Conventions> conventions_;
970975
QuantLib::ext::shared_ptr<ore::data::IborFallbackConfig> iborFallbackConfig_;
971976
CurveConfigurationsManager curveConfigs_;

OREAnalytics/orea/app/oreapp.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,14 @@ void OREAppInputParameters::loadParameters() {
784784
WLOG("Using default Ibor fallback config");
785785
}
786786

787+
if (params_->has("setup", "baselTrafficLightConfig") && params_->get("setup", "baselTrafficLightConfig") != "") {
788+
filesystem::path tmp = inputPath / params_->get("setup", "baselTrafficLightConfig");
789+
LOG("Loading Basel Traffic Light from file: " << tmp);
790+
setBaselTrafficLightFromFile(tmp.generic_string());
791+
} else {
792+
WLOG("Using default Basel Traffic Light config");
793+
}
794+
787795
if (params_->has("setup", "curveConfigFile") && params_->get("setup", "curveConfigFile") != "") {
788796
filesystem::path curveConfigFile = inputPath / params_->get("setup", "curveConfigFile");
789797
LOG("Load curve configurations from file: ");

OREAnalytics/orea/engine/marketriskbacktest.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ void MarketRiskBacktest::initialise() {
6868
// If there is a mismatch between call and post, then we will have to exclude trade-level PnLs from the total (scenario) PnL
6969
requireTradePnl_ = callTradeIds_ != postTradeIds_;
7070

71+
baselTrafficLightMatrix_ = btArgs_->baselTrafficLight_->baselTrafficLightData();
72+
7173
MarketRiskReport::initialise();
7274
}
7375

@@ -192,7 +194,7 @@ MarketRiskBacktest::SummaryResults MarketRiskBacktest::calculateSummary(
192194
SummaryResults sr = {pnls.size(), 0.0, 0, 0.0, 0, {}, 0, 0, {}};
193195

194196
sr.callValue = callValue(data);
195-
sr.postValue = postValue(data);
197+
sr.postValue = postValue(data);
196198

197199
auto pnlScenDates = hisScenGen_->filteredScenarioDates(btArgs_->backtestPeriod_);
198200
QL_REQUIRE(pnlScenDates.size() == pnls.size(), "Backtest::calculateSummary(): internal error, pnlScenDates ("
@@ -302,8 +304,18 @@ MarketRiskBacktest::SummaryResults MarketRiskBacktest::calculateSummary(
302304
// Now calculate the [red, amber] and [amber, green] bounds
303305
if (hisScenGen_->overlapping()) {
304306
try {
307+
308+
ore::data::BaselTrafficLightData::ObservationData trafficLightObs;
309+
try {
310+
trafficLightObs = baselTrafficLightMatrix_[hisScenGen_->mporDays()];
311+
} catch (...) {
312+
LOG("Couldn't parse BaselTrafficLight for " << hisScenGen_->mporDays() << " mporDays, defaulting to 10.");
313+
trafficLightObs = baselTrafficLightMatrix_[10];
314+
}
315+
305316
sr.bounds = QuantExt::stopLightBoundsTabulated(btArgs_->ragLevels_, sr.observations,
306-
hisScenGen_->mporDays(), btArgs_->confidence_);
317+
hisScenGen_->mporDays(), btArgs_->confidence_,
318+
trafficLightObs.observationCount, trafficLightObs.amberLimit, trafficLightObs.redLimit);
307319
} catch (const std::exception& e) {
308320
ALOG("error while retrieving tabulated stop light bounds: " << e.what());
309321
}

OREAnalytics/orea/engine/marketriskbacktest.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,18 @@ class MarketRiskBacktest : public ore::analytics::MarketRiskReport {
8282
//! Post side trade IDs to be considered in the backtest. Other trades' PnLs will be removed from the total PnL
8383
std::set<std::string> postTradeIds_ = {};
8484

85+
const QuantLib::ext::shared_ptr<ore::data::BaselTrafficLightData> baselTrafficLight_;
86+
8587
//! Confidence levels that feed in to defining the stop light bounds
8688
std::vector<QuantLib::Real> ragLevels_ = {0.95, 0.9999};
8789
BacktestArgs(
8890
ore::data::TimePeriod btPeriod, ore::data::TimePeriod bmPeriod,
8991
QuantLib::Real conf = 0.99, QuantLib::Real exThres = 0.01,
9092
bool tdc = false, const std::set<std::string>& callTradeIds = {},
91-
const std::set<std::string>& postTradeIds = {})
93+
const std::set<std::string>& postTradeIds = {}, const QuantLib::ext::shared_ptr<ore::data::BaselTrafficLightData>& baselTrafficLight = nullptr)
9294
: backtestPeriod_(btPeriod), benchmarkPeriod_(bmPeriod),
9395
confidence_(conf), exceptionThreshold_(exThres),
94-
tradeDetailIncludeAllColumns_(tdc), callTradeIds_(callTradeIds), postTradeIds_(postTradeIds) {}
96+
tradeDetailIncludeAllColumns_(tdc), callTradeIds_(callTradeIds), postTradeIds_(postTradeIds), baselTrafficLight_(baselTrafficLight) {}
9597
};
9698

9799
//! Used to pass information
@@ -168,6 +170,8 @@ class MarketRiskBacktest : public ore::analytics::MarketRiskReport {
168170
std::set<std::string> callTradeIds_;
169171
std::set<std::string> postTradeIds_;
170172

173+
std::map<int, ore::data::BaselTrafficLightData::ObservationData> baselTrafficLightMatrix_;
174+
171175
virtual const std::vector<std::tuple<std::string, ore::data::Report::ReportType, QuantLib::Size>> summaryColumns() = 0;
172176
virtual const std::vector<std::tuple<std::string, ore::data::Report::ReportType, QuantLib::Size, bool>> detailColumns() = 0;
173177
virtual const std::vector<std::tuple<std::string, ore::data::Report::ReportType, QuantLib::Size>> pnlColumns() = 0;

OREAnalytics/orea/engine/marketriskreport.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <orea/engine/historicalpnlgenerator.hpp>
3030
#include <orea/engine/riskfilter.hpp>
3131
#include <orea/scenario/scenariofilter.hpp>
32+
#include <ored/configuration/baseltrafficlightconfig.hpp>
3233

3334
#include <vector>
3435

OREData/ored/CMakeLists.txt

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

33
set(OREData_SRC configuration/basecorrelationcurveconfig.cpp
44
configuration/bootstrapconfig.cpp
5+
configuration/baseltrafficlightconfig.cpp
56
configuration/capfloorvolcurveconfig.cpp
67
configuration/cdsvolcurveconfig.cpp
78
configuration/commoditycurveconfig.cpp
@@ -391,6 +392,7 @@ utilities/xmlutils.cpp)
391392

392393
set(OREData_HDR auto_link.hpp
393394
configuration/basecorrelationcurveconfig.hpp
395+
configuration/baseltrafficlightconfig.hpp
394396
configuration/bootstrapconfig.hpp
395397
configuration/capfloorvolcurveconfig.hpp
396398
configuration/cdsvolcurveconfig.hpp
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
Copyright (C) 2021 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 <ored/configuration/baseltrafficlightconfig.hpp>
20+
#include <ored/portfolio/structuredconfigurationwarning.hpp>
21+
#include <ored/utilities/log.hpp>
22+
#include <ored/utilities/parsers.hpp>
23+
#include <ored/utilities/to_string.hpp>
24+
25+
#include <ql/time/date.hpp>
26+
27+
namespace ore {
28+
namespace data {
29+
30+
using namespace QuantLib;
31+
32+
BaselTrafficLightData::BaselTrafficLightData() { clear(); }
33+
BaselTrafficLightData::BaselTrafficLightData(const std::map<int, ObservationData>& baselTrafficLight) :
34+
baselTrafficLight_(baselTrafficLight) {}
35+
36+
void BaselTrafficLightData::clear() {
37+
baselTrafficLight_.clear();
38+
}
39+
/*
40+
<BaselTrafficLightConfig>
41+
<Configuration>
42+
<mporDays>10</mporDays>
43+
<ObservationThresholds>
44+
<ObservationCount>1,2,3,...,6190</ObservationCount>
45+
<AmberLimit>0,0,0,...,89</AmberLimit>
46+
<RedLimit>0,1,2,3...133</RedLimit>
47+
</ObservationThresholds>
48+
</Configuration>
49+
<Configuration>
50+
<mporDays>1</mporDays>
51+
<ObservationThresholds>
52+
<ObservationCount>1,2,3,..,2200</ObservationCount>
53+
<AmberLimit>1,1,1...,30</AmberLimit>
54+
<RedLimit>1,1,...41</RedLimit>
55+
</ObservationThresholds>
56+
</Configuration>
57+
</BaselTrafficLightConfig>
58+
*/
59+
void BaselTrafficLightData::fromXML(XMLNode* node) {
60+
XMLUtils::checkNode(node, "BaselTrafficLightConfig");
61+
for (auto const c : XMLUtils::getChildrenNodes(node, "Configuration")) {
62+
int mporDays = XMLUtils::getChildValueAsInt(c, "mporDays", true);
63+
auto obsThreshold = XMLUtils::getChildNode(c, "ObservationThresholds");
64+
auto observationCount = XMLUtils::getChildNode(obsThreshold, "ObservationCount");
65+
auto amberLimit = XMLUtils::getChildNode(obsThreshold, "AmberLimit");
66+
auto redLimit = XMLUtils::getChildNode(obsThreshold, "RedLimit");
67+
std::vector<int> observationCt = parseListOfValuesAsInt(XMLUtils::getNodeValue(observationCount));
68+
std::vector<int> amberLim = parseListOfValuesAsInt(XMLUtils::getNodeValue(amberLimit));
69+
std::vector<int> redLim = parseListOfValuesAsInt(XMLUtils::getNodeValue(redLimit));
70+
std::transform(amberLim.begin(), amberLim.end(), amberLim.begin(), [](int x) { return x - 1; });
71+
std::transform(redLim.begin(), redLim.end(), redLim.begin(), [](int x) { return x - 1; });
72+
QL_REQUIRE(observationCt.size() == amberLim.size() && amberLim.size() == redLim.size(),
73+
"We must have the same number number of observation and limits.");
74+
baselTrafficLight_[mporDays] = {observationCt, amberLim, redLim};
75+
}
76+
}
77+
78+
XMLNode* BaselTrafficLightData::toXML(XMLDocument& doc) const {
79+
XMLNode* node = doc.allocNode("BaselTrafficLightConfig");
80+
for (const auto& pair : baselTrafficLight_) {
81+
int mporDays = pair.first;
82+
const ObservationData& data = pair.second;
83+
XMLNode* rdNode = XMLUtils::addChild(doc, node, "Configuration");
84+
XMLUtils::addChild(doc, rdNode, "mporDays", std::to_string(mporDays));
85+
XMLNode* oNode = XMLUtils::addChild(doc, rdNode, "ObservationThresholds");
86+
XMLUtils::addGenericChildAsList(doc, oNode, "ObservationCount", data.observationCount);
87+
XMLUtils::addGenericChildAsList(doc, oNode, "AmberLimit", data.amberLimit);
88+
XMLUtils::addGenericChildAsList(doc, oNode, "RedLimit", data.redLimit);
89+
}
90+
91+
return node;
92+
}
93+
94+
} // namespace data
95+
} // namespace ore
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright (C) 2021 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 ored/configuration/iborfallbackconfig.hpp
20+
\brief ibor fallback configuration
21+
\ingroup utilities
22+
*/
23+
24+
#pragma once
25+
26+
#include <ored/utilities/xmlutils.hpp>
27+
28+
namespace ore {
29+
namespace data {
30+
31+
class BaselTrafficLightData : public XMLSerializable {
32+
public:
33+
struct ObservationData {
34+
std::vector<int> observationCount;
35+
std::vector<int> amberLimit;
36+
std::vector<int> redLimit;
37+
};
38+
BaselTrafficLightData();
39+
BaselTrafficLightData(const string& filename) { fromFile(filename); }
40+
BaselTrafficLightData(const std::map<int, ObservationData>& baselTrafficLight);
41+
42+
void clear();
43+
44+
void fromXML(XMLNode* node) override;
45+
XMLNode* toXML(XMLDocument& doc) const override;
46+
47+
std::map<int, ObservationData>& baselTrafficLightData() { return baselTrafficLight_; }
48+
void setbaselTrafficLightData(std::map<int, ObservationData> baselTrafficLight) {
49+
baselTrafficLight_ = baselTrafficLight;
50+
}
51+
52+
private:
53+
std::map<int, ObservationData> baselTrafficLight_;
54+
};
55+
56+
} // namespace data
57+
} // namespace ore

OREData/ored/ored.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#endif
77

88
#include <ored/configuration/basecorrelationcurveconfig.hpp>
9+
#include <ored/configuration/baseltrafficlightconfig.hpp>
910
#include <ored/configuration/bootstrapconfig.hpp>
1011
#include <ored/configuration/capfloorvolcurveconfig.hpp>
1112
#include <ored/configuration/cdsvolcurveconfig.hpp>

0 commit comments

Comments
 (0)