Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
dimcalculator.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 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
23
24#include <ql/errors.hpp>
25#include <ql/time/calendars/weekendsonly.hpp>
26#include <ql/math/distributions/normaldistribution.hpp>
27#include <ql/math/generallinearleastsquares.hpp>
28#include <ql/math/kernelfunctions.hpp>
29#include <ql/methods/montecarlo/lsmbasissystem.hpp>
30#include <ql/time/daycounters/actualactual.hpp>
31
34
35#include <boost/accumulators/accumulators.hpp>
36#include <boost/accumulators/statistics/error_of_mean.hpp>
37#include <boost/accumulators/statistics/mean.hpp>
38#include <boost/accumulators/statistics/stats.hpp>
39
40using namespace std;
41using namespace QuantLib;
42
43using namespace boost::accumulators;
44
45namespace ore {
46namespace analytics {
47
49 const QuantLib::ext::shared_ptr<InputParameters>& inputs,
50 const QuantLib::ext::shared_ptr<Portfolio>& portfolio, const QuantLib::ext::shared_ptr<NPVCube>& cube,
51 const QuantLib::ext::shared_ptr<CubeInterpretation>& cubeInterpretation,
52 const QuantLib::ext::shared_ptr<AggregationScenarioData>& scenarioData, Real quantile, Size horizonCalendarDays,
53 const std::map<std::string, Real>& currentIM)
54 : inputs_(inputs), portfolio_(portfolio), cube_(cube), cubeInterpretation_(cubeInterpretation), scenarioData_(scenarioData),
55 quantile_(quantile), horizonCalendarDays_(horizonCalendarDays), currentIM_(currentIM) {
56
57 QL_REQUIRE(portfolio_, "portfolio is null");
58 QL_REQUIRE(cube_, "cube is null");
59 QL_REQUIRE(cubeInterpretation_, "cube interpretation is null");
60 QL_REQUIRE(scenarioData_, "aggregation scenario data is null");
61
62 cubeIsRegular_ = !cubeInterpretation_->withCloseOutLag();
63 datesLoopSize_ = cubeIsRegular_ ? cube_->dates().size() - 1 : cube_->dates().size();
64
65 Size dates = cube_->dates().size();
66 Size samples = cube_->samples();
67
68 if (!cubeInterpretation_->storeFlows()) {
69 WLOG("cube holds no mpor flows, will assume no flows in the dim calculation");
70 }
71
72 // initialise aggregate NPV and Flow by date and scenario
73 set<string> nettingSets;
74 size_t i = 0;
75 for (auto tradeIt = portfolio_->trades().begin(); tradeIt != portfolio_->trades().end(); ++tradeIt, ++i) {
76 auto trade = tradeIt->second;
77 string tradeId = tradeIt->first;
78 string nettingSetId = trade->envelope().nettingSetId();
79 if (nettingSets.find(nettingSetId) == nettingSets.end()) {
80 nettingSets.insert(nettingSetId);
81 nettingSetNPV_[nettingSetId] = vector<vector<Real>>(dates, vector<Real>(samples, 0.0));
82 nettingSetCloseOutNPV_[nettingSetId] = vector<vector<Real>>(dates, vector<Real>(samples, 0.0));
83 nettingSetFLOW_[nettingSetId] = vector<vector<Real>>(dates, vector<Real>(samples, 0.0));
84 nettingSetDeltaNPV_[nettingSetId] = vector<vector<Real>>(dates, vector<Real>(samples, 0.0));
85 nettingSetDIM_[nettingSetId] = vector<vector<Real>>(dates, vector<Real>(samples, 0.0));
86 nettingSetExpectedDIM_[nettingSetId] = vector<Real>(dates, 0.0);
87 }
88 for (Size j = 0; j < datesLoopSize_; ++j) {
89 for (Size k = 0; k < samples; ++k) {
90 Real defaultNpv = cubeInterpretation_->getDefaultNpv(cube_, i, j, k);
91 Real closeOutNpv = cubeInterpretation_->getCloseOutNpv(cube_, i, j, k);
92 Real mporFlow =
93 cubeInterpretation_->storeFlows() ? cubeInterpretation_->getMporFlows(cube_, i, j, k) : 0.0;
94 nettingSetNPV_[nettingSetId][j][k] += defaultNpv;
95 nettingSetCloseOutNPV_[nettingSetId][j][k] += closeOutNpv;
96 nettingSetFLOW_[nettingSetId][j][k] += mporFlow;
97 }
98 }
99 }
100
101
102 nettingSetIds_ = std::move(nettingSets);
103
104 dimCube_ = QuantLib::ext::make_shared<SinglePrecisionInMemoryCube>(cube_->asof(), nettingSetIds_, cube_->dates(),
105 cube_->samples());
106}
107
108const vector<vector<Real>>& DynamicInitialMarginCalculator::dynamicIM(const std::string& nettingSet) {
109 if (nettingSetDIM_.find(nettingSet) != nettingSetDIM_.end())
110 return nettingSetDIM_[nettingSet];
111 else
112 QL_FAIL("netting set " << nettingSet << " not found in DIM results");
113}
114
115const vector<Real>& DynamicInitialMarginCalculator::expectedIM(const std::string& nettingSet) {
116 if (nettingSetExpectedDIM_.find(nettingSet) != nettingSetExpectedDIM_.end())
117 return nettingSetExpectedDIM_[nettingSet];
118 else
119 QL_FAIL("netting set " << nettingSet << " not found in expected DIM results");
120}
121
122const vector<vector<Real>>& DynamicInitialMarginCalculator::cashFlow(const std::string& nettingSet) {
123 if (nettingSetFLOW_.find(nettingSet) != nettingSetFLOW_.end())
124 return nettingSetFLOW_[nettingSet];
125 else
126 QL_FAIL("netting set " << nettingSet << " not found in DIM results");
127}
128
130
131 Size samples = dimCube_->samples();
132 Size stopDatesLoop = datesLoopSize_;
133 Date asof = cube_->asof();
134
135 dimEvolutionReport.addColumn("TimeStep", Size())
136 .addColumn("Date", Date())
137 .addColumn("DaysInPeriod", Size())
138 .addColumn("AverageDIM", Real(), 6)
139 .addColumn("AverageFLOW", Real(), 6)
140 .addColumn("NettingSet", string())
141 .addColumn("Time", Real(), 6);
142
143 for (auto [nettingSet, _] : dimCube_->idsAndIndexes()) {
144
145 LOG("Export DIM evolution for netting set " << nettingSet);
146 for (Size i = 0; i < stopDatesLoop; ++i) {
147 Real expectedFlow = 0.0;
148 for (Size j = 0; j < samples; ++j) {
149 expectedFlow += nettingSetFLOW_.find(nettingSet)->second[i][j] / samples;
150 }
151
152 Date defaultDate = dimCube_->dates()[i];
153 Time t = ActualActual(ActualActual::ISDA).yearFraction(asof, defaultDate);
154 Size days = cubeInterpretation_->getMporCalendarDays(dimCube_, i);
155 dimEvolutionReport.next()
156 .add(i)
157 .add(defaultDate)
158 .add(days)
159 .add(nettingSetExpectedDIM_.find(nettingSet)->second[i])
160 .add(expectedFlow)
161 .add(nettingSet)
162 .add(t);
163 }
164 }
165 dimEvolutionReport.end();
166 LOG("Exporting expected DIM through time done");
167}
168
169} // namespace analytics
170} // namespace ore
map< string, vector< vector< Real > > > nettingSetNPV_
const vector< vector< Real > > & dynamicIM(const string &nettingSet)
DIM matrix by date and sample index for the specified netting set.
DynamicInitialMarginCalculator(const QuantLib::ext::shared_ptr< InputParameters > &inputs, const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NPVCube > &cube, const QuantLib::ext::shared_ptr< CubeInterpretation > &cubeInterpretation, const QuantLib::ext::shared_ptr< AggregationScenarioData > &scenarioData, Real quantile=0.99, Size horizonCalendarDays=14, const std::map< std::string, Real > &currentIM=std::map< std::string, Real >())
map< string, vector< vector< Real > > > nettingSetCloseOutNPV_
map< string, vector< vector< Real > > > nettingSetDeltaNPV_
map< string, vector< Real > > nettingSetExpectedDIM_
QuantLib::ext::shared_ptr< Portfolio > portfolio_
virtual void exportDimEvolution(ore::data::Report &dimEvolutionReport) const
DIM evolution report.
QuantLib::ext::shared_ptr< AggregationScenarioData > scenarioData_
QuantLib::ext::shared_ptr< CubeInterpretation > cubeInterpretation_
QuantLib::ext::shared_ptr< NPVCube > dimCube_
map< string, vector< vector< Real > > > nettingSetFLOW_
const vector< Real > & expectedIM(const string &nettingSet)
Expected DIM vector by date for the specified netting set.
map< string, vector< vector< Real > > > nettingSetDIM_
QuantLib::ext::shared_ptr< NPVCube > cube_
const vector< vector< Real > > & cashFlow(const string &nettingSet)
Cash flow matrix by date and sample index for the specified netting set.
virtual Report & add(const ReportType &rt)=0
virtual Report & next()=0
virtual void end()=0
virtual Report & addColumn(const string &name, const ReportType &, Size precision=0)=0
Dynamic Initial Margin calculator base class.
#define LOG(text)
#define WLOG(text)
Date asof(14, Jun, 2018)