Skip to content

Commit fcf2764

Browse files
damienbarkerjenkins
authored andcommitted
QPR-12145 CRIF refactoring
1 parent 3561c88 commit fcf2764

74 files changed

Lines changed: 2117 additions & 1437 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

OREAnalytics/orea/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ scenario/shiftscenariogenerator.cpp
9292
scenario/simplescenario.cpp
9393
scenario/stressscenariodata.cpp
9494
scenario/stressscenariogenerator.cpp
95+
simm/crif.cpp
9596
simm/crifloader.cpp
9697
simm/crifrecord.cpp
9798
simm/simmbasicnamemapper.cpp
@@ -240,6 +241,7 @@ scenario/simplescenario.hpp
240241
scenario/simplescenariofactory.hpp
241242
scenario/stressscenariodata.hpp
242243
scenario/stressscenariogenerator.hpp
244+
simm/crif.hpp
243245
simm/crifloader.hpp
244246
simm/crifrecord.hpp
245247
simm/simmbasicnamemapper.hpp

OREAnalytics/orea/app/analytics/simmanalytic.cpp

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,16 @@ void SimmAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLo
4646
LOG("Get CRIF records from CRIF loader and fill amountUSD");
4747
simmAnalytic->loadCrifRecords(loader);
4848

49-
auto simmConfiguration = inputs_->crifLoader()->simmConfiguration();
50-
5149
if (analytic()->getWriteIntermediateReports()) {
5250
boost::shared_ptr<InMemoryReport> crifReport = boost::make_shared<InMemoryReport>();
53-
ReportWriter(inputs_->reportNaString()).writeCrifReport(crifReport, *simmAnalytic->crifRecords());
51+
ReportWriter(inputs_->reportNaString()).writeCrifReport(crifReport, simmAnalytic->crif());
5452
analytic()->reports()[LABEL]["crif"] = crifReport;
5553
LOG("CRIF report generated");
5654

57-
auto crifLoader = boost::make_shared<CrifLoader>(simmConfiguration, CrifRecord::additionalHeaders, true, true);
58-
for (const auto& cr : *simmAnalytic->crifRecords())
59-
crifLoader->add(cr);
55+
Crif simmDataCrif = simmAnalytic->crif().aggregate();
6056
boost::shared_ptr<InMemoryReport> simmDataReport = boost::make_shared<InMemoryReport>();
6157
ReportWriter(inputs_->reportNaString())
62-
.writeSIMMData(crifLoader->netRecords(true), simmDataReport);
58+
.writeSIMMData(simmAnalytic->crif(), simmDataReport);
6359
analytic()->reports()[LABEL]["simm_data"] = simmDataReport;
6460
LOG("SIMM data report generated");
6561
}
@@ -72,8 +68,8 @@ void SimmAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLo
7268
inputs_->simmCalibrationData()->toFile((inputs_->resultsPath() / "simmcalibration.xml").string());
7369

