Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Public Attributes | Protected Member Functions | Protected Attributes | List of all members
NettedExposureCalculator Class Reference

XVA Calculator base class. More...

#include <orea/aggregation/nettedexposurecalculator.hpp>

+ Collaboration diagram for NettedExposureCalculator:

Public Types

enum  ExposureIndex { EPE , ENE }
 

Public Member Functions

 NettedExposureCalculator (const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< Market > &market, const QuantLib::ext::shared_ptr< NPVCube > &cube, const string &baseCurrency, const string &configuration, const Real quantile, const CollateralExposureHelper::CalculationType calcType, const bool multiPath, const QuantLib::ext::shared_ptr< NettingSetManager > &nettingSetManager, const QuantLib::ext::shared_ptr< CollateralBalances > &collateralBalances, const map< string, vector< vector< Real > > > &nettingSetDefaultValue, const map< string, vector< vector< Real > > > &nettingSetCloseOutValue, const map< string, vector< vector< Real > > > &nettingSetMporPositiveFlow, const map< string, vector< vector< Real > > > &nettingSetMporNegativeFlow, const QuantLib::ext::shared_ptr< AggregationScenarioData > &scenarioData, const QuantLib::ext::shared_ptr< CubeInterpretation > cubeInterpretation, const bool applyInitialMargin, const QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > &dimCalculator, const bool fullInitialCollateralisation, const bool marginalAllocation, const Real marginalAllocationLimit, const QuantLib::ext::shared_ptr< NPVCube > &tradeExposureCube, const Size allocatedEpeIndex, const Size allocatedEneIndex, const bool flipViewXVA, const bool withMporStickyDate, const MporCashFlowMode mporCashFlowMode)
 
virtual ~NettedExposureCalculator ()
 
const QuantLib::ext::shared_ptr< NPVCube > & exposureCube ()
 
const QuantLib::ext::shared_ptr< NPVCube > & nettedCube ()
 
virtual void build ()
 Compute exposures along all paths and fill result structures. More...
 
vector< Real > epe (const string &nid)
 
vector< Real > ene (const string &nid)
 
vector< Real > & ee_b (const string &nid)
 
vector< Real > & eee_b (const string &nid)
 
vector< Real > & pfe (const string &nid)
 
vector< Real > & expectedCollateral (const string &nid)
 
vector< Real > & colvaIncrements (const string &nid)
 
vector< Real > & collateralFloorIncrements (const string &nid)
 
Real & epe_b (const string &nid)
 
Real & eepe_b (const string &nid)
 
Real & colva (const string &nid)
 
Real & collateralFloor (const string &nid)
 
const string & counterparty (const string nettingSetId)
 
const map< string, string > & counterpartyMap ()
 
map< string, vector< vector< Real > > > nettingSetCloseOutValue ()
 
map< string, vector< vector< Real > > > nettingSetDefaultValue ()
 
map< string, vector< vector< Real > > > nettingSetMporPositiveFlow ()
 
map< string, vector< vector< Real > > > nettingSetMporNegativeFlow ()
 

Public Attributes

const Size EXPOSURE_CUBE_DEPTH = 3
 

Protected Member Functions

vector< Real > getMeanExposure (const string &tid, ExposureIndex index)
 
QuantLib::ext::shared_ptr< vector< QuantLib::ext::shared_ptr< CollateralAccount > > > collateralPaths (const string &nettingSetId, const Real &nettingSetValueToday, const vector< vector< Real > > &nettingSetValue, const Date &nettingSetMaturity)
 

Protected Attributes

QuantLib::ext::shared_ptr< Portfolioportfolio_
 
QuantLib::ext::shared_ptr< Marketmarket_
 
QuantLib::ext::shared_ptr< NPVCubecube_
 
string baseCurrency_
 
string configuration_
 
Real quantile_
 
CollateralExposureHelper::CalculationType calcType_
 
bool multiPath_
 
const QuantLib::ext::shared_ptr< NettingSetManagernettingSetManager_
 
const QuantLib::ext::shared_ptr< CollateralBalancescollateralBalances_
 
map< string, vector< vector< Real > > > nettingSetDefaultValue_
 
map< string, vector< vector< Real > > > nettingSetCloseOutValue_
 
map< string, vector< vector< Real > > > nettingSetMporPositiveFlow_
 
map< string, vector< vector< Real > > > nettingSetMporNegativeFlow_
 
const QuantLib::ext::shared_ptr< AggregationScenarioDatascenarioData_
 
QuantLib::ext::shared_ptr< CubeInterpretationcubeInterpretation_
 
const bool applyInitialMargin_
 
const QuantLib::ext::shared_ptr< DynamicInitialMarginCalculatordimCalculator_
 
const bool fullInitialCollateralisation_
 
const bool marginalAllocation_
 
const Real marginalAllocationLimit_
 
QuantLib::ext::shared_ptr< NPVCubetradeExposureCube_
 
const Size allocatedEpeIndex_
 
const Size allocatedEneIndex_
 
const bool flipViewXVA_
 
QuantLib::ext::shared_ptr< NPVCubenettedCube_
 
QuantLib::ext::shared_ptr< NPVCubeexposureCube_
 
map< string, string > counterpartyMap_
 
map< string, std::vector< Real > > ee_b_
 
map< string, std::vector< Real > > eee_b_
 
map< string, std::vector< Real > > pfe_
 
map< string, std::vector< Real > > expectedCollateral_
 
map< string, std::vector< Real > > colvaInc_
 
map< string, std::vector< Real > > eoniaFloorInc_
 
map< string, Real > epe_b_
 
map< string, Real > eepe_b_
 
map< string, Real > colva_
 
map< string, Real > collateralFloor_
 
bool withMporStickyDate_
 
MporCashFlowMode mporCashFlowMode_
 

Detailed Description

XVA Calculator base class.

Derived classes implement a constructor with the relevant additional input data and a build function that performs the XVA calculations for all netting sets and along all paths.

Definition at line 45 of file nettedexposurecalculator.hpp.

Member Enumeration Documentation

◆ ExposureIndex

