| 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 | Real nominal() const { return nominal_; } |
| 137 | Real lgd() const { return lgd_; } |
| 138 | Real attachment() const { return attachment_; } |
| 139 | Real detachment() const { return detachment_; } |
| 140 | std::vector<Real> nominals() { return nominals_; } |
| 141 | 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 |
| 187 | |