Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
exposureallocator.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
21
23
24using namespace std;
25using namespace QuantLib;
26
27namespace ore {
28namespace analytics {
29
31 const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
32 const QuantLib::ext::shared_ptr<NPVCube>& tradeExposureCube,
33 const QuantLib::ext::shared_ptr<NPVCube>& nettedExposureCube,
34 const Size allocatedTradeEpeIndex, const Size allocatedTradeEneIndex,
35 const Size tradeEpeIndex, const Size tradeEneIndex,
36 const Size nettingSetEpeIndex, const Size nettingSetEneIndex)
37 : portfolio_(portfolio), tradeExposureCube_(tradeExposureCube),
38 nettedExposureCube_(nettedExposureCube),
39 tradeEpeIndex_(tradeEpeIndex), tradeEneIndex_(tradeEneIndex),
40 allocatedTradeEpeIndex_(allocatedTradeEpeIndex), allocatedTradeEneIndex_(allocatedTradeEneIndex),
41 nettingSetEpeIndex_(nettingSetEpeIndex), nettingSetEneIndex_(nettingSetEneIndex) {}
42
44 LOG("Compute allocated trade exposures");
45
46 for (const auto& [nettingSetId, idx] : nettedExposureCube_->idsAndIndexes()) {
47
48 for (const auto & [tid, trade] : portfolio_->trades()) {
49 string nid = trade->envelope().nettingSetId();
50 if (nid != nettingSetId)
51 continue;
52
53
54 for (Date date : tradeExposureCube_->dates()) {
55 for (Size k = 0; k < tradeExposureCube_->samples(); ++k) {
56 tradeExposureCube_->set(calculateAllocatedEpe(tid, nid, date, k),
57 tid, date, k, allocatedTradeEpeIndex_);
58 tradeExposureCube_->set(calculateAllocatedEne(tid, nid, date, k),
59 tid, date, k, allocatedTradeEneIndex_);
60 }
61 }
62 }
63 }
64 LOG("Completed calculating allocated trade exposures");
65}
66
68 const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
69 const QuantLib::ext::shared_ptr<NPVCube>& tradeExposureCube,
70 const QuantLib::ext::shared_ptr<NPVCube>& nettedExposureCube,
71 const QuantLib::ext::shared_ptr<NPVCube>& npvCube,
72 const Size allocatedTradeEpeIndex, const Size allocatedTradeEneIndex,
73 const Size tradeEpeIndex, const Size tradeEneIndex,
74 const Size nettingSetEpeIndex, const Size nettingSetEneIndex)
75 : ExposureAllocator(portfolio, tradeExposureCube, nettedExposureCube,
76 allocatedTradeEpeIndex, allocatedTradeEneIndex,
77 tradeEpeIndex, tradeEneIndex,
78 nettingSetEpeIndex, nettingSetEneIndex) {
79 size_t i = 0;
80 for (auto tradeIt = portfolio_->trades().begin(); tradeIt != portfolio_->trades().end(); ++tradeIt, ++i) {
81 auto trade = tradeIt->second;
82 string tradeId = tradeIt->first;
83 string nettingSetId = trade->envelope().nettingSetId();
84 if (nettingSetPositiveValueToday_.find(nettingSetId) == nettingSetPositiveValueToday_.end()) {
85 nettingSetPositiveValueToday_[nettingSetId] = 0.0;
86 nettingSetNegativeValueToday_[nettingSetId] = 0.0;
87 }
88 Real npv = npvCube->getT0(i);
89 tradeValueToday_[tradeId] = npv;
90 if (npv > 0)
91 nettingSetPositiveValueToday_[nettingSetId] += npv;
92 else
93 nettingSetNegativeValueToday_[nettingSetId] += npv;
94 }
95}
96
97Real RelativeFairValueNetExposureAllocator::calculateAllocatedEpe(const string& tid, const string& nid,
98 const Date& date, const Size sample) {
99 // FIXME: What to do when either the pos. or neg. netting set value is zero?
100 QL_REQUIRE(nettingSetPositiveValueToday_[nid] > 0.0, "non-zero positive NPV expected");
101 Real netEPE = nettedExposureCube_->get(nid, date, sample, nettingSetEpeIndex_);
102 return netEPE * std::max(tradeValueToday_[tid], 0.0) / nettingSetPositiveValueToday_[nid];
103}
104
105Real RelativeFairValueNetExposureAllocator::calculateAllocatedEne(const string& tid, const string& nid,
106 const Date& date, const Size sample) {
107 // FIXME: What to do when either the pos. or neg. netting set value is zero?
108 QL_REQUIRE(nettingSetNegativeValueToday_[nid] > 0.0, "non-zero negative NPV expected");
109 Real netENE = nettedExposureCube_->get(nid, date, sample, nettingSetEneIndex_);
110 return netENE * -std::max(-tradeValueToday_[tid], 0.0) / nettingSetPositiveValueToday_[nid];
111}
112
114 const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
115 const QuantLib::ext::shared_ptr<NPVCube>& tradeExposureCube,
116 const QuantLib::ext::shared_ptr<NPVCube>& nettedExposureCube,
117 const QuantLib::ext::shared_ptr<NPVCube>& npvCube,
118 const Size allocatedTradeEpeIndex, const Size allocatedTradeEneIndex,
119 const Size tradeEpeIndex, const Size tradeEneIndex,
120 const Size nettingSetEpeIndex, const Size nettingSetEneIndex)
121 : ExposureAllocator(portfolio, tradeExposureCube, nettedExposureCube,
122 allocatedTradeEpeIndex, allocatedTradeEneIndex,
123 tradeEpeIndex, tradeEneIndex,
124 nettingSetEpeIndex, nettingSetEneIndex) {
125 size_t i = 0;
126 for (auto tradeIt = portfolio_->trades().begin(); tradeIt != portfolio_->trades().end(); ++tradeIt, ++i) {
127 auto trade = tradeIt->second;
128 string tradeId = tradeIt->first;
129 string nettingSetId = trade->envelope().nettingSetId();
130 if (nettingSetValueToday_.find(nettingSetId) == nettingSetValueToday_.end())
131 nettingSetValueToday_[nettingSetId] = 0.0;
132 Real npv = npvCube->getT0(i);
133 tradeValueToday_[tradeId] = npv;
134 nettingSetValueToday_[nettingSetId] += npv;
135 }
136}
137
139 const Date& date, const Size sample) {
140 // FIXME: What to do when the netting set value is zero?
141 QL_REQUIRE(nettingSetValueToday_[nid] != 0.0, "non-zero netting set value expected");
142 Real netEPE = nettedExposureCube_->get(nid, date, sample, nettingSetEpeIndex_);
143 return netEPE * tradeValueToday_[tid] / nettingSetValueToday_[nid];
144}
145
147 const Date& date, const Size sample) {
148 // FIXME: What to do when the netting set value is zero?
149 QL_REQUIRE(nettingSetValueToday_[nid] != 0.0, "non-zero netting set value expected");
150 Real netENE = nettedExposureCube_->get(nid, date, sample, nettingSetEneIndex_);
151 return netENE * tradeValueToday_[tid] / nettingSetValueToday_[nid];
152}
153
155 const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
156 const QuantLib::ext::shared_ptr<NPVCube>& tradeExposureCube,
157 const QuantLib::ext::shared_ptr<NPVCube>& nettedExposureCube,
158 const QuantLib::ext::shared_ptr<NPVCube>& npvCube,
159 const map<string, Real>& tradeCva,
160 const map<string, Real>& tradeDva,
161 const map<string, Real>& nettingSetSumCva,
162 const map<string, Real>& nettingSetSumDva,
163 const Size allocatedTradeEpeIndex, const Size allocatedTradeEneIndex,
164 const Size tradeEpeIndex, const Size tradeEneIndex,
165 const Size nettingSetEpeIndex, const Size nettingSetEneIndex)
166 : ExposureAllocator(portfolio, tradeExposureCube, nettedExposureCube,
167 allocatedTradeEpeIndex, allocatedTradeEneIndex,
168 tradeEpeIndex, tradeEneIndex,
169 nettingSetEpeIndex, nettingSetEneIndex),
170 tradeCva_(tradeCva), tradeDva_(tradeDva),
171 nettingSetSumCva_(nettingSetSumCva), nettingSetSumDva_(nettingSetSumDva) {}
172
173Real RelativeXvaExposureAllocator::calculateAllocatedEpe(const string& tid, const string& nid,
174 const Date& date, const Size sample) {
175 Real netEPE = nettedExposureCube_->get(nid, date, sample, nettingSetEpeIndex_);
176 return netEPE * tradeCva_[tid] / nettingSetSumCva_[nid];
177}
178Real RelativeXvaExposureAllocator::calculateAllocatedEne(const string& tid, const string& nid,
179 const Date& date, const Size sample) {
180 Real netENE = nettedExposureCube_->get(nid, date, sample, nettingSetEneIndex_);
181 return netENE * tradeDva_[tid] / nettingSetSumDva_[nid];
182}
183
185 const QuantLib::ext::shared_ptr<Portfolio>& portfolio,
186 const QuantLib::ext::shared_ptr<NPVCube>& tradeExposureCube,
187 const QuantLib::ext::shared_ptr<NPVCube>& nettedExposureCube)
188 : ExposureAllocator(portfolio, tradeExposureCube, nettedExposureCube) {}
189
190Real NoneExposureAllocator::calculateAllocatedEpe(const string& tid, const string& nid,
191 const Date& date, const Size sample) {
192 return 0;
193}
194Real NoneExposureAllocator::calculateAllocatedEne(const string& tid, const string& nid,
195 const Date& date, const Size sample) {
196 return 0;
197}
198
200 static map<string, ExposureAllocator::AllocationMethod> m = {
206 };
207
208 auto it = m.find(s);
209 if (it != m.end()) {
210 return it->second;
211 } else {
212 QL_FAIL("AllocationMethod \"" << s << "\" not recognized");
213 }
214}
215
216std::ostream& operator<<(std::ostream& out, ExposureAllocator::AllocationMethod m) {
218 out << "None";
220 out << "Marginal";
222 out << "RelativeFairValueGross";
224 out << "RelativeFairValueNet";
226 out << "RelativeXVA";
227 else
228 QL_FAIL("Allocation method not covered");
229 return out;
230}
231
232} // namespace analytics
233} // namespace ore
Exposure allocator base class.
QuantLib::ext::shared_ptr< NPVCube > tradeExposureCube_
virtual Real calculateAllocatedEpe(const string &tid, const string &nid, const Date &date, const Size sample)=0
QuantLib::ext::shared_ptr< NPVCube > nettedExposureCube_
virtual void build()
Compute exposures along all paths and fill result structures.
QuantLib::ext::shared_ptr< Portfolio > portfolio_
ExposureAllocator(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NPVCube > &tradeExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &nettedExposureCube, const Size allocatedTradeEpeIndex=2, const Size allocatedTradeEneIndex=3, const Size tradeEpeIndex=0, const Size tradeEneIndex=1, const Size nettingSetEpeIndex=1, const Size nettingSetEneIndex=2)
virtual Real calculateAllocatedEne(const string &tid, const string &nid, const Date &date, const Size sample)=0
virtual Real calculateAllocatedEpe(const string &tid, const string &nid, const Date &date, const Size sample) override
NoneExposureAllocator(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NPVCube > &tradeExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &nettedExposureCube)
virtual Real calculateAllocatedEne(const string &tid, const string &nid, const Date &date, const Size sample) override
virtual Real calculateAllocatedEpe(const string &tid, const string &nid, const Date &date, const Size sample) override
virtual Real calculateAllocatedEne(const string &tid, const string &nid, const Date &date, const Size sample) override
RelativeFairValueGrossExposureAllocator(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NPVCube > &tradeExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &nettedExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &npvCube, const Size allocatedTradeEpeIndex=2, const Size allocatedTradeEneIndex=3, const Size tradeEpeIndex=0, const Size tradeEneIndex=1, const Size nettingSetEpeIndex=1, const Size nettingSetEneIndex=2)
virtual Real calculateAllocatedEpe(const string &tid, const string &nid, const Date &date, const Size sample) override
virtual Real calculateAllocatedEne(const string &tid, const string &nid, const Date &date, const Size sample) override
RelativeFairValueNetExposureAllocator(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NPVCube > &tradeExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &nettedExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &npvCube, const Size allocatedTradeEpeIndex=2, const Size allocatedTradeEneIndex=3, const Size tradeEpeIndex=0, const Size tradeEneIndex=1, const Size nettingSetEpeIndex=1, const Size nettingSetEneIndex=2)
virtual Real calculateAllocatedEpe(const string &tid, const string &nid, const Date &date, const Size sample) override
RelativeXvaExposureAllocator(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NPVCube > &tradeExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &nettedExposureCube, const QuantLib::ext::shared_ptr< NPVCube > &npvCube, const map< string, Real > &tradeCva, const map< string, Real > &tradeDva, const map< string, Real > &nettingSetSumCva, const map< string, Real > &nettingSetSumDva, const Size allocatedTradeEpeIndex=2, const Size allocatedTradeEneIndex=3, const Size tradeEpeIndex=0, const Size tradeEneIndex=1, const Size nettingSetEpeIndex=0, const Size nettingSetEneIndex=1)
virtual Real calculateAllocatedEne(const string &tid, const string &nid, const Date &date, const Size sample) override
Exposure allocator.
A cube implementation that stores the cube in memory.
#define LOG(text)
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
ExposureAllocator::AllocationMethod parseAllocationMethod(const string &s)
Convert text representation to ExposureAllocator::AllocationMethod.