/src/quantlib/ql/experimental/credit/cdo.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2008 Roland Lichters |
5 | | |
6 | | This file is part of QuantLib, a free-software/open-source library |
7 | | for financial quantitative analysts and developers - http://quantlib.org/ |
8 | | |
9 | | QuantLib is free software: you can redistribute it and/or modify it |
10 | | under the terms of the QuantLib license. You should have received a |
11 | | copy of the license along with this program; if not, please email |
12 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
13 | | <http://quantlib.org/license.shtml>. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, but WITHOUT |
16 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
17 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
18 | | */ |
19 | | |
20 | | /*! \file cdo.hpp |
21 | | \brief collateralized debt obligation |
22 | | */ |
23 | | |
24 | | #ifndef quantlib_cdo_hpp |
25 | | #define quantlib_cdo_hpp |
26 | | |
27 | | #include <ql/instrument.hpp> |
28 | | #include <ql/termstructures/yieldtermstructure.hpp> |
29 | | #include <ql/termstructures/defaulttermstructure.hpp> |
30 | | #include <ql/experimental/credit/lossdistribution.hpp> |
31 | | #include <ql/experimental/credit/onefactorcopula.hpp> |
32 | | #include <ql/time/schedule.hpp> |
33 | | |
34 | | namespace QuantLib { |
35 | | |
36 | | //! collateralized debt obligation |
37 | | /*! The instrument prices a mezzanine CDO tranche with loss given |
38 | | default between attachment point \f$ D_1\f$ and detachment |
39 | | point \f$ D_2 > D_1 \f$. |
40 | | |
41 | | For purchased protection, the instrument value is given by the |
42 | | difference of the protection value \f$ V_1 \f$ and premium |
43 | | value \f$ V_2 \f$, |
44 | | |
45 | | \f[ V = V_1 - V_2. \f] |
46 | | |
47 | | The protection leg is priced as follows: |
48 | | |
49 | | - Build the probability distribution for volume of defaults |
50 | | \f$ L \f$ (before recovery) or Loss Given Default \f$ LGD = |
51 | | (1-r)\,L \f$ at times/dates \f$ t_i, i=1, ..., N\f$ (premium |
52 | | schedule times with intermediate steps) |
53 | | - Determine the expected value |
54 | | \f$ E_i = E_{t_i}\,\left[Pay(LGD)\right] \f$ |
55 | | of the protection payoff \f$ Pay(LGD) \f$ at each time |
56 | | \f$ t_i\f$ where |
57 | | \f[ |
58 | | Pay(L) = min (D_1, LGD) - min (D_2, LGD) = \left\{ |
59 | | \begin{array}{lcl} |
60 | | \displaystyle 0 &;& LGD < D_1 \\ |
61 | | \displaystyle LGD - D_1 &;& D_1 \leq LGD \leq D_2 \\ |
62 | | \displaystyle D_2 - D_1 &;& LGD > D_2 |
63 | | \end{array} |
64 | | \right. |
65 | | \f] |
66 | | - The protection value is then calculated as |
67 | | \f[ V_1 \:=\: \sum_{i=1}^N (E_i - E_{i-1}) \cdot d_i \f] |
68 | | where \f$ d_i\f$ is the discount factor at time/date \f$ t_i \f$ |
69 | | |
70 | | The premium is paid on the protected notional amount, |
71 | | initially \f$ D_2 - D_1. \f$ This notional amount is reduced |
72 | | by the expected protection payments \f$ E_i \f$ at times |
73 | | \f$ t_i, \f$ so that the premium value is calculated as |
74 | | |
75 | | \f[ |
76 | | V_2 = m \, \cdot \sum_{i=1}^N \,(D_2 - D_1 - E_i) |
77 | | \cdot \Delta_{i-1,i}\,d_i |
78 | | \f] |
79 | | |
80 | | where \f$ m \f$ is the premium rate, \f$ \Delta_{i-1, i}\f$ is |
81 | | the day count fraction between date/time \f$ t_{i-1}\f$ and |
82 | | \f$ t_i.\f$ |
83 | | |
84 | | The construction of the portfolio loss distribution \f$ E_i |
85 | | \f$ is based on the probability bucketing algorithm described |
86 | | in |
87 | | |
88 | | <strong> |
89 | | John Hull and Alan White, "Valuation of a CDO and nth to default CDS |
90 | | without Monte Carlo simulation", Journal of Derivatives 12, 2, 2004 |
91 | | </strong> |
92 | | |
93 | | The pricing algorithm allows for varying notional amounts and |
94 | | default termstructures of the underlyings. |
95 | | |
96 | | \todo Investigate and fix cases \f$ E_{i+1} < E_i. \f$ |
97 | | */ |
98 | | class CDO : public Instrument { |
99 | | public: |
100 | | /*! \param attachment fraction of the LGD where protection starts |
101 | | \param detachment fraction of the LGD where protection ends |
102 | | \param nominals vector of basket nominal amounts |
103 | | \param basket default basket represented by a vector of |
104 | | default term structures that allow |
105 | | computing single name default |
106 | | probabilities depending on time |
107 | | \param copula one-factor copula |
108 | | \param protectionSeller sold protection if set to true, purchased |
109 | | otherwise |
110 | | \param premiumSchedule schedule for premium payments |
111 | | \param premiumRate annual premium rate, e.g. 0.05 for 5% p.a. |
112 | | \param dayCounter day count convention for the premium rate |
113 | | \param recoveryRate recovery rate as a fraction |
114 | | \param upfrontPremiumRate premium as a tranche notional fraction |
115 | | \param yieldTS yield term structure handle |
116 | | \param nBuckets number of distribution buckets |
117 | | \param integrationStep time step for integrating over one |
118 | | premium period; if larger than premium |
119 | | period length, a single step is taken |
120 | | */ |
121 | | CDO(Real attachment, |
122 | | Real detachment, |
123 | | std::vector<Real> nominals, |
124 | | const std::vector<Handle<DefaultProbabilityTermStructure> >& basket, |
125 | | Handle<OneFactorCopula> copula, |
126 | | bool protectionSeller, |
127 | | Schedule premiumSchedule, |
128 | | Rate premiumRate, |
129 | | DayCounter dayCounter, |
130 | | Rate recoveryRate, |
131 | | Rate upfrontPremiumRate, |
132 | | Handle<YieldTermStructure> yieldTS, |
133 | | Size nBuckets, |
134 | | const Period& integrationStep = Period(10, Years)); |
135 | | |
136 | 0 | Real nominal() const { return nominal_; } |
137 | 0 | Real lgd() const { return lgd_; } |
138 | 0 | Real attachment() const { return attachment_; } |
139 | 0 | Real detachment() const { return detachment_; } |
140 | 0 | std::vector<Real> nominals() { return nominals_; } |
141 | 0 | Size size() { return basket_.size(); } |
142 | | |
143 | | bool isExpired() const override; |
144 | | Rate fairPremium() const; |
145 | | Rate premiumValue () const; |
146 | | Rate protectionValue () const; |
147 | | Size error () const; |
148 | | |
149 | | private: |
150 | | void setupExpired() const override; |
151 | | void performCalculations() const override; |
152 | | Real expectedTrancheLoss (Date d) const; |
153 | | |
154 | | Real attachment_; |
155 | | Real detachment_; |
156 | | std::vector<Real> nominals_; |
157 | | std::vector<Handle<DefaultProbabilityTermStructure> > basket_; |
158 | | Handle<OneFactorCopula> copula_; |
159 | | bool protectionSeller_; |
160 | | |
161 | | Schedule premiumSchedule_; |
162 | | Rate premiumRate_; |
163 | | DayCounter dayCounter_; |
164 | | Rate recoveryRate_; |
165 | | Rate upfrontPremiumRate_; |
166 | | Handle<YieldTermStructure> yieldTS_; |
167 | | Size nBuckets_; // number of buckets up to detachment point |
168 | | Period integrationStep_; |
169 | | |
170 | | std::vector<Real> lgds_; |
171 | | |
172 | | Real nominal_; // total basket volume (sum of nominals_) |
173 | | Real lgd_; // maximum loss given default (sum of lgds_) |
174 | | Real xMax_; // tranche detachment point (tranche_ * nominal_) |
175 | | Real xMin_; // tranche attachment point (tranche_ * nominal_) |
176 | | |
177 | | mutable Size error_; |
178 | | |
179 | | mutable Real premiumValue_; |
180 | | mutable Real protectionValue_; |
181 | | mutable Real upfrontPremiumValue_; |
182 | | }; |
183 | | |
184 | | } |
185 | | |
186 | | #endif |