26#include <ql/errors.hpp>
37 const QuantLib::ext::shared_ptr<Portfolio> portfolio,
38 const QuantLib::ext::shared_ptr<Market> market,
39 const string& configuration,
40 const string& baseCurrency,
41 const string& dvaName,
42 const string& fvaBorrowingCurve,
43 const string& fvaLendingCurve,
44 const bool applyDynamicInitialMargin,
45 const QuantLib::ext::shared_ptr<DynamicInitialMarginCalculator> dimCalculator,
46 const QuantLib::ext::shared_ptr<NPVCube> tradeExposureCube,
47 const QuantLib::ext::shared_ptr<NPVCube> nettingSetExposureCube,
48 const Size tradeEpeIndex,
const Size tradeEneIndex,
49 const Size nettingSetEpeIndex,
const Size nettingSetEneIndex,
50 const bool flipViewXVA,
const string& flipViewBorrowingCurvePostfix,
const string& flipViewLendingCurvePostfix)
51 : portfolio_(portfolio), market_(market), configuration_(configuration),
52 baseCurrency_(baseCurrency), dvaName_(dvaName),
53 fvaBorrowingCurve_(fvaBorrowingCurve), fvaLendingCurve_(fvaLendingCurve),
54 applyDynamicInitialMargin_(applyDynamicInitialMargin),
55 dimCalculator_(dimCalculator),
56 tradeExposureCube_(tradeExposureCube),
57 nettingSetExposureCube_(nettingSetExposureCube),
58 tradeEpeIndex_(tradeEpeIndex), tradeEneIndex_(tradeEneIndex), nettingSetEpeIndex_(nettingSetEpeIndex),
59 nettingSetEneIndex_(nettingSetEneIndex), flipViewXVA_(flipViewXVA),
60 flipViewBorrowingCurvePostfix_(flipViewBorrowingCurvePostfix), flipViewLendingCurvePostfix_(flipViewLendingCurvePostfix) {
64 for (
const auto& [tradeId, trade] :
portfolio_->trades()) {
65 string nettingSetId = trade->envelope().nettingSetId();
74 "number of trades in tradeExposureCube and portfolio mismatch ("
78 "number of netting sets in nettingSetExposureCube and nettingSetCpty map mismatch ("
82 "number of dates in tradeExposureCube and nettingSetExposureCube mismatch ("
87 "date at " << i <<
" in tradeExposureCube and nettingSetExposureCube mismatch ("
91 QL_REQUIRE(tradeEpeIndex < tradeExposureCube_->depth(),
"tradeEpeIndex("
92 << tradeEpeIndex <<
") exceeds depth of tradeExposureCube("
95 QL_REQUIRE(tradeEneIndex < tradeExposureCube_->depth(),
"tradeEneIndex("
96 << tradeEneIndex <<
") exceeds depth of tradeExposureCube("
99 QL_REQUIRE(nettingSetEpeIndex < nettingSetExposureCube_->depth(),
"nettingSetEpeIndex("
100 << nettingSetEpeIndex <<
") exceeds depth of nettingSetExposureCube("
103 QL_REQUIRE(nettingSetEneIndex < nettingSetExposureCube_->depth(),
"nettingSetEneIndex("
104 << nettingSetEneIndex <<
") exceeds depth of nettingSetExposureCube("
137 QL_FAIL(
"trade " << trade <<
" not found in expected CVA results");
144 QL_FAIL(
"trade " << trade <<
" not found in expected DVA results");
151 QL_FAIL(
"trade " << trade <<
" not found in expected FBA results");
158 QL_FAIL(
"trade " << trade <<
" not found in expected FBA ex own sp results");
165 QL_FAIL(
"trade " << trade <<
" not found in expected FBA ex all sp results");
172 QL_FAIL(
"trade " << trade <<
" not found in expected FCA results");
179 QL_FAIL(
"trade " << trade <<
" not found in expected FCA ex own sp results");
186 QL_FAIL(
"trade " << trade <<
" not found in expected FCA ex all sp results");
193 QL_FAIL(
"trade " << trade <<
" not found in expected MVA results");
200 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected CVA results");
207 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected DVA results");
214 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected CVA results");
221 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected DVA results");
228 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected FBA results");
235 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected FBA ex own sp results");
242 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected FBA ex all sp results");
249 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected FBA results");
256 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected FBA ex own sp results");
263 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected FBA ex all sp results");
270 QL_FAIL(
"netting set " << nettingSet <<
" not found in expected MVA results");
274 const auto& numDates =
dates().size();
275 const auto& today =
asof();
277 Handle<YieldTermStructure> borrowingCurve, lendingCurve, oisCurve;
283 for (
const auto& [tid, trade] :
portfolio_->trades()) {
285 LOG(
"Update XVA for trade " << tid
287 :
", regular (flipViewXVA = N)"));
291 dvaName_ = trade->envelope().counterparty();
295 cid = trade->envelope().counterparty();
302 if (!borrowingCurve.empty() || !lendingCurve.empty()) {
303 QL_REQUIRE(
baseCurrency_ !=
"",
"baseCurrency required for FVA calculation");
305 string nid = trade->envelope().nettingSetId();
320 for (Size j = 0; j < numDates; ++j) {
323 Date d0 = j == 0 ? today :
dates()[j - 1];
324 Date d1 =
dates()[j];
331 if (!borrowingCurve.empty()) {
332 Real dcf = borrowingCurve->discount(d0) / borrowingCurve->discount(d1) -
333 oisCurve->discount(d0) / oisCurve->discount(d1);
343 if (!lendingCurve.empty()) {
344 Real dcf = lendingCurve->discount(d0) / lendingCurve->discount(d1) -
345 oisCurve->discount(d0) / oisCurve->discount(d1);
360 }
catch (
const std::exception& e) {
368 for (
const auto& pair : nettingSetCpty_) {
369 string nid = pair.first;
370 LOG(
"Update XVA for netting set "
371 << nid << (flipViewXVA_ ?
", inverted (flipViewXVA = Y)" :
", regular (flipViewXVA = N)"));
376 dvaName_ = pair.second;
377 fvaBorrowingCurve_ = dvaName_ + flipViewBorrowingCurvePostfix_;
378 fvaLendingCurve_ = dvaName_ + flipViewLendingCurvePostfix_;
382 Real cvaRR = market_->recoveryRate(cid, configuration_)->value();
384 if (dvaName_ !=
"") {
385 dvaRR = market_->recoveryRate(dvaName_, configuration_)->value();
387 if (fvaBorrowingCurve_ !=
"")
388 borrowingCurve = market_->yieldCurve(fvaBorrowingCurve_, configuration_);
389 if (fvaLendingCurve_ !=
"")
390 lendingCurve = market_->yieldCurve(fvaLendingCurve_, configuration_);
392 if (!borrowingCurve.empty() || !lendingCurve.empty()) {
393 QL_REQUIRE(baseCurrency_ !=
"",
"baseCurrency required for FVA calculation");
396 nettingSetCva_[nid] = 0.0;
397 nettingSetDva_[nid] = 0.0;
398 nettingSetFca_[nid] = 0.0;
399 nettingSetFca_exOwnSp_[nid] = 0.0;
400 nettingSetFca_exAllSp_[nid] = 0.0;
401 nettingSetFba_[nid] = 0.0;
402 nettingSetFba_exOwnSp_[nid] = 0.0;
403 nettingSetFba_exAllSp_[nid] = 0.0;
404 nettingSetMva_[nid] = 0.0;
405 for (Size j = 0; j < numDates; ++j) {
407 Date d0 = j == 0 ? today : dates()[j - 1];
408 Date d1 = dates()[j];
409 Real cvaIncrement = calculateNettingSetCvaIncrement(nid, cid, d0, d1, cvaRR);
410 Real dvaIncrement = dvaName_ !=
"" ? calculateNettingSetDvaIncrement(nid, d0, d1, dvaRR) : 0;
411 nettingSetCva_[nid] += cvaIncrement;
412 nettingSetDva_[nid] += dvaIncrement;
415 if (!borrowingCurve.empty()) {
416 Real dcf = borrowingCurve->discount(d0) / borrowingCurve->discount(d1) -
417 oisCurve->discount(d0) / oisCurve->discount(d1);
418 Real fcaIncrement = calculateNettingSetFcaIncrement(nid, cid, dvaName_, d0, d1, dcf);
419 Real fcaIncrement_exOwnSP = calculateNettingSetFcaIncrement(nid, cid,
"", d0, d1, dcf);
420 Real fcaIncrement_exAllSP = calculateNettingSetFcaIncrement(nid,
"",
"", d0, d1, dcf);
421 nettingSetFca_[nid] += fcaIncrement;
422 nettingSetFca_exOwnSp_[nid] += fcaIncrement_exOwnSP;
423 nettingSetFca_exAllSp_[nid] += fcaIncrement_exAllSP;
426 if (dimCalculator_) {
427 Real mvaIncrement = calculateNettingSetMvaIncrement(nid, cid, d0, d1, dcf);
428 nettingSetMva_[nid] += mvaIncrement;
433 if (!lendingCurve.empty()) {
434 Real dcf = lendingCurve->discount(d0) / lendingCurve->discount(d1) -
435 oisCurve->discount(d0) / oisCurve->discount(d1);
436 Real fbaIncrement = calculateNettingSetFbaIncrement(nid, cid, dvaName_, d0, d1, dcf);
437 Real fbaIncrement_exOwnSP = calculateNettingSetFbaIncrement(nid, cid,
"", d0, d1, dcf);
438 Real fbaIncrement_exAllSP = calculateNettingSetFbaIncrement(nid,
"",
"", d0, d1, dcf);
439 nettingSetFba_[nid] += fbaIncrement;
440 nettingSetFba_exOwnSp_[nid] += fbaIncrement_exOwnSP;
441 nettingSetFba_exAllSp_[nid] += fbaIncrement_exAllSP;
444 }
catch (
const std::exception& e) {
445 StructuredAnalyticsErrorMessage(
"ValueAdjustmentCalculator",
"Error processing netting set.", e.what(),
446 {{
"nettingSetId", nid}})
map< string, Real > nettingSetSumCva_
string flipViewBorrowingCurvePostfix_
const map< string, Real > & nettingSetSumDva()
Sum DVA map for all the netting sets.
const Real & tradeFca(const string &trade)
FCA for the specified trade.
map< string, Real > nettingSetSumDva_
QuantLib::ext::shared_ptr< Market > market_
const Real & tradeFca_exAllSp(const string &trade)
FCA (excl all survival probability) for the specified trade.
map< string, Real > tradeFba_exAllSp_
string fvaBorrowingCurve_
const map< string, Real > & tradeDva()
DVA map for all the trades.
map< string, Real > nettingSetCva_
map< string, Real > tradeFca_exAllSp_
map< string, Real > nettingSetFca_
const Real & tradeFba_exOwnSp(const string &trade)
FBA (excl own survival probability) for the specified trade.
const Real & nettingSetFba_exOwnSp(const string &nettingSet)
FBA (excl own survival probability) for the specified netting set.
virtual const Real calculateFcaIncrement(const string &tid, const string &cid, const string &dvaName, const Date &d0, const Date &d1, const Real &dcf)=0
virtual const Date asof()
const Real & tradeFba(const string &trade)
FBA for the specified trade.
virtual const Real calculateDvaIncrement(const string &tid, const Date &d0, const Date &d1, const Real &rr)=0
map< string, Real > tradeFba_exOwnSp_
map< string, Real > tradeFca_
map< string, Real > tradeDva_
map< string, Real > tradeCva_
map< string, Real > nettingSetMva_
const Real & nettingSetFba_exAllSp(const string &nettingSet)
FBA (excl all survival probability) for the specified netting set.
map< string, Real > nettingSetFca_exOwnSp_
map< string, string > nettingSetCpty_
string flipViewLendingCurvePostfix_
virtual void build()
Compute cva along all paths and fill result structures.
const Real & nettingSetFca(const string &nettingSet)
FCA for the specified netting set.
virtual const Real calculateFbaIncrement(const string &tid, const string &cid, const string &dvaName, const Date &d0, const Date &d1, const Real &dcf)=0
virtual const vector< Date > & dates()
const map< string, Real > & tradeCva()
CVA map for all the trades.
const Real & nettingSetFca_exOwnSp(const string &nettingSet)
FCA (excl own survival probability) for the specified netting set.
QuantLib::ext::shared_ptr< Portfolio > portfolio_
const map< string, Real > & nettingSetDva()
DVA map for all the netting sets.
const map< string, Real > & nettingSetSumCva()
Sum CVA map for all the netting sets.
map< string, Real > nettingSetFba_exOwnSp_
const Real & tradeMva(const string &trade)
MVA for the specified trade.
map< string, Real > tradeFba_
virtual const Real calculateCvaIncrement(const string &tid, const string &cid, const Date &d0, const Date &d1, const Real &rr)=0
const Real & nettingSetFba(const string &nettingSet)
FBA for the specified netting set.
map< string, Real > nettingSetFba_
const QuantLib::ext::shared_ptr< NPVCube > nettingSetExposureCube_
const map< string, Real > & nettingSetCva()
CVA map for all the netting sets.
const Real & nettingSetFca_exAllSp(const string &nettingSet)
FCA (excl all survival probability) for the specified netting set.
map< string, Real > nettingSetDva_
map< string, Real > nettingSetFca_exAllSp_
map< string, Real > tradeMva_
ValueAdjustmentCalculator(const QuantLib::ext::shared_ptr< Portfolio > portfolio, const QuantLib::ext::shared_ptr< Market > market, const string &configuration, const string &baseCurrency, const string &dvaName, const string &fvaBorrowingCurve, const string &fvaLendingCurve, const bool applyDynamicInitialMargin, const QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > dimCalculator, const QuantLib::ext::shared_ptr< NPVCube > tradeExposureCube, const QuantLib::ext::shared_ptr< NPVCube > nettingSetExposureCube, const Size tradeEpeIndex=0, const Size tradeEneIndex=1, const Size nettingSetEpeIndex=1, const Size nettingSetEneIndex=2, const bool flipViewXVA=false, const string &flipViewBorrowingCurvePostfix="_BORROW", const string &flipViewLendingCurvePostfix="_LEND")
map< string, Real > nettingSetFba_exAllSp_
const Real & tradeFba_exAllSp(const string &trade)
FBA (excl all survival probability) for the specified trade.
const Real & tradeFca_exOwnSp(const string &trade)
FCA (excl own survival probability) for the specified trade.
const QuantLib::ext::shared_ptr< NPVCube > tradeExposureCube_
const Real & nettingSetMva(const string &nettingSet)
MVA for the specified netting set.
map< string, Real > tradeFca_exOwnSp_
RandomVariable log(RandomVariable x)
Structured analytics error.
CVA calculator base class.