Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
marketriskbacktest.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2023 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#include <qle/math/stoplightbounds.hpp>
29
30using namespace QuantLib;
31using namespace ore::data;
32using namespace ore::analytics;
33
34namespace ore {
35namespace analytics {
36
37const QuantLib::ext::shared_ptr<ore::data::Report>& MarketRiskBacktest::BacktestReports::get(ReportType type) {
38 QL_REQUIRE(types_.size() == reports_.size(), "types and reports must be the same length");
39 auto it = std::find(types_.begin(), types_.end(), type);
40 if (it == types_.end()) {
41 QL_FAIL("Cannot find report");
42 } else {
43 auto index = std::distance(types_.begin(), it);
44 return reports_.at(index);
45 }
46}
47
49 const std::string& calculationCurrency,
50 const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
51 const std::string& portfolioFilter,
52 std::unique_ptr<BacktestArgs> btArgs,
53 std::unique_ptr<SensiRunArgs> sensiArgs,
54 std::unique_ptr<FullRevalArgs> revalArgs,
55 std::unique_ptr<MultiThreadArgs> mtArgs,
56 const ext::shared_ptr<HistoricalScenarioGenerator>& hisScenGen,
57 const bool breakdown,
58 const bool requireTradePnl)
59 : MarketRiskReport(calculationCurrency, portfolio, portfolioFilter, btArgs->backtestPeriod_, hisScenGen, std::move(sensiArgs), std::move(revalArgs),
60 std::move(mtArgs), breakdown, requireTradePnl),
61 btArgs_(std::move(btArgs)) {
62}
63
65 callTradeIds_ = btArgs_->callTradeIds_;
66 postTradeIds_ = btArgs_->postTradeIds_;
67
68 // If there is a mismatch between call and post, then we will have to exclude trade-level PnLs from the total (scenario) PnL
70
72}
73
74
75std::vector<ore::data::TimePeriod> MarketRiskBacktest::timePeriods() {
76 std::vector<TimePeriod> tps{btArgs_->benchmarkPeriod_, btArgs_->backtestPeriod_};
77 return tps;
78}
79
80bool MarketRiskBacktest::runTradeDetail(const ext::shared_ptr<MarketRiskReport::Reports>& reports) {
81 auto rpts = ext::dynamic_pointer_cast<BacktestReports>(reports);
82 bool trdDetail = false;
84 auto detailTrade = rpts->get(BacktestReports::ReportType::DetailTrade);
85 trdDetail = detailTrade != nullptr;
86 }
87 return requireTradePnl_ || trdDetail;
88}
89
90void MarketRiskBacktest::addPnlCalculators(const ext::shared_ptr<MarketRiskReport::Reports>& reports) {
91 pnlCalculators_.push_back(
92 QuantLib::ext::make_shared<PNLCalculator>(btArgs_->benchmarkPeriod_));
93 auto btRpts = ext::dynamic_pointer_cast<BacktestReports>(reports);
94 pnlCalculators_.push_back(
95 QuantLib::ext::make_shared<BacktestPNLCalculator>(btArgs_->backtestPeriod_, writePnl_, this, btRpts));
96}
97
98
99void MarketRiskBacktest::handleSensiResults(const ext::shared_ptr<MarketRiskReport::Reports>& reports,
100 const ext::shared_ptr<MarketRiskGroupBase>& riskGroup,
101 const ext::shared_ptr<TradeGroupBase>& tradeGroup) {
102 QL_REQUIRE(pnlCalculators_.size() == 2, "Expecting 2 PNL Calculators for Backtest");
103 bmSensiPnls_ = pnlCalculators_[0]->pnls();
104 bmFoSensiPnls_ = pnlCalculators_[0]->foPnls();
105 sensiPnls_ = pnlCalculators_[1]->pnls();
106 foSensiPnls_ = pnlCalculators_[1]->foPnls();
107
108 auto backtestPnlCalc = ext::dynamic_pointer_cast < BacktestPNLCalculator>(pnlCalculators_[1]);
109 QL_REQUIRE(backtestPnlCalc, "We must have a BacktestPnLCalculator");
110 if (runTradeDetail(reports)) {
111 foTradePnls_ = backtestPnlCalc->foTradePnls();
112 sensiTradePnls_ = backtestPnlCalc->tradePnls();
113 }
114
115 // Calculate benchmarks
116 calculateBenchmarks(sensiCallBenchmarks_, btArgs_->confidence_, true, riskGroup, tradeIdIdxPairs_);
117 calculateBenchmarks(sensiPostBenchmarks_, btArgs_->confidence_, false, riskGroup, tradeIdIdxPairs_);
118}
119
120void MarketRiskBacktest::handleFullRevalResults(const ext::shared_ptr<MarketRiskReport::Reports>& reports,
121 const ext::shared_ptr<ore::analytics::MarketRiskGroupBase>& riskGroup,
122 const ext::shared_ptr<ore::analytics::TradeGroupBase>& tradeGroup) {
123
124 QL_REQUIRE(histPnlGen_, "Must have a Historical PNL Generator");
125 pnls_ = histPnlGen_->pnl(btArgs_->backtestPeriod_, tradeIdIdxPairs_);
126 bmPnls_ = histPnlGen_->pnl(btArgs_->benchmarkPeriod_, tradeIdIdxPairs_);
127
128 if (runTradeDetail(reports))
129 tradePnls_ = histPnlGen_->tradeLevelPnl(btArgs_->backtestPeriod_, tradeIdIdxPairs_);
130
132
135}
136
137void MarketRiskBacktest::writeReports(const QuantLib::ext::shared_ptr<MarketRiskReport::Reports>& reports,
138 const ext::shared_ptr<ore::analytics::MarketRiskGroupBase>& riskGroup,
139 const ext::shared_ptr<ore::analytics::TradeGroupBase>& tradeGroup) {
140
141 // Data for the current backtest
142 std::string cpty = tradeIdIdxPairs_.empty() ? "INVALID" : counterparty(tradeIdIdxPairs_.begin()->first);
143 Data data = {cpty, tradeGroup, riskGroup};
144
145 auto backtestRpts = ext::dynamic_pointer_cast<BacktestReports>(reports);
146 QL_REQUIRE(backtestRpts, "We must have backtest reports");
147
148 SummaryResults srSensi;
149 bool runSensi = sensiPnls_.size() > 0;
150 if (runSensi)
151 // Give back summary results for sensitivity backtest
152 srSensi = calculateSummary(backtestRpts, data, false, sensiPnls_, tradeIds_, sensiTradePnls_);
153
154 if (runFullReval(riskGroup)) {
155 // Give back summary results for full revaluation backtest
156 SummaryResults srFull = calculateSummary(backtestRpts, data, true, pnls_, tradeIds_, tradePnls_);
157
158 // Write the rows in the summary report
159 addSummaryRow(backtestRpts, data, true, srFull.callValue, srFull.observations, true, srFull.callExceptions,
161 addSummaryRow(backtestRpts, data, false, srFull.postValue, srFull.observations, true, srFull.postExceptions,
163 }
164
165 if (runSensi) {
166 addSummaryRow(backtestRpts, data, true, srSensi.callValue, srSensi.observations, false, srSensi.callExceptions,
168 addSummaryRow(backtestRpts, data, false, srSensi.postValue, srSensi.observations, false, srSensi.postExceptions,
170 }
171}
172
173bool MarketRiskBacktest::disablesAll(const QuantLib::ext::shared_ptr<ScenarioFilter>& filter) const {
174 // Return false if we hit any risk factor that is "allowed" i.e. enabled
175 for (const auto& key : hisScenGen_->baseScenario()->keys()) {
176 if (filter->allow(key)) {
177 return false;
178 }
179 }
180 // If we get to here, all risk factors are "not allowed" i.e. disabled
181 return true;
182}
183
185 const ext::shared_ptr<BacktestReports>& reports, const Data& data, bool isFull, const vector<Real>& pnls,
186 const vector<string>& tradeIds, const PNLCalculator::TradePnLStore& tradePnls) {
187
188 SummaryResults sr = {pnls.size(), 0.0, 0, 0.0, 0, {}};
189
191 sr.postValue = postValue(data);
192
193 auto pnlScenDates = hisScenGen_->filteredScenarioDates(btArgs_->backtestPeriod_);
194 QL_REQUIRE(pnlScenDates.size() == pnls.size(), "Backtest::calculateSummary(): internal error, pnlScenDates ("
195 << pnlScenDates.size() << ") do not match pnls (" << pnls.size()
196 << ")");
197
198 // If a trade level backtest detail report has been requested.
199 bool detailTrd = runTradeDetail(reports);
200 if (detailTrd)
201 QL_REQUIRE(pnls.size() == tradePnls.size(), "For trade level backtest detail report,"
202 << " expect the number of aggregate P&Ls (" << pnls.size()
203 << ") to equal the number"
204 << " of trade P&Ls (" << tradePnls.size() << ").");
205
206 // List of trades to exclude in the PnL calcs.
207 // This would happen when a trade is under a winning reg in the call side but not on the post side, or vice versa.
208 vector<Size> callTradesToSkip;
209 vector<Size> postTradesToSkip;
210 if (requireTradePnl_) {
211 for (Size t = 0; t < tradeIds.size(); t++) {
212 const string& tid = tradeIds[t];
213 if (callTradeIds_.find(tid) == callTradeIds_.end())
214 callTradesToSkip.push_back(t);
215 if (postTradeIds_.find(tid) == postTradeIds_.end())
216 postTradesToSkip.push_back(t);
217 }
218 }
219
220 Real callScenPnl;
221 Real postScenPnl;
222 vector<Real> scenTradePnls;
223 string cPassFail;
224 string pPassFail;
225 for (Size i = 0; i < pnls.size(); i++) {
226 const auto& start = pnlScenDates[i].first;
227 const auto& end = pnlScenDates[i].second;
228
229 // Deal with call and write report row
230 callScenPnl = pnls[i];
231 if (!callTradesToSkip.empty()) {
232 scenTradePnls = tradePnls[i];
233 for (const Size& t : callTradesToSkip) {
234 callScenPnl -= scenTradePnls[t];
235 }
236 }
237 if (callScenPnl > std::max(sr.callValue, btArgs_->exceptionThreshold_))
238 sr.callExceptions++;
239
240 cPassFail = callScenPnl > std::max(sr.callValue, btArgs_->exceptionThreshold_) ? "fail" : "pass";
241 addDetailRow(reports, data, true, sr.callValue, start, end, isFull, callScenPnl, cPassFail);
242
243 // Deal with post and write report row
244 postScenPnl = pnls[i];
245 if (!postTradesToSkip.empty()) {
246 scenTradePnls = tradePnls[i];
247 for (const Size& t : postTradesToSkip) {
248 postScenPnl -= scenTradePnls[t];
249 }
250 }
251 if (-postScenPnl > std::max(sr.postValue, btArgs_->exceptionThreshold_))
252 sr.postExceptions++;
253 pPassFail = -postScenPnl > std::max(sr.postValue, btArgs_->exceptionThreshold_) ? "fail" : "pass";
254 addDetailRow(reports, data, false, sr.postValue, start, end, isFull, -postScenPnl, pPassFail);
255
256 // Add the trade level breakdown if requested. Note that we are clearly not recomputing the IM for the
257 // trade - all we are doing is adding the P&L for each trade and the trade ID.
258 if (detailTrd && !data.tradeGroup->allLevel()) {
259 const auto& scenTradePnls = tradePnls[i];
260 QL_REQUIRE(tradeIds.size() == scenTradePnls.size(), "For trade level backtest detail report,"
261 << " the number of trades (" << tradeIds.size()
262 << ") does not equal the size of the trade level P&L"
263 << " container (" << scenTradePnls.size()
264 << ") on scenario date " << io::iso_date(start)
265 << ".");
266 for (Size j = 0; j < scenTradePnls.size(); ++j) {
267 if (std::find(callTradesToSkip.begin(), callTradesToSkip.end(), j) == callTradesToSkip.end())
268 addDetailRow(reports, data, true, sr.callValue, start, end, isFull, scenTradePnls[j], cPassFail, tradeIds[j]);
269 if (std::find(postTradesToSkip.begin(), postTradesToSkip.end(), j) == postTradesToSkip.end())
270 addDetailRow(reports, data, false, sr.postValue, start, end, isFull, -scenTradePnls[j], pPassFail, tradeIds[j]);
271 }
272 }
273 }
274
275 LOG("Got " << sr.callExceptions << " Call exceptions from " << sr.observations << " observations.");
276 LOG("Got " << sr.postExceptions << " Post exceptions from " << sr.observations << " observations.");
277
278 // Now calculate the [red, amber] and [amber, green] bounds
279 if (hisScenGen_->mporDays() != 10) {
280 ALOG("SimmBacktest: MPOR days is " << hisScenGen_->mporDays());
281 } else {
282 sr.bounds = hisScenGen_->overlapping() ? QuantExt::stopLightBoundsTabulated(btArgs_->ragLevels_, sr.observations,
283 hisScenGen_->mporDays(), btArgs_->confidence_)
284 : QuantExt::stopLightBounds(btArgs_->ragLevels_, sr.observations, btArgs_->confidence_);
285 }
286
287 return sr;
288}
289
290void MarketRiskBacktest::createReports(const ext::shared_ptr<MarketRiskReport::Reports>& reports) {
291
292 auto rpts = ext::dynamic_pointer_cast<BacktestReports>(reports);
293 QL_REQUIRE(rpts, "Reports must be of type BacktestReports");
294
296 auto summary = rpts->get(BacktestReports::ReportType::Summary);
297 if (summary) {
298 for (const auto& t : summaryColumns())
299 summary->addColumn(std::get<0>(t), std::get<1>(t), std::get<2>(t));
300 }
301 }
302
304 auto detail = rpts->get(BacktestReports::ReportType::Detail);
305 if (detail) {
306 for (const auto& t : detailColumns())
307 detail->addColumn(std::get<0>(t), std::get<1>(t), std::get<2>(t));
308 }
309 }
310
312 auto detailTrade = rpts->get(BacktestReports::ReportType::DetailTrade);
313 if (detailTrade) {
314 detailTrade->addColumn("TradeId", string());
315 for (const auto& t : detailColumns()) {
316 if (btArgs_->tradeDetailIncludeAllColumns_ || std::get<3>(t))
317 detailTrade->addColumn(std::get<0>(t), std::get<1>(t), std::get<2>(t));
318 }
319 }
320 }
321
324 if (pnl) {
325 for (const auto& t : pnlColumns())
326 pnl->addColumn(std::get<0>(t), std::get<1>(t), std::get<2>(t));
327 }
328 }
329
331 auto pnlTrade = rpts->get(BacktestReports::ReportType::PnlContributionTrade);
332 if (pnlTrade) {
333 pnlTrade->addColumn("TradeId", string());
334 for (const auto& t : pnlColumns())
335 pnlTrade->addColumn(std::get<0>(t), std::get<1>(t), std::get<2>(t));
336 }
337 }
338}
339
341 VarBenchmarks& benchmarks, Real confidence, const bool isCall,
342 const QuantLib::ext::shared_ptr<MarketRiskGroupBase>& riskGroup,
343 std::set<std::pair<std::string, QuantLib::Size>>&
344 tradeIdIdxPairs) {
345 for (auto& [type, value] : benchmarks) {
346 if (value.first)
347 value.second = value.first->var(confidence, isCall, tradeIdIdxPairs);
348 }
349}
350
351void MarketRiskBacktest::reset(const QuantLib::ext::shared_ptr<MarketRiskGroupBase>& riskGroup) {
352 MarketRiskReport::reset(riskGroup);
353 bmSensiPnls_.clear();
354 pnls_.clear();
355 bmPnls_.clear();
356 foSensiPnls_.clear();
357 bmFoSensiPnls_.clear();
358 sensiPnls_.clear();
359 tradePnls_.clear();
360 sensiTradePnls_.clear();
361 foTradePnls_.clear();
362 for (auto& [type, value] : sensiCallBenchmarks_)
363 value.second = 0.0;
364 for (auto& [type, value] : sensiPostBenchmarks_)
365 value.second = 0.0;
366 for (auto& [type, value] : fullRevalCallBenchmarks_)
367 value.second = 0.0;
368 for (auto& [type, value] : fullRevalPostBenchmarks_)
369 value.second = 0.0;
370}
371
372void MarketRiskBacktest::addPnlRow(const QuantLib::ext::shared_ptr<BacktestReports>& reports, Size scenarioIdx,
373 bool isCall, const RiskFactorKey& key_1, Real shift_1, Real delta, Real gamma, Real deltaPnl, Real gammaPnl,
374 const RiskFactorKey& key_2, Real shift_2, const string& tradeId, const string& currency, Real fxSpot) {
375
376 // Do we have a report to write to?
377 // Is this too slow to do on every call to addPnlRow? Need to find the report each time in any case.
378 QuantLib::ext::shared_ptr<ore::data::Report> rpt;
379 if (tradeId.empty()) {
382 } else {
385 }
386
387 // If we have no report or below threshold, do nothing.
388 if (!rpt ||
389 (std::abs(deltaPnl) < sensiArgs_->pnlWriteThreshold_ && std::abs(gammaPnl) < sensiArgs_->pnlWriteThreshold_))
390 return;
391
392 // Add the trade ID if we are writing trade level entries.
393 auto& report = tradeId.empty() ? rpt->next() : rpt->next().add(tradeId);
394
395 // Add the fields common to the trade level and aggregate reports.
396 report.add(hisScenGen_->startDates()[scenarioIdx])
397 .add(hisScenGen_->endDates()[scenarioIdx])
398 .add(isCall ? "call" : "post")
399 .add(to_string(key_1))
400 .add(to_string(key_2))
401 .add(delta)
402 .add(gamma)
403 .add(shift_1)
404 .add(shift_2)
405 .add(currency.empty() || currency == calculationCurrency_ ? deltaPnl : deltaPnl / fxSpot)
406 .add(currency.empty() || currency == calculationCurrency_ ? gammaPnl : gammaPnl / fxSpot)
407 .add(currency.empty() ? calculationCurrency_ : currency);
408}
409
410void BacktestPNLCalculator::writePNL(Size scenarioIdx, bool isCall, const RiskFactorKey& key_1, Real shift_1,
411 Real delta, Real gamma, Real deltaPnl, Real gammaPnl,
412 const RiskFactorKey& key_2, Real shift_2, const string& tradeId) {
413 if (writePnl_)
414 backtest_->addPnlRow(reports_, scenarioIdx, isCall, key_1, shift_1, delta, gamma, deltaPnl, gammaPnl, key_2, shift_2,
415 tradeId);
416}
417
418} // namespace analytics
419} // namespace ore
QuantLib::ext::shared_ptr< MarketRiskBacktest::BacktestReports > reports_
void writePNL(QuantLib::Size scenarioIdx, bool isCall, const RiskFactorKey &key_1, QuantLib::Real shift_1, QuantLib::Real delta, QuantLib::Real gamma, QuantLib::Real deltaPnl, QuantLib::Real gammaPnl, const RiskFactorKey &key_2=RiskFactorKey(), QuantLib::Real shift_2=0.0, const std::string &tradeId="") override
const QuantLib::ext::shared_ptr< ore::data::Report > & get(ReportType type)
ReportType
Report types that can be populated during a SIMM backtest.
ore::analytics::TradePnLStore tradePnls_
std::vector< QuantLib::Real > pnls_
bool disablesAll(const QuantLib::ext::shared_ptr< ore::analytics::ScenarioFilter > &filter) const override
virtual void addSummaryRow(const QuantLib::ext::shared_ptr< BacktestReports > &reports, const Data &data, bool isCall, QuantLib::Real im, QuantLib::Size observations, bool isFull, QuantLib::Size exceptions, const std::vector< QuantLib::Size > &ragBounds, const VarBenchmarks &sensiBenchmarks, const VarBenchmarks &fullBenchmarks) const =0
Add a row to the summary report.
ore::analytics::TradePnLStore sensiTradePnls_
virtual const std::vector< std::tuple< std::string, ore::data::Report::ReportType, QuantLib::Size, bool > > detailColumns()=0
virtual bool runTradeDetail(const QuantLib::ext::shared_ptr< MarketRiskReport::Reports > &reports) override
std::vector< ore::data::TimePeriod > timePeriods() override
virtual void calculateBenchmarks(VarBenchmarks &benchmarks, QuantLib::Real confidence, const bool isCall, const QuantLib::ext::shared_ptr< ore::analytics::MarketRiskGroupBase > &riskGroup, std::set< std::pair< std::string, QuantLib::Size > > &tradeIdIdxPairs)
Calculate and update the benchmarks.
std::vector< QuantLib::Real > sensiPnls_
virtual void reset(const QuantLib::ext::shared_ptr< ore::analytics::MarketRiskGroupBase > &riskGroup) override
void writeReports(const QuantLib::ext::shared_ptr< MarketRiskReport::Reports > &reports, const QuantLib::ext::shared_ptr< ore::analytics::MarketRiskGroupBase > &riskGroup, const QuantLib::ext::shared_ptr< ore::analytics::TradeGroupBase > &tradeGroup) override
ore::analytics::TradePnLStore foTradePnls_
SummaryResults calculateSummary(const QuantLib::ext::shared_ptr< BacktestReports > &reports, const Data &data, bool isFull, const std::vector< QuantLib::Real > &pnls, const std::vector< std::string > &tradeIds, const TradePnLStore &tradePnls)
void createReports(const QuantLib::ext::shared_ptr< MarketRiskReport::Reports > &reports) override
virtual QuantLib::Real postValue(const Data &data)=0
std::vector< QuantLib::Real > bmPnls_
std::map< VarType, std::pair< QuantLib::ext::shared_ptr< ore::analytics::VarCalculator >, QuantLib::Real > > VarBenchmarks
pointers to the VAR benchmarks
std::vector< QuantLib::Real > foSensiPnls_
virtual QuantLib::Real callValue(const Data &data)=0
void addPnlCalculators(const QuantLib::ext::shared_ptr< MarketRiskReport::Reports > &reports) override
virtual std::string counterparty(const std::string &tradeId) const =0
virtual void addDetailRow(const QuantLib::ext::shared_ptr< BacktestReports > &reports, const Data &data, bool isCall, QuantLib::Real im, const QuantLib::Date &start, const QuantLib::Date &end, bool isFull, QuantLib::Real pnl, const std::string &result, const std::string &tradeId="") const =0
Add a row to the detail report.
virtual const std::vector< std::tuple< std::string, ore::data::Report::ReportType, QuantLib::Size > > pnlColumns()=0
virtual void adjustFullRevalPnls(std::vector< QuantLib::Real > &pnls, std::vector< QuantLib::Real > &bmPnls, ore::analytics::TradePnLStore &tradePnls, const std::vector< QuantLib::Real > &foSensiPnls, const std::vector< QuantLib::Real > &bmFoSensiPnls, const ore::analytics::TradePnLStore &foTradePnls, const QuantLib::ext::shared_ptr< ore::analytics::MarketRiskGroupBase > &riskGroup)
std::vector< QuantLib::Real > bmFoSensiPnls_
void handleSensiResults(const QuantLib::ext::shared_ptr< MarketRiskReport::Reports > &reports, const QuantLib::ext::shared_ptr< ore::analytics::MarketRiskGroupBase > &riskGroup, const QuantLib::ext::shared_ptr< ore::analytics::TradeGroupBase > &tradeGroup) override
virtual void addPnlRow(const QuantLib::ext::shared_ptr< BacktestReports > &reports, QuantLib::Size scenarioIdx, bool isCall, const ore::analytics::RiskFactorKey &key_1, QuantLib::Real shift_1, QuantLib::Real delta, QuantLib::Real gamma, QuantLib::Real deltaPnl, QuantLib::Real gammaPnl, const ore::analytics::RiskFactorKey &key_2=ore::analytics::RiskFactorKey(), QuantLib::Real shift_2=0.0, const std::string &tradeId="", const std::string &currency="", QuantLib::Real fxSpot=1.0)
Add a row to the P&L contribution report.
std::vector< QuantLib::Real > bmSensiPnls_
variables for benchmark calculations
void handleFullRevalResults(const QuantLib::ext::shared_ptr< MarketRiskReport::Reports > &reports, const QuantLib::ext::shared_ptr< ore::analytics::MarketRiskGroupBase > &riskGroup, const QuantLib::ext::shared_ptr< ore::analytics::TradeGroupBase > &tradeGroup) override
std::unique_ptr< BacktestArgs > btArgs_
MarketRiskBacktest(const std::string &calculationCurrency, const QuantLib::ext::shared_ptr< ore::data::Portfolio > &portfolio, const std::string &portfolioFilter, std::unique_ptr< BacktestArgs > btArgs, std::unique_ptr< SensiRunArgs > sensiArgs=nullptr, std::unique_ptr< FullRevalArgs > revalArgs=nullptr, std::unique_ptr< MultiThreadArgs > mtArgs=nullptr, const QuantLib::ext::shared_ptr< ore::analytics::HistoricalScenarioGenerator > &hisScenGen=nullptr, const bool breakdown=false, const bool requireTradePnl=false)
virtual const std::vector< std::tuple< std::string, ore::data::Report::ReportType, QuantLib::Size > > summaryColumns()=0
std::vector< QuantLib::ext::shared_ptr< ore::data::Report > > reports_
std::vector< QuantLib::ext::shared_ptr< PNLCalculator > > pnlCalculators_
QuantLib::ext::shared_ptr< HistoricalScenarioGenerator > hisScenGen_
std::vector< std::string > tradeIds_
virtual bool runFullReval(const QuantLib::ext::shared_ptr< MarketRiskGroupBase > &riskGroup) const
std::set< std::pair< std::string, QuantLib::Size > > tradeIdIdxPairs_
virtual void reset(const QuantLib::ext::shared_ptr< MarketRiskGroupBase > &riskGroup)
std::unique_ptr< SensiRunArgs > sensiArgs_
QuantLib::ext::shared_ptr< ore::analytics::HistoricalPnlGenerator > histPnlGen_
std::vector< std::vector< QuantLib::Real > > TradePnLStore
Data types stored in the scenario class.
Definition: scenario.hpp:48
SafeStack< ValueType > value
SafeStack< Filter > filter
A Class to write a cube out to file.
scenario generator that builds from historical shifts
Class for generating sensi pnl.
A cube implementation that stores the cube in memory.
data
#define LOG(text)
#define ALOG(text)
bace class for all market risk backtests
std::string to_string(const LocationInfo &l)
Class for aggregating SensitivityRecords.
Used to store results for writing rows in the summary report.