QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
gaussianlhplossmodel.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 Roland Lichters
5 Copyright (C) 2009, 2014 Jose Aparicio
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21#ifndef quantlib_gaussian_lhp_lossmodel_hpp
22#define quantlib_gaussian_lhp_lossmodel_hpp
23
24#include <ql/qldefines.hpp>
25
26#ifndef QL_PATCH_SOLARIS
27
28#include <ql/math/distributions/bivariatenormaldistribution.hpp>
29#include <ql/experimental/credit/recoveryratequote.hpp>
30#include <ql/quotes/simplequote.hpp>
31#include <ql/experimental/credit/defaultlossmodel.hpp>
32#include <ql/experimental/credit/basket.hpp>
33#include <ql/experimental/math/latentmodel.hpp>
34#include <ql/functional.hpp>
35#include <numeric>
36
37/* Intended to replace GaussianLHPCDOEngine in
38 ql/experimental/credit/syntheticcdoengines.hpp
39 Moved from an engine to a loss model, CDO engines might refer to it.
40*/
41
42namespace QuantLib {
43
62 public LatentModel<GaussianCopulaPolicy> {
63 public:
65
67 const Handle<Quote>& correlQuote,
68 const std::vector<Handle<RecoveryRateQuote> >& quotes);
69
71 Real correlation,
72 const std::vector<Real>& recoveries);
73
75 const Handle<Quote>& correlQuote,
76 const std::vector<Real>& recoveries);
77
78 void update() override {
79 sqrt1minuscorrel_ = std::sqrt(1.-correl_->value());
80 beta_ = std::sqrt(correl_->value());
82 -beta_);
83 // tell basket to notify instruments, etc, we are invalid
84 if(!basket_.empty()) basket_->notifyObservers();
85 }
86
87 private:
88 void resetModel() override {}
92 Real expectedTrancheLossImpl(Real remainingNot, // << at the given date 'd'
93 Real prob, // << at the given date 'd'
94 Real averageRR, // << at the given date 'd'
95 Real attachLimit,
96 Real detachLimit) const;
97 public:
98 Real expectedTrancheLoss(const Date& d) const override {
99 // can calls to Basket::remainingNotional(d) be cached?<<<<<<<<<<<<<
100 const Real remainingfullNot = basket_->remainingNotional(d);
101 Real averageRR = averageRecovery(d);
102 Probability prob = averageProb(d);
103 Real remainingAttachAmount = basket_->remainingAttachmentAmount();
104 Real remainingDetachAmount = basket_->remainingDetachmentAmount();
105
106
107 // const Real attach = std::min(remainingAttachAmount
108 // / remainingfullNot, 1.);
109 // const Real detach = std::min(remainingDetachAmount
110 // / remainingfullNot, 1.);
111 const Real attach = remainingAttachAmount / remainingfullNot;
112 const Real detach = remainingDetachAmount / remainingfullNot;
113
114 return expectedTrancheLossImpl(remainingfullNot, prob, averageRR, attach, detach);
115 }
116
121 Real probOverLoss(const Date& d, Real remainingLossFraction) const override;
122
124 /* The way it is implemented here is a transformation from ETL to ESF
125 is a generic algorithm, not specific to this model so it should be moved
126 to the Basket/DefaultLossModel class.
127 TO DO: Implement the inverse transformation
128 */
129 Real expectedShortfall(const Date& d, Probability perctl) const override;
130
131 protected:
132 // This is wrong, it is not accounting for the current defaults ....
133 // returns the loss value in actual loss units, returns the loss value
134 // for the underlying portfolio, untranched
135 Real percentilePortfolioLossFraction(const Date& d, Real perctl) const;
136 Real expectedRecovery(const Date& d, Size iName, const DefaultProbKey& ik) const override {
137 return rrQuotes_[iName].currentLink()->value();
138 }
139
140 public:
141 // same as percentilePortfolio but tranched
142 Real percentile(const Date& d, Real perctl) const override {
143 const Real remainingNot = basket_->remainingNotional(d);
144 Real remainingAttachAmount = basket_->remainingAttachmentAmount();
145 Real remainingDetachAmount = basket_->remainingDetachmentAmount();
146 const Real attach = std::min(remainingAttachAmount / remainingNot, 1.);
147 const Real detach = std::min(remainingDetachAmount / remainingNot, 1.);
148 return remainingNot *
149 std::min(std::max(percentilePortfolioLossFraction(d, perctl) - attach, 0.),
150 detach - attach);
151 }
152
153 Probability averageProb(const Date& d) const {// not an overload of Deflossmodel ???<<<<<???
154 // weighted average by programmed exposure.
155 const std::vector<Probability> probs =
156 basket_->remainingProbabilities(d);//use remaining basket
157 const std::vector<Real> remainingNots =
158 basket_->remainingNotionals(d);
159 return std::inner_product(probs.begin(), probs.end(),
160 remainingNots.begin(), Real(0.)) / basket_->remainingNotional(d);
161 }
162
163 /* One could define the average recovery without the probability
164 factor, weighting only by notional instead, but that way the expected
165 loss of the average/aggregated and the original portfolio would not
166 coincide. This introduces however a time dependence in the recovery
167 value.
168 Weighting by notional implies time dependent weighting since the basket
169 might amortize.
170 */
172 const Date& d) const //no explicit time dependence in this model
173 {
174 const std::vector<Probability> probs =
175 basket_->remainingProbabilities(d);
176 std::vector<Real> recoveries;
177 for(Size i=0; i<basket_->remainingSize(); i++)
178 recoveries.push_back(rrQuotes_[i]->value());
179 std::vector<Real> notionals = basket_->remainingNotionals(d);
180 Real denominator = std::inner_product(notionals.begin(),
181 notionals.end(), probs.begin(), Real(0.));
182 if(denominator == 0.) return 0.;
183
184 std::transform(notionals.begin(), notionals.end(), probs.begin(),
185 notionals.begin(), std::multiplies<>());
186
187 return std::inner_product(recoveries.begin(), recoveries.end(),
188 notionals.begin(), Real(0.)) / denominator;
189 }
190
191 private:
192 // cached
194
196 std::vector<Handle<RecoveryRateQuote> > rrQuotes_;
197 // calculation buffers
198
199 /* The problem with defining a fixed average recovery on a portfolio
200 with uneven exposures is that it does not preserve portfolio
201 moments like the expected loss. To achieve it one should define the
202 averarage recovery with a time dependence:
203 $\hat{R}(t) = \frac{\sum_i R_i N_i P_i(t)}{\sum_i N_i P_i(t)}$
204 But the date dependence increases significantly the calculations cost.
205 Notice that this problem dissapears if the recoveries are all equal.
206 */
207
211 };
212
213}
214
215#endif
216
217#endif
Cumulative bivariate normal distibution function (West 2004)
Cumulative normal distribution function.
Concrete date class.
Definition: date.hpp:125
RelinkableHandle< Basket > basket_
Probability averageProb(const Date &d) const
Real percentilePortfolioLossFraction(const Date &d, Real perctl) const
Real percentile(const Date &d, Real perctl) const override
Value at Risk given a default loss percentile.
Real expectedTrancheLossImpl(Real remainingNot, Real prob, Real averageRR, Real attachLimit, Real detachLimit) const
std::vector< Handle< RecoveryRateQuote > > rrQuotes_
BivariateCumulativeNormalDistribution biphi_
Real averageRecovery(const Date &d) const
Real probOverLoss(const Date &d, Real remainingLossFraction) const override
void resetModel() override
Concrete models do now any updates/inits they need on basket reset.
Real expectedTrancheLoss(const Date &d) const override
Real expectedShortfall(const Date &d, Probability perctl) const override
Returns the ESF as an absolute amount (rather than a fraction)
Real expectedRecovery(const Date &d, Size iName, const DefaultProbKey &ik) const override
static CumulativeNormalDistribution const phi_
Shared handle to an observable.
Definition: handle.hpp:41
Generic multifactor latent variable model.
QL_REAL Real
real number
Definition: types.hpp:50
Real Probability
probability
Definition: types.hpp:82
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
BivariateCumulativeNormalDistributionWe04DP BivariateCumulativeNormalDistribution
default bivariate implementation