Skip to content

Commit 7371b46

Browse files
damienbarkerjenkins
authored andcommitted
QPR-9793 restore regression tests
1 parent ad6e3e2 commit 7371b46

8 files changed

Lines changed: 193 additions & 21 deletions

File tree

OREAnalytics/orea/app/analytics/varanalytic.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ void ParametricVarAnalyticImpl::setVarReport(const QuantLib::ext::shared_ptr<ore
107107
adjFactors = boost::make_shared<ore::data::AdjustmentFactors>(adjLoader->adjustmentFactors());
108108

109109
auto scenarios = buildHistoricalScenarioGenerator(inputs_->historicalScenarioReader(), adjFactors,
110-
benchmarkVarPeriod, inputs_->mporCalendar(),
111-
inputs_->mporDays(), inputs_->mporOverlappingPeriods());
110+
benchmarkVarPeriod, inputs_->mporCalendar(), inputs_->mporDays(), analytic()->configurations().simMarketParams,
111+
analytic()->configurations().todaysMarketParams, inputs_->mporOverlappingPeriods());
112112

113113
auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(
114114
analytic()->market(), analytic()->configurations().simMarketParams, Market::defaultConfiguration,
@@ -146,8 +146,9 @@ void HistoricalSimulationVarAnalyticImpl::setVarReport(
146146
adjFactors = boost::make_shared<ore::data::AdjustmentFactors>(adjLoader->adjustmentFactors());
147147

148148
auto scenarios =
149-
buildHistoricalScenarioGenerator(inputs_->historicalScenarioReader(), adjFactors, benchmarkVarPeriod,
150-
inputs_->mporCalendar(), inputs_->mporDays(), inputs_->mporOverlappingPeriods());
149+
buildHistoricalScenarioGenerator(inputs_->historicalScenarioReader(), adjFactors, benchmarkVarPeriod, inputs_->mporCalendar(),
150+
inputs_->mporDays(), analytic()->configurations().simMarketParams,
151+
analytic()->configurations().todaysMarketParams, inputs_->mporOverlappingPeriods());
151152

152153
auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(
153154
analytic()->market(), analytic()->configurations().simMarketParams, Market::defaultConfiguration,

OREAnalytics/orea/app/reportwriter.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <orea/app/reportwriter.hpp>
2222
#include <orea/app/structuredanalyticserror.hpp>
2323
#include <orea/simm/utilities.hpp>
24+
#include <orea/scenario/scenariowriter.hpp>
2425

2526
#include <ored/utilities/marketdata.hpp>
2627
#include <ored/portfolio/structuredtradeerror.hpp>
@@ -2000,5 +2001,142 @@ void ReportWriter::writeScenarioDistributions(const boost::shared_ptr<ScenarioGe
20002001
report.end();
20012002
}
20022003

2004+
void ReportWriter::writeHistoricalScenarioDetails(
2005+
const boost::shared_ptr<ore::analytics::HistoricalScenarioGenerator>& generator, ore::data::Report& report) {
2006+
2007+
report.addColumn("PLDate1", Date())
2008+
.addColumn("PLDate2", Date())
2009+
.addColumn("Key", string())
2010+
.addColumn("BaseValue", double(), 8)
2011+
.addColumn("AdjustmentFactor1", double(), 8)
2012+
.addColumn("AdjustmentFactor2", double(), 8)
2013+
.addColumn("ScenarioValue1", double(), 8)
2014+
.addColumn("ScenarioValue2", double(), 8)
2015+
.addColumn("ShiftType", string())
2016+
.addColumn("Return", double(), 8)
2017+
.addColumn("ScenarioValue", double(), 8);
2018+
2019+
Date asof = generator->baseScenario()->asof();
2020+
for (Size i = 0; i < generator->startDates().size(); ++i) {
2021+
std::ignore = generator->next(asof);
2022+
for (auto const& d : generator->lastHistoricalScenarioCalculationDetails()) {
2023+
report.next()
2024+
.add(d.scenarioDate1)
2025+
.add(d.scenarioDate2)
2026+
.add(ore::data::to_string(d.key))
2027+
.add(d.baseValue)
2028+
.add(d.adjustmentFactor1)
2029+
.add(d.adjustmentFactor2)
2030+
.add(d.scenarioValue1)
2031+
.add(d.scenarioValue2)
2032+
.add(ore::data::to_string(d.returnType))
2033+
.add(d.returnValue)
2034+
.add(d.scenarioValue);
2035+
}
2036+
}
2037+
report.end();
2038+
}
2039+
2040+
void ReportWriter::writeStockSplitReport(const boost::shared_ptr<Scenario>& baseScenario,
2041+
const boost::shared_ptr<ore::analytics::HistoricalScenarioLoader>& hsloader,
2042+
const boost::shared_ptr<ore::data::AdjustmentFactors>& adjFactors,
2043+
const boost::shared_ptr<ore::data::Report>& report) {
2044+
2045+
report->addColumn("EquityId", string())
2046+
.addColumn("Date", Date())
2047+
.addColumn("Price", double(), 8)
2048+
.addColumn("Factor", double(), 8)
2049+
.addColumn("CumulatedFactor", double(), 8)
2050+
.addColumn("AdjustedPrice", double(), 8);
2051+
2052+
if (adjFactors) {
2053+
std::set<std::string> names;
2054+
for (auto const& k : baseScenario->keys()) {
2055+
if (k.keytype == RiskFactorKey::KeyType::EquitySpot) {
2056+
names.insert(k.name);
2057+
}
2058+
}
2059+
2060+
std::vector<QuantLib::Date> hsdates = hsloader->dates();
2061+
2062+
for (auto const& name : names) {
2063+
2064+
std::set<QuantLib::Date> dates = adjFactors->dates(name);
2065+
dates.insert(hsdates.begin(), hsdates.end());
2066+
2067+
for (auto const& d : dates) {
2068+
2069+
Real price = Null<Real>();
2070+
if (std::find(hsdates.begin(), hsdates.end(), d) != hsdates.end()) {
2071+
auto scen = hsloader->getHistoricalScenario(d);
2072+
RiskFactorKey rf(RiskFactorKey::KeyType::EquitySpot, name);
2073+
if (scen->has(rf))
2074+
price = scen->get(rf);
2075+
}
2076+
Real factor = adjFactors->getFactorContribution(name, d);
2077+
Real cumFactor = adjFactors->getFactor(name, d);
2078+
Real adjPrice = price == Null<Real>() ? Null<Real>() : price * cumFactor;
2079+
2080+
report->next().add(name).add(d).add(price).add(factor).add(cumFactor).add(adjPrice);
2081+
}
2082+
}
2083+
}
2084+
report->end();
2085+
}
2086+
2087+
void ReportWriter::writeHistoricalScenarioDistributions(
2088+
boost::shared_ptr<HistoricalScenarioGenerator>& hsgen,
2089+
const boost::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
2090+
const boost::shared_ptr<ore::analytics::ScenarioSimMarketParameters>& simMarketParams,
2091+
boost::shared_ptr<ore::data::Report> histScenDetailsReport, boost::shared_ptr<ore::data::Report> statReport,
2092+
boost::shared_ptr<ore::data::Report> distReport, Size distSteps) {
2093+
2094+
// Don't leave it up to the caller to do this
2095+
simMarket->scenarioGenerator() = hsgen;
2096+
hsgen->baseScenario() = simMarket->baseScenario();
2097+
2098+
// If both report pointers are null, return early
2099+
if (!statReport && !distReport)
2100+
return;
2101+
2102+
// Make a transformed generator i.e. discount -> zero etc.
2103+
auto hsgent = boost::make_shared<HistoricalScenarioGeneratorTransform>(hsgen, simMarket, simMarketParams);
2104+
2105+
const vector<RiskFactorKey>& keys = hsgen->baseScenario()->keys();
2106+
Size numScen = hsgen->numScenarios();
2107+
Date asof = hsgen->baseScenario()->asof();
2108+
2109+
// Write the statistics report if requested
2110+
if (statReport) {
2111+
hsgent->reset();
2112+
writeScenarioStatistics(hsgent, keys, numScen, {asof}, *statReport);
2113+
}
2114+
2115+
// Write the distribution report if requested
2116+
if (distReport) {
2117+
QL_REQUIRE(distSteps != Null<Size>(),
2118+
"When creating a distribution report, a valid distribution step size is required");
2119+
hsgent->reset();
2120+
writeScenarioDistributions(hsgent, keys, numScen, {asof}, distSteps, *distReport);
2121+
}
2122+
2123+
// Write the scenario report if requested
2124+
if (histScenDetailsReport) {
2125+
hsgent->reset();
2126+
writeHistoricalScenarioDetails(hsgent, *histScenDetailsReport);
2127+
}
2128+
}
2129+
2130+
void ReportWriter::writeHistoricalScenarios(const boost::shared_ptr<HistoricalScenarioLoader>& hsloader,
2131+
const boost::shared_ptr<ore::data::Report>& report) {
2132+
ScenarioWriter sw(nullptr, report);
2133+
auto scenarios = hsloader->historicalScenarios();
2134+
bool writeHeader = true;
2135+
for (const auto& s : scenarios) {
2136+
sw.writeScenario(s, writeHeader);
2137+
writeHeader = false;
2138+
}
2139+
}
2140+
20032141
} // namespace analytics
20042142
} // namespace ore

OREAnalytics/orea/app/reportwriter.hpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,25 @@ class ReportWriter {
166166
QuantLib::Size numPaths, const std::vector<QuantLib::Date>& dates,
167167
QuantLib::Size distSteps, ore::data::Report& report);
168168

169+
virtual void
170+
writeHistoricalScenarioDetails(const boost::shared_ptr<ore::analytics::HistoricalScenarioGenerator>& generator,
171+
ore::data::Report& report);
172+
173+
virtual void writeStockSplitReport(const boost::shared_ptr<ore::analytics::Scenario>& baseScenario,
174+
const boost::shared_ptr<ore::analytics::HistoricalScenarioLoader>& hsloader,
175+
const boost::shared_ptr<ore::data::AdjustmentFactors>& adjFactors,
176+
const boost::shared_ptr<ore::data::Report>& report);
177+
178+
void writeHistoricalScenarios(const boost::shared_ptr<HistoricalScenarioLoader>& hsloader,
179+
const boost::shared_ptr<ore::data::Report>& report);
180+
181+
void writeHistoricalScenarioDistributions(
182+
boost::shared_ptr<HistoricalScenarioGenerator>& hsgen,
183+
const boost::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket,
184+
const boost::shared_ptr<ore::analytics::ScenarioSimMarketParameters>& simMarketParams,
185+
boost::shared_ptr<ore::data::Report> histScenDetailsReport, boost::shared_ptr<ore::data::Report> statReport,
186+
boost::shared_ptr<ore::data::Report> distReport, QuantLib::Size distSteps = Null<Size>());
187+
169188
protected:
170189
std::string nullString_;
171190
void addMarketDatum(ore::data::Report& report, const ore::data::MarketDatum& md,

OREAnalytics/orea/scenario/historicalscenariogenerator.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ void HistoricalScenarioGeneratorWithFilteredDates::reset() {
470470
i_orig_ = 0;
471471
}
472472

473-
boost::shared_ptr<Scenario> HistoricalScenarioGeneratorWithFilteredDates::next(const Date& d) {
473+
QuantLib::ext::shared_ptr<Scenario> HistoricalScenarioGeneratorWithFilteredDates::next(const Date& d) {
474474
while (i_orig_ < gen_->numScenarios() && !isRelevantScenario_[i_orig_]) {
475475
gen_->next(d);
476476
++i_orig_;
@@ -482,9 +482,13 @@ boost::shared_ptr<Scenario> HistoricalScenarioGeneratorWithFilteredDates::next(c
482482
}
483483

484484
QuantLib::ext::shared_ptr<HistoricalScenarioGenerator> buildHistoricalScenarioGenerator(
485-
const boost::shared_ptr<HistoricalScenarioReader>& hsr,
486-
const QuantLib::ext::shared_ptr<ore::data::AdjustmentFactors>& adjFactors,
487-
const TimePeriod& period, Calendar calendar, Size mporDays, const bool overlapping) {
485+
const QuantLib::ext::shared_ptr<HistoricalScenarioReader>& hsr,
486+
const QuantLib::ext::shared_ptr<ore::data::AdjustmentFactors>& adjFactors, const TimePeriod& period,
487+
Calendar calendar, Size mporDays,
488+
const QuantLib::ext::shared_ptr<ScenarioSimMarketParameters>& simParams,
489+
const QuantLib::ext::shared_ptr<TodaysMarketParameters>& marketParams, const bool overlapping) {
490+
491+
hsr->load(simParams, marketParams);
488492

489493
auto scenarioFactory = boost::make_shared<SimpleScenarioFactory>();
490494

OREAnalytics/orea/scenario/historicalscenariogenerator.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -274,20 +274,22 @@ class HistoricalScenarioGeneratorTransform : public HistoricalScenarioGenerator
274274
class HistoricalScenarioGeneratorWithFilteredDates : public HistoricalScenarioGenerator {
275275
public:
276276
HistoricalScenarioGeneratorWithFilteredDates(const std::vector<ore::data::TimePeriod>& filter,
277-
const boost::shared_ptr<HistoricalScenarioGenerator>& gen);
277+
const QuantLib::ext::shared_ptr<HistoricalScenarioGenerator>& gen);
278278
void reset() override;
279-
boost::shared_ptr<Scenario> next(const QuantLib::Date& d) override;
279+
QuantLib::ext::shared_ptr<Scenario> next(const QuantLib::Date& d) override;
280280

281281
private:
282-
boost::shared_ptr<HistoricalScenarioGenerator> gen_;
282+
QuantLib::ext::shared_ptr<HistoricalScenarioGenerator> gen_;
283283
std::vector<bool> isRelevantScenario_;
284284
QuantLib::Size i_orig_;
285285
};
286286

287287
QuantLib::ext::shared_ptr<HistoricalScenarioGenerator> buildHistoricalScenarioGenerator(
288288
const QuantLib::ext::shared_ptr<HistoricalScenarioReader>& hsr,
289-
const QuantLib::ext::shared_ptr<ore::data::AdjustmentFactors>& adjFactors,
290-
const TimePeriod& period, Calendar calendar, Size mporDays,
289+
const QuantLib::ext::shared_ptr<ore::data::AdjustmentFactors>& adjFactors, const TimePeriod& period,
290+
Calendar calendar, Size mporDays,
291+
const QuantLib::ext::shared_ptr<ScenarioSimMarketParameters>& simParams,
292+
const QuantLib::ext::shared_ptr<TodaysMarketParameters>& marketParam,
291293
const bool overlapping = true);
292294

293295
} // namespace analytics

OREAnalytics/orea/scenario/historicalscenarioreader.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#pragma once
2525

2626
#include <orea/scenario/scenario.hpp>
27+
#include <orea/scenario/scenariosimmarketparameters.hpp>
28+
#include <ored/marketdata/todaysmarketparameters.hpp>
2729

2830
namespace ore {
2931
namespace analytics {
@@ -39,6 +41,12 @@ class HistoricalScenarioReader {
3941
virtual QuantLib::Date date() const = 0;
4042
//! Return the current scenario if reader is still valid and `nullptr` otherwise
4143
virtual boost::shared_ptr<ore::analytics::Scenario> scenario() const = 0;
44+
// load the scenarios
45+
virtual void load(
46+
//! Simulation parameters - to provide list of curves to request
47+
const boost::shared_ptr<ore::analytics::ScenarioSimMarketParameters>& simParams,
48+
//! Todays market params to provide the discount curves
49+
const boost::shared_ptr<ore::data::TodaysMarketParameters>& marketParams){};
4250
};
4351

4452
} // namespace analytics

OREAnalytics/orea/scenario/scenariowriter.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ ScenarioWriter::ScenarioWriter(const std::string& filename, const char sep, cons
3535
open(filename, filemode);
3636
}
3737

38-
ScenarioWriter::ScenarioWriter(const boost::shared_ptr<ScenarioGenerator>& src, boost::shared_ptr<ore::data::InMemoryReport> report)
38+
ScenarioWriter::ScenarioWriter(const boost::shared_ptr<ScenarioGenerator>& src, boost::shared_ptr<ore::data::Report> report)
3939
: src_(src), report_(report), fp_(nullptr), i_(0), sep_(',') {}
4040

4141
void ScenarioWriter::open(const std::string& filename, const std::string& filemode) {
@@ -67,7 +67,7 @@ boost::shared_ptr<Scenario> ScenarioWriter::next(const Date& d) {
6767
return s;
6868
}
6969

70-
void ScenarioWriter::writeScenario(boost::shared_ptr<Scenario>& s, const bool writeHeader) {
70+
void ScenarioWriter::writeScenario(const boost::shared_ptr<Scenario>& s, const bool writeHeader) {
7171
const Date d = s->asof();
7272
// take a copy of the keys here to ensure the order is preserved
7373
keys_ = s->keys();
@@ -98,9 +98,9 @@ void ScenarioWriter::writeScenario(boost::shared_ptr<Scenario>& s, const bool wr
9898
QL_REQUIRE(keys_.size() > 0, "No keys in scenario");
9999
report_->addColumn("Date", string());
100100
report_->addColumn("Scenario", Size());
101-
report_->addColumn("Numeraire", double(), 8);
101+
report_->addColumn("Numeraire", double(), 16);
102102
for (Size i = 0; i < keys_.size(); i++)
103-
report_->addColumn(to_string(keys_[i]), double(), 8);
103+
report_->addColumn(to_string(keys_[i]), double(), 16);
104104
// set the first date, this will bump i_ to 1 below
105105
firstDate_ = d;
106106
}

OREAnalytics/orea/scenario/scenariowriter.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
#include <orea/scenario/scenario.hpp>
2727
#include <orea/scenario/scenariogenerator.hpp>
28-
#include <ored/report/inmemoryreport.hpp>
28+
#include <ored/report/report.hpp>
2929

3030
namespace ore {
3131
namespace analytics {
@@ -41,7 +41,7 @@ class ScenarioWriter : public ScenarioGenerator {
4141
ScenarioWriter(const std::string& filename, const char sep = ',', const string& filemode = "w+");
4242

4343
//! Constructor to write into an in-memory report for later io
44-
ScenarioWriter(const boost::shared_ptr<ScenarioGenerator>& src, boost::shared_ptr<ore::data::InMemoryReport> report);
44+
ScenarioWriter(const boost::shared_ptr<ScenarioGenerator>& src, boost::shared_ptr<ore::data::Report> report);
4545

4646
//! Destructor
4747
virtual ~ScenarioWriter();
@@ -50,7 +50,7 @@ class ScenarioWriter : public ScenarioGenerator {
5050
virtual boost::shared_ptr<Scenario> next(const Date& d) override;
5151

5252
//! Write a single scenario
53-
void writeScenario(boost::shared_ptr<Scenario>& s, const bool writeHeader);
53+
void writeScenario(const boost::shared_ptr<Scenario>& s, const bool writeHeader);
5454

5555
//! Reset the generator so calls to next() return the first scenario.
5656
virtual void reset() override;
@@ -63,7 +63,7 @@ class ScenarioWriter : public ScenarioGenerator {
6363

6464
boost::shared_ptr<ScenarioGenerator> src_;
6565
std::vector<RiskFactorKey> keys_;
66-
boost::shared_ptr<ore::data::InMemoryReport> report_;
66+
boost::shared_ptr<ore::data::Report> report_;
6767
FILE* fp_;
6868
Date firstDate_;
6969
Size i_;

0 commit comments

Comments
 (0)