Constructor & Destructor Documentation

◆ NettedExposureCalculator()

NettedExposureCalculator ( const QuantLib::ext::shared_ptr< Portfolio > &  portfolio,
const QuantLib::ext::shared_ptr< Market > &  market,
const QuantLib::ext::shared_ptr< NPVCube > &  cube,
const string &  baseCurrency,
const string &  configuration,
const Real  quantile,
const CollateralExposureHelper::CalculationType  calcType,
const bool  multiPath,
const QuantLib::ext::shared_ptr< NettingSetManager > &  nettingSetManager,
const QuantLib::ext::shared_ptr< CollateralBalances > &  collateralBalances,
const map< string, vector< vector< Real > > > &  nettingSetDefaultValue,
const map< string, vector< vector< Real > > > &  nettingSetCloseOutValue,
const map< string, vector< vector< Real > > > &  nettingSetMporPositiveFlow,
const map< string, vector< vector< Real > > > &  nettingSetMporNegativeFlow,
const QuantLib::ext::shared_ptr< AggregationScenarioData > &  scenarioData,
const QuantLib::ext::shared_ptr< CubeInterpretation cubeInterpretation,
const bool  applyInitialMargin,
const QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > &  dimCalculator,
const bool  fullInitialCollateralisation,
const bool  marginalAllocation,
const Real  marginalAllocationLimit,
const QuantLib::ext::shared_ptr< NPVCube > &  tradeExposureCube,
const Size  allocatedEpeIndex,
const Size  allocatedEneIndex,
const bool  flipViewXVA,
const bool  withMporStickyDate,
const MporCashFlowMode  mporCashFlowMode 
)

Definition at line 32 of file nettedexposurecalculator.cpp.

48 : portfolio_(portfolio), market_(market), cube_(cube), baseCurrency_(baseCurrency), configuration_(configuration),
49 quantile_(quantile), calcType_(calcType), multiPath_(multiPath), nettingSetManager_(nettingSetManager),
50 collateralBalances_(collateralBalances),
53 scenarioData_(scenarioData), cubeInterpretation_(cubeInterpretation), applyInitialMargin_(applyInitialMargin),
54 dimCalculator_(dimCalculator), fullInitialCollateralisation_(fullInitialCollateralisation),
55 marginalAllocation_(marginalAllocation), marginalAllocationLimit_(marginalAllocationLimit),
56 tradeExposureCube_(tradeExposureCube), allocatedEpeIndex_(allocatedEpeIndex),
57 allocatedEneIndex_(allocatedEneIndex), flipViewXVA_(flipViewXVA), withMporStickyDate_(withMporStickyDate),
58 mporCashFlowMode_(mporCashFlowMode) {
59
60 set<string> nettingSetIds;
61 for (auto nettingSet : nettingSetDefaultValue) {
62 nettingSetIds.insert(nettingSet.first);
63 if (flipViewXVA_) {
64 if (nettingSetManager_->get(nettingSet.first)->activeCsaFlag()) {
65 nettingSetManager_->get(nettingSet.first)->csaDetails()->invertCSA();
66 }
67 }
68 }
69
70 nettedCube_= QuantLib::ext::make_shared<SinglePrecisionInMemoryCube>(
71 market_->asofDate(), nettingSetIds, cube->dates(),
72 cube->samples()); // Exposure after collateral
73 if (multiPath) {
74 exposureCube_ = QuantLib::ext::make_shared<SinglePrecisionInMemoryCubeN>(
75 market_->asofDate(), nettingSetIds, cube->dates(),
76 cube->samples(), EXPOSURE_CUBE_DEPTH); // EPE, ENE
77 } else {
78 exposureCube_ = QuantLib::ext::make_shared<DoublePrecisionInMemoryCubeN>(
79 market_->asofDate(), nettingSetIds, cube->dates(),
80 1, EXPOSURE_CUBE_DEPTH); // EPE, ENE
81 }
82};
QuantLib::ext::shared_ptr< Market > market_
map< string, vector< vector< Real > > > nettingSetDefaultValue()
QuantLib::ext::shared_ptr< NPVCube > tradeExposureCube_
map< string, vector< vector< Real > > > nettingSetDefaultValue_
map< string, vector< vector< Real > > > nettingSetMporPositiveFlow_
const QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > dimCalculator_
const QuantLib::ext::shared_ptr< CollateralBalances > collateralBalances_
QuantLib::ext::shared_ptr< NPVCube > nettedCube_
QuantLib::ext::shared_ptr< NPVCube > exposureCube_
map< string, vector< vector< Real > > > nettingSetMporPositiveFlow()
QuantLib::ext::shared_ptr< Portfolio > portfolio_
const QuantLib::ext::shared_ptr< AggregationScenarioData > scenarioData_
map< string, vector< vector< Real > > > nettingSetMporNegativeFlow_
QuantLib::ext::shared_ptr< CubeInterpretation > cubeInterpretation_
map< string, vector< vector< Real > > > nettingSetCloseOutValue()
map< string, vector< vector< Real > > > nettingSetCloseOutValue_
CollateralExposureHelper::CalculationType calcType_
map< string, vector< vector< Real > > > nettingSetMporNegativeFlow()
const QuantLib::ext::shared_ptr< NettingSetManager > nettingSetManager_
QuantLib::ext::shared_ptr< NPVCube > cube_
+ Here is the call graph for this function:

◆ ~NettedExposureCalculator()

virtual ~NettedExposureCalculator ( )
virtual

Definition at line 65 of file nettedexposurecalculator.hpp.

65{}

Member Function Documentation

◆ exposureCube()

const QuantLib::ext::shared_ptr< NPVCube > & exposureCube ( )

Definition at line 66 of file nettedexposurecalculator.hpp.

66{ return exposureCube_; }

◆ nettedCube()

const QuantLib::ext::shared_ptr< NPVCube > & nettedCube ( )

Definition at line 67 of file nettedexposurecalculator.hpp.

67{ return nettedCube_; }

◆ build()

void build ( )
virtual

Compute exposures along all paths and fill result structures.

