Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
basket.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/*! \file qle/models/basket.hpp
20 \brief basket of issuers and related notionals
21*/
22
23#ifndef quantext_basket_hpp
24#define quantext_basket_hpp
25
26#include <ql/experimental/credit/defaultprobabilitykey.hpp>
27#include <ql/experimental/credit/issuer.hpp>
28#include <ql/experimental/credit/loss.hpp>
29#include <ql/experimental/credit/pool.hpp>
30#include <ql/experimental/credit/recoveryratemodel.hpp>
31#include <ql/instruments/claim.hpp>
32#include <ql/patterns/lazyobject.hpp>
33#include <ql/termstructures/defaulttermstructure.hpp>
34
35namespace QuantExt {
36using namespace QuantLib;
37
38// include QuantExt::DefaultLossModel from qle/models/defaultlossmodel.hpp instead
39class DefaultLossModel;
40
41/*! Credit Basket.\par
42 A basket is a collection of credit names, represented by a
43 unique identifier (a text string), associated notional
44 amounts, a pool and tranche information. The pool is a map of
45 "names" to issuers. The Basket structure is motivated by CDO
46 squared instruments containing various underlying inner CDOs
47 which can be represented by respective baskets including their
48 tranche structure. The role of the Pool is providing a unique
49 list of relevant issuers while names may appear multiple times
50 across different baskets (overlap).
51 */
52class Basket : public LazyObject {
53public:
54 Basket() {}
55 /*! Constructs a basket of simple collection of constant notional
56 positions subject to default risk only.
57
58 The refDate parameter is the basket inception date, that is,
59 the date at which defaultable events are relevant. (There
60 are no constraints on forward baskets but models assigned
61 should be consistent.)
62 */
63 Basket(const Date& refDate, const std::vector<std::string>& names, const std::vector<Real>& notionals,
64 const QuantLib::ext::shared_ptr<Pool> pool, Real attachmentRatio = 0.0, Real detachmentRatio = 1.0,
65 const QuantLib::ext::shared_ptr<Claim>& claim = QuantLib::ext::shared_ptr<Claim>(new FaceValueClaim()));
66 void computeBasket() const {
67 Date today = Settings::instance().evaluationDate();
68 /* update cache values at the calculation date (work as arguments
69 to the Loss Models)
70 \to do: IMPORTANT: notice that defaults added to Issuers dont get
71 notify as the codes stnds today. Issuers need to be observables.
72 */
73 // this one must remain on top since there are dependencies
82 }
83 //! Basket inception number of counterparties.
84 Size size() const;
85 //! Basket counterparties names at inception.
86 const std::vector<std::string>& names() const { return pool_->names(); }
87 //! Basket counterparties notionals at inception.
88 const std::vector<Real>& notionals() const;
89 //! Returns the total expected exposures for that name.
90 Real exposure(const std::string& name, const Date& = Date()) const;
91 //! Underlying pool
92 const QuantLib::ext::shared_ptr<Pool>& pool() const;
93 //! The keys each counterparty enters the basket with (sensitive to)
94 std::vector<DefaultProbKey> defaultKeys() const;
95 /*! Loss Given Default for all issuers/notionals based on
96 expected recovery rates for the respective issuers.
97 */
98 //! Basket inception date.
99 const Date& refDate() const { return refDate_; }
100 /*! Attachment point expressed as a fraction of the total inception
101 notional.
102 */
103 Real attachmentRatio() const { return attachmentRatio_; }
104 //! Detachment point expressed as a fraction of the total pool notional
105 Real detachmentRatio() const { return detachmentRatio_; }
106 //! Original basket notional ignoring any losses.
107 Real basketNotional() const {
108 calculate();
109 return basketNotional_;
110 }
111 //! Original tranche notional ignoring any realized losses.
112 Real trancheNotional() const {
113 calculate();
114 return trancheNotional_;
115 }
116 //! Attachment amount = attachmentRatio() * basketNotional()
117 Real attachmentAmount() const {
118 calculate();
119 return attachmentAmount_;
120 }
121 //! Detachment amount = detachmentRatio() * basketNotional()
122 Real detachmentAmount() const {
123 calculate();
124 return detachmentAmount_;
125 }
126 //! default claim, same for all positions and counterparties
127 QuantLib::ext::shared_ptr<Claim> claim() const { return claim_; }
128 /*! Vector of cumulative default probability to date d for all
129 issuers in the basket.
130 */
131 std::vector<Probability> probabilities(const Date& d) const;
132 /*! Realized basket losses between the reference date and the
133 calculation date, taking the actual recovery rates of loss events
134 into account.
135 Only default events that have settled (have a realized RR) are
136 accounted for. For contingent losses after a default you need
137 to compute the losses through a DefaultLossModel
138
139 Optionally one can pass a date in the future and that will collect
140 events stored in the issuers list. This shows the effect of
141 'programmed' (after today's) events on top of past ones. The
142 intention is to be used in risk analysis (jump to default, etc).
143 */
144 Real settledLoss() const;
145 Real settledLoss(const Date&) const;
146 /*! Actual basket losses between the reference date and the calculation
147 date, taking the actual recovery rates of loss events into account.
148 If the event has not settled yet a model driven recovery is used.
149
150 Returns the realized losses in this portfolio since the portfolio
151 default reference date.
152 This method relies on an implementation of the loss given default
153 since the events have not necessarily settled.
154 */
155 Real cumulatedLoss() const;
156 Real cumulatedLoss(const Date&) const;
157 /*! Remaining full basket (untranched) notional after settled losses
158 between the reference date and the given date. The full notional
159 for defaulted names is subracted, recovery ignored.
160 */
161 Real remainingNotional() const;
162 Real remainingNotional(const Date&) const;
163 /*! Vector of surviving notionals after settled losses between the
164 reference date and the given date, recovery ignored.
165 */
166 const std::vector<Real>& remainingNotionals() const;
167 std::vector<Real> remainingNotionals(const Date&) const;
168 /*! Vector of surviving issuers after defaults between the reference
169 basket date and the given (or evaluation) date.
170 */
171 const std::vector<std::string>& remainingNames() const;
172 std::vector<std::string> remainingNames(const Date&) const;
173 /*! Default keys of non defaulted counterparties
174 */
175 const std::vector<DefaultProbKey>& remainingDefaultKeys() const;
176 std::vector<DefaultProbKey> remainingDefaultKeys(const Date&) const;
177 //! Number of counterparties alive on the requested date.
178 Size remainingSize() const;
179 Size remainingSize(const Date&) const;
180 /*! Vector of cumulative default probability to date d for all
181 issuers still (at the evaluation date) alive in the basket.
182 */
183 std::vector<Probability> remainingProbabilities(const Date& d) const;
184 /*!
185 Attachment amount of the equivalent (after defaults) remaining basket
186 The remaining attachment amount is
187 RAA = max (0, attachmentAmount - cumulatedLoss())
188
189 The remaining attachment ratio is then
190 RAR = RAA / remainingNotional()
191 */
192 Real remainingAttachmentAmount() const;
193 Real remainingAttachmentAmount(const Date& endDate) const;
194
195 /*!
196 Detachment amount of the equivalent remaining basket.
197 The remaining detachment amount is
198 RDA = max (0, detachmentAmount - cumulatedLoss())
199
200 The remaining detachment ratio is then
201 RDR = RDA / remainingNotional()
202 */
203 Real remainingDetachmentAmount() const;
204 Real remainingDetachmentAmount(const Date& endDate) const;
205
206 //! Remaining basket tranched notional on calculation date
208 calculate();
210 }
211 /*! Expected basket tranched notional on the requested date
212 according to the basket model. Model should have been assigned.
213 */
214 Real remainingTrancheNotional(const Date& endDate) const {
215 calculate();
216 return remainingDetachmentAmount(endDate) - remainingAttachmentAmount(endDate);
217 }
218 //! Indexes of remaining names. Notice these are names and not positions.
219 const std::vector<Size>& liveList() const;
220 std::vector<Size> liveList(const Date&) const; //?? keep?
221 //! Assigns the default loss model to this basket. Resets calculations.
222 // RL: Use QuantExt version here
223 void setLossModel(const QuantLib::ext::shared_ptr<QuantExt::DefaultLossModel>& lossModel);
224 /*! \name Basket Loss Statistics
225 Methods providing statistical metrics on the loss or value
226 distribution of the basket. Most calculations rely on the pressence
227 of a model assigned to the basket.
228 */
229 //@{
230 Real expectedTrancheLoss(const Date& d, Real recoveryRate = Null<Real>()) const;
231 /*! The lossFraction is the fraction of losses expressed in
232 inception (no losses) tranche units (e.g. 'attach level'=0%,
233 'detach level'=100%)
234 */
235 Probability probOverLoss(const Date& d, Real lossFraction) const;
236 /*!
237 */
238 Real percentile(const Date& d, Probability prob) const;
239 /*! ESF
240 */
241 Real expectedShortfall(const Date& d, Probability prob) const;
242 /* Split a portfolio loss along counterparties. Typically loss
243 corresponds to some percentile.*/
244 std::vector<Real> splitVaRLevel(const Date& date, Real loss) const;
245 /*! Full loss distribution
246 */
247 std::map<Real, Probability> lossDistribution(const Date&) const;
248 Real densityTrancheLoss(const Date& d, Real lossFraction) const;
249 Real defaultCorrelation(const Date& d, Size iName, Size jName) const;
250 /*! Probability vector that each of the remaining live names (at eval
251 date) is the n-th default by date d.
252
253 The n parameter is the internal index to the name; it should
254 be alive at the evaluation date.
255
256 ---------TO DO: Implement with a string passed----------------------
257 ---------TO DO: Perform check the name is alive---------------------
258 */
259 std::vector<Probability> probsBeingNthEvent(Size n, const Date& d) const;
260 /*! Returns the probaility of having a given or larger number of
261 defaults in the basket portfolio at a given time.
262 */
263 Probability probAtLeastNEvents(Size n, const Date& d) const;
264 /*! Expected recovery rate of the underlying position as a fraction of
265 its exposure value at date d _given_ it has defaulted _on_ that date.
266 NOTICE THE ARG IS THE CTPTY....SHOULDNT IT BE THE POSITION/INSTRUMENT?????<<<<<<<<<<<<<<<<<<<<<<<
267 */
268 Real recoveryRate(const Date& d, Size iName) const;
269
270 /*! Return single correlation number from the underlying loss model if it is a one factor model.
271 If the underlying loss model is null, this returns a \c Null<Real>().
272 */
273 QuantLib::Real correlation() const;
274 //@}
275private:
276 // LazyObject interface
277 void performCalculations() const override;
278
279 std::vector<Real> notionals_;
280 QuantLib::ext::shared_ptr<Pool> pool_;
281 //! The claim is the same for all names
282 const QuantLib::ext::shared_ptr<Claim> claim_;
283
286 mutable Real basketNotional_;
287 //! basket tranched inception attachment amount:
288 mutable Real attachmentAmount_;
289 //! basket tranched inception detachment amount:
290 mutable Real detachmentAmount_;
291 //! basket tranched notional amount:
292 mutable Real trancheNotional_;
293 /* Caches. Most of the times one wants statistics on the distribution of
294 futures losses at arbitrary dates but some problems (e.g. derivatives
295 pricing) work with todays (evalDate) magnitudes which do not require a
296 loss model and would be too expensive to recompute on every call.
297 */
299 mutable std::vector<Size> evalDateLiveList_;
300 mutable std::vector<Real> evalDateLiveNotionals_;
301 mutable std::vector<std::string> evalDateLiveNames_;
302 mutable std::vector<DefaultProbKey> evalDateLiveKeys_;
303 //! Basket inception date.
304 const Date refDate_;
305 /* It is the basket responsibility to ensure that the model assigned it
306 is properly initialized to the basket current data.
307 This might not be the case for various reasons: the basket data might
308 have been updated, the evaluation date has changed or the model has
309 received another request from another basket pointing to it. For
310 this last reason we can never be sure between calls that this is the
311 case (and that is true in a single thread environment only).
312 */
313 // RL: Use QuantExt version here
314 QuantLib::ext::shared_ptr<QuantExt::DefaultLossModel> lossModel_;
315};
316
317// ------------ Inlines -------------------------------------------------
318
319inline Size Basket::size() const { return pool_->size(); }
320
321inline const std::vector<Real>& Basket::notionals() const { return notionals_; }
322
323inline std::vector<DefaultProbKey> Basket::defaultKeys() const { return pool_->defaultKeys(); }
324
325inline const QuantLib::ext::shared_ptr<Pool>& Basket::pool() const { return pool_; }
326
327inline const std::vector<Size>& Basket::liveList() const {
328 calculate();
329 return evalDateLiveList_;
330}
331
333 calculate();
335}
336
338 calculate();
340}
341
342inline const std::vector<std::string>& Basket::remainingNames() const {
343 calculate();
344 return evalDateLiveNames_;
345}
346
347inline const std::vector<Real>& Basket::remainingNotionals() const {
348 calculate();
350}
351
352inline Real Basket::cumulatedLoss() const {
353 calculate();
354 return this->evalDateSettledLoss_;
355}
356
357inline Real Basket::settledLoss() const {
358 calculate();
360}
361
362inline const std::vector<DefaultProbKey>& Basket::remainingDefaultKeys() const {
363 calculate();
364 return evalDateLiveKeys_;
365}
366
367} // namespace QuantExt
368
369#endif
std::vector< Probability > probabilities(const Date &d) const
Definition: basket.cpp:91
Real recoveryRate(const Date &d, Size iName) const
Definition: basket.cpp:335
Real evalDateAttachAmount_
Definition: basket.hpp:298
void performCalculations() const override
Definition: basket.cpp:66
Real defaultCorrelation(const Date &d, Size iName, Size jName) const
Definition: basket.cpp:322
Real detachmentAmount_
basket tranched inception detachment amount:
Definition: basket.hpp:290
Real remainingAttachmentAmount() const
Definition: basket.hpp:337
Real detachmentAmount() const
Detachment amount = detachmentRatio() * basketNotional()
Definition: basket.hpp:122
const std::vector< DefaultProbKey > & remainingDefaultKeys() const
Definition: basket.hpp:362
Real evalDateSettledLoss_
Definition: basket.hpp:298
std::vector< DefaultProbKey > evalDateLiveKeys_
Definition: basket.hpp:302
std::vector< Real > evalDateLiveNotionals_
Definition: basket.hpp:300
const std::vector< Real > & notionals() const
Basket counterparties notionals at inception.
Definition: basket.hpp:321
Real remainingTrancheNotional() const
Remaining basket tranched notional on calculation date.
Definition: basket.hpp:207
std::vector< Size > evalDateLiveList_
Definition: basket.hpp:299
Real attachmentAmount_
basket tranched inception attachment amount:
Definition: basket.hpp:288
QuantLib::ext::shared_ptr< Pool > pool_
Definition: basket.hpp:280
const QuantLib::ext::shared_ptr< Claim > claim_
The claim is the same for all names.
Definition: basket.hpp:282
Real detachmentRatio() const
Detachment point expressed as a fraction of the total pool notional.
Definition: basket.hpp:105
Real attachmentRatio() const
Definition: basket.hpp:103
std::vector< DefaultProbKey > defaultKeys() const
The keys each counterparty enters the basket with (sensitive to)
Definition: basket.hpp:323
QuantLib::Real correlation() const
Definition: basket.cpp:340
Real attachmentAmount() const
Attachment amount = attachmentRatio() * basketNotional()
Definition: basket.hpp:117
void computeBasket() const
Definition: basket.hpp:66
Real detachmentRatio_
Definition: basket.hpp:285
const Date refDate_
Basket inception date.
Definition: basket.hpp:304
Probability probOverLoss(const Date &d, Real lossFraction) const
Definition: basket.cpp:263
std::vector< Real > notionals_
Definition: basket.hpp:279
Size remainingSize() const
Number of counterparties alive on the requested date.
Definition: basket.cpp:242
Real remainingTrancheNotional(const Date &endDate) const
Definition: basket.hpp:214
Real exposure(const std::string &name, const Date &=Date()) const
Returns the total expected exposures for that name.
Definition: basket.cpp:196
Real densityTrancheLoss(const Date &d, Real lossFraction) const
Real trancheNotional_
basket tranched notional amount:
Definition: basket.hpp:292
Probability probAtLeastNEvents(Size n, const Date &d) const
Definition: basket.cpp:330
Real evalDateRemainingNot_
Definition: basket.hpp:298
const std::vector< Size > & liveList() const
Indexes of remaining names. Notice these are names and not positions.
Definition: basket.hpp:327
const std::vector< std::string > & names() const
Basket counterparties names at inception.
Definition: basket.hpp:86
const QuantLib::ext::shared_ptr< Pool > & pool() const
Underlying pool.
Definition: basket.hpp:325
QuantLib::ext::shared_ptr< Claim > claim() const
default claim, same for all positions and counterparties
Definition: basket.hpp:127
const Date & refDate() const
Basket inception date.
Definition: basket.hpp:99
Real percentile(const Date &d, Probability prob) const
Definition: basket.cpp:282
Size remainingSize(const Date &) const
std::vector< std::string > evalDateLiveNames_
Definition: basket.hpp:301
Real attachmentRatio_
Definition: basket.hpp:284
Real expectedTrancheLoss(const Date &d, Real recoveryRate=Null< Real >()) const
Definition: basket.cpp:293
QuantLib::ext::shared_ptr< QuantExt::DefaultLossModel > lossModel_
Definition: basket.hpp:314
std::vector< Probability > probsBeingNthEvent(Size n, const Date &d) const
Definition: basket.cpp:313
Real basketNotional() const
Original basket notional ignoring any losses.
Definition: basket.hpp:107
Real trancheNotional() const
Original tranche notional ignoring any realized losses.
Definition: basket.hpp:112
Real remainingDetachmentAmount() const
Definition: basket.hpp:332
Size size() const
Basket inception number of counterparties.
Definition: basket.hpp:319
const std::vector< std::string > & remainingNames() const
Definition: basket.hpp:342
Real expectedShortfall(const Date &d, Probability prob) const
Definition: basket.cpp:303
std::vector< Real > splitVaRLevel(const Date &date, Real loss) const
Definition: basket.cpp:298
Real cumulatedLoss() const
Definition: basket.hpp:352
void setLossModel(const QuantLib::ext::shared_ptr< QuantExt::DefaultLossModel > &lossModel)
Assigns the default loss model to this basket. Resets calculations.
Definition: basket.cpp:53
const std::vector< Real > & remainingNotionals() const
Definition: basket.hpp:347
Real evalDateDetachAmmount_
Definition: basket.hpp:298
std::vector< Probability > remainingProbabilities(const Date &d) const
Definition: basket.cpp:182
Real basketNotional_
Definition: basket.hpp:286
Real remainingNotional() const
Definition: basket.cpp:145
Real settledLoss() const
Definition: basket.hpp:357
std::map< Real, Probability > lossDistribution(const Date &) const
Definition: basket.cpp:308