QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
gaussianlhplossmodel.hpp
Go to the documentation of this file.
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
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
44 /*!
45 Portfolio loss model with analytical expected tranche loss for a large
46 homogeneous pool with Gaussian one-factor copula. See for example
47 "The Normal Inverse Gaussian Distribution for Synthetic CDO pricing.",
48 Anna Kalemanova, Bernd Schmid, Ralf Werner,
49 Journal of Derivatives, Vol. 14, No. 3, (Spring 2007), pp. 80-93.
50 http://www.defaultrisk.com/pp_crdrv_91.htm
51
52 It can be used to price a credit derivative or to provide risk metrics of
53 a portfolio.
54
55 \todo It should be checking that basket exposures are deterministic (fixed
56 or programmed amortizing) otherwise the model is not fit for the basket.
57
58 \todo Bugging on tranched baskets with upper limit over maximum
59 attainable loss?
60 */
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 {}
89 /*! @param attachLimit as a fraction of the underlying live portfolio
90 notional
91 */
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
117 /*! The passed remainingLossFraction is in live tranche units,
118 not portfolio as a fraction of the remaining(live) tranche
119 (i.e. a_remaining=0% and det_remaining=100%)
120 */
121 Real probOverLoss(const Date& d, Real remainingLossFraction) const override;
122
123 //! Returns the ESF as an absolute amount (rather than a fraction)
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
basket of issuers and related notionals
bivariate cumulative normal distribution
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.
Date d
Maps function, bind and cref to either the boost or std implementation.
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
Generic multifactor latent variable model.
Definition: any.hpp:35
BivariateCumulativeNormalDistributionWe04DP BivariateCumulativeNormalDistribution
default bivariate implementation
Global definitions and compiler switches.
simple quote class