Definition at line 84 of file nettedexposurecalculator.cpp.

84 {
85 LOG("Compute netting set exposure profiles");
86
87 const Date today = market_->asofDate();
88 const DayCounter dc = ActualActual(ActualActual::ISDA);
89
90 vector<Real> times = vector<Real>(cube_->dates().size(), 0.0);
91 for (Size i = 0; i < cube_->dates().size(); i++)
92 times[i] = dc.yearFraction(today, cube_->dates()[i]);
93
94 map<string, Real> nettingSetValueToday;
95 map<string, Date> nettingSetMaturity;
96 map<string, Size> nettingSetSize;
97 Size cubeIndex = 0;
98 for (auto tradeIt = portfolio_->trades().begin(); tradeIt != portfolio_->trades().end(); ++tradeIt, ++cubeIndex) {
99 const auto& trade = tradeIt->second;
100 string tradeId = tradeIt->first;
101 string nettingSetId = trade->envelope().nettingSetId();
102 string cp = trade->envelope().counterparty();
103 if (counterpartyMap_.find(nettingSetId) == counterpartyMap_.end())
104 counterpartyMap_[nettingSetId] = trade->envelope().counterparty();
105 else {
106 QL_REQUIRE(counterpartyMap_[nettingSetId] == cp, "counterparty name is not unique within the netting set");
107 }
108 Real npv;
109 if (flipViewXVA_) {
110 npv = -cube_->getT0(cubeIndex);
111 } else {
112 npv = cube_->getT0(cubeIndex);
113 }
114
115 if (nettingSetValueToday.find(nettingSetId) == nettingSetValueToday.end()) {
116 nettingSetValueToday[nettingSetId] = 0.0;
117 nettingSetMaturity[nettingSetId] = today;
118 nettingSetSize[nettingSetId] = 0;
119 }
120
121 nettingSetValueToday[nettingSetId] += npv;
122
123 if (trade->maturity() > nettingSetMaturity[nettingSetId])
124 nettingSetMaturity[nettingSetId] = trade->maturity();
125 nettingSetSize[nettingSetId]++;
126 }
127
128 vector<vector<Real>> averagePositiveAllocation(portfolio_->size(), vector<Real>(cube_->dates().size(), 0.0));
129 vector<vector<Real>> averageNegativeAllocation(portfolio_->size(), vector<Real>(cube_->dates().size(), 0.0));
130
131 Size nettingSetCount = 0;
132 for (auto n : nettingSetDefaultValue_) {
133 string nettingSetId = n.first;
134 vector<vector<Real>> data = n.second;
135 QuantLib::ext::shared_ptr<NettingSetDefinition> netting = nettingSetManager_->get(nettingSetId);
136
137 // retrieve collateral balances object, if possible
138 QuantLib::ext::shared_ptr<CollateralBalance> balance = nullptr;
139 if (collateralBalances_ && collateralBalances_->has(nettingSetId)) {
140 balance = collateralBalances_->get(nettingSetId);
141 DLOG("got collateral balances for netting set " << nettingSetId);
142 }
143
144 //only for active CSA and calcType == NoLag close-out value is relevant
145 if (netting->activeCsaFlag() && calcType_ == CollateralExposureHelper::CalculationType::NoLag)
146 data = nettingSetCloseOutValue_[nettingSetId];
147
148 vector<vector<Real>> nettingSetMporPositiveFlow = nettingSetMporPositiveFlow_[nettingSetId];
149 vector<vector<Real>> nettingSetMporNegativeFlow = nettingSetMporNegativeFlow_[nettingSetId];
150
151 LOG("Aggregate exposure for netting set " << nettingSetId);
152 // Get the collateral account balance paths for the netting set.
153 // The pointer may remain empty if there is no CSA or if it is inactive.
154 QuantLib::ext::shared_ptr<vector<QuantLib::ext::shared_ptr<CollateralAccount>>> collateral =
155 collateralPaths(nettingSetId,
156 nettingSetValueToday[nettingSetId],
157 nettingSetDefaultValue_[nettingSetId],
158 nettingSetMaturity[nettingSetId]);
159
160 // Get the CSA index for Eonia Floor calculation below
161 colva_[nettingSetId] = 0.0;
162 collateralFloor_[nettingSetId] = 0.0;
163 string csaIndexName;
164 Handle<IborIndex> csaIndex;
165 bool applyInitialMargin = false;
166 CSA::Type initialMarginType = CSA::Bilateral;
167 if (netting->activeCsaFlag()) {
168 csaIndexName = netting->csaDetails()->index();
169 if (csaIndexName != "") {
170 csaIndex = market_->iborIndex(csaIndexName);
171 QL_REQUIRE(scenarioData_->has(AggregationScenarioDataType::IndexFixing, csaIndexName),
172 "scenario data does not provide index values for " << csaIndexName);
173 }
174 QL_REQUIRE(netting->csaDetails(), "active CSA for netting set " << nettingSetId
175 << ", but CSA details not initialised");
176 applyInitialMargin = netting->csaDetails()->applyInitialMargin() && applyInitialMargin_;
177 initialMarginType = netting->csaDetails()->initialMarginType();
178 LOG("ApplyInitialMargin=" << applyInitialMargin << " for netting set " << nettingSetId
179 << ", CSA IM=" << netting->csaDetails()->applyInitialMargin()
180 << ", CSA IM Type=" << initialMarginType
181 << ", Analytics DIM=" << applyInitialMargin_);
182 if (applyInitialMargin_ && !netting->csaDetails()->applyInitialMargin())
183 ALOG("ApplyInitialMargin deactivated at netting set level " << nettingSetId);
184 if (!applyInitialMargin_ && netting->csaDetails()->applyInitialMargin())
185 ALOG("ApplyInitialMargin deactivated in analytics, but active at netting set level " << nettingSetId);
186 }
187
188 // Retrieve the constant independent amount from the CSA data and the VM balance
189 // This is used below to reduce the exposure across all paths and time steps.
190 // See below for the conversion to base currency.
191 Real initialVM = 0, initialVMbase = 0;
192 Real initialIM = 0, initialIMbase = 0;
193 string csaCurrency = "";
194 if (netting->activeCsaFlag() && balance) {
195 initialVM = balance->variationMargin();
196 initialIM = balance->initialMargin();
197 double fx = 1.0;
198 if (baseCurrency_ != balance->currency())
199 fx = market_->fxSpot(balance->currency() + baseCurrency_)->value();
200 initialVMbase = fx * initialVM;
201 initialIMbase = fx * initialIM;
202 DLOG("Netting set " << nettingSetId << ", initial VM: " << initialVMbase << " " << baseCurrency_);
203 DLOG("Netting set " << nettingSetId << ", initial IM: " << initialIMbase << " " << baseCurrency_);
204 }
205 else {
206 DLOG("Netting set " << nettingSetId << ", IA base = VM base = 0");
207 }
208
209 Handle<YieldTermStructure> curve = market_->discountCurve(baseCurrency_, configuration_);
210 vector<Real> epe(cube_->dates().size() + 1, 0.0);
211 vector<Real> ene(cube_->dates().size() + 1, 0.0);
212 vector<Real> ee_b(cube_->dates().size() + 1, 0.0);
213 vector<Real> eee_b(cube_->dates().size() + 1, 0.0);
214 vector<Real> eee_b_kva_1(cube_->dates().size() + 1, 0.0);
215 vector<Real> eee_b_kva_2(cube_->dates().size() + 1, 0.0);
216 vector<Real> eepe_b_kva_1(cube_->dates().size() + 1, 0.0);
217 vector<Real> eepe_b_kva_2(cube_->dates().size() + 1, 0.0);
218 vector<Real> eab(cube_->dates().size() + 1, 0.0);
219 vector<Real> pfe(cube_->dates().size() + 1, 0.0);
220 vector<Real> colvaInc(cube_->dates().size() + 1, 0.0);
221 vector<Real> eoniaFloorInc(cube_->dates().size() + 1, 0.0);
222 Real npv = nettingSetValueToday[nettingSetId];
223 if ((fullInitialCollateralisation_) & (netting->activeCsaFlag())) {
224 // This assumes that the collateral at t=0 is the same as the npv at t=0.
225 epe[0] = 0;
226 ene[0] = 0;
227 pfe[0] = 0;
228 } else {
229 epe[0] = std::max(npv - initialVMbase - initialIMbase, 0.0);
230 ene[0] = std::max(-npv + initialVMbase, 0.0);
231 pfe[0] = std::max(npv - initialVMbase - initialIMbase, 0.0);
232 }
233 // The fullInitialCollateralisation flag doesn't affect the eab, which feeds into the "ExpectedCollateral"
234 // column of the 'exposure_nettingset_*' reports. We always assume the full collateral here.
235 eab[0] = npv;
236 ee_b[0] = epe[0];
237 eee_b[0] = ee_b[0];
238 nettedCube_->setT0(npv, nettingSetCount);
239 exposureCube_->setT0(epe[0], nettingSetCount, ExposureIndex::EPE);
240 exposureCube_->setT0(ene[0], nettingSetCount, ExposureIndex::ENE);
241
242 for (Size j = 0; j < cube_->dates().size(); ++j) {
243
244 Date date = cube_->dates()[j];
245 Date prevDate = j > 0 ? cube_->dates()[j - 1] : today;
246 vector<Real> distribution(cube_->samples(), 0.0);
247 for (Size k = 0; k < cube_->samples(); ++k) {
248 Real balance = 0.0;
249 if (collateral) {
250 balance = collateral->at(k)->accountBalance(date);
251 if (netting->csaDetails()->csaCurrency() != baseCurrency_) {
252 // Convert from CSACurrency to baseCurrency
253 double fxRate = scenarioData_->get(j, k, AggregationScenarioDataType::FXSpot,
254 netting->csaDetails()->csaCurrency());
255 balance *= fxRate;
256 }
257 }
258
259 eab[j + 1] += balance / cube_->samples();
260
261 Real mporCashFlow = 0;
262 // If ActualDate is active, then the cash flows over mpor can be configured.
263 // Otherwise (StickyDate is active), it is assumed that no cash flow over mpor is paid out.
264 if (!withMporStickyDate_) {
265 if (mporCashFlowMode_ == MporCashFlowMode::BothPay) {
266 // in cube generation -actual date- the (+/-) cashflows over mpor are
267 // payed out, i.e. are not part of the exposure .
268 mporCashFlow = 0;
269 } else if (mporCashFlowMode_ == MporCashFlowMode::NonePay) {
270 // +/- cashflows is to be incorporated in the exposure
271 mporCashFlow = (nettingSetMporPositiveFlow[j][k] + nettingSetMporNegativeFlow[j][k]);
272 } else if (mporCashFlowMode_ ==
273 MporCashFlowMode::WePay) {
274 // only positive cash flows (i.e. cp's cashflows) is to be
275 // incorporated in the exposure, since cp does not pay out cash
276 // flows
277 mporCashFlow = nettingSetMporPositiveFlow[j][k];
278 } else if (mporCashFlowMode_ ==
279 MporCashFlowMode::TheyPay) { // onyl negative cash flows (i.e. our cashflows) is to be
280 // incorporated in the exposure, ince we do not pay out cash
281 // flows
282 mporCashFlow = nettingSetMporNegativeFlow[j][k];
283 }
284 }
285 Real exposure = data[j][k] - balance + mporCashFlow;
286 Real dim = 0.0;
287 if (applyInitialMargin && collateral) { // don't apply initial margin without VM, i.e. inactive CSA
288 // Initial Margin
289 // Use IM to reduce exposure
290 // Size dimIndex = j == 0 ? 0 : j - 1;
291 Size dimIndex = j;
292 dim = dimCalculator_->dynamicIM(nettingSetId)[dimIndex][k];
293 QL_REQUIRE(dim >= 0, "negative DIM for set " << nettingSetId << ", date " << j << ", sample " << k
294 << ": " << dim);
295 }
296 Real dim_epe = 0;
297 Real dim_ene = 0;
298 if (initialMarginType != CSA::Type::PostOnly)
299 dim_epe = dim;
300 if (initialMarginType != CSA::Type::CallOnly)
301 dim_ene = dim;
302
303 // dim here represents the held IM, and is expressed as a positive number
304 epe[j + 1] += std::max(exposure - dim_epe, 0.0) / cube_->samples();
305 // dim here represents the posted IM, and is expressed as a positive number
306 ene[j + 1] += std::max(-exposure - dim_ene, 0.0) / cube_->samples();
307 distribution[k] = exposure - dim_epe;
308 nettedCube_->set(exposure, nettingSetCount, j, k);
309
310 Real epeIncrement = std::max(exposure - dim_epe, 0.0) / cube_->samples();
311 DLOG("sample " << k << " date " << j << fixed << showpos << setprecision(2)
312 << ": VM " << setw(15) << balance
313 << ": NPV " << setw(15) << data[j][k]
314 << ": NPV-C " << setw(15) << distribution[k]
315 << ": EPE " << setw(15) << epeIncrement);
316
317 if (multiPath_) {
318 exposureCube_->set(std::max(exposure - dim_epe, 0.0), nettingSetCount, j, k, ExposureIndex::EPE);
319 exposureCube_->set(std::max(-exposure - dim_ene, 0.0), nettingSetCount, j, k, ExposureIndex::ENE);
320 }
321
322 if (netting->activeCsaFlag()) {
323 Real indexValue = 0.0;
324 DayCounter dc = ActualActual(ActualActual::ISDA);
325 if (csaIndexName != "") {
326 indexValue = scenarioData_->get(j, k, AggregationScenarioDataType::IndexFixing, csaIndexName);
327 dc = csaIndex->dayCounter();
328 }
329 Real dcf = dc.yearFraction(prevDate, date);
330 Real collateralSpread = (balance >= 0.0 ? netting->csaDetails()->collatSpreadRcv() : netting->csaDetails()->collatSpreadPay());
331 Real numeraire = scenarioData_->get(j, k, AggregationScenarioDataType::Numeraire);
332 Real colvaDelta = -balance * collateralSpread * dcf / numeraire / cube_->samples();
333 // intuitive floorDelta including collateralSpread would be:
334 // -balance * (max(indexValue - collateralSpread,0) - (indexValue - collateralSpread)) * dcf /
335 // samples
336 Real floorDelta = -balance * std::max(-(indexValue - collateralSpread), 0.0) * dcf / numeraire / cube_->samples();
337 colvaInc[j + 1] += colvaDelta;
338 colva_[nettingSetId] += colvaDelta;
339 eoniaFloorInc[j + 1] += floorDelta;
340 collateralFloor_[nettingSetId] += floorDelta;
341 }
342
344 Size i = 0;
345 for (auto tradeIt = portfolio_->trades().begin(); tradeIt != portfolio_->trades().end();
346 ++tradeIt, ++i) {
347 const auto& trade = tradeIt->second;
348 string nid = trade->envelope().nettingSetId();
349 if (nid != nettingSetId)
350 continue;
351
352 Real allocation = 0.0;
353 if (balance == 0.0)
354 allocation = cubeInterpretation_->getDefaultNpv(cube_, i, j, k);
355 // else if (data[j][k] == 0.0)
356 else if (fabs(data[j][k]) <= marginalAllocationLimit_)
357 allocation = exposure / nettingSetSize[nid];
358 else
359 allocation = exposure * cubeInterpretation_->getDefaultNpv(cube_, i, j, k) / data[j][k];
360
361 if (multiPath_) {
362 if (exposure > 0.0)
363 tradeExposureCube_->set(allocation, i, j, k, allocatedEpeIndex_);
364 else
365 tradeExposureCube_->set(-allocation, i, j, k, allocatedEneIndex_);
366 } else {
367 if (exposure > 0.0)
368 averagePositiveAllocation[i][j] += allocation / cube_->samples();
369 else
370 averageNegativeAllocation[i][j] -= allocation / cube_->samples();
371 }
372 }
373 }
374 }
375 if (!multiPath_) {
376 exposureCube_->set(epe[j + 1], nettingSetCount, j, 0, ExposureIndex::EPE);
377 exposureCube_->set(ene[j + 1], nettingSetCount, j, 0, ExposureIndex::ENE);
378 }
379 ee_b[j + 1] = epe[j + 1] / curve->discount(cube_->dates()[j]);
380 eee_b[j + 1] = std::max(eee_b[j], ee_b[j + 1]);
381 std::sort(distribution.begin(), distribution.end());
382 Size index = Size(floor(quantile_ * (cube_->samples() - 1) + 0.5));
383 pfe[j + 1] = std::max(distribution[index], 0.0);
384 }
385 ee_b_[nettingSetId] = ee_b;
386 eee_b_[nettingSetId] = eee_b;
387 pfe_[nettingSetId] = pfe;
388 expectedCollateral_[nettingSetId] = eab;
389 colvaInc_[nettingSetId] = colvaInc;
390 eoniaFloorInc_[nettingSetId] = eoniaFloorInc;
391
392 nettingSetCount++;
393
394 Real epe_b = 0;
395 Real eepe_b = 0;
396
397 Size t = 0;
398 Calendar cal = WeekendsOnly();
399 Date maturity = std::min(cal.adjust(today + 1 * Years + 4 * Days), nettingSetMaturity[nettingSetId]);
400 QuantLib::Real maturityTime = dc.yearFraction(today, maturity);
401
402 while (t < cube_->dates().size() && times[t] <= maturityTime)
403 ++t;
404
405 if (t > 0) {
406 vector<double> weights(t);
407 weights[0] = times[0];
408 for (Size k = 1; k < t; k++)
409 weights[k] = times[k] - times[k - 1];
410 double totalWeights = std::accumulate(weights.begin(), weights.end(), 0.0);
411 for (Size k = 0; k < t; k++)
412 weights[k] /= totalWeights;
413
414 for (Size k = 0; k < t; k++) {
415 epe_b += ee_b[k] * weights[k];
416 eepe_b += eee_b[k] * weights[k];
417 }
418 }
419 epe_b_[nettingSetId] = epe_b;
420 eepe_b_[nettingSetId] = eepe_b;
421 }
422
424 for (Size i = 0; i < portfolio_->trades().size(); ++i) {
425 for (Size j = 0; j < cube_->dates().size(); ++j) {
426 tradeExposureCube_->set(averagePositiveAllocation[i][j], i, j, 0, allocatedEpeIndex_);
427 tradeExposureCube_->set(averageNegativeAllocation[i][j], i, j, 0, allocatedEneIndex_);
428 }
429 }
430 }
431}
vector< Real > & eee_b(const string &nid)
vector< Real > & pfe(const string &nid)
map< string, std::vector< Real > > eoniaFloorInc_
map< string, std::vector< Real > > colvaInc_
QuantLib::ext::shared_ptr< vector< QuantLib::ext::shared_ptr< CollateralAccount > > > collateralPaths(const string &nettingSetId, const Real &nettingSetValueToday, const vector< vector< Real > > &nettingSetValue, const Date &nettingSetMaturity)
vector< Real > & ee_b(const string &nid)
map< string, std::vector< Real > > expectedCollateral_
data
#define LOG(text)
#define DLOG(text)
#define ALOG(text)
Time maturity
Size size(const ValueType &v)
+ Here is the call graph for this function:

◆ epe()

vector< Real > epe ( const string &  nid)

Definition at line 77 of file nettedexposurecalculator.hpp.

77{ return getMeanExposure(nid, ExposureIndex::EPE); }
vector< Real > getMeanExposure(const string &tid, ExposureIndex index)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ene()

vector< Real > ene ( const string &  nid)

Definition at line 78 of file nettedexposurecalculator.hpp.

78{ return getMeanExposure(nid, ExposureIndex::ENE); }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ee_b()

vector< Real > & ee_b ( const string &  nid)

Definition at line 79 of file nettedexposurecalculator.hpp.

79{ return ee_b_[nid]; }
+ Here is the caller graph for this function:

◆ eee_b()

vector< Real > & eee_b ( const string &  nid)

Definition at line 80 of file nettedexposurecalculator.hpp.

80{ return eee_b_[nid]; }
+ Here is the caller graph for this function:

◆ pfe()

vector< Real > & pfe ( const string &  nid)

Definition at line 81 of file nettedexposurecalculator.hpp.

81{ return pfe_[nid]; }
+ Here is the caller graph for this function:

◆ expectedCollateral()

vector< Real > & expectedCollateral ( const string &  nid)

Definition at line 82 of file nettedexposurecalculator.hpp.

82{ return expectedCollateral_[nid]; }

◆ colvaIncrements()

vector< Real > & colvaIncrements ( const string &  nid)

Definition at line 83 of file nettedexposurecalculator.hpp.

83{ return colvaInc_[nid]; }

◆ collateralFloorIncrements()

vector< Real > & collateralFloorIncrements ( const string &  nid)

Definition at line 84 of file nettedexposurecalculator.hpp.

84{ return eoniaFloorInc_[nid]; }

◆ epe_b()

Real & epe_b ( const string &  nid)

Definition at line 85 of file nettedexposurecalculator.hpp.

85{ return epe_b_[nid]; }
+ Here is the caller graph for this function:

◆ eepe_b()

Real & eepe_b ( const string &  nid)

Definition at line 86 of file nettedexposurecalculator.hpp.

86{ return eepe_b_[nid]; }
+ Here is the caller graph for this function:

◆ colva()

Real & colva ( const string &  nid)

Definition at line 87 of file nettedexposurecalculator.hpp.

87{ return colva_[nid]; }

◆ collateralFloor()

Real & collateralFloor ( const string &  nid)

Definition at line 88 of file nettedexposurecalculator.hpp.

88{ return collateralFloor_[nid]; }

◆ counterparty()

const string & counterparty ( const string  nettingSetId)

Definition at line 532 of file nettedexposurecalculator.cpp.

532 {
533 auto it = counterpartyMap_.find(nettingSetId);
534 QL_REQUIRE(it != counterpartyMap_.end(),
535 "counterparty not found for netting set id " << nettingSetId);
536 return it->second;
537}

◆ counterpartyMap()

const map< string, string > & counterpartyMap ( )

Definition at line 91 of file nettedexposurecalculator.hpp.

91{ return counterpartyMap_; }

◆ nettingSetCloseOutValue()

map< string, vector< vector< Real > > > nettingSetCloseOutValue ( )

Definition at line 92 of file nettedexposurecalculator.hpp.

◆ nettingSetDefaultValue()

map< string, vector< vector< Real > > > nettingSetDefaultValue ( )

Definition at line 93 of file nettedexposurecalculator.hpp.

+ Here is the caller graph for this function:

◆ nettingSetMporPositiveFlow()

map< string, vector< vector< Real > > > nettingSetMporPositiveFlow ( )

Definition at line 94 of file nettedexposurecalculator.hpp.

+ Here is the caller graph for this function:

◆ nettingSetMporNegativeFlow()

map< string, vector< vector< Real > > > nettingSetMporNegativeFlow ( )

Definition at line 95 of file nettedexposurecalculator.hpp.

+ Here is the caller graph for this function:

◆ getMeanExposure()

vector< Real > getMeanExposure ( const string &  tid,
ExposureIndex  index 
)
protected

Definition at line 515 of file nettedexposurecalculator.cpp.

515 {
516 vector<Real> exp(cube_->dates().size() + 1, 0.0);
517 exp[0] = exposureCube_->getT0(tid, index);
518 for (Size i = 0; i < cube_->dates().size(); i++) {
519 if (multiPath_) {
520 for (Size k = 0; k < exposureCube_->samples(); k++) {
521 exp[i + 1] += exposureCube_->get(tid, cube_->dates()[i], k, index);
522 }
523 exp[i + 1] /= exposureCube_->samples();
524 }
525 else {
526 exp[i + 1] = exposureCube_->get(tid, cube_->dates()[i], 0, index);
527 }
528 }
529 return exp;
530}
RandomVariable exp(RandomVariable x)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ collateralPaths()

QuantLib::ext::shared_ptr< vector< QuantLib::ext::shared_ptr< CollateralAccount > > > collateralPaths ( const string &  nettingSetId,
const Real &  nettingSetValueToday,
const vector< vector< Real > > &  nettingSetValue,
const Date &  nettingSetMaturity 
)
protected

Definition at line 434 of file nettedexposurecalculator.cpp.

438 {
439
440 QuantLib::ext::shared_ptr<vector<QuantLib::ext::shared_ptr<CollateralAccount>>> collateral;
441
442 if (!nettingSetManager_->has(nettingSetId) || !nettingSetManager_->get(nettingSetId)->activeCsaFlag()) {
443 LOG("CSA missing or inactive for netting set " << nettingSetId);
444 return collateral;
445 }
446
447 // retrieve collateral balances object, if possible
448 QuantLib::ext::shared_ptr<CollateralBalance> balance = nullptr;
449 if (collateralBalances_ && collateralBalances_->has(nettingSetId)) {
450 balance = collateralBalances_->get(nettingSetId);
451 LOG("got collateral balances for netting set " << nettingSetId);
452 }
453
454 LOG("Build collateral account balance paths for netting set " << nettingSetId);
455 QuantLib::ext::shared_ptr<NettingSetDefinition> netting = nettingSetManager_->get(nettingSetId);
456 string csaFxPair = netting->csaDetails()->csaCurrency() + baseCurrency_;
457 Real csaFxRateToday = 1.0;
458 if (netting->csaDetails()->csaCurrency() != baseCurrency_)
459 csaFxRateToday = market_->fxRate(csaFxPair, configuration_)->value();
460 LOG("CSA FX rate for pair " << csaFxPair << " = " << csaFxRateToday);
461
462 // Don't use Settings::instance().evaluationDate() here, this has moved to simulation end date.
463 Date today = market_->asofDate();
464 string csaIndexName = netting->csaDetails()->index();
465 // avoid thrown errors of the index fixing here on holidays of the index, instead take the preceding date then.
466 if (!market_->iborIndex(csaIndexName, configuration_)->isValidFixingDate(today)) {
467 today = market_->iborIndex(csaIndexName, configuration_)->fixingCalendar().adjust(today, Preceding);
468 }
469 Real csaRateToday = market_->iborIndex(csaIndexName, configuration_)->fixing(today);
470 LOG("CSA compounding rate for index " << csaIndexName << " = " << setprecision(8) << csaRateToday << " as of " << today);
471
472 // Copy scenario data to keep the collateral exposure helper unchanged
473 vector<vector<Real>> csaScenFxRates(cube_->dates().size(), vector<Real>(cube_->samples(), 0.0));
474 vector<vector<Real>> csaScenRates(cube_->dates().size(), vector<Real>(cube_->samples(), 0.0));
475 if (netting->csaDetails()->csaCurrency() != baseCurrency_) {
476 QL_REQUIRE(scenarioData_->has(AggregationScenarioDataType::FXSpot, netting->csaDetails()->csaCurrency()),
477 "scenario data does not provide FX rates for " << csaFxPair);
478 }
479 if (csaIndexName != "") {
480 QL_REQUIRE(scenarioData_->has(AggregationScenarioDataType::IndexFixing, csaIndexName),
481 "scenario data does not provide index values for " << csaIndexName);
482 }
483 for (Size j = 0; j < cube_->dates().size(); ++j) {
484 for (Size k = 0; k < cube_->samples(); ++k) {
485 if (netting->csaDetails()->csaCurrency() != baseCurrency_)
486 csaScenFxRates[j][k] = cubeInterpretation_->getDefaultAggregationScenarioData(
487 AggregationScenarioDataType::FXSpot, j, k, netting->csaDetails()->csaCurrency());
488 else
489 csaScenFxRates[j][k] = 1.0;
490 if (csaIndexName != "") {
491 csaScenRates[j][k] = cubeInterpretation_->getDefaultAggregationScenarioData(
492 AggregationScenarioDataType::IndexFixing, j, k, csaIndexName);
493 }
494 }
495 }
496
498 netting, // this netting set's definition
499 nettingSetValueToday, // today's netting set NPV
500 market_->asofDate(), // original evaluation date
501 nettingSetValue, // matrix of netting set values by date and sample
502 nettingSetMaturity, // netting set's maximum maturity date
503 cube_->dates(), // vector of future evaluation dates
504 csaFxRateToday, // today's FX rate for CSA to base currency, possibly 1
505 csaScenFxRates, // matrix of fx rates by date and sample, possibly 1
506 csaRateToday, // today's collateral compounding rate in CSA currency
507 csaScenRates, // matrix of CSA ccy short rates by date and sample
508 calcType_,
509 balance); // initial collateral balances (VM, IM, IA) for the netting set
510 LOG("Collateral account balance paths for netting set " << nettingSetId << " done");
511
512 return collateral;
513}
static QuantLib::ext::shared_ptr< vector< QuantLib::ext::shared_ptr< CollateralAccount > > > collateralBalancePaths(const QuantLib::ext::shared_ptr< NettingSetDefinition > &csaDef, const Real &nettingSetPv, const Date &date_t0, const vector< vector< Real > > &nettingSetValues, const Date &nettingSet_maturity, const vector< Date > &dateGrid, const Real &csaFxTodayRate, const vector< vector< Real > > &csaFxScenarioRates, const Real &csaTodayCollatCurve, const vector< vector< Real > > &csaScenCollatCurves, const CalculationType &calcType=Symmetric, const QuantLib::ext::shared_ptr< CollateralBalance > &balance=QuantLib::ext::shared_ptr< CollateralBalance >())
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ EXPOSURE_CUBE_DEPTH

const Size EXPOSURE_CUBE_DEPTH = 3

Definition at line 75 of file nettedexposurecalculator.hpp.

◆ portfolio_

QuantLib::ext::shared_ptr<Portfolio> portfolio_
protected

Definition at line 97 of file nettedexposurecalculator.hpp.

◆ market_

QuantLib::ext::shared_ptr<Market> market_
protected

Definition at line 98 of file nettedexposurecalculator.hpp.

◆ cube_

QuantLib::ext::shared_ptr<NPVCube> cube_
protected

Definition at line 99 of file nettedexposurecalculator.hpp.

◆ baseCurrency_

string baseCurrency_
protected

Definition at line 100 of file nettedexposurecalculator.hpp.

◆ configuration_

string configuration_
protected

Definition at line 101 of file nettedexposurecalculator.hpp.

◆ quantile_

Real quantile_
protected

Definition at line 102 of file nettedexposurecalculator.hpp.

◆ calcType_

Definition at line 103 of file nettedexposurecalculator.hpp.

◆ multiPath_

bool multiPath_
protected

Definition at line 104 of file nettedexposurecalculator.hpp.

◆ nettingSetManager_

const QuantLib::ext::shared_ptr<NettingSetManager> nettingSetManager_
protected

Definition at line 105 of file nettedexposurecalculator.hpp.

◆ collateralBalances_

const QuantLib::ext::shared_ptr<CollateralBalances> collateralBalances_
protected

Definition at line 106 of file nettedexposurecalculator.hpp.

◆ nettingSetDefaultValue_

map<string, vector<vector<Real> > > nettingSetDefaultValue_
protected

Definition at line 107 of file nettedexposurecalculator.hpp.

◆ nettingSetCloseOutValue_

map<string, vector<vector<Real> > > nettingSetCloseOutValue_
protected

Definition at line 108 of file nettedexposurecalculator.hpp.

◆ nettingSetMporPositiveFlow_

map<string, vector<vector<Real> > > nettingSetMporPositiveFlow_
protected

Definition at line 109 of file nettedexposurecalculator.hpp.

◆ nettingSetMporNegativeFlow_

map<string, vector<vector<Real> > > nettingSetMporNegativeFlow_
protected

Definition at line 110 of file nettedexposurecalculator.hpp.

◆ scenarioData_

const QuantLib::ext::shared_ptr<AggregationScenarioData> scenarioData_
protected

Definition at line 111 of file nettedexposurecalculator.hpp.

◆ cubeInterpretation_

QuantLib::ext::shared_ptr<CubeInterpretation> cubeInterpretation_
protected

Definition at line 112 of file nettedexposurecalculator.hpp.

◆ applyInitialMargin_

const bool applyInitialMargin_
protected

Definition at line 113 of file nettedexposurecalculator.hpp.

◆ dimCalculator_

const QuantLib::ext::shared_ptr<DynamicInitialMarginCalculator> dimCalculator_
protected

Definition at line 114 of file nettedexposurecalculator.hpp.

◆ fullInitialCollateralisation_

const bool fullInitialCollateralisation_
protected

Definition at line 115 of file nettedexposurecalculator.hpp.

◆ marginalAllocation_

const bool marginalAllocation_
protected

Definition at line 117 of file nettedexposurecalculator.hpp.

◆ marginalAllocationLimit_

const Real marginalAllocationLimit_
protected

Definition at line 118 of file nettedexposurecalculator.hpp.

◆ tradeExposureCube_

QuantLib::ext::shared_ptr<NPVCube> tradeExposureCube_
protected

Definition at line 119 of file nettedexposurecalculator.hpp.

◆ allocatedEpeIndex_

const Size allocatedEpeIndex_
protected

Definition at line 120 of file nettedexposurecalculator.hpp.

◆ allocatedEneIndex_

const Size allocatedEneIndex_
protected

Definition at line 121 of file nettedexposurecalculator.hpp.

◆ flipViewXVA_

const bool flipViewXVA_
protected

Definition at line 122 of file nettedexposurecalculator.hpp.

◆ nettedCube_

QuantLib::ext::shared_ptr<NPVCube> nettedCube_
protected

Definition at line 125 of file nettedexposurecalculator.hpp.

◆ exposureCube_

QuantLib::ext::shared_ptr<NPVCube> exposureCube_
protected

Definition at line 126 of file nettedexposurecalculator.hpp.

◆ counterpartyMap_

map<string, string> counterpartyMap_
protected

Definition at line 127 of file nettedexposurecalculator.hpp.

◆ ee_b_

map<string, std::vector<Real> > ee_b_
protected

Definition at line 128 of file nettedexposurecalculator.hpp.

◆ eee_b_

map<string, std::vector<Real> > eee_b_
protected

Definition at line 129 of file nettedexposurecalculator.hpp.

◆ pfe_

map<string, std::vector<Real> > pfe_
protected

Definition at line 130 of file nettedexposurecalculator.hpp.

◆ expectedCollateral_

map<string, std::vector<Real> > expectedCollateral_
protected

Definition at line 131 of file nettedexposurecalculator.hpp.

◆ colvaInc_

map<string, std::vector<Real> > colvaInc_
protected

Definition at line 132 of file nettedexposurecalculator.hpp.

◆ eoniaFloorInc_

map<string, std::vector<Real> > eoniaFloorInc_
protected

Definition at line 133 of file nettedexposurecalculator.hpp.

◆ epe_b_

map<string, Real> epe_b_
protected

Definition at line 134 of file nettedexposurecalculator.hpp.

◆ eepe_b_

map<string, Real> eepe_b_
protected

Definition at line 135 of file nettedexposurecalculator.hpp.

◆ colva_

map<string, Real> colva_
protected

Definition at line 136 of file nettedexposurecalculator.hpp.

◆ collateralFloor_

map<string, Real> collateralFloor_
protected

Definition at line 137 of file nettedexposurecalculator.hpp.

◆ withMporStickyDate_

bool withMporStickyDate_
protected

Definition at line 146 of file nettedexposurecalculator.hpp.

◆ mporCashFlowMode_

MporCashFlowMode mporCashFlowMode_
protected

Definition at line 147 of file nettedexposurecalculator.hpp.