Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
SyntheticCDO Class Reference

Synthetic Collateralized Debt Obligation. More...

#include <qle/instruments/syntheticcdo.hpp>

+ Inheritance diagram for SyntheticCDO:
+ Collaboration diagram for SyntheticCDO:

Classes

class  arguments
 
class  engine
 CDO base engine. More...
 
class  results
 

Public Member Functions

 SyntheticCDO (const QuantLib::ext::shared_ptr< QuantExt::Basket > &basket, Protection::Side side, const Schedule &schedule, Rate upfrontRate, Rate runningRate, const DayCounter &dayCounter, BusinessDayConvention paymentConvention, bool settlesAccrual=true, const QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime=QuantLib::CreditDefaultSwap::ProtectionPaymentTime::atDefault, Date protectionStart=Date(), Date upfrontDate=Date(), boost::optional< Real > notional=boost::none, Real recoveryRate=Null< Real >(), const DayCounter &lastPeriodDayCounter=DayCounter())
 
const QuantLib::ext::shared_ptr< QuantExt::Basket > & basket () const
 
bool isExpired () const override
 
Rate fairPremium () const
 
Rate fairUpfrontPremium () const
 
Rate premiumValue () const
 
Rate protectionValue () const
 
Real premiumLegNPV () const
 
Real protectionLegNPV () const
 
Real recoveryRate () const
 Returns the recovery rate for fixed recovery CDO, otherwise returns Null<Real>() More...
 
Real remainingNotional () const
 
Real leverageFactor () const
 
const Date & maturity () const
 Last protection date. More...
 
Real implicitCorrelation (const std::vector< Real > &recoveries, const Handle< YieldTermStructure > &discountCurve, Real targetNPV=0., Real accuracy=1.0e-3) const
 
std::vector< Real > expectedTrancheLoss () const
 
Size error () const
 
void setupArguments (PricingEngine::arguments *) const override
 
void fetchResults (const PricingEngine::results *) const override
 

Private Member Functions

void setupExpired () const override
 

Private Attributes

QuantLib::ext::shared_ptr< QuantExt::Basketbasket_
 
Protection::Side side_
 
Leg normalizedLeg_
 
Rate upfrontRate_
 
Rate runningRate_
 
const Real leverageFactor_
 
DayCounter dayCounter_
 
BusinessDayConvention paymentConvention_
 
bool settlesAccrual_
 
QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime_
 
Date protectionStart_
 
Date upfrontDate_
 
QuantLib::ext::shared_ptr< CashFlow > upfrontPayment_
 
QuantLib::ext::shared_ptr< CashFlow > accrualRebate_
 
QuantLib::ext::shared_ptr< CashFlow > accrualRebateCurrent_
 
Real recoveryRate_
 
Real premiumValue_
 
Real protectionValue_
 
Real upfrontPremiumValue_
 
Real remainingNotional_
 
Size error_
 
std::vector< Real > expectedTrancheLoss_
 

Detailed Description

Synthetic Collateralized Debt Obligation.

The instrument prices a mezzanine CDO tranche with loss given default between attachment point \( D_1\) and detachment point \( D_2 > D_1 \).

For purchased protection, the instrument value is given by the difference of the protection value \( V_1 \) and premium value \( V_2 \),

\[ V = V_1 - V_2. \]

The protection leg is priced as follows:

The premium is paid on the protected notional amount, initially \( D_2 - D_1. \) This notional amount is reduced by the expected protection payments \( E_i \) at times \( t_i, \) so that the premium value is calculated as

\[ V_2 =m \, \cdot \sum_{i=1}^N \,(D_2 - D_1 - E_i) \cdot \Delta_{i-1,i}\,d_i \]

where \( m \) is the premium rate, \( \Delta_{i-1, i}\) is the day count fraction between date/time \( t_{i-1}\) and \( t_i.\)

The construction of the portfolio loss distribution \( E_i \) is based on the probability bucketing algorithm described in

John Hull and Alan White, "Valuation of a CDO and nth to default CDS without Monte Carlo simulation", Journal of Derivatives 12, 2, 2004

The pricing algorithm allows for varying notional amounts and default termstructures of the underlyings.

Definition at line 108 of file syntheticcdo.hpp.

Constructor & Destructor Documentation

◆ SyntheticCDO()

SyntheticCDO ( const QuantLib::ext::shared_ptr< QuantExt::Basket > &  basket,
Protection::Side  side,
const Schedule &  schedule,
Rate  upfrontRate,
Rate  runningRate,
const DayCounter &  dayCounter,
BusinessDayConvention  paymentConvention,
bool  settlesAccrual = true,
const QuantLib::CreditDefaultSwap::ProtectionPaymentTime  protectionPaymentTime = QuantLib::CreditDefaultSwap::ProtectionPaymentTime::atDefault,
Date  protectionStart = Date(),
Date  upfrontDate = Date(),
boost::optional< Real >  notional = boost::none,
Real  recoveryRate = Null<Real>(),
const DayCounter &  lastPeriodDayCounter = DayCounter() 
)

If the notional exceeds the basket inception tranche notional, the cdo is leveraged by that factor.

Definition at line 40 of file syntheticcdo.cpp.

46 : basket_(basket), side_(side), upfrontRate_(upfrontRate), runningRate_(runningRate),
47 leverageFactor_(notional ? notional.get() / basket->trancheNotional() : 1.), dayCounter_(dayCounter),
48 paymentConvention_(paymentConvention), settlesAccrual_(settlesAccrual),
49 protectionPaymentTime_(protectionPaymentTime),
50 protectionStart_(protectionStart == Null<Date>() ? schedule[0] : protectionStart),
52 QL_REQUIRE((schedule.rule() == DateGeneration::CDS || schedule.rule() == DateGeneration::CDS2015) ||
53 protectionStart_ <= schedule[0],
54 "protection can not start after accrual for (pre big bang-) CDS");
55 QL_REQUIRE(basket->names().size() > 0, "basket is empty");
56 // Basket inception must lie before contract protection start.
57 QL_REQUIRE(basket->refDate() <= schedule.startDate(),
58 // using the start date of the schedule might be wrong, think of the
59 // CDS rule
60 "Basket did not exist before contract start.");
61
62 // Notice the notional is that of the basket at basket inception, some
63 // names might have defaulted in between
64 normalizedLeg_ = FixedRateLeg(schedule)
65 .withNotionals(basket_->trancheNotional() * leverageFactor_)
66 .withCouponRates(runningRate, dayCounter)
67 .withPaymentAdjustment(paymentConvention)
68 .withLastPeriodDayCounter(lastPeriodDayCounter);
69
70 // If empty, adjust to T+3 standard settlement
71 Date effectiveUpfrontDate =
72 upfrontDate == Null<Date>()
73 ? schedule.calendar().advance(schedule.calendar().adjust(protectionStart_, paymentConvention), 3, Days,
74 paymentConvention)
75 : upfrontDate;
76 // '2' is used above since the protection start is assumed to be
77 // on trade_date + 1
78 upfrontPayment_.reset(
79 new SimpleCashFlow(basket_->trancheNotional() * leverageFactor_ * upfrontRate, effectiveUpfrontDate));
80
81 QL_REQUIRE(upfrontPayment_->date() >= protectionStart_, "upfront can not be due before contract start");
82
83 if (schedule.rule() == DateGeneration::CDS || schedule.rule() == DateGeneration::CDS2015) {
84 accrualRebate_= QuantLib::ext::make_shared<SimpleCashFlow>(QuantLib::CashFlows::accruedAmount(normalizedLeg_, false, protectionStart_+1),
85 effectiveUpfrontDate);
86 Date current = std::max((Date)Settings::instance().evaluationDate(), protectionStart_);
87 accrualRebateCurrent_ = QuantLib::ext::make_shared<SimpleCashFlow>(
88 CashFlows::accruedAmount(normalizedLeg_, false, current + 1),
89 schedule.calendar().advance(current, 3, Days, paymentConvention));
90
91 }
92
93
94
95 // register with probabilities if the corresponding issuer is, baskets
96 // are not registered with the DTS
97 for (Size i = 0; i < basket->names().size(); i++) {
98 /* This turns out to be a problem: depends on today but I am not
99 modifying the registrations, if we go back in time in the
100 calculations this would left me unregistered to some. Not impossible
101 to de-register and register when updating but i am dropping it.
102
103 if(!basket->pool()->get(basket->names()[i]).
104 defaultedBetween(schedule.dates()[0], today,
105 basket->pool()->defaultKeys()[i]))
106 */
107 // registers with the associated curve (issuer and event type)
108 // \todo make it possible to access them by name instead of index
109 registerWith(basket->pool()->get(basket->names()[i]).defaultProbability(basket->pool()->defaultKeys()[i]));
110 /* \todo Issuers should be observables/obsrvr and they would in turn
111 regiter with the DTS; only we might get updates from curves we do
112 not use.
113 */
114 }
115 registerWith(basket_);
116}
QuantLib::ext::shared_ptr< CashFlow > accrualRebateCurrent_
QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime_
QuantLib::ext::shared_ptr< QuantExt::Basket > basket_
const QuantLib::ext::shared_ptr< QuantExt::Basket > & basket() const
Protection::Side side_
QuantLib::ext::shared_ptr< CashFlow > accrualRebate_
BusinessDayConvention paymentConvention_
Real recoveryRate() const
Returns the recovery rate for fixed recovery CDO, otherwise returns Null<Real>()
QuantLib::ext::shared_ptr< CashFlow > upfrontPayment_
+ Here is the call graph for this function:

Member Function Documentation

◆ basket()

const QuantLib::ext::shared_ptr< QuantExt::Basket > & basket ( ) const

Definition at line 134 of file syntheticcdo.hpp.

134{ return basket_; }
+ Here is the caller graph for this function:

◆ isExpired()

bool isExpired ( ) const
override

Definition at line 162 of file syntheticcdo.cpp.

162 {
163 // FIXME: it could have also expired (knocked out) because theres
164 // no remaining tranche notional.
165 return detail::simple_event(normalizedLeg_.back()->date()).hasOccurred();
166}

◆ fairPremium()

Rate fairPremium ( ) const

Definition at line 142 of file syntheticcdo.cpp.

◆ fairUpfrontPremium()

Rate fairUpfrontPremium ( ) const

Definition at line 147 of file syntheticcdo.cpp.

147 {
148 calculate();
150}

◆ premiumValue()

Rate premiumValue ( ) const

Definition at line 118 of file syntheticcdo.cpp.

118 {
119 calculate();
120 return premiumValue_;
121}
+ Here is the caller graph for this function:

◆ protectionValue()

Rate protectionValue ( ) const

Definition at line 123 of file syntheticcdo.cpp.

123 {
124 calculate();
125 return protectionValue_;
126}
+ Here is the caller graph for this function:

◆ premiumLegNPV()

Real premiumLegNPV ( ) const

Definition at line 128 of file syntheticcdo.cpp.

128 {
129 calculate();
130 if (side_ == Protection::Buyer)
131 return premiumValue_;
132 return -premiumValue_;
133}

◆ protectionLegNPV()

Real protectionLegNPV ( ) const

Definition at line 135 of file syntheticcdo.cpp.

135 {
136 calculate();
137 if (side_ == Protection::Buyer)
138 return -protectionValue_;
139 return premiumValue_;
140}

◆ recoveryRate()

Real recoveryRate ( ) const

Returns the recovery rate for fixed recovery CDO, otherwise returns Null<Real>()

Definition at line 144 of file syntheticcdo.hpp.

144{ return recoveryRate_; }

◆ remainingNotional()

Real remainingNotional ( ) const

Total outstanding tranche notional, not wiped out

Definition at line 168 of file syntheticcdo.cpp.

168 {
169 calculate();
170 return remainingNotional_;
171}
+ Here is the caller graph for this function:

◆ leverageFactor()

Real leverageFactor ( ) const

The number of times the contract contains the portfolio tranched notional.

Definition at line 152 of file syntheticcdo.hpp.

152{ return leverageFactor_; }

◆ maturity()

const Date & maturity ( ) const

Last protection date.

Definition at line 154 of file syntheticcdo.hpp.

154 {
155 return QuantLib::ext::dynamic_pointer_cast<FixedRateCoupon>(normalizedLeg_.back())->accrualEndDate();
156 }
+ Here is the caller graph for this function:

◆ implicitCorrelation()

Real implicitCorrelation ( const std::vector< Real > &  recoveries,
const Handle< YieldTermStructure > &  discountCurve,
Real  targetNPV = 0.,
Real  accuracy = 1.0e-3 
) const

The Gaussian Copula LHP implied correlation that makes the contract zero value. This is for a flat correlation along time and portfolio loss level.

Definition at line 259 of file syntheticcdo.cpp.

261 {
262 QuantLib::ext::shared_ptr<SimpleQuote> correl(new SimpleQuote(0.0));
263
264 QuantLib::ext::shared_ptr<GaussianLHPLossModel> lhp(new GaussianLHPLossModel(Handle<Quote>(correl), recoveries));
265
266 // lock
267 basket_->setLossModel(lhp);
268
269 QuantExt::MidPointCDOEngine engineIC(discountCurve);
270 setupArguments(engineIC.getArguments());
271 const SyntheticCDO::results* results = dynamic_cast<const SyntheticCDO::results*>(engineIC.getResults());
272
273 // aviod recal of the basket on engine updates through the quote
274 basket_->recalculate();
275 basket_->freeze();
276
277 ObjectiveFunction f(targetNPV, *correl, engineIC, results);
278 Rate guess = 0.001;
279 // Rate step = guess*0.1;
280
281 // wrap/catch to be able to unfreeze the basket:
282 Real solution = Brent().solve(f, accuracy, guess, QL_EPSILON, 1. - QL_EPSILON);
283 basket_->unfreeze();
284 return solution;
285}
CDO base engine taking schedule steps.
void setupArguments(PricingEngine::arguments *) const override
+ Here is the call graph for this function:

◆ expectedTrancheLoss()

vector< Real > expectedTrancheLoss ( ) const

Expected tranche loss for all payment dates

Definition at line 152 of file syntheticcdo.cpp.

152 {
153 calculate();
155}
std::vector< Real > expectedTrancheLoss_
+ Here is the caller graph for this function:

◆ error()

Size error ( ) const

Definition at line 157 of file syntheticcdo.cpp.

157 {
158 calculate();
159 return error_;
160}
+ Here is the caller graph for this function:

◆ setupArguments()

void setupArguments ( PricingEngine::arguments *  args) const
override

Definition at line 173 of file syntheticcdo.cpp.

173 {
174 SyntheticCDO::arguments* arguments = dynamic_cast<SyntheticCDO::arguments*>(args);
175 QL_REQUIRE(arguments != 0, "wrong argument type");
176 arguments->basket = basket_;
177 arguments->side = side_;
178 arguments->normalizedLeg = normalizedLeg_;
179
180 arguments->upfrontRate = upfrontRate_;
181 arguments->runningRate = runningRate_;
182 arguments->dayCounter = dayCounter_;
183 arguments->paymentConvention = paymentConvention_;
184 arguments->leverageFactor = leverageFactor_;
185 arguments->upfrontPayment = upfrontPayment_;
186 arguments->accrualRebate = accrualRebate_;
187 arguments->accrualRebateCurrent = accrualRebateCurrent_;
188 arguments->settlesAccrual = settlesAccrual_;
189 arguments->protectionPaymentTime = protectionPaymentTime_;
190 arguments->protectionStart = protectionStart_;
191 arguments->maturity = maturity();
192 arguments->recoveryRate = recoveryRate_;
193}
const Date & maturity() const
Last protection date.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fetchResults()

void fetchResults ( const PricingEngine::results *  r) const
override

Definition at line 195 of file syntheticcdo.cpp.

195 {
196 Instrument::fetchResults(r);
197
198 const SyntheticCDO::results* results = dynamic_cast<const SyntheticCDO::results*>(r);
199 QL_REQUIRE(results != 0, "wrong result type");
200
201 premiumValue_ = results->premiumValue;
202 protectionValue_ = results->protectionValue;
203 upfrontPremiumValue_ = results->upfrontPremiumValue;
204 remainingNotional_ = results->remainingNotional;
205 error_ = results->error;
206 expectedTrancheLoss_ = results->expectedTrancheLoss;
207}

◆ setupExpired()

void setupExpired ( ) const
overrideprivate

Definition at line 209 of file syntheticcdo.cpp.

209 {
210 Instrument::setupExpired();
211 premiumValue_ = 0.0;
212 protectionValue_ = 0.0;
214 remainingNotional_ = 1.0;
215 expectedTrancheLoss_.clear();
216}

Member Data Documentation

◆ basket_

QuantLib::ext::shared_ptr<QuantExt::Basket> basket_
private

Definition at line 177 of file syntheticcdo.hpp.

◆ side_

Protection::Side side_
private

Definition at line 178 of file syntheticcdo.hpp.

◆ normalizedLeg_

Leg normalizedLeg_
private

Definition at line 179 of file syntheticcdo.hpp.

◆ upfrontRate_

Rate upfrontRate_
private

Definition at line 181 of file syntheticcdo.hpp.

◆ runningRate_

Rate runningRate_
private

Definition at line 182 of file syntheticcdo.hpp.

◆ leverageFactor_

const Real leverageFactor_
private

Definition at line 183 of file syntheticcdo.hpp.

◆ dayCounter_

DayCounter dayCounter_
private

Definition at line 184 of file syntheticcdo.hpp.

◆ paymentConvention_

BusinessDayConvention paymentConvention_
private

Definition at line 185 of file syntheticcdo.hpp.

◆ settlesAccrual_

bool settlesAccrual_
private

Definition at line 186 of file syntheticcdo.hpp.

◆ protectionPaymentTime_

QuantLib::CreditDefaultSwap::ProtectionPaymentTime protectionPaymentTime_
private

Definition at line 187 of file syntheticcdo.hpp.

◆ protectionStart_

Date protectionStart_
private

Definition at line 188 of file syntheticcdo.hpp.

◆ upfrontDate_

Date upfrontDate_
private

Definition at line 189 of file syntheticcdo.hpp.

◆ upfrontPayment_

QuantLib::ext::shared_ptr<CashFlow> upfrontPayment_
private

Definition at line 190 of file syntheticcdo.hpp.

◆ accrualRebate_

QuantLib::ext::shared_ptr<CashFlow> accrualRebate_
private

Definition at line 190 of file syntheticcdo.hpp.

◆ accrualRebateCurrent_

QuantLib::ext::shared_ptr<CashFlow> accrualRebateCurrent_
private

Definition at line 190 of file syntheticcdo.hpp.

◆ recoveryRate_

Real recoveryRate_
private

Definition at line 191 of file syntheticcdo.hpp.

◆ premiumValue_

Real premiumValue_
mutableprivate

Definition at line 193 of file syntheticcdo.hpp.

◆ protectionValue_

Real protectionValue_
mutableprivate

Definition at line 194 of file syntheticcdo.hpp.

◆ upfrontPremiumValue_

Real upfrontPremiumValue_
mutableprivate

Definition at line 195 of file syntheticcdo.hpp.

◆ remainingNotional_

Real remainingNotional_
mutableprivate

Definition at line 196 of file syntheticcdo.hpp.

◆ error_

Size error_
mutableprivate

Definition at line 197 of file syntheticcdo.hpp.

◆ expectedTrancheLoss_

std::vector<Real> expectedTrancheLoss_
mutableprivate

Definition at line 198 of file syntheticcdo.hpp.