7470
// Calculate SIMM
75-
auto simm = boost::make_shared<SimmCalculator>(*simmAnalytic->crifRecords(),
76-
simmConfiguration,
71+
auto simm = boost::make_shared<SimmCalculator>(simmAnalytic->crif(),
72+
inputs_->getSimmConfiguration(),
7773
inputs_->simmCalculationCurrency(),
7874
inputs_->simmResultCurrency(),
7975
analytic()->market(),
@@ -110,12 +106,11 @@ void SimmAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLo
110106

111107
void SimmAnalytic::loadCrifRecords(const boost::shared_ptr<ore::data::InMemoryLoader>& loader) {
112108
QL_REQUIRE(inputs_, "Inputs not set");
113-
QL_REQUIRE(inputs_->crifLoader(), "CRIF loader not set");
114-
QL_REQUIRE(inputs_->crifLoader()->hasCrifRecords(), "CRIF loader does not contain any records");
109+
QL_REQUIRE(!inputs_->crif().empty(), "CRIF loader does not contain any records");
115110

116-
inputs_->crifLoader()->fillAmountUsd(market());
117-
crifRecords_ = boost::make_shared<SimmNetSensitivities>(inputs_->crifLoader()->netRecords(true));
118-
hasNettingSetDetails_ = inputs_->crifLoader()->hasNettingSetDetails();
111+
crif_ = inputs_->crif();
112+
crif_.fillAmountUsd(market());
113+
hasNettingSetDetails_ = crif_.hasNettingSetDetails();
119114
}
120115

121116
} // namespace analytics

OREAnalytics/orea/app/analytics/simmanalytic.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#pragma once
2323

2424
#include <orea/app/analytic.hpp>
25+
#include <orea/simm/crif.hpp>
2526

2627
namespace ore {
2728
namespace analytics {
@@ -40,23 +41,23 @@ class SimmAnalyticImpl : public Analytic::Impl {
4041

4142
class SimmAnalytic : public Analytic {
4243
public:
43-
SimmAnalytic(const boost::shared_ptr<InputParameters>& inputs,
44-
const boost::shared_ptr<SimmNetSensitivities>& crifRecords = nullptr,
44+
SimmAnalytic(const boost::shared_ptr<InputParameters>& inputs, const Crif& crif = Crif(),
4545
const bool hasNettingSetDetails = false,
4646
const bool determineWinningRegulations = true)
4747
: Analytic(std::make_unique<SimmAnalyticImpl>(inputs), {"SIMM"}, inputs, false, false, false, false),
48+
crif_(crif),
4849
hasNettingSetDetails_(hasNettingSetDetails),
4950
determineWinningRegulations_(determineWinningRegulations) {}
5051

51-
const boost::shared_ptr<SimmNetSensitivities>& crifRecords() const { return crifRecords_; }
52+
const Crif& crif() const { return crif_; }
5253
bool hasNettingSetDetails() { return hasNettingSetDetails_; }
5354
bool determineWinningRegulations() { return determineWinningRegulations_; }
5455

5556
//! Load CRIF from external source, override to generate CRIF
5657
virtual void loadCrifRecords(const boost::shared_ptr<ore::data::InMemoryLoader>& loader);
5758

5859
private:
59-
boost::shared_ptr<SimmNetSensitivities> crifRecords_;
60+
Crif crif_;
6061
bool hasNettingSetDetails_;
6162
bool determineWinningRegulations_;
6263
};

OREAnalytics/orea/app/inputparameters.cpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <ored/utilities/currencyconfig.hpp>
2828
#include <ored/utilities/parsers.hpp>
2929
#include <ored/portfolio/scriptedtrade.hpp>
30+
#include <orea/simm/crifloader.hpp>
3031

3132
namespace ore {
3233
namespace analytics {
@@ -43,6 +44,7 @@ vector<string> getFileNames(const string& fileString, const string& path) {
4344

4445
InputParameters::InputParameters() {
4546
iborFallbackConfig_ = boost::make_shared<IborFallbackConfig>(IborFallbackConfig::defaultConfig());
47+
simmBucketMapper_ = boost::make_shared<SimmBucketMapperBase>();
4648
loadParameters();
4749
}
4850

@@ -417,26 +419,23 @@ void InputParameters::setCreditSimulationParametersFromBuffer(const std::string&
417419
creditSimulationParameters_ = boost::make_shared<CreditSimulationParameters>();
418420
creditSimulationParameters_->fromXMLString(xml);
419421
}
420-
421-
void InputParameters::setCrifLoader() {
422-
boost::shared_ptr<SimmConfiguration> configuration = buildSimmConfiguration(
423-
simmVersion_, boost::make_shared<SimmBucketMapperBase>(), simmCalibrationData(), mporDays());
424-
bool updateMappings = true;
425-
bool aggregateTrades = false;
426-
crifLoader_ =
427-
boost::make_shared<CrifLoader>(configuration, CrifRecord::additionalHeaders, updateMappings, aggregateTrades);
428-
}
429422

430423
void InputParameters::setCrifFromFile(const std::string& fileName, char eol, char delim, char quoteChar, char escapeChar) {
431-
if (!crifLoader_)
432-
setCrifLoader();
433-
crifLoader_->loadFromFile(fileName, eol, delim, quoteChar, escapeChar);
424+
boost::shared_ptr<SimmConfiguration> configuration =
425+
buildSimmConfiguration(simmVersion_, boost::make_shared<SimmBucketMapperBase>(),simmCalibrationData(), mporDays());
426+
bool updateMappings = true;
427+
bool aggregateTrades = false;
428+
auto crifLoader = CsvFileCrifLoader(fileName, configuration, CrifRecord::additionalHeaders, updateMappings, aggregateTrades, eol, delim, quoteChar, escapeChar, reportNaString());
429+
crif_ = crifLoader.loadCrif();
434430
}
435431

436432
void InputParameters::setCrifFromBuffer(const std::string& csvBuffer, char eol, char delim, char quoteChar, char escapeChar) {
437-
if (!crifLoader_)
438-
setCrifLoader();
439-
crifLoader_->loadFromString(csvBuffer, eol, delim, quoteChar, escapeChar);
433+
boost::shared_ptr<SimmConfiguration> configuration =
434+
buildSimmConfiguration(simmVersion_, boost::make_shared<SimmBucketMapperBase>(), simmCalibrationData(), mporDays());
435+
bool updateMappings = true;
436+
bool aggregateTrades = false;
437+
auto crifLoader = CsvBufferCrifLoader(csvBuffer, configuration, CrifRecord::additionalHeaders, updateMappings, aggregateTrades, eol, delim, quoteChar, escapeChar, reportNaString());
438+
crif_ = crifLoader.loadCrif();
440439
}
441440

442441
void InputParameters::setSimmNameMapper(const std::string& xml) {
@@ -597,5 +596,13 @@ Date InputParameters::mporDate() {
597596
}
598597
return mporDate_;
599598
}
599+
600+
boost::shared_ptr<SimmConfiguration> InputParameters::getSimmConfiguration() {
601+
QL_REQUIRE(simmBucketMapper() != nullptr,
602+
"Internal error, load simm bucket mapper before retrieving simmconfiguration");
603+
return buildSimmConfiguration(simmVersion(), simmBucketMapper(), simmCalibrationData(), mporDays());
604+
}
605+
606+
600607
} // namespace analytics
601608
} // namespace ore

OREAnalytics/orea/app/inputparameters.hpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222

2323
#pragma once
2424

25+
#include <boost/filesystem/path.hpp>
26+
#include <orea/aggregation/creditsimulationparameters.hpp>
2527
#include <orea/app/parameters.hpp>
2628
#include <orea/cube/npvcube.hpp>
27-
#include <orea/aggregation/creditsimulationparameters.hpp>
29+
#include <orea/engine/sensitivitystream.hpp>
30+
#include <orea/scenario/scenariogenerator.hpp>
31+
#include <orea/scenario/scenariogeneratorbuilder.hpp>
2832
#include <orea/scenario/scenariosimmarketparameters.hpp>
2933
#include <orea/scenario/sensitivityscenariodata.hpp>
3034
#include <orea/scenario/stressscenariodata.hpp>
@@ -33,18 +37,19 @@
3337
#include <orea/engine/sensitivitystream.hpp>
3438
#include <orea/simm/crifloader.hpp>
3539
#include <orea/simm/simmcalibration.hpp>
40+
#include <orea/simm/crif.hpp>
3641
#include <orea/simm/simmbasicnamemapper.hpp>
3742
#include <orea/simm/simmbucketmapper.hpp>
43+
#include <orea/simm/simmconfiguration.hpp>
3844
#include <ored/configuration/curveconfigurations.hpp>
3945
#include <ored/configuration/iborfallbackconfig.hpp>
40-
#include <ored/model/crossassetmodeldata.hpp>
46+
#include <ored/marketdata/csvloader.hpp>
4147
#include <ored/marketdata/todaysmarketparameters.hpp>
48+
#include <ored/model/crossassetmodeldata.hpp>
4249
#include <ored/portfolio/nettingsetmanager.hpp>
4350
#include <ored/portfolio/portfolio.hpp>
4451
#include <ored/portfolio/referencedata.hpp>
45-
#include <ored/marketdata/csvloader.hpp>
4652
#include <ored/utilities/csvfilereader.hpp>
47-
#include <boost/filesystem/path.hpp>
4853

4954
namespace ore {
5055
namespace analytics {
@@ -278,7 +283,7 @@ class InputParameters {
278283

279284
// Setters for SIMM
280285
void setSimmVersion(const std::string& s) { simmVersion_ = s; }
281-
void setCrifLoader();
286+
282287
void setCrifFromFile(const std::string& fileName,
283288
char eol = '\n', char delim = ',', char quoteChar = '\0', char escapeChar = '\\');
284289
void setCrifFromBuffer(const std::string& csvBuffer,
@@ -542,14 +547,15 @@ class InputParameters {
542547
* Getters for SIMM
543548
******************/
544549
const std::string& simmVersion() { return simmVersion_; }
545-
const boost::shared_ptr<ore::analytics::CrifLoader>& crifLoader() { return crifLoader_; }
550+
const ore::analytics::Crif& crif() { return crif_; }
546551
const boost::shared_ptr<ore::analytics::SimmBasicNameMapper>& simmNameMapper() { return simmNameMapper_; }
547552
const boost::shared_ptr<ore::analytics::SimmBucketMapper>& simmBucketMapper() { return simmBucketMapper_; }
548553
const boost::shared_ptr<ore::analytics::SimmCalibrationData>& simmCalibrationData() { return simmCalibrationData_; }
549554
const std::string& simmCalculationCurrency() { return simmCalculationCurrency_; }
550555
const std::string& simmResultCurrency() { return simmResultCurrency_; }
551556
const std::string& simmReportingCurrency() { return simmReportingCurrency_; }
552557
bool enforceIMRegulations() { return enforceIMRegulations_; }
558+
boost::shared_ptr<SimmConfiguration> getSimmConfiguration();
553559

554560
/**************************************************
555561
* Getters for Zero to Par Sensi conversion
@@ -787,7 +793,7 @@ class InputParameters {
787793
* SIMM analytic
788794
***************/
789795
std::string simmVersion_;
790-
boost::shared_ptr<ore::analytics::CrifLoader> crifLoader_;
796+
ore::analytics::Crif crif_;
791797
boost::shared_ptr<ore::analytics::SimmBasicNameMapper> simmNameMapper_;
792798
boost::shared_ptr<ore::analytics::SimmBucketMapper> simmBucketMapper_;
793799
boost::shared_ptr<ore::analytics::SimmCalibrationData> simmCalibrationData_;

OREAnalytics/orea/app/reportwriter.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,7 @@ void ReportWriter::writeCube(ore::data::Report& report, const boost::shared_ptr<
14911491
}
14921492

14931493
// Ease notation again
1494-
typedef SimmConfiguration::ProductClass ProductClass;
1494+
typedef CrifRecord::ProductClass ProductClass;
14951495
typedef SimmConfiguration::RiskClass RiskClass;
14961496
typedef SimmConfiguration::MarginType MarginType;
14971497
typedef SimmConfiguration::SimmSide SimmSide;
@@ -1660,7 +1660,7 @@ void ReportWriter::writeSIMMReport(
16601660
}
16611661
}
16621662

1663-
void ReportWriter::writeSIMMData(const SimmNetSensitivities& simmData, const boost::shared_ptr<Report>& dataReport,
1663+
void ReportWriter::writeSIMMData(const ore::analytics::Crif& simmData, const boost::shared_ptr<Report>& dataReport,
16641664
const bool hasNettingSetDetails) {
16651665

16661666
LOG("Writing SIMM data report.");
@@ -1708,7 +1708,7 @@ void ReportWriter::writeSIMMData(const SimmNetSensitivities& simmData, const boo
17081708
// Same check as above, but for backwards compatibility, if im_model is not used
17091709
// but Risk::Type is PV or Notional
17101710
if (cr.imModel.empty() &&
1711-
(cr.riskType == SimmConfiguration::RiskType::Notional || cr.riskType == SimmConfiguration::RiskType::PV))
1711+
(cr.riskType == CrifRecord::RiskType::Notional || cr.riskType == CrifRecord::RiskType::PV))
17121712
continue;
17131713

17141714
// Write current netted CRIF record
@@ -1743,13 +1743,13 @@ void ReportWriter::writeSIMMData(const SimmNetSensitivities& simmData, const boo
17431743
LOG("SIMM data report written.");
17441744
}
17451745

1746-
void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, const SimmNetSensitivities& crifRecords) {
1746+
void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, const Crif& crif) {
17471747

17481748
// If we have SIMM parameters, check if at least one of them uses netting set details optional field/s
17491749
// It is easier to check here than to pass the flag from other places, since otherwise we'd have to handle certain edge cases
17501750
// e.g. SIMM parameters use optional NSDs, but trades don't. So SIMM report should not display NSDs, but CRIF report still should.
17511751
bool hasNettingSetDetails = false;
1752-
for (const CrifRecord& cr : crifRecords) {
1752+
for (const auto& cr : crif) {
17531753
if (!cr.nettingSetDetails.emptyOptionalFields())
17541754
hasNettingSetDetails = true;
17551755
}
@@ -1758,7 +1758,7 @@ void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, cons
17581758
bool hasCollectRegulations = false;
17591759
bool hasPostRegulations = false;
17601760
bool hasScheduleTrades = false;
1761-
for (const auto& cr : crifRecords) {
1761+
for (const auto& cr : crif) {
17621762
// Check which additional fields are being used/populated
17631763
for (const auto& af : cr.additionalFields) {
17641764
if (std::find(addFields.begin(), addFields.end(), af.first) == addFields.end()) {
@@ -1803,9 +1803,18 @@ void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, cons
18031803
.addColumn("IMModel", string())
18041804
.addColumn("TradeType", string());
18051805

1806-
if (hasScheduleTrades)
1806+
if (hasScheduleTrades || crif.type() == Crif::CrifType::Frtb)
18071807
report->addColumn("end_date", string());
18081808

1809+
if (crif.type() == Crif::CrifType::Frtb) {
1810+
report->addColumn("Label3", string())
1811+
.addColumn("CreditQuality", string())
1812+
.addColumn("LongShortInd", string())
1813+
.addColumn("CoveredBondInd", string())
1814+
.addColumn("TrancheThickness", string())
1815+
.addColumn("BB_RW", string());
1816+
}
1817+
18091818
if (hasCollectRegulations)
18101819
report->addColumn("collect_regulations", string());
18111820

@@ -1818,7 +1827,7 @@ void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, cons
18181827
}
18191828

18201829
// Write individual CRIF records
1821-
for (const auto& cr : crifRecords) {
1830+
for (const auto& cr : crif) {
18221831

18231832
report->next().add(cr.tradeId).add(cr.portfolioId);
18241833

@@ -1840,9 +1849,18 @@ void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, cons
18401849
.add(cr.imModel)
18411850
.add(cr.tradeType);
18421851

1843-
if (hasScheduleTrades)
1852+
if (hasScheduleTrades || crif.type() == Crif::CrifType::Frtb)
18441853
report->add(cr.endDate);
18451854

1855+
if (crif.type() == Crif::CrifType::Frtb) {
1856+
report->add(cr.label3)
1857+
.add(cr.creditQuality)
1858+
.add(cr.longShortInd)
1859+
.add(cr.coveredBondInd)
1860+
.add(cr.trancheThickness)
1861+
.add(cr.bb_rw);
1862+
}
1863+
18461864
if (hasCollectRegulations) {
18471865
string regString = escapeCommaSeparatedList(cr.collectRegulations, '\0');
18481866
report->add(regString);
@@ -1857,7 +1875,7 @@ void ReportWriter::writeCrifReport(const boost::shared_ptr<Report>& report, cons
18571875
if (cr.additionalFields.find(af) == cr.additionalFields.end())
18581876
report->add("");
18591877
else
1860-
report->add(cr.additionalFields.at(af));
1878+
report->add(cr.getAdditionalFieldAsStr(af));
18611879
}
18621880
}
18631881

OREAnalytics/orea/app/reportwriter.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <orea/engine/sensitivitystream.hpp>
3333
#include <orea/simm/crifrecord.hpp>
3434
#include <orea/simm/simmresults.hpp>
35+
#include <orea/simm/crif.hpp>
3536
#include <orea/scenario/scenariogenerator.hpp>
3637
#include <ored/marketdata/market.hpp>
3738
#include <ored/marketdata/todaysmarketparameters.hpp>
@@ -147,13 +148,13 @@ class ReportWriter {
147148
const bool isFinalSimm = true, QuantLib::Real fxSpot = 1.0, QuantLib::Real outputThreshold = 0.005);
148149

149150
//! Write the SIMM data report i.e. the netted CRIF records used in a SIMM calculation
150-
virtual void writeSIMMData(const SimmNetSensitivities& simmData,
151+
virtual void writeSIMMData(const ore::analytics::Crif& simmData,
151152
const boost::shared_ptr<ore::data::Report>& dataReport,
152153
const bool hasNettingSetDetails = false);
153154

154155
//! Write out CRIF records to a report
155156
virtual void writeCrifReport(const boost::shared_ptr<ore::data::Report>& report,
156-
const SimmNetSensitivities& crifRecords);
157+
const ore::analytics::Crif& crifRecords);
157158

158159
virtual void writeScenarioStatistics(const boost::shared_ptr<ore::analytics::ScenarioGenerator>& generator,
159160
const std::vector<ore::analytics::RiskFactorKey>& keys,

OREAnalytics/orea/orea.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
#include <orea/scenario/simplescenariofactory.hpp>
114114
#include <orea/scenario/stressscenariodata.hpp>
115115
#include <orea/scenario/stressscenariogenerator.hpp>
116+
#include <orea/simm/crif.hpp>
116117
#include <orea/simm/crifloader.hpp>
117118
#include <orea/simm/crifrecord.hpp>
118119
#include <orea/simm/simmbasicnamemapper.hpp>

0 commit comments

Comments
 (0)