Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
inhomogeneouspooldef.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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
19#ifndef quantext_inhomogenous_pool_default_model_hpp
20#define quantext_inhomogenous_pool_default_model_hpp
21
22#include <ql/experimental/credit/lossdistribution.hpp>
23//#include <ql/experimental/credit/basket.hpp>
24#include <qle/models/basket.hpp>
25//#include <ql/experimental/credit/constantlosslatentmodel.hpp>
27//#include <ql/experimental/credit/defaultlossmodel.hpp>
29
30// Intended to replace InhomogeneousPoolCDOEngine in syntheticcdoengines.hpp
31
32namespace QuantExt {
33using namespace QuantLib;
34
35//-------------------------------------------------------------------------
36//! Default loss distribution convolution for finite non homogeneous pool
37/* A note on the number of buckets: As it is now the code goes splitting
38losses into buckets from loses equal to zero to losses up to the value of
39the underlying basket. This is in view of a stochastic loss given default
40but in a constant LGD situation this is a waste and it is more efficient to
41go up to the attainable losses.
42\todo Extend to the multifactor case for a generic LM
43\todo Many common code with the homogeneous version, both classes perform
44the same work on different loss distribution types, merge and send the
45distribution object?
46*/
47template <class copulaPolicy> class InhomogeneousPoolLossModel : public QuantExt::DefaultLossModel {
48private:
49 void resetModel();
50
51public:
52 // allow base correlations:
53 typedef copulaPolicy copulaType;
54
56 // restricted to non random recoveries, but it could be possible.
57 const QuantLib::ext::shared_ptr<ConstantLossLatentmodel<copulaPolicy>>& copula, Size nBuckets, Real max = 5.,
58 Real min = -5., Real nSteps = 50)
59 : copula_(copula), nBuckets_(nBuckets), max_(max), min_(min), nSteps_(nSteps), delta_((max - min) / nSteps) {
60 QL_REQUIRE(copula->numFactors() == 1, "Inhomogeneous model not implemented for multifactor");
61 }
62 // Write another constructor sending the LM factors and recoveries.
63protected:
64 // RL: additional flag
65 Distribution lossDistrib(const Date& d, bool zeroRecovery = false) const;
66
67public:
68 // RL: additional flag
69 Real expectedTrancheLoss(const Date& d, bool zeroRecovery = false) const {
70 Distribution dist = lossDistrib(d, zeroRecovery);
71 // RL: dist.trancheExpectedValue() using x = dist.average(i)
72 // FIXME: some remaining inaccuracy in dist.cumulativeDensity(detachAmount_)
73 Real expectedLoss = 0;
74 dist.normalize();
75 for (Size i = 0; i < dist.size(); i++) {
76 // Real x = dist.x(i) + dist.dx(i)/2; // in QL distribution.cpp
77 Real x = dist.average(i);
78 if (x < attachAmount_)
79 continue;
80 if (x > detachAmount_)
81 break;
82 expectedLoss += (x - attachAmount_) * dist.dx(i) * dist.density(i);
83 }
84 expectedLoss += (detachAmount_ - attachAmount_) * (1.0 - dist.cumulativeDensity(detachAmount_));
85 return expectedLoss;
86
87 return lossDistrib(d, zeroRecovery).cumulativeExcessProbability(attachAmount_, detachAmount_);
88 // This one if the distribution is over the whole loss structure:
89 // but it becomes very expensive
90 /*
91 return lossDistrib(d).trancheExpectedValue(
92 attachAmount_, detachAmount_);
93 */
94 }
95 Real percentile(const Date& d, Real percentile) const {
96 Real portfLoss = lossDistrib(d).confidenceLevel(percentile);
97 return std::min(std::max(portfLoss - attachAmount_, 0.), detachAmount_ - attachAmount_);
98 }
99 Real expectedShortfall(const Date& d, Probability percentile) const {
100 Distribution dist = lossDistrib(d);
101 dist.tranche(attachAmount_, detachAmount_);
102 return dist.expectedShortfall(percentile);
103 }
104
105protected:
106 const QuantLib::ext::shared_ptr<ConstantLossLatentmodel<copulaPolicy>> copula_;
109 mutable std::vector<Real> notionals_;
110
111private:
112 // integration:
113 // \todo move integration to latent model types when moving to a
114 // multifactor version
115 const Real max_; // redundant?
116 const Real min_;
117 const Real nSteps_;
118 const Real delta_;
119};
120// \todo Add other loss distribution statistics
123
124//-----------------------------------------------------------------------
125
127 // need to be capped now since the limit amounts might be over the
128 // remaining notional (think amortizing)
129 attach_ = std::min(basket_->remainingAttachmentAmount() / basket_->remainingNotional(), 1.);
130 detach_ = std::min(basket_->remainingDetachmentAmount() / basket_->remainingNotional(), 1.);
131 notional_ = basket_->remainingNotional();
132 notionals_ = basket_->remainingNotionals();
133 attachAmount_ = basket_->remainingAttachmentAmount();
134 detachAmount_ = basket_->remainingDetachmentAmount();
135
136 copula_->resetBasket(basket_.currentLink());
137}
138// RL: additional flag
139template <class CP> Distribution InhomogeneousPoolLossModel<CP>::lossDistrib(const Date& d, bool zeroRecovery) const {
140 LossDistBucketing bucktLDistBuff(nBuckets_, detachAmount_);
141
142 std::vector<Real> lgd; // switch to a mutable cache member
143 // RL: additional option used to set set recovery rates to zero
144 std::vector<Real> recoveries =
145 zeroRecovery ? std::vector<Real>(copula_->recoveries().size(), 0.0) : copula_->recoveries();
146 std::transform(recoveries.begin(), recoveries.end(), std::back_inserter(lgd), [](Real x) { return 1.0 - x; });
147 std::transform(lgd.begin(), lgd.end(), notionals_.begin(), lgd.begin(), std::multiplies<Real>());
148 std::vector<Real> prob = basket_->remainingProbabilities(d);
149 for (Size iName = 0; iName < prob.size(); iName++)
150 prob[iName] = copula_->inverseCumulativeY(prob[iName], iName);
151
152 // integrate locally (1 factor).
153 // use explicitly a 1D latent model object?
154 // \todo Use a library integrator here and in the homogeneous case.
155 Distribution dist(nBuckets_, 0.0, detachAmount_);
156 // notional_);
157 std::vector<Real> mkft(1, min_ + delta_ / 2.);
158 for (Size i = 0; i < nSteps_; i++) {
159 std::vector<Real> conditionalProbs;
160 for (Size iName = 0; iName < notionals_.size(); iName++)
161 conditionalProbs.push_back(copula_->conditionalDefaultProbabilityInvP(prob[iName], iName, mkft));
162 Distribution d = bucktLDistBuff(lgd, conditionalProbs);
163 Real densitydm = delta_ * copula_->density(mkft);
164 // also, instead of calling the static method it could be wrapped
165 // through an inlined call in the latent model
166 for (Size j = 0; j < nBuckets_; j++) {
167 dist.addDensity(j, d.density(j) * densitydm);
168 dist.addAverage(j, d.average(j) * densitydm); // RL
169 }
170 mkft[0] += delta_;
171 }
172 return dist;
173}
174
175} // namespace QuantExt
176
177#endif
basket of issuers and related notionals
Default loss distribution convolution for finite non homogeneous pool.
Real expectedTrancheLoss(const Date &d, bool zeroRecovery=false) const
InhomogeneousPoolLossModel(const QuantLib::ext::shared_ptr< ConstantLossLatentmodel< copulaPolicy > > &copula, Size nBuckets, Real max=5., Real min=-5., Real nSteps=50)
Real expectedShortfall(const Date &d, Probability percentile) const
const QuantLib::ext::shared_ptr< ConstantLossLatentmodel< copulaPolicy > > copula_
Distribution lossDistrib(const Date &d, bool zeroRecovery=false) const
void resetModel()
Concrete models do now any updates/inits they need on basket reset.
Real percentile(const Date &d, Real percentile) const
Value at Risk given a default loss percentile.
InhomogeneousPoolLossModel< GaussianCopulaPolicy > IHGaussPoolLossModel
CompiledFormula min(CompiledFormula x, const CompiledFormula &y)
InhomogeneousPoolLossModel< TCopulaPolicy > IHStudentPoolLossModel
CompiledFormula max(CompiledFormula x, const CompiledFormula &y)