Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
analyticsmanager.cpp
Go to the documentation of this file.
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
36
39
40#include <ql/errors.hpp>
41
42using namespace std;
43using namespace boost::filesystem;
45
46namespace ore {
47namespace analytics {
48
49AnalyticsManager::AnalyticsManager(const QuantLib::ext::shared_ptr<InputParameters>& inputs,
50 const QuantLib::ext::shared_ptr<MarketDataLoader>& marketDataLoader)
51 : inputs_(inputs), marketDataLoader_(marketDataLoader) {
52
53 for (const auto& a : inputs_->analytics()) {
54 auto ap = AnalyticFactory::instance().build(a, inputs);
55 if (ap.second)
56 addAnalytic(ap.first, ap.second);
57 }
58}
59
61 LOG("AnalyticsManager: Remove all analytics currently registered");
62 analytics_.clear();
63 validAnalytics_.clear();
64}
65
66void AnalyticsManager::addAnalytic(const std::string& label, const QuantLib::ext::shared_ptr<Analytic>& analytic) {
67 // Label is not necessarily a valid analytics type
68 // Get the latter via analytic->analyticTypes()
69 LOG("register analytic with label '" << label << "' and sub-analytics " << to_string(analytic->analyticTypes()));
70 analytics_[label] = analytic;
71 // This forces an update of valid analytics vector with the next call to validAnalytics()
72 validAnalytics_.clear();
73}
74
75const std::set<std::string>& AnalyticsManager::validAnalytics() {
76 if (validAnalytics_.size() == 0) {
77 for (auto a : analytics_) {
78 const std::set<std::string>& types = a.second->analyticTypes();
79 validAnalytics_.insert(types.begin(), types.end());
80 }
81 }
82 return validAnalytics_;
83}
84
85const std::set<std::string>& AnalyticsManager::requestedAnalytics() {
86 return inputs_->analytics();
87}
88
89bool AnalyticsManager::hasAnalytic(const std::string& type) {
90 const std::set<std::string>& va = validAnalytics();
91 return va.find(type) != va.end();
92}
93
94const QuantLib::ext::shared_ptr<Analytic>& AnalyticsManager::getAnalytic(const std::string& type) const {
95 for (const auto& a : analytics_) {
96 const std::set<std::string>& types = a.second->analyticTypes();
97 if (types.find(type) != types.end())
98 return a.second;
99 }
100 QL_FAIL("analytic type " << type << " not found, check validAnalytics()");
101}
102
103std::vector<QuantLib::ext::shared_ptr<ore::data::TodaysMarketParameters>> AnalyticsManager::todaysMarketParams() {
104 std::vector<QuantLib::ext::shared_ptr<ore::data::TodaysMarketParameters>> tmps;
105 for (const auto& a : analytics_) {
106 std::vector<QuantLib::ext::shared_ptr<ore::data::TodaysMarketParameters>> atmps = a.second->todaysMarketParams();
107 tmps.insert(end(tmps), begin(atmps), end(atmps));
108 }
109 return tmps;
110}
111
112void AnalyticsManager::runAnalytics(const QuantLib::ext::shared_ptr<MarketCalibrationReportBase>& marketCalibrationReport) {
113 if (analytics_.size() == 0)
114 return;
115
116 std::vector<QuantLib::ext::shared_ptr<ore::data::TodaysMarketParameters>> tmps = todaysMarketParams();
117 std::set<Date> marketDates;
118 for (const auto& a : analytics_) {
119 auto mdates = a.second->marketDates();
120 marketDates.insert(mdates.begin(), mdates.end());
121 }
122
123 // Do we need market data
124 bool requireMarketData = false;
125 for (const auto& tmp : tmps) {
126 if (!tmp->empty())
127 requireMarketData = true;
128 }
129
130 LOG("AnalyticsManager::runAnalytics: requireMarketData " << (requireMarketData ? "Y" : "N"));
131
132 if (requireMarketData) {
133 // load the market data
134 if (tmps.size() > 0) {
135 LOG("AnalyticsManager::runAnalytics: populate loader for dates: " << to_string(marketDates));
136 marketDataLoader_->populateLoader(tmps, marketDates);
137 }
138
139 QuantLib::ext::shared_ptr<InMemoryReport> mdReport = QuantLib::ext::make_shared<InMemoryReport>();
140 QuantLib::ext::shared_ptr<InMemoryReport> fixingReport = QuantLib::ext::make_shared<InMemoryReport>();
141 QuantLib::ext::shared_ptr<InMemoryReport> dividendReport = QuantLib::ext::make_shared<InMemoryReport>();
142
143 ore::analytics::ReportWriter(inputs_->reportNaString())
144 .writeMarketData(*mdReport, marketDataLoader_->loader(), inputs_->asof(),
145 marketDataLoader_->quotes()[inputs_->asof()],
146 !inputs_->entireMarket());
147 ore::analytics::ReportWriter(inputs_->reportNaString())
148 .writeFixings(*fixingReport, marketDataLoader_->loader());
149 ore::analytics::ReportWriter(inputs_->reportNaString())
150 .writeDividends(*dividendReport, marketDataLoader_->loader());
151
152 reports_["MARKETDATA"]["marketdata"] = mdReport;
153 reports_["FIXINGS"]["fixings"] = fixingReport;
154 reports_["DIVIDENDS"]["dividends"] = dividendReport;
155 }
156
157 // run requested analytics
158 for (auto a : analytics_) {
159 LOG("run analytic with label '" << a.first << "'");
160 a.second->runAnalytic(marketDataLoader_->loader(), inputs_->analytics());
161 LOG("run analytic with label '" << a.first << "' finished.");
162 // then populate the market calibration report if required
163 if (marketCalibrationReport)
164 a.second->marketCalibration(marketCalibrationReport);
165 }
166
167 if (inputs_->portfolio()) {
168 auto pricingStatsReport = QuantLib::ext::make_shared<InMemoryReport>();
169 ReportWriter(inputs_->reportNaString())
170 .writePricingStats(*pricingStatsReport, inputs_->portfolio());
171 reports_["STATS"]["pricingstats"] = pricingStatsReport;
172 }
173
174 if (marketCalibrationReport) {
175 auto report = marketCalibrationReport->outputCalibrationReport();
176 if (report) {
177 if (auto rpt = QuantLib::ext::dynamic_pointer_cast<InMemoryReport>(report))
178 reports_["MARKET"]["todaysmarketcalibration"] = rpt;
179 }
180 }
181
182 inputs_->writeOutParameters();
183}
184
187 for (auto a : analytics_) {
188 auto rs = a.second->reports();
189 reports.insert(rs.begin(), rs.end());
190 }
191 return reports;
192}
193
196 for (auto a : analytics_) {
197 auto rs = a.second->npvCubes();
198 results.insert(rs.begin(), rs.end());
199 }
200 return results;
201}
202
205 for (auto a : analytics_) {
206 auto rs = a.second->mktCubes();
207 results.insert(rs.begin(), rs.end());
208 }
209 return results;
210}
211
214 for (auto a : analytics_) {
215 auto rs = a.second->stressTests();
216 results.insert(rs.begin(), rs.end());
217 }
218 return results;
219}
220
221std::map<std::string, Size> checkReportNames(const ore::analytics::Analytic::analytic_reports& rpts) {
222 std::map<std::string, Size> m;
223 for (const auto& rep : rpts) {
224 for (auto b : rep.second) {
225 string reportName = b.first;
226 auto it = m.find(reportName);
227 if (it == m.end())
228 m[reportName] = 1;
229 else
230 m[reportName] ++;
231 }
232 }
233 for (auto r : m) {
234 LOG("report name " << r.first << " occurs " << r.second << " times");
235 }
236 return m;
237}
238
239bool endsWith(const std::string& name, const std::string& suffix) {
240 if (suffix.size() > name.size())
241 return false;
242 else
243 return std::equal(suffix.rbegin(), suffix.rend(), name.rbegin());
244}
245
246void AnalyticsManager::toFile(const ore::analytics::Analytic::analytic_reports& rpts, const std::string& outputPath,
247 const std::map<std::string, std::string>& reportNames, const char sep,
248 const bool commentCharacter, char quoteChar, const string& nullString,
249 const std::set<std::string>& lowerHeaderReportNames) {
250 std::map<std::string, Size> hits = checkReportNames(rpts);
251 for (const auto& rep : rpts) {
252 string analytic = rep.first;
253 for (auto b : rep.second) {
254 string reportName = b.first;
255 QuantLib::ext::shared_ptr<InMemoryReport> report = b.second;
256 string fileName;
257 auto it = hits.find(reportName);
258 QL_REQUIRE(it != hits.end(), "something wrong here");
259 if (it->second == 1) {
260 // The report name is unique, check whether we want to rename it or use the standard name
261 auto it2 = reportNames.find(reportName);
262 fileName = (it2 != reportNames.end() && !it2->second.empty()) ? it2->second : reportName;
263 }
264 else {
265 ALOG("Report " << reportName << " occurs " << it->second << " times, fix report naming");
266 fileName = analytic + "_" + reportName + "_" + to_string(hits[fileName]);
267 }
268
269 // attach a suffix only if it does not have one already
270 string suffix = "";
271 if (!endsWith(fileName,".csv") && !endsWith(fileName, ".txt"))
272 suffix = ".csv";
273 std::string fullFileName = outputPath + "/" + fileName + suffix;
274
275 report->toFile(fullFileName, sep, commentCharacter, quoteChar, nullString,
276 lowerHeaderReportNames.find(reportName) != lowerHeaderReportNames.end());
277 LOG("report " << reportName << " written to " << fullFileName);
278 }
279 }
280}
281}
282}
ORE Analytics Manager.
std::map< std::string, std::map< std::string, QuantLib::ext::shared_ptr< AggregationScenarioData > > > analytic_mktcubes
Definition: analytic.hpp:57
std::map< std::string, std::map< std::string, QuantLib::ext::shared_ptr< ore::data::InMemoryReport > > > analytic_reports
Definition: analytic.hpp:51
std::map< std::string, std::map< std::string, QuantLib::ext::shared_ptr< StressTestScenarioData > > > analytic_stresstests
Definition: analytic.hpp:60
std::map< std::string, std::map< std::string, QuantLib::ext::shared_ptr< NPVCube > > > analytic_npvcubes
Definition: analytic.hpp:54
Analytic::analytic_stresstests const stressTests()
const std::set< std::string > & validAnalytics()
const QuantLib::ext::shared_ptr< InputParameters > & inputs()
AnalyticsManager(const QuantLib::ext::shared_ptr< InputParameters > &inputs, const QuantLib::ext::shared_ptr< MarketDataLoader > &marketDataLoader)
bool hasAnalytic(const std::string &type)
Valid analytics in the analytics manager are the union of analytics types provided by analytics_ map.
const std::set< std::string > & requestedAnalytics()
std::map< std::string, QuantLib::ext::shared_ptr< Analytic > > analytics_
Analytic::analytic_npvcubes const npvCubes()
std::set< std::string > validAnalytics_
QuantLib::ext::shared_ptr< MarketDataLoader > marketDataLoader_
void addAnalytic(const std::string &label, const QuantLib::ext::shared_ptr< Analytic > &analytic)
void toFile(const Analytic::analytic_reports &reports, const std::string &outputPath, const std::map< std::string, std::string > &reportNames={}, const char sep=',', const bool commentCharacter=false, char quoteChar='\0', const string &nullString="#N/A", const std::set< std::string > &lowerHeaderReportNames={})
const QuantLib::ext::shared_ptr< Analytic > & getAnalytic(const std::string &type) const
Analytic::analytic_reports const reports()
void runAnalytics(const QuantLib::ext::shared_ptr< MarketCalibrationReportBase > &marketCalibrationReport=nullptr)
std::vector< QuantLib::ext::shared_ptr< ore::data::TodaysMarketParameters > > todaysMarketParams()
QuantLib::ext::shared_ptr< InputParameters > inputs_
Analytic::analytic_reports reports_
Analytic::analytic_mktcubes const mktCubes()
Write ORE outputs to reports.
virtual void writeMarketData(ore::data::Report &report, const QuantLib::ext::shared_ptr< ore::data::Loader > &loader, const QuantLib::Date &asof, const set< string > &quoteNames, bool returnAll)
virtual void writeDividends(ore::data::Report &report, const QuantLib::ext::shared_ptr< ore::data::Loader > &loader)
virtual void writeFixings(ore::data::Report &report, const QuantLib::ext::shared_ptr< ore::data::Loader > &loader)
virtual void writePricingStats(ore::data::Report &report, const QuantLib::ext::shared_ptr< Portfolio > &portfolio)
ORE IM Schedule Analytic.
#define LOG(text)
#define ALOG(text)
bool endsWith(const std::string &name, const std::string &suffix)
std::map< std::string, Size > checkReportNames(const ore::analytics::Analytic::analytic_reports &rpts)
std::string to_string(const LocationInfo &l)
boost::bimap< std::string, TRS::FundingData::NotionalType > types
ORE Par-Stresstest-Conversion Analytic.
ORE NPV Lagged Analytic.
A Class to write ORE outputs to reports.
ORE Scenario Analytic.
ORE Scenario Statistics Analytics.
ORE SIMM Analytic.
ORE Stresstest Analytic.
Structured analytics error.
string name
xva stress analytic