QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
gaussianlhplossmodel.cpp
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#include <ql/experimental/credit/gaussianlhplossmodel.hpp>
22
23#ifndef QL_PATCH_SOLARIS
24
25
26using std::sqrt;
27
28namespace QuantLib {
29
30 CumulativeNormalDistribution const GaussianLHPLossModel::phi_ =
31 CumulativeNormalDistribution();
32
34 const Handle<Quote>& correlQuote,
35 const std::vector<Handle<RecoveryRateQuote> >& quotes)
36 : LatentModel<GaussianCopulaPolicy>(sqrt(correlQuote->value()),
37 quotes.size(),
38 //g++ complains default value not seen as typename
39 GaussianCopulaPolicy::initTraits()),
40 sqrt1minuscorrel_(std::sqrt(1.-correlQuote->value())),
41 correl_(correlQuote),
42 rrQuotes_(quotes),
43 beta_(sqrt(correlQuote->value())),
44 biphi_(-sqrt(correlQuote->value()))
45 {
47 for (const auto& quote : quotes)
48 registerWith(quote);
49 }
50
52 Real correlation,
53 const std::vector<Real>& recoveries)
54 : LatentModel<GaussianCopulaPolicy>(sqrt(correlation),
55 recoveries.size(),
56 //g++ complains default value not seen as typename
57 GaussianCopulaPolicy::initTraits()),
58 sqrt1minuscorrel_(std::sqrt(1.-correlation)),
59 correl_(Handle<Quote>(ext::make_shared<SimpleQuote>(correlation))),
60 beta_(sqrt(correlation)),
61 biphi_(-sqrt(correlation))
62 {
63 for (Real recoverie : recoveries)
64 rrQuotes_.emplace_back(ext::make_shared<RecoveryRateQuote>(recoverie));
65 }
66
68 const Handle<Quote>& correlQuote,
69 const std::vector<Real>& recoveries)
70 : LatentModel<GaussianCopulaPolicy>(sqrt(correlQuote->value()),
71 recoveries.size(),
72 //g++ complains default value not seen as typename
73 GaussianCopulaPolicy::initTraits()),
74 sqrt1minuscorrel_(std::sqrt(1.-correlQuote->value())),
75 correl_(correlQuote),
76 beta_(sqrt(correlQuote->value())),
77 biphi_(-sqrt(correlQuote->value()))
78 {
80 for (Real recoverie : recoveries)
81 rrQuotes_.emplace_back(ext::make_shared<RecoveryRateQuote>(recoverie));
82 }
83
84
86 Real remainingNot, // << at the given date 'd'
87 Real prob, // << at the given date 'd'
88 Real averageRR, // << at the given date 'd'
89 // these are percentual values:
90 Real attachLimit, Real detachLimit) const
91 {
92
93 if (attachLimit >= detachLimit) return 0.;// or is it an error?
94 // expected remaining notional:
95 if (remainingNot == 0.) return 0.;
96
97 const Real one = 1.0 - 1.0e-12; // FIXME DUE TO THE INV CUMUL AT 1
98 const Real k1 = std::min(one, attachLimit /(1.0 - averageRR)
99 ) + QL_EPSILON;
100 const Real k2 = std::min(one, detachLimit /(1.0 - averageRR)
101 ) + QL_EPSILON;
102
103 if (prob > 0) {
105 const Real invFlightK1 =
106 (ip-sqrt1minuscorrel_ *
108 const Real invFlightK2 = (ip-sqrt1minuscorrel_*
110
111 return remainingNot * (detachLimit * phi_(invFlightK2)
112 - attachLimit * phi_(invFlightK1) + (1.-averageRR) *
113 (biphi_(ip, -invFlightK2) - biphi_(ip, -invFlightK1)) );
114 }
115 else return 0.0;
116 }
117
119 Real remainingLossFraction) const {
120 // these test goes into basket<<<<<<<<<<<<<<<<<<<<<<<<<
121 QL_REQUIRE(remainingLossFraction >=0., "Incorrect loss fraction.");
122 QL_REQUIRE(remainingLossFraction <=1., "Incorrect loss fraction.");
123
124 Real remainingAttachAmount = basket_->remainingAttachmentAmount();
125 Real remainingDetachAmount = basket_->remainingDetachmentAmount();
126 // live unerlying portfolio loss fraction (remaining portf fraction)
127
128 const Real remainingBasktNot = basket_->remainingNotional(d);
129 const Real attach =
130 std::min(remainingAttachAmount / remainingBasktNot, 1.);
131 const Real detach =
132 std::min(remainingDetachAmount / remainingBasktNot, 1.);
133
134 Real portfFract =
135 attach + remainingLossFraction * (detach - attach);
136
137 Real averageRR = averageRecovery(d);
138 Real maxAttLossFract = (1.-averageRR);
139 if(portfFract > maxAttLossFract) return 0.;
140
141 // for non-equity losses add the probability jump at zero tranche
142 // losses (since this method returns prob of losing more or
143 // equal to)
144 if(portfFract <= QL_EPSILON) return 1.;
145
146 Probability prob = averageProb(d);
147
149 Real invFlightK = (ip-sqrt1minuscorrel_*
151 /(1.-averageRR)))/beta_;
152
153 return phi_(invFlightK);//probOver
154 }
155
157 Probability perctl) const
158 {
159 // loss as a fraction of the live portfolio
160 Real ptflLossPerc = percentilePortfolioLossFraction(d, perctl);
161 Real remainingAttachAmount = basket_->remainingAttachmentAmount();
162 Real remainingDetachAmount = basket_->remainingDetachmentAmount();
163
164 const Real remainingNot = basket_->remainingNotional(d);
165 const Real attach =
166 std::min(remainingAttachAmount / remainingNot, 1.);
167 const Real detach =
168 std::min(remainingDetachAmount / remainingNot, 1.);
169
170 if(ptflLossPerc >= detach-QL_EPSILON)
171 return remainingNot * (detach-attach);//equivalent
172
173 Real maxLossLevel = std::max(attach, ptflLossPerc);
174 Probability prob = averageProb(d);
175 Real averageRR = averageRecovery(d);
176
177 Real valA = expectedTrancheLossImpl(remainingNot, prob,
178 averageRR, maxLossLevel, detach);
179 Real valB = // probOverLoss(d, maxLossLevel);//in live tranche units
180 // from fraction of basket notional to fraction of tranche notional
181 probOverLoss(d, std::min(std::max((maxLossLevel - attach)
182 /(detach - attach), 0.), 1.));
183 return ( valA + (maxLossLevel - attach) * remainingNot * valB )
184 / (1.-perctl);
185 }
186
188 const Date& d, Real perctl) const
189 {
190 // this test goes into basket<<<<<<<<<<<<<<<<<<<<<<<<<
191 QL_REQUIRE(perctl >= 0. && perctl <=1.,
192 "Percentile argument out of bounds.");
193
194 if(perctl==0.) return 0.;// portfl == attach
195 if(perctl==1.) perctl = 1. - QL_EPSILON; // portfl == detach
196
197 return (1.-averageRecovery(d)) *
201 }
202
203}
204
205#endif
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 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
GaussianLHPLossModel(const Handle< Quote > &correlQuote, const std::vector< Handle< RecoveryRateQuote > > &quotes)
Real expectedShortfall(const Date &d, Probability perctl) const override
Returns the ESF as an absolute amount (rather than a fraction)
static CumulativeNormalDistribution const phi_
Shared handle to an observable.
Definition: handle.hpp:41
Generic multifactor latent variable model.
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
purely virtual base class for market observables
Definition: quote.hpp:37
market element returning a stored value
Definition: simplequote.hpp:33
#define QL_EPSILON
Definition: qldefines.hpp:178
QL_REAL Real
real number
Definition: types.hpp:50
Real Probability
probability
Definition: types.hpp:82
Definition: any.hpp:35
STL namespace.