Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
postprocess.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016-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
29#include <ql/errors.hpp>
30#include <ql/time/calendars/weekendsonly.hpp>
31
32#include <ql/math/distributions/normaldistribution.hpp>
33#include <ql/math/generallinearleastsquares.hpp>
34#include <ql/math/kernelfunctions.hpp>
35#include <ql/methods/montecarlo/lsmbasissystem.hpp>
36#include <ql/time/daycounters/actualactual.hpp>
37
40
41#include <boost/range/adaptors.hpp>
42#include <boost/accumulators/accumulators.hpp>
43#include <boost/accumulators/statistics/error_of_mean.hpp>
44#include <boost/accumulators/statistics/mean.hpp>
45#include <boost/accumulators/statistics/stats.hpp>
46
47using namespace std;
48using namespace QuantLib;
49
50using namespace boost::accumulators;
51
52namespace ore {
53namespace analytics {
54
56 const QuantLib::ext::shared_ptr<Portfolio>& portfolio, const QuantLib::ext::shared_ptr<NettingSetManager>& nettingSetManager,
57 const QuantLib::ext::shared_ptr<CollateralBalances>& collateralBalances,
58 const QuantLib::ext::shared_ptr<Market>& market, const std::string& configuration, const QuantLib::ext::shared_ptr<NPVCube>& cube,
59 const QuantLib::ext::shared_ptr<AggregationScenarioData>& scenarioData, const map<string, bool>& analytics,
60 const string& baseCurrency, const string& allocMethod, Real marginalAllocationLimit, Real quantile,
61 const string& calculationType, const string& dvaName, const string& fvaBorrowingCurve,
62 const string& fvaLendingCurve, const QuantLib::ext::shared_ptr<DynamicInitialMarginCalculator>& dimCalculator,
63 const QuantLib::ext::shared_ptr<CubeInterpretation>& cubeInterpretation, bool fullInitialCollateralisation,
64 vector<Period> cvaSensiGrid, Real cvaSensiShiftSize, Real kvaCapitalDiscountRate, Real kvaAlpha,
65 Real kvaRegAdjustment, Real kvaCapitalHurdle, Real kvaOurPdFloor, Real kvaTheirPdFloor, Real kvaOurCvaRiskWeight,
66 Real kvaTheirCvaRiskWeight, const QuantLib::ext::shared_ptr<NPVCube>& cptyCube, const string& flipViewBorrowingCurvePostfix,
67 const string& flipViewLendingCurvePostfix,
68 const QuantLib::ext::shared_ptr<CreditSimulationParameters>& creditSimulationParameters,
69 const std::vector<Real>& creditMigrationDistributionGrid, const std::vector<Size>& creditMigrationTimeSteps,
70 const Matrix& creditStateCorrelationMatrix, bool withMporStickyDate, MporCashFlowMode mporCashFlowMode)
71: portfolio_(portfolio), nettingSetManager_(nettingSetManager), collateralBalances_(collateralBalances),
72 market_(market), configuration_(configuration),
73 cube_(cube), cptyCube_(cptyCube), scenarioData_(scenarioData), analytics_(analytics), baseCurrency_(baseCurrency),
74 quantile_(quantile), calcType_(parseCollateralCalculationType(calculationType)), dvaName_(dvaName),
75 fvaBorrowingCurve_(fvaBorrowingCurve), fvaLendingCurve_(fvaLendingCurve), dimCalculator_(dimCalculator),
76 cubeInterpretation_(cubeInterpretation), fullInitialCollateralisation_(fullInitialCollateralisation),
77 cvaSpreadSensiGrid_(cvaSensiGrid), cvaSpreadSensiShiftSize_(cvaSensiShiftSize),
78 kvaCapitalDiscountRate_(kvaCapitalDiscountRate), kvaAlpha_(kvaAlpha), kvaRegAdjustment_(kvaRegAdjustment),
79 kvaCapitalHurdle_(kvaCapitalHurdle), kvaOurPdFloor_(kvaOurPdFloor), kvaTheirPdFloor_(kvaTheirPdFloor),
80 kvaOurCvaRiskWeight_(kvaOurCvaRiskWeight), kvaTheirCvaRiskWeight_(kvaTheirCvaRiskWeight),
81 creditSimulationParameters_(creditSimulationParameters),
82 creditMigrationDistributionGrid_(creditMigrationDistributionGrid),
83 creditMigrationTimeSteps_(creditMigrationTimeSteps), creditStateCorrelationMatrix_(creditStateCorrelationMatrix),
84 withMporStickyDate_(withMporStickyDate), mporCashFlowMode_(mporCashFlowMode) {
85
86 QL_REQUIRE(cubeInterpretation_ != nullptr, "PostProcess: cubeInterpretation is not given.");
87
88 if (mporCashFlowMode_ == MporCashFlowMode::Unspecified) {
89 mporCashFlowMode_ = withMporStickyDate_ ? MporCashFlowMode::NonePay : MporCashFlowMode::BothPay;
90 }
91
92 QL_REQUIRE(!withMporStickyDate_ || mporCashFlowMode_ == MporCashFlowMode::NonePay,
93 "PostProcess: MporMode StickyDate supports only MporCashFlowMode NonePay");
94 QL_REQUIRE(cubeInterpretation_->storeFlows() || withMporStickyDate || mporCashFlowMode_ == MporCashFlowMode::BothPay,
95 "PostProcess: If cube does not hold any mpor flows and MporMode is set to ActualDate, then "
96 "MporCashFlowMode must "
97 "be set to BothPay");
98
99 bool isRegularCubeStorage = !cubeInterpretation_->withCloseOutLag();
100
101 LOG("cube storage is regular: " << isRegularCubeStorage);
102 LOG("cube dates: " << cube->dates().size());
103
104 QL_REQUIRE(marginalAllocationLimit > 0.0, "positive allocationLimit expected");
105
106 // check portfolio and cube have the same trade ids, in the same order
107 QL_REQUIRE(portfolio->size() == cube_->idsAndIndexes().size(),
108 "PostProcess::PostProcess(): portfolio size ("
109 << portfolio->size() << ") does not match cube trade size (" << cube_->idsAndIndexes().size() << ")");
110
111 auto portfolioIt = portfolio->trades().begin();
112 auto cubeIdIt = cube_->idsAndIndexes().begin();
113 for (size_t i = 0; i < portfolio->size(); i++, portfolioIt++, cubeIdIt++) {
114 const std::string& portfolioTradeId = portfolioIt->first;
115 const std::string& cubeTradeId = cubeIdIt->first;
116 QL_REQUIRE(portfolioTradeId == cubeTradeId, "PostProcess::PostProcess(): portfolio trade #"
117 << i << " (id=" << portfolioTradeId
118 << ") does not match cube trade id (" << cubeTradeId);
119 }
120
121 if (analytics_["dynamicCredit"]) {
122 QL_REQUIRE(cptyCube_, "cptyCube cannot be null when dynamicCredit is ON");
123 // check portfolio and cptyCube have the same counterparties, in the same order
124 auto cptyIds = portfolio->counterparties();
125 cptyIds.insert(dvaName_);
126 QL_REQUIRE(cptyIds.size() == cptyCube_->idsAndIndexes().size(),
127 "PostProcess::PostProcess(): portfolio counterparty size ("
128 << cptyIds.size() << ") does not match cpty cube trade size ("
129 << cptyCube_->idsAndIndexes().size() << ")");
130
131 auto cptyIt = cptyIds.begin();
132 cubeIdIt = cptyCube_->idsAndIndexes().begin();
133 for (size_t i = 0; i < cptyIds.size(); ++i, ++cptyIt, ++cubeIdIt) {
134 const std::string& counterpartyId = *cptyIt;
135 const std::string& cubeTradeId = cubeIdIt->first;
136 QL_REQUIRE(counterpartyId == cubeTradeId, "PostProcess::PostProcess(): portfolio counterparty #"
137 << i << " (id=" << counterpartyId
138 << ") does not match cube name id (" << cubeTradeId);
139 }
140 }
141
142 ExposureAllocator::AllocationMethod allocationMethod = parseAllocationMethod(allocMethod);
143
144 /***********************************************
145 * Step 0: Netting as of today
146 * a) Compute the netting set NPV as of today
147 * b) Find the final maturity of the netting set
148 */
149 LOG("Compute netting set NPVs as of today and netting set maturity");
150 // Don't use Settings::instance().evaluationDate() here, this has moved to simulation end date.
151 Date today = market->asofDate();
152 LOG("AsOfDate = " << QuantLib::io::iso_date(today));
153
154 /***************************************************************
155 * Step 1: Dynamic Initial Margin calculation
156 * Fills DIM cube per netting set that can be
157 * - returned to be further analysed
158 * - used in collateral calculation
159 * - used in MVA calculation
160 */
161 if (analytics_["dim"] || analytics_["mva"]) {
162 QL_REQUIRE(dimCalculator_, "DIM calculator not set");
163 dimCalculator_->build();
164 }
165
166 /************************************************************
167 * Step 2: Trade Exposure and Netting
168 * a) Aggregation across scenarios per trade and date
169 * This yields single trade exposure profiles, EPE and ENE
170 * b) Aggregation of NPVs within netting sets per date
171 * and scenario. This prepares the netting set exposure
172 * calculation below
173 */
175 QuantLib::ext::make_shared<ExposureCalculator>(
176 portfolio, cube_, cubeInterpretation_,
177 market_, analytics_["exerciseNextBreak"], baseCurrency_, configuration_,
178 quantile_, calcType_, analytics_["dynamicCredit"], analytics_["flipViewXVA"]
179 );
180 exposureCalculator_->build();
181
182 /******************************************************************
183 * Step 3: Netting set exposure and allocation to trades
184 *
185 * a) Compute all netting set exposure profiles EPE and ENE using
186 * collateral if CSAs are given and active.
187 * b) Compute the expected collateral balance for each netting set.
188 * c) Allocate each netting set's exposure profile to the trade
189 * level such that the trade exposures add up to the netting
190 * set exposure.
191 * Reference:
192 * Michael Pykhtin & Dan Rosen, Pricing Counterparty Risk
193 * at the Trade Level and CVA Allocations, October 2010
194 */
195 nettedExposureCalculator_ = QuantLib::ext::make_shared<NettedExposureCalculator>(
196 portfolio_, market_, cube_, baseCurrency, configuration_, quantile_, calcType_, analytics_["dynamicCredit"],
198 exposureCalculator_->nettingSetCloseOutValue(), exposureCalculator_->nettingSetMporPositiveFlow(),
199 exposureCalculator_->nettingSetMporNegativeFlow(), scenarioData_, cubeInterpretation_, analytics_["dim"],
201 allocationMethod == ExposureAllocator::AllocationMethod::Marginal, marginalAllocationLimit,
205
206 /********************************************************
207 * Update Stand Alone XVAs
208 * needed for some of the simple allocation methods below
209 */
210 if (analytics_["dynamicCredit"]) {
211 cvaCalculator_ = QuantLib::ext::make_shared<DynamicCreditXvaCalculator>(
214 dimCalculator, exposureCalculator_->exposureCube(),
215 nettedExposureCalculator_->exposureCube(), cptyCube_,
220 flipViewBorrowingCurvePostfix, flipViewLendingCurvePostfix);
221 } else {
222 cvaCalculator_ = QuantLib::ext::make_shared<StaticCreditXvaCalculator>(
225 dimCalculator, exposureCalculator_->exposureCube(),
226 nettedExposureCalculator_->exposureCube(),
231 flipViewBorrowingCurvePostfix, flipViewLendingCurvePostfix);
232 }
233 cvaCalculator_->build();
234
235 /***************************
236 * Simple allocation methods
237 */
238 QuantLib::ext::shared_ptr<ExposureAllocator> exposureAllocator;
239 if (allocationMethod == ExposureAllocator::AllocationMethod::Marginal) {
240 DLOG("Marginal Calculation handled in NettedExposureCalculator");
241 }
243 exposureAllocator = QuantLib::ext::make_shared<RelativeFairValueNetExposureAllocator>(
244 portfolio, exposureCalculator_->exposureCube(),
245 nettedExposureCalculator_->exposureCube(), cube_,
250 exposureAllocator = QuantLib::ext::make_shared<RelativeFairValueGrossExposureAllocator>(
251 portfolio, exposureCalculator_->exposureCube(),
252 nettedExposureCalculator_->exposureCube(), cube_,
256 else if (allocationMethod == ExposureAllocator::AllocationMethod::RelativeXVA)
257 exposureAllocator = QuantLib::ext::make_shared<RelativeXvaExposureAllocator>(
258 portfolio, exposureCalculator_->exposureCube(),
259 nettedExposureCalculator_->exposureCube(), cube_,
260 cvaCalculator_->tradeCva(), cvaCalculator_->tradeDva(),
261 cvaCalculator_->nettingSetSumCva(), cvaCalculator_->nettingSetSumDva(),
265 else if (allocationMethod == ExposureAllocator::AllocationMethod::None)
266 exposureAllocator = QuantLib::ext::make_shared<NoneExposureAllocator>(
267 portfolio, exposureCalculator_->exposureCube(),
268 nettedExposureCalculator_->exposureCube());
269 else
270 QL_FAIL("allocationMethod " << allocationMethod << " not available");
271 if(exposureAllocator)
272 exposureAllocator->build();
273
274 /********************************************************
275 * Update Allocated XVAs
276 */
277 if (analytics_["dynamicCredit"]) {
278 allocatedCvaCalculator_ = QuantLib::ext::make_shared<DynamicCreditXvaCalculator>(
280 analytics_["dim"], dimCalculator, exposureCalculator_->exposureCube(),
283 NettedExposureCalculator::ExposureIndex::ENE, 0, analytics_["flipViewXVA"], flipViewBorrowingCurvePostfix,
284 flipViewLendingCurvePostfix);
285 } else {
286 allocatedCvaCalculator_ = QuantLib::ext::make_shared<StaticCreditXvaCalculator>(
288 analytics_["dim"], dimCalculator, exposureCalculator_->exposureCube(),
291 NettedExposureCalculator::ExposureIndex::ENE, analytics_["flipViewXVA"], flipViewBorrowingCurvePostfix,
292 flipViewLendingCurvePostfix);
293 }
295
296 /********************************************************
297 * Cache average EPE and ENE
298 */
299 for (const auto& [tradeId,_]: tradeIds()) {
300 tradeEPE_[tradeId] = exposureCalculator_->epe(tradeId);
301 tradeENE_[tradeId] = exposureCalculator_->ene(tradeId);
302 allocatedTradeEPE_[tradeId] = exposureCalculator_->allocatedEpe(tradeId);
303 allocatedTradeENE_[tradeId] = exposureCalculator_->allocatedEne(tradeId);
304 }
305 for (const auto& [nettingSetId, pos] : nettingSetIds()) {
306 netEPE_[nettingSetId] = nettedExposureCalculator_->epe(nettingSetId);
307 netENE_[nettingSetId] = nettedExposureCalculator_->ene(nettingSetId);
308 }
309
310 /********************************************************
311 * Calculate netting set KVA-CCR and KVA-CVA
312 */
314
315 /***************************************
316 * Calculate netting set CVA sensitivity
317 */
319
320 /***************************************
321 * Credit migration analysis
322 */
323 if (analytics_["creditMigration"]) {
324 creditMigrationCalculator_ = QuantLib::ext::make_shared<CreditMigrationCalculator>(
332 }
333}
334
336
337 // Loop over all netting sets
338 for (const auto& [nettingSetId,pos] : nettingSetIds()) {
339 // Init results
340 ourNettingSetKVACCR_[nettingSetId] = 0.0;
341 theirNettingSetKVACCR_[nettingSetId] = 0.0;
342 ourNettingSetKVACVA_[nettingSetId] = 0.0;
343 theirNettingSetKVACVA_[nettingSetId] = 0.0;
344 }
345
346 if (!analytics_["kva"])
347 return;
348
349 LOG("Update netting set KVA");
350
351 vector<Date> dateVector = cube_->dates();
352 Size dates = dateVector.size();
353 Date today = market_->asofDate();
354 Handle<YieldTermStructure> discountCurve = market_->discountCurve(baseCurrency_, configuration_);
355 DayCounter dc = ActualActual(ActualActual::ISDA);
356
357 // Loop over all netting sets
358 for (const auto& [nettingSetId, pos] : nettingSetIds()) {
359 string cid;
360 if (analytics_["flipViewXVA"]) {
361 cid = dvaName_;
362 } else {
363 cid = nettedExposureCalculator_->counterparty(nettingSetId);
364 }
365 LOG("KVA for netting set " << nettingSetId);
366
367 // Main input are the EPE and ENE profiles, previously computed
368 vector<Real> epe = netEPE_[nettingSetId];
369 vector<Real> ene = netENE_[nettingSetId];
370
371 // PD from counterparty Dts, floored to avoid 0 ...
372 // Today changed to today+1Y to get the one-year PD
373 Handle<DefaultProbabilityTermStructure> cvaDts = market_->defaultCurve(cid, configuration_)->curve();
374 QL_REQUIRE(!cvaDts.empty(), "Default curve missing for counterparty " << cid);
375 Real cvaRR = market_->recoveryRate(cid, configuration_)->value();
376 Real PD1 = std::max(cvaDts->defaultProbability(today + 1 * Years), 0.000000000001);
377 Real LGD1 = (1 - cvaRR);
378
379 // FIXME: if flipViewXVA is sufficient, then all code for their KVA-CCR could be discarded here...
380 Handle<DefaultProbabilityTermStructure> dvaDts;
381 Real dvaRR = 0.0;
382 Real PD2 = 0;
383 if (analytics_["flipViewXVA"]) {
384 dvaName_ = nettedExposureCalculator_->counterparty(nettingSetId);
385 }
386 if (dvaName_ != "") {
387 dvaDts = market_->defaultCurve(dvaName_, configuration_)->curve();
388 dvaRR = market_->recoveryRate(dvaName_, configuration_)->value();
389 PD2 = std::max(dvaDts->defaultProbability(today + 1 * Years), 0.000000000001);
390 } else {
391 ALOG("dvaName not specified, own PD set to zero for their KVA calculation");
392 }
393 Real LGD2 = (1 - dvaRR);
394
395 // Granularity adjustment, Gordy (2004):
396 Real rho1 = 0.12 * (1 - std::exp(-50 * PD1)) / (1 - std::exp(-50)) +
397 0.24 * (1 - (1 - std::exp(-50 * PD1)) / (1 - std::exp(-50)));
398 Real rho2 = 0.12 * (1 - std::exp(-50 * PD2)) / (1 - std::exp(-50)) +
399 0.24 * (1 - (1 - std::exp(-50 * PD2)) / (1 - std::exp(-50)));
400
401 // Basel II internal rating based (IRB) estimate of worst case PD:
402 // Large homogeneous pool (LHP) approximation of Vasicek (1997)
403 InverseCumulativeNormal icn;
404 CumulativeNormalDistribution cnd;
405 Real PD99_1 = cnd((icn(PD1) + std::sqrt(rho1) * icn(0.999)) / (std::sqrt(1 - rho1))) - PD1;
406 Real PD99_2 = cnd((icn(PD2) + std::sqrt(rho2) * icn(0.999)) / (std::sqrt(1 - rho2))) - PD2;
407
408 // KVA regulatory PD, worst case PD, floored at 0.03 for corporates and banks, not floored for sovereigns
409 Real kva99PD1 = std::max(PD99_1, kvaTheirPdFloor_);
410 Real kva99PD2 = std::max(PD99_2, kvaOurPdFloor_);
411
412 // Factor B(PD) for the maturity adjustment factor, B(PD) = (0.11852 - 0.05478 * ln(PD)) ^ 2
413 Real kvaMatAdjB1 = std::pow((0.11852 - 0.05478 * std::log(PD1)), 2.0);
414 Real kvaMatAdjB2 = std::pow((0.11852 - 0.05478 * std::log(PD2)), 2.0);
415
416 DLOG("Our KVA-CCR " << nettingSetId << ": PD=" << PD1);
417 DLOG("Our KVA-CCR " << nettingSetId << ": LGD=" << LGD1);
418 DLOG("Our KVA-CCR " << nettingSetId << ": rho=" << rho1);
419 DLOG("Our KVA-CCR " << nettingSetId << ": PD99=" << PD99_1);
420 DLOG("Our KVA-CCR " << nettingSetId << ": PD Floor=" << kvaTheirPdFloor_);
421 DLOG("Our KVA-CCR " << nettingSetId << ": Floored PD99=" << kva99PD1);
422 DLOG("Our KVA-CCR " << nettingSetId << ": B(PD)=" << kvaMatAdjB1);
423
424 DLOG("Their KVA-CCR " << nettingSetId << ": PD=" << PD2);
425 DLOG("Their KVA-CCR " << nettingSetId << ": LGD=" << LGD2);
426 DLOG("Their KVA-CCR " << nettingSetId << ": rho=" << rho2);
427 DLOG("Their KVA-CCR " << nettingSetId << ": PD99=" << PD99_2);
428 DLOG("Their KVA-CCR " << nettingSetId << ": PD Floor=" << kvaOurPdFloor_);
429 DLOG("Their KVA-CCR " << nettingSetId << ": Floored PD99=" << kva99PD2);
430 DLOG("Their KVA-CCR " << nettingSetId << ": B(PD)=" << kvaMatAdjB2);
431
432 for (Size j = 0; j < dates; ++j) {
433 Date d0 = j == 0 ? today : cube_->dates()[j - 1];
434 Date d1 = cube_->dates()[j];
435
436 // Preprocess:
437 // 1) Effective maturity from effective expected exposure as of time j
438 // Index _1 corresponds to our perspective, index _2 to their perspective.
439 // 2) Basel EEPE as of time j, i.e. as time average over EEE, starting at time j
440 // More accuracy may be achieved here by using a Longstaff-Schwartz method / regression
441 Real eee_kva_1 = 0.0, eee_kva_2 = 0.0;
442 Real effMatNumer1 = 0.0, effMatNumer2 = 0.0;
443 Real effMatDenom1 = 0.0, effMatDenom2 = 0.0;
444 Real eepe_kva_1 = 0, eepe_kva_2 = 0.0;
445 Size kmax = j, count = 0;
446 // Cut off index for EEPE/EENE calculation: One year ahead
447 while (dateVector[kmax] < dateVector[j] + 1 * Years + 4 * Days && kmax < dates - 1)
448 kmax++;
449 Real sumdt = 0.0, eee1_b = 0.0, eee2_b = 0.0;
450 for (Size k = j; k < dates; ++k) {
451 Date d2 = cube_->dates()[k];
452 Date prevDate = k == 0 ? today : dateVector[k - 1];
453
454 eee_kva_1 = std::max(eee_kva_1, epe[k + 1]);
455 eee_kva_2 = std::max(eee_kva_2, ene[k + 1]);
456
457 // Components of the KVA maturity adjustment MA as of time j
458 if (dc.yearFraction(d1, d2) > 1.0) {
459 effMatNumer1 += epe[k + 1] * dc.yearFraction(prevDate, d2);
460 effMatNumer2 += ene[k + 1] * dc.yearFraction(prevDate, d2);
461 }
462 if (dc.yearFraction(d1, d2) <= 1.0) {
463 effMatDenom1 += eee_kva_1 * dc.yearFraction(prevDate, d2);
464 effMatDenom2 += eee_kva_2 * dc.yearFraction(prevDate, d2);
465 }
466
467 if (k < kmax) {
468 Real dt = dc.yearFraction(cube_->dates()[k], cube_->dates()[k + 1]);
469 sumdt += dt;
470 Real epe_b = epe[k + 1] / discountCurve->discount(dateVector[k]);
471 Real ene_b = ene[k + 1] / discountCurve->discount(dateVector[k]);
472 eee1_b = std::max(epe_b, eee1_b);
473 eee2_b = std::max(ene_b, eee2_b);
474 eepe_kva_1 += eee1_b * dt;
475 eepe_kva_2 += eee2_b * dt;
476 count++;
477 }
478 }
479
480 // Normalize EEPE/EENE calculation
481 eepe_kva_1 = count > 0 ? eepe_kva_1 / sumdt : 0.0;
482 eepe_kva_2 = count > 0 ? eepe_kva_2 / sumdt : 0.0;
483
484 // KVA CCR using the IRB risk weighted asset method and IMM:
485 // KVA effective maturity of the nettingSet, capped at 5
486 Real kvaNWMaturity1 = std::min(1.0 + (effMatDenom1 == 0.0 ? 0.0 : effMatNumer1 / effMatDenom1), 5.0);
487 Real kvaNWMaturity2 = std::min(1.0 + (effMatDenom2 == 0.0 ? 0.0 : effMatNumer2 / effMatDenom2), 5.0);
488
489 // Maturity adjustment factor for the RWA method:
490 // MA(PD, M) = (1 + (M - 2.5) * B(PD)) / (1 - 1.5 * B(PD)), capped at 5, floored at 1, M = effective
491 // maturity
492 Real kvaMatAdj1 =
493 std::max(std::min((1.0 + (kvaNWMaturity1 - 2.5) * kvaMatAdjB1) / (1.0 - 1.5 * kvaMatAdjB1), 5.0), 1.0);
494 Real kvaMatAdj2 =
495 std::max(std::min((1.0 + (kvaNWMaturity2 - 2.5) * kvaMatAdjB2) / (1.0 - 1.5 * kvaMatAdjB2), 5.0), 1.0);
496
497 // CCR Capital: RC = EAD x LGD x PD99.9 x MA(PD, M); EAD = alpha x EEPE(t) (approximated by EPE here);
498 Real kvaRC1 = kvaAlpha_ * eepe_kva_1 * LGD1 * kva99PD1 * kvaMatAdj1;
499 Real kvaRC2 = kvaAlpha_ * eepe_kva_2 * LGD2 * kva99PD2 * kvaMatAdj2;
500
501 // Expected risk capital discounted at capital discount rate
502 Real kvaCapitalDiscount = 1 / std::pow(1 + kvaCapitalDiscountRate_, dc.yearFraction(today, d0));
503 Real kvaCCRIncrement1 =
504 kvaRC1 * kvaCapitalDiscount * dc.yearFraction(d0, d1) * kvaCapitalHurdle_ * kvaRegAdjustment_;
505 Real kvaCCRIncrement2 =
506 kvaRC2 * kvaCapitalDiscount * dc.yearFraction(d0, d1) * kvaCapitalHurdle_ * kvaRegAdjustment_;
507
508 ourNettingSetKVACCR_[nettingSetId] += kvaCCRIncrement1;
509 theirNettingSetKVACCR_[nettingSetId] += kvaCCRIncrement2;
510
511 DLOG("Our KVA-CCR for " << nettingSetId << ": " << j << " EEPE=" << setprecision(2) << eepe_kva_1
512 << " EPE=" << epe[j] << " RC=" << kvaRC1 << " M=" << setprecision(6)
513 << kvaNWMaturity1 << " MA=" << kvaMatAdj1 << " Cost=" << setprecision(2)
514 << kvaCCRIncrement1 << " KVA=" << ourNettingSetKVACCR_[nettingSetId]);
515 DLOG("Their KVA-CCR for " << nettingSetId << ": " << j << " EENE=" << eepe_kva_2 << " ENE=" << ene[j]
516 << " RC=" << kvaRC2 << " M=" << setprecision(6) << kvaNWMaturity2
517 << " MA=" << kvaMatAdj2 << " Cost=" << setprecision(2) << kvaCCRIncrement2
518 << " KVA=" << theirNettingSetKVACCR_[nettingSetId]);
519
520 // CVA Capital
521 // effective maturity without cap at 5, DF set to 1 for IMM banks
522 // TODO: Set MA in CCR capital calculation to 1
523 Real kvaCvaMaturity1 = 1.0 + (effMatDenom1 == 0.0 ? 0.0 : effMatNumer1 / effMatDenom1);
524 Real kvaCvaMaturity2 = 1.0 + (effMatDenom2 == 0.0 ? 0.0 : effMatNumer2 / effMatDenom2);
525 Real scva1 = kvaTheirCvaRiskWeight_ * kvaCvaMaturity1 * eepe_kva_1;
526 Real scva2 = kvaOurCvaRiskWeight_ * kvaCvaMaturity2 * eepe_kva_2;
527 Real kvaCVAIncrement1 =
528 scva1 * kvaCapitalDiscount * dc.yearFraction(d0, d1) * kvaCapitalHurdle_ * kvaRegAdjustment_;
529 Real kvaCVAIncrement2 =
530 scva2 * kvaCapitalDiscount * dc.yearFraction(d0, d1) * kvaCapitalHurdle_ * kvaRegAdjustment_;
531
532 DLOG("Our KVA-CVA for " << nettingSetId << ": " << j << " EEPE=" << eepe_kva_1 << " SCVA=" << scva1
533 << " Cost=" << kvaCVAIncrement1);
534 DLOG("Their KVA-CVA for " << nettingSetId << ": " << j << " EENE=" << eepe_kva_2 << " SCVA=" << scva2
535 << " Cost=" << kvaCVAIncrement2);
536
537 ourNettingSetKVACVA_[nettingSetId] += kvaCVAIncrement1;
538 theirNettingSetKVACVA_[nettingSetId] += kvaCVAIncrement2;
539 }
540 }
541
542 LOG("Update netting set KVA done");
543}
544
546
547 if (!analytics_["cvaSensi"])
548 return;
549
550 LOG("Update netting set CVA sensitivities");
551
552 Handle<YieldTermStructure> discountCurve = market_->discountCurve(baseCurrency_, configuration_);
553
554 for (auto n : netEPE_) {
555 string nettingSetId = n.first;
556 vector<Real> epe = netEPE_[nettingSetId];
557 string cid;
558 Handle<DefaultProbabilityTermStructure> cvaDts;
559 Real cvaRR;
560 if (analytics_["flipViewXVA"]) {
561 cid = dvaName_;
562 } else {
563 cid = nettedExposureCalculator_->counterparty(nettingSetId);
564 }
565 cvaDts = market_->defaultCurve(cid)->curve();
566 QL_REQUIRE(!cvaDts.empty(), "Default curve missing for counterparty " << cid);
567 cvaRR = market_->recoveryRate(cid, configuration_)->value();
568
569 bool cvaSensi = analytics_["cvaSensi"];
570 LOG("CVA Sensitivity: " << cvaSensi);
571 if (cvaSensi) {
572 QuantLib::ext::shared_ptr<CVASpreadSensitivityCalculator> cvaSensiCalculator = QuantLib::ext::make_shared<CVASpreadSensitivityCalculator>(
573 nettingSetId, market_->asofDate(), epe, cube_->dates(), cvaDts, cvaRR, discountCurve, cvaSpreadSensiGrid_, cvaSpreadSensiShiftSize_);
574
575 for (Size i = 0; i < cvaSensiCalculator->shiftTimes().size(); ++i) {
576 DLOG("CVA Sensi Calculator: t=" << cvaSensiCalculator->shiftTimes()[i]
577 << " h=" << cvaSensiCalculator->hazardRateSensitivities()[i]
578 << " s=" << cvaSensiCalculator->cdsSpreadSensitivities()[i]);
579 }
580
581 netCvaHazardRateSensi_[nettingSetId] = cvaSensiCalculator->hazardRateSensitivities();
582 netCvaSpreadSensi_[nettingSetId] = cvaSensiCalculator->cdsSpreadSensitivities();
583 cvaSpreadSensiTimes_ = cvaSensiCalculator->shiftTimes();
584 } else {
585 cvaSpreadSensiTimes_ = vector<Real>();
586 netCvaHazardRateSensi_[nettingSetId] = vector<Real>();
587 netCvaSpreadSensi_[nettingSetId] = vector<Real>();
588 }
589 }
590
591 LOG("Update netting set CVA sensitivities done");
592}
593
594const vector<Real>& PostProcess::tradeEPE(const string& tradeId) {
595 QL_REQUIRE(tradeEPE_.find(tradeId) != tradeEPE_.end(), "Trade " << tradeId << " not found in exposure map");
596 return tradeEPE_[tradeId];
597}
598
599const vector<Real>& PostProcess::tradeENE(const string& tradeId) {
600 QL_REQUIRE(tradeENE_.find(tradeId) != tradeENE_.end(), "Trade " << tradeId << " not found in exposure map");
601 return tradeENE_[tradeId];
602}
603
604const vector<Real>& PostProcess::tradeEE_B(const string& tradeId) {
605 return exposureCalculator_->ee_b(tradeId);
606}
607
608const Real& PostProcess::tradeEPE_B(const string& tradeId) {
609 return exposureCalculator_->epe_b(tradeId);
610}
611
612const vector<Real>& PostProcess::tradeEEE_B(const string& tradeId) {
613 return exposureCalculator_->eee_b(tradeId);
614}
615
616const Real& PostProcess::tradeEEPE_B(const string& tradeId) {
617 return exposureCalculator_->eepe_b(tradeId);
618}
619
620const vector<Real>& PostProcess::tradePFE(const string& tradeId) {
621 return exposureCalculator_->pfe(tradeId);
622}
623
624const vector<Real>& PostProcess::netEPE(const string& nettingSetId) {
625 QL_REQUIRE(netEPE_.find(nettingSetId) != netEPE_.end(),
626 "Netting set " << nettingSetId << " not found in exposure map");
627 return netEPE_[nettingSetId];
628}
629
630const vector<Real>& PostProcess::netENE(const string& nettingSetId) {
631 QL_REQUIRE(netENE_.find(nettingSetId) != netENE_.end(),
632 "Netting set " << nettingSetId << " not found in exposure map");
633 return netENE_[nettingSetId];
634}
635
636vector<Real> PostProcess::netCvaHazardRateSensitivity(const string& nettingSetId) {
637 if (netCvaHazardRateSensi_.find(nettingSetId) != netCvaHazardRateSensi_.end())
638 return netCvaHazardRateSensi_[nettingSetId];
639 else
640 return vector<Real>();
641}
642
643vector<Real> PostProcess::netCvaSpreadSensitivity(const string& nettingSetId) {
644 if (netCvaSpreadSensi_.find(nettingSetId) != netCvaSpreadSensi_.end())
645 return netCvaSpreadSensi_[nettingSetId];
646 else
647 return vector<Real>();
648}
649
650const vector<Real>& PostProcess::netEE_B(const string& nettingSetId) {
651 return nettedExposureCalculator_->ee_b(nettingSetId);
652}
653
654const Real& PostProcess::netEPE_B(const string& nettingSetId) {
655 return nettedExposureCalculator_->epe_b(nettingSetId);
656}
657
658const vector<Real>& PostProcess::netEEE_B(const string& nettingSetId) {
659 return nettedExposureCalculator_->eee_b(nettingSetId);
660}
661
662const Real& PostProcess::netEEPE_B(const string& nettingSetId) {
663 return nettedExposureCalculator_->eepe_b(nettingSetId);
664}
665
666const vector<Real>& PostProcess::netPFE(const string& nettingSetId) {
667 return nettedExposureCalculator_->pfe(nettingSetId);
668}
669
670const vector<Real>& PostProcess::expectedCollateral(const string& nettingSetId) {
671 return nettedExposureCalculator_->expectedCollateral(nettingSetId);
672}
673
674const vector<Real>& PostProcess::colvaIncrements(const string& nettingSetId) {
675 return nettedExposureCalculator_->colvaIncrements(nettingSetId);
676}
677
678const vector<Real>& PostProcess::collateralFloorIncrements(const string& nettingSetId) {
679 return nettedExposureCalculator_->collateralFloorIncrements(nettingSetId);
680}
681
682const vector<Real>& PostProcess::allocatedTradeEPE(const string& tradeId) {
683 QL_REQUIRE(allocatedTradeEPE_.find(tradeId) != allocatedTradeEPE_.end(),
684 "Trade " << tradeId << " not found in exposure map");
685 return allocatedTradeEPE_[tradeId];
686}
687
688const vector<Real>& PostProcess::allocatedTradeENE(const string& tradeId) {
689 QL_REQUIRE(allocatedTradeENE_.find(tradeId) != allocatedTradeENE_.end(),
690 "Trade " << tradeId << " not found in exposure map");
691 return allocatedTradeENE_[tradeId];
692}
693
694Real PostProcess::tradeCVA(const string& tradeId) {
695 return cvaCalculator_->tradeCva(tradeId);
696}
697
698Real PostProcess::tradeDVA(const string& tradeId) {
699 return cvaCalculator_->tradeDva(tradeId);
700}
701
702Real PostProcess::tradeMVA(const string& tradeId) {
703 return cvaCalculator_->tradeMva(tradeId);
704}
705
706Real PostProcess::tradeFBA(const string& tradeId) {
707 return cvaCalculator_->tradeFba(tradeId);
708}
709
710Real PostProcess::tradeFCA(const string& tradeId) {
711 return cvaCalculator_->tradeFca(tradeId);
712}
713
714Real PostProcess::tradeFBA_exOwnSP(const string& tradeId) {
715 return cvaCalculator_->tradeFba_exOwnSp(tradeId);
716}
717
718Real PostProcess::tradeFCA_exOwnSP(const string& tradeId) {
719 return cvaCalculator_->tradeFca_exOwnSp(tradeId);
720}
721
722Real PostProcess::tradeFBA_exAllSP(const string& tradeId) {
723 return cvaCalculator_->tradeFba_exAllSp(tradeId);
724}
725
726Real PostProcess::tradeFCA_exAllSP(const string& tradeId) {
727 return cvaCalculator_->tradeFca_exAllSp(tradeId);
728}
729
730Real PostProcess::nettingSetCVA(const string& nettingSetId) {
731 return cvaCalculator_->nettingSetCva(nettingSetId);
732}
733
734Real PostProcess::nettingSetDVA(const string& nettingSetId) {
735 return cvaCalculator_->nettingSetDva(nettingSetId);
736}
737
738Real PostProcess::nettingSetMVA(const string& nettingSetId) {
739 return cvaCalculator_->nettingSetMva(nettingSetId);
740
741}
742
743Real PostProcess::nettingSetFBA(const string& nettingSetId) {
744 return cvaCalculator_->nettingSetFba(nettingSetId);
745
746}
747
748Real PostProcess::nettingSetFCA(const string& nettingSetId) {
749 return cvaCalculator_->nettingSetFca(nettingSetId);
750
751}
752
753Real PostProcess::nettingSetOurKVACCR(const string& nettingSetId) {
754 QL_REQUIRE(ourNettingSetKVACCR_.find(nettingSetId) != ourNettingSetKVACCR_.end(),
755 "NettingSetId " << nettingSetId << " not found in nettingSet KVACCR map");
756 return ourNettingSetKVACCR_[nettingSetId];
757}
758
759Real PostProcess::nettingSetTheirKVACCR(const string& nettingSetId) {
760 QL_REQUIRE(theirNettingSetKVACCR_.find(nettingSetId) != theirNettingSetKVACCR_.end(),
761 "NettingSetId " << nettingSetId << " not found in nettingSet KVACCR map");
762 return theirNettingSetKVACCR_[nettingSetId];
763}
764
765Real PostProcess::nettingSetOurKVACVA(const string& nettingSetId) {
766 QL_REQUIRE(ourNettingSetKVACVA_.find(nettingSetId) != ourNettingSetKVACVA_.end(),
767 "NettingSetId " << nettingSetId << " not found in nettingSet KVACVA map");
768 return ourNettingSetKVACVA_[nettingSetId];
769}
770
771Real PostProcess::nettingSetTheirKVACVA(const string& nettingSetId) {
772 QL_REQUIRE(theirNettingSetKVACVA_.find(nettingSetId) != theirNettingSetKVACVA_.end(),
773 "NettingSetId " << nettingSetId << " not found in nettingSet KVACVA map");
774 return theirNettingSetKVACVA_[nettingSetId];
775}
776
777Real PostProcess::nettingSetFBA_exOwnSP(const string& nettingSetId) {
778 return cvaCalculator_->nettingSetFba_exOwnSp(nettingSetId);
779}
780
781Real PostProcess::nettingSetFCA_exOwnSP(const string& nettingSetId) {
782 return cvaCalculator_->nettingSetFca_exOwnSp(nettingSetId);
783}
784
785Real PostProcess::nettingSetFBA_exAllSP(const string& nettingSetId) {
786 return cvaCalculator_->nettingSetFba_exAllSp(nettingSetId);
787}
788
789Real PostProcess::nettingSetFCA_exAllSP(const string& nettingSetId) {
790 return cvaCalculator_->nettingSetFca_exAllSp(nettingSetId);
791}
792
793Real PostProcess::allocatedTradeCVA(const string& allocatedTradeId) {
794 return allocatedCvaCalculator_->tradeCva(allocatedTradeId);
795}
796
797Real PostProcess::allocatedTradeDVA(const string& allocatedTradeId) {
798 return allocatedCvaCalculator_->tradeDva(allocatedTradeId);
799}
800
801Real PostProcess::nettingSetCOLVA(const string& nettingSetId) {
802 return nettedExposureCalculator_->colva(nettingSetId);
803}
804
805Real PostProcess::nettingSetCollateralFloor(const string& nettingSetId) {
806 return nettedExposureCalculator_->collateralFloor(nettingSetId);
807}
808
810 dimCalculator_->exportDimEvolution(dimEvolutionReport);
811}
812
813void PostProcess::exportDimRegression(const std::string& nettingSet, const std::vector<Size>& timeSteps,
814 const std::vector<QuantLib::ext::shared_ptr<ore::data::Report>>& dimRegReports) {
815
816 QuantLib::ext::shared_ptr<RegressionDynamicInitialMarginCalculator> regCalc =
817 QuantLib::ext::dynamic_pointer_cast<RegressionDynamicInitialMarginCalculator>(dimCalculator_);
818
819 if (regCalc)
820 regCalc->exportDimRegression(nettingSet, timeSteps, dimRegReports);
821}
822
823} // namespace analytics
824} // namespace ore
const Real & tradeEEPE_B(const string &tradeId)
Return trade level Effective Expected Positive Exposure evolution.
Real tradeFBA_exAllSP(const string &tradeId)
Return trade (stand-alone) FBA (Funding Benefit Adjustment) excluding both survival probabilities.
Real tradeFCA(const string &tradeId)
Return trade (stand-alone) FCA (Funding Cost Adjustment)
const vector< Real > & tradeEEE_B(const string &tradeId)
Return trade level Effective Expected Exposure evolution.
map< string, Real > theirNettingSetKVACVA_
const std::string configuration_
Real nettingSetOurKVACVA(const string &nettingSetId)
Return netting set KVA-CVA.
Real kvaCapitalDiscountRate_
QuantLib::ext::shared_ptr< Market > market_
Real nettingSetCollateralFloor(const string &nettingSetId)
Return netting set Collateral Floor value.
const std::map< string, Size > tradeIds()
Return list of Trade IDs in the portfolio.
const vector< Real > & tradeENE(const string &tradeId)
Return trade level Expected Negative Exposure evolution.
string fvaBorrowingCurve_
QuantLib::ext::shared_ptr< ExposureCalculator > exposureCalculator_
Real nettingSetFCA_exOwnSP(const string &nettingSetId)
Return netting set FCA excluding own survival probability.
const vector< Real > & colvaIncrements(const string &nettingSetId)
Return the netting set's expected COLVA increments through time.
const vector< Real > & netEEE_B(const string &nettingSetId)
Return Netting Set Effective Expected Exposure evolution.
map< string, vector< Real > > netEPE_
void exportDimRegression(const std::string &nettingSet, const std::vector< Size > &timeSteps, const std::vector< QuantLib::ext::shared_ptr< ore::data::Report > > &dimRegReports)
Write DIM as a function of sample netting set NPV for a given time step.
const vector< Real > & netEPE(const string &nettingSetId)
Return Netting Set Expected Positive Exposure evolution.
Real cvaSpreadSensiShiftSize_
Real tradeFBA(const string &tradeId)
Return trade (stand-alone) FBA (Funding Benefit Adjustment)
const vector< Real > & netPFE(const string &nettingSetId)
Return Netting Set Potential Future Exposure evolution.
const map< string, string > & counterpartyId()
Return the map of counterparty Ids.
Real kvaOurPdFloor_
Real kvaCapitalHurdle_
Real nettingSetCVA(const string &nettingSetId)
Return netting set CVA.
const vector< Real > & netEE_B(const string &nettingSetId)
Return Netting Set Basel Expected Exposure evolution.
bool fullInitialCollateralisation_
Real tradeFBA_exOwnSP(const string &tradeId)
Return trade (stand-alone) FBA (Funding Benefit Adjustment) excluding own survival probability.
Real nettingSetMVA(const string &nettingSetId)
Return netting set MVA.
std::vector< std::vector< Real > > creditMigrationCdf_
map< string, vector< Real > > netCvaSpreadSensi_
const vector< Real > & allocatedTradeEPE(const string &tradeId)
Return the trade EPE, allocated down from the netting set level.
Real nettingSetFBA_exOwnSP(const string &nettingSetId)
Return netting set FBA excluding own survival probability.
const vector< Real > & expectedCollateral(const string &nettingSetId)
Return the netting set's expected collateral evolution.
Real nettingSetTheirKVACVA(const string &nettingSetId)
Return netting set KVA-CVA from counterparty perspective.
string dvaName_
Real nettingSetFCA(const string &nettingSetId)
Return netting set FCA.
const vector< Real > & tradeEPE(const string &tradeId)
Return trade level Expected Positive Exposure evolution.
vector< Period > cvaSpreadSensiGrid_
const Real & tradeEPE_B(const string &tradeId)
Return trade level Basel Expected Positive Exposure evolution.
PostProcess(const QuantLib::ext::shared_ptr< Portfolio > &portfolio, const QuantLib::ext::shared_ptr< NettingSetManager > &nettingSetManager, const QuantLib::ext::shared_ptr< CollateralBalances > &collateralBalances, const QuantLib::ext::shared_ptr< Market > &market, const std::string &configuration, const QuantLib::ext::shared_ptr< NPVCube > &cube, const QuantLib::ext::shared_ptr< AggregationScenarioData > &scenarioData, const map< string, bool > &analytics, const string &baseCurrency, const string &allocationMethod, Real cvaMarginalAllocationLimit, Real quantile=0.95, const string &calculationType="Symmetric", const string &dvaName="", const string &fvaBorrowingCurve="", const string &fvaLendingCurve="", const QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > &dimCalculator=QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator >(), const QuantLib::ext::shared_ptr< CubeInterpretation > &cubeInterpretation=QuantLib::ext::shared_ptr< CubeInterpretation >(), bool fullInitialCollateralisation=false, vector< Period > cvaSpreadSensiGrid={6 *Months, 1 *Years, 3 *Years, 5 *Years, 10 *Years}, Real cvaSpreadSensiShiftSize=0.0001, Real kvaCapitalDiscountRate=0.10, Real kvaAlpha=1.4, Real kvaRegAdjustment=12.5, Real kvaCapitalHurdle=0.012, Real kvaOurPdFloor=0.03, Real kvaTheirPdFloor=0.03, Real kvaOurCvaRiskWeight=0.05, Real kvaTheirCvaRiskWeight=0.05, const QuantLib::ext::shared_ptr< NPVCube > &cptyCube_=nullptr, const string &flipViewBorrowingCurvePostfix="_BORROW", const string &flipViewLendingCurvePostfix="_LEND", const QuantLib::ext::shared_ptr< CreditSimulationParameters > &creditSimulationParameters=nullptr, const std::vector< Real > &creditMigrationDistributionGrid={}, const std::vector< Size > &creditMigrationTimeSteps={}, const Matrix &creditStateCorrelationMatrix=Matrix(), bool withMporStickyDate=false, const MporCashFlowMode mporCashFlowMode=MporCashFlowMode::Unspecified)
Constructor.
Definition: postprocess.cpp:55
Real nettingSetFBA(const string &nettingSetId)
Return netting set FBA.
string fvaLendingCurve_
Real tradeMVA(const string &tradeId)
Return trade (stand-alone) MVA.
void updateNettingSetKVA()
const Real & netEEPE_B(const string &nettingSetId)
Return Netting Set Effective Expected Positive Exposure evolution.
vector< Real > netCvaHazardRateSensitivity(const string &nettingSetId)
Return Netting Set CVA Hazard Rate Sensitivity vector.
map< string, bool > analytics_
const QuantLib::ext::shared_ptr< NPVCube > & cube()
Inspector for the input NPV cube (by trade, time, scenario)
map< string, vector< Real > > allocatedTradeEPE_
map< string, vector< Real > > tradeEPE_
QuantLib::ext::shared_ptr< ValueAdjustmentCalculator > allocatedCvaCalculator_
Real nettingSetCOLVA(const string &nettingSetId)
Return netting set COLVA.
map< string, vector< Real > > allocatedTradeENE_
QuantLib::ext::shared_ptr< Portfolio > portfolio_
vector< Time > cvaSpreadSensiTimes_
QuantLib::ext::shared_ptr< NettedExposureCalculator > nettedExposureCalculator_
const std::map< string, Size > nettingSetIds()
Return list of netting set IDs in the portfolio.
const vector< Real > & tradePFE(const string &tradeId)
Return trade level Potential Future Exposure evolution.
void updateNettingSetCvaSensitivity()
QuantLib::ext::shared_ptr< AggregationScenarioData > scenarioData_
Real tradeCVA(const string &tradeId)
Return trade (stand-alone) CVA.
QuantLib::ext::shared_ptr< CubeInterpretation > cubeInterpretation_
map< string, Real > ourNettingSetKVACCR_
map< string, vector< Real > > tradeENE_
map< string, vector< Real > > netENE_
Real allocatedTradeDVA(const string &tradeId)
Return allocated trade DVA (trade DVAs add up to netting set DVA)
std::vector< Size > creditMigrationTimeSteps_
QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > dimCalculator_
CollateralExposureHelper::CalculationType calcType_
Real tradeFCA_exAllSP(const string &tradeId)
Return trade (stand-alone) FCA (Funding Cost Adjustment) excluding both survival probabilities.
const vector< Real > & allocatedTradeENE(const string &tradeId)
Return trade ENE, allocated down from the netting set level.
std::vector< Real > creditMigrationUpperBucketBounds_
QuantLib::ext::shared_ptr< CollateralBalances > collateralBalances_
Real allocatedTradeCVA(const string &tradeId)
Return allocated trade CVA (trade CVAs add up to netting set CVA)
Real nettingSetDVA(const string &nettingSetId)
Return netting set DVA.
Real tradeFCA_exOwnSP(const string &tradeId)
Return trade (stand-alone) FCA (Funding Cost Adjustment) excluding own survival probability.
QuantLib::ext::shared_ptr< CreditSimulationParameters > creditSimulationParameters_
MporCashFlowMode mporCashFlowMode_
Matrix creditStateCorrelationMatrix_
QuantLib::ext::shared_ptr< NPVCube > cptyCube_
Real nettingSetOurKVACCR(const string &nettingSetId)
Return netting set KVA-CCR.
Real kvaTheirPdFloor_
QuantLib::ext::shared_ptr< NettingSetManager > nettingSetManager_
Real kvaTheirCvaRiskWeight_
std::vector< Real > creditMigrationDistributionGrid_
Real quantile_
Real kvaAlpha_
Real nettingSetFBA_exAllSP(const string &nettingSetId)
Return netting set FBA excluding both survival probabilities.
Real kvaRegAdjustment_
map< string, Real > ourNettingSetKVACVA_
Real kvaOurCvaRiskWeight_
map< string, Real > theirNettingSetKVACCR_
QuantLib::ext::shared_ptr< CreditMigrationCalculator > creditMigrationCalculator_
void exportDimEvolution(ore::data::Report &dimEvolutionReport)
Return the dynamic initial margin cube (regression approach)
Real tradeDVA(const string &tradeId)
Return trade (stand-alone) DVA.
Real nettingSetFCA_exAllSP(const string &nettingSetId)
Return netting set FCA excluding both survival probabilities.
const vector< Real > & netENE(const string &nettingSetId)
Return Netting Set Expected Negative Exposure evolution.
map< string, vector< Real > > netCvaHazardRateSensi_
bool withMporStickyDate_
const std::map< std::string, std::vector< QuantLib::Real > > & netCvaSpreadSensitivity() const
Return Netting Set CVA Spread Sensitivity vector.
std::vector< std::vector< Real > > creditMigrationPdf_
const vector< Real > & tradeEE_B(const string &tradeId)
Return trade level Basel Expected Exposure evolution.
string baseCurrency_
QuantLib::ext::shared_ptr< NPVCube > cube_
const vector< Real > & collateralFloorIncrements(const string &nettingSetId)
Return the netting set's expected Collateral Floor increments through time.
QuantLib::ext::shared_ptr< ValueAdjustmentCalculator > cvaCalculator_
Real nettingSetTheirKVACCR(const string &nettingSetId)
Return netting set KVA-CCR from counterparty perspective.
const Real & netEPE_B(const string &nettingSetId)
Return Netting Set Basel Expected Positive Exposure evolution.
Dynamic Initial Margin calculator base class.
Dynamic Initial Margin calculator by regression.
XVA calculator with dynamic credit.
Exposure allocator.
#define LOG(text)
#define DLOG(text)
#define ALOG(text)
ExposureAllocator::AllocationMethod parseAllocationMethod(const string &s)
Convert text representation to ExposureAllocator::AllocationMethod.
CollateralExposureHelper::CalculationType parseCollateralCalculationType(const string &s)
Convert text representation to CollateralExposureHelper::CalculationType.
Size size(const ValueType &v)
std::size_t count
Exposure aggregation and XVA calculation.
XVA calculator with static credit.
CVA calculator base class.