Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
syntheticcdo.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 syntheticcdo.hpp
20 \brief Synthetic Collateralized Debt Obligation and pricing engines
21*/
22
23#ifndef quantext_synthetic_cdo_hpp
24#define quantext_synthetic_cdo_hpp
25
26#include <ql/qldefines.hpp>
27
28#ifndef QL_PATCH_SOLARIS
29
30#include <ql/default.hpp>
31#include <ql/instrument.hpp>
32#include <ql/time/schedule.hpp>
33
34//#include <ql/experimental/credit/basket.hpp>
35#include <ql/cashflows/fixedratecoupon.hpp>
36#include <ql/termstructures/yieldtermstructure.hpp>
37#include <ql/instruments/creditdefaultswap.hpp>
38#include <qle/models/basket.hpp>
39
40namespace QuantExt {
41using namespace QuantLib;
42
43// class YieldTermStructure;
44
45//! Synthetic Collateralized Debt Obligation
46/*!
47 The instrument prices a mezzanine CDO tranche with loss given default
48 between attachment point \f$ D_1\f$ and detachment point
49 \f$ D_2 > D_1 \f$.
50
51 For purchased protection, the instrument value is given by the difference
52 of the protection value \f$ V_1 \f$ and premium value \f$ V_2 \f$,
53
54 \f[ V = V_1 - V_2. \f]
55
56 The protection leg is priced as follows:
57
58 - Build the probability distribution for volume of defaults \f$ L \f$
59 (before recovery) or Loss Given Default \f$ LGD = (1-r)\,L \f$ at
60 times/dates \f$ t_i, i=1, ..., N\f$ (premium schedule times with
61 intermediate steps)
62
63 - Determine the expected value
64 \f$ E_i = E_{t_i}\,\left[Pay(LGD)\right] \f$
65 of the protection payoff \f$ Pay(LGD) \f$ at each time \f$ t_i\f$ where
66 \f[
67 Pay(L) = min (D_1, LGD) - min (D_2, LGD) = \left\{
68 \begin{array}{lcl}
69 \displaystyle 0 &;& LGD < D_1 \\
70 \displaystyle LGD - D_1 &;& D_1 \leq LGD \leq D_2 \\
71 \displaystyle D_2 - D_1 &;& LGD > D_2
72 \end{array}
73 \right.
74 \f]
75
76 - The protection value is then calculated as
77 \f[ V_1 \:=\: \sum_{i=1}^N (E_i - E_{i-1}) \cdot d_i \f]
78 where \f$ d_i\f$ is the discount factor at time/date \f$ t_i \f$
79
80 The premium is paid on the protected notional amount, initially
81 \f$ D_2 - D_1. \f$ This notional amount is reduced by the expected
82 protection
83 payments \f$ E_i \f$ at times \f$ t_i, \f$ so that the premium value is
84 calculated as
85
86 \f[
87 V_2 =m \, \cdot \sum_{i=1}^N \,(D_2 - D_1 - E_i) \cdot \Delta_{i-1,i}\,d_i
88 \f]
89
90 where \f$ m \f$ is the premium rate, \f$ \Delta_{i-1, i}\f$ is the day
91 count fraction between date/time \f$ t_{i-1}\f$ and \f$ t_i.\f$
92
93 The construction of the portfolio loss distribution \f$ E_i \f$ is
94 based on the probability bucketing algorithm described in
95
96 <strong>
97 John Hull and Alan White, "Valuation of a CDO and nth to default CDS
98 without Monte Carlo simulation", Journal of Derivatives 12, 2, 2004
99 </strong>
100
101 The pricing algorithm allows for varying notional amounts and
102 default termstructures of the underlyings.
103
104 \ingroup credit
105
106 \todo Investigate and fix cases \f$ E_{i+1} < E_i. \f$
107*/
108class SyntheticCDO : public Instrument {
109public:
110 class arguments;
111 class results;
112 class engine;
113
114 // Review: No accrual settlement flag. No separate upfront payment date.
115 // Review: Forward start case.
116 /*! If the notional exceeds the basket inception tranche
117 notional, the cdo is leveraged by that factor.
118
119 \todo: allow for extra payment flags, arbitrary upfront
120 payment date...
121 */
122 // RL: QuantExt version
123 SyntheticCDO(const QuantLib::ext::shared_ptr<QuantExt::Basket>& basket, Protection::Side side, const Schedule& schedule,
124 Rate upfrontRate, Rate runningRate, const DayCounter& dayCounter,
125 BusinessDayConvention paymentConvention, bool settlesAccrual = true,
126 const QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime =
127 QuantLib::CreditDefaultSwap::ProtectionPaymentTime::atDefault,
128 Date protectionStart = Date(), Date upfrontDate = Date(),
129 boost::optional<Real> notional = boost::none,
130 Real recoveryRate = Null<Real>(),
131 const DayCounter& lastPeriodDayCounter = DayCounter());
132
133 // RL: QuantExt version
134 const QuantLib::ext::shared_ptr<QuantExt::Basket>& basket() const { return basket_; }
135
136 bool isExpired() const override;
137 Rate fairPremium() const;
138 Rate fairUpfrontPremium() const;
139 Rate premiumValue() const;
140 Rate protectionValue() const;
141 Real premiumLegNPV() const;
142 Real protectionLegNPV() const;
143 //! Returns the recovery rate for fixed recovery CDO, otherwise returns Null<Real>()
144 Real recoveryRate() const { return recoveryRate_; }
145 /*!
146 Total outstanding tranche notional, not wiped out
147 */
148 Real remainingNotional() const;
149 /*! The number of times the contract contains the portfolio tranched
150 notional.
151 */
152 Real leverageFactor() const { return leverageFactor_; }
153 //! Last protection date.
154 const Date& maturity() const {
155 return QuantLib::ext::dynamic_pointer_cast<FixedRateCoupon>(normalizedLeg_.back())->accrualEndDate();
156 }
157 /*! The Gaussian Copula LHP implied correlation that makes the
158 contract zero value. This is for a flat correlation along
159 time and portfolio loss level.
160 */
161 Real implicitCorrelation(const std::vector<Real>& recoveries, const Handle<YieldTermStructure>& discountCurve,
162 Real targetNPV = 0., Real accuracy = 1.0e-3) const;
163
164 /*!
165 Expected tranche loss for all payment dates
166 */
167 std::vector<Real> expectedTrancheLoss() const;
168 Size error() const;
169
170 void setupArguments(PricingEngine::arguments*) const override;
171 void fetchResults(const PricingEngine::results*) const override;
172
173private:
174 void setupExpired() const override;
175
176 // RL: QuantExt version
177 QuantLib::ext::shared_ptr<QuantExt::Basket> basket_;
178 Protection::Side side_;
180
183 const Real leverageFactor_;
184 DayCounter dayCounter_;
185 BusinessDayConvention paymentConvention_;
187 QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime_;
190 QuantLib::ext::shared_ptr<CashFlow> upfrontPayment_, accrualRebate_, accrualRebateCurrent_;
192
193 mutable Real premiumValue_;
194 mutable Real protectionValue_;
196 mutable Real remainingNotional_;
197 mutable Size error_;
198 mutable std::vector<Real> expectedTrancheLoss_;
199};
200
202public:
203 arguments() : side(Protection::Side(-1)), upfrontRate(Null<Real>()), runningRate(Null<Real>()) {}
204 void validate() const override;
205
206 // RL: QuantExt version
207 QuantLib::ext::shared_ptr<QuantExt::Basket> basket;
208 Protection::Side side;
210
214 DayCounter dayCounter;
215 BusinessDayConvention paymentConvention;
216 QuantLib::ext::shared_ptr<CashFlow> upfrontPayment, accrualRebate, accrualRebateCurrent;
218 QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime;
222};
223
225public:
226 void reset() override;
233 Real xMin, xMax;
234 Size error;
235 /* Expected tranche losses affecting this tranche coupons. Notice this
236 number might be below the actual basket losses, since the cdo protection
237 might start after basket inception (forward start CDO)*/
238 std::vector<Real> expectedTrancheLoss;
239};
240
241//! CDO base engine
242class SyntheticCDO::engine : public GenericEngine<SyntheticCDO::arguments, SyntheticCDO::results> {};
243
244} // namespace QuantExt
245
246#endif
247
248#endif
basket of issuers and related notionals
QuantLib::ext::shared_ptr< QuantExt::Basket > basket
QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime
QuantLib::ext::shared_ptr< CashFlow > upfrontPayment
void validate() const override
QuantLib::ext::shared_ptr< CashFlow > accrualRebate
QuantLib::ext::shared_ptr< CashFlow > accrualRebateCurrent
BusinessDayConvention paymentConvention
std::vector< Real > expectedTrancheLoss
Synthetic Collateralized Debt Obligation.
QuantLib::ext::shared_ptr< CashFlow > accrualRebateCurrent_
std::vector< Real > expectedTrancheLoss() const
Rate fairUpfrontPremium() const
QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime_
QuantLib::ext::shared_ptr< QuantExt::Basket > basket_
const QuantLib::ext::shared_ptr< QuantExt::Basket > & basket() const
void setupArguments(PricingEngine::arguments *) const override
bool isExpired() const override
const Date & maturity() const
Last protection date.
Real implicitCorrelation(const std::vector< Real > &recoveries, const Handle< YieldTermStructure > &discountCurve, Real targetNPV=0., Real accuracy=1.0e-3) const
Rate protectionValue() const
Protection::Side side_
Real protectionLegNPV() const
QuantLib::ext::shared_ptr< CashFlow > accrualRebate_
BusinessDayConvention paymentConvention_
Real premiumLegNPV() const
Real recoveryRate() const
Returns the recovery rate for fixed recovery CDO, otherwise returns Null<Real>()
void setupExpired() const override
void fetchResults(const PricingEngine::results *) const override
Real leverageFactor() const
std::vector< Real > expectedTrancheLoss_
Real remainingNotional() const
QuantLib::ext::shared_ptr< CashFlow > upfrontPayment_