Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
creditdefaultswap.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 portfolio/builders/creditdefaultswap.hpp
20\brief Builder that returns an engine to price a credit default swap
21\ingroup builders
22*/
23
24#pragma once
25
29
31
32#include <ql/pricingengines/credit/midpointcdsengine.hpp>
33
34#include <boost/make_shared.hpp>
35
36#include <regex>
37
38namespace ore {
39namespace data {
40
41/*! This class provides a key with which we will cache the CDS engine builders
42
43 In general, the CDS engine builders will be cached by the credit curve Id of the reference entity and the currency
44 of the trade that needs to be priced. If we are caching by credit curve Id and currency only, the recovery rate
45 member should be \c Null<Real>().
46
47 In some cases, for fixed recovery CDS trades for example, we need to cache the CDS engine builder not only by
48 credit curve Id and currency but also with an exogenous recovery rate that we wish to use instead of the market
49 supplied recovery rate.
50*/
52public:
53 /*! Constructor that takes a credit curve Id, \p creditCurveId, a currency, \p ccy, and optionally a recovery
54 rate, \p recoveryRate.
55 */
56 CDSEngineKey(const std::string& creditCurveId, const QuantLib::Currency& ccy,
57 QuantLib::Real recoveryRate = QuantLib::Null<QuantLib::Real>())
59
60 //! Return the credit curve Id
61 const std::string& creditCurveId() const { return creditCurveId_; }
62
63 //! Return the currency
64 const QuantLib::Currency& currency() const { return ccy_; }
65
66 //! Return the recovery rate if it is set, otherwise \c Null<Real>()
67 QuantLib::Real recoveryRate() const { return recoveryRate_; }
68
69private:
70 std::string creditCurveId_;
71 QuantLib::Currency ccy_;
72 QuantLib::Real recoveryRate_;
73};
74
75inline bool operator==(const CDSEngineKey& lhs, const CDSEngineKey& rhs) {
76
77 // Check the credit curve IDs first
78 if (lhs.creditCurveId() != rhs.creditCurveId())
79 return false;
80
81 // Check the currencies
82 if (lhs.currency() != rhs.currency())
83 return false;
84
85 // Now check recovery rates.
86 if (lhs.recoveryRate() == QuantLib::Null<QuantLib::Real>() &&
87 rhs.recoveryRate() == QuantLib::Null<QuantLib::Real>()) {
88 // Most usual case is both are Null<Real> and using the recovery rate from the market.
89 return true;
90 } else if ((lhs.recoveryRate() != QuantLib::Null<QuantLib::Real>() &&
91 rhs.recoveryRate() == QuantLib::Null<QuantLib::Real>()) ||
92 (lhs.recoveryRate() == QuantLib::Null<QuantLib::Real>() &&
93 rhs.recoveryRate() != QuantLib::Null<QuantLib::Real>())) {
94 return false;
95 } else {
96 return QuantLib::close(lhs.recoveryRate(), rhs.recoveryRate());
97 }
98}
99
100inline bool operator<(const CDSEngineKey& lhs, const CDSEngineKey& rhs) {
101
102 // Check equality first
103 if (lhs == rhs)
104 return false;
105
106 // Now check credit curve Ids.
107 if (lhs.creditCurveId() != rhs.creditCurveId())
108 return lhs.creditCurveId() < rhs.creditCurveId();
109
110 // Now check currencies.
111 if (lhs.currency() != rhs.currency())
112 return lhs.currency().name() < rhs.currency().name();
113
114 // Now use the recovery rates
115 return lhs.recoveryRate() < rhs.recoveryRate();
116}
117
118inline bool operator!=(const CDSEngineKey& lhs, const CDSEngineKey& rhs) { return !(lhs == rhs); }
119inline bool operator>(const CDSEngineKey& lhs, const CDSEngineKey& rhs) { return rhs < lhs; }
120inline bool operator<=(const CDSEngineKey& lhs, const CDSEngineKey& rhs) { return !(lhs > rhs); }
121inline bool operator>=(const CDSEngineKey& lhs, const CDSEngineKey& rhs) { return !(lhs < rhs); }
122
123//! Engine builder base class for credit default swaps
124/*! Pricing engines are cached by CDSEngineKey
125 \ingroup builders
126*/
128 : public CachingPricingEngineBuilder<CDSEngineKey, QuantLib::Currency, std::string, QuantLib::Real> {
129
130protected:
131 CreditDefaultSwapEngineBuilder(const std::string& model, const std::string& engine)
132 : CachingEngineBuilder(model, engine, {"CreditDefaultSwap"}) {}
133
134 CDSEngineKey keyImpl(QuantLib::Currency ccy, std::string creditCurveId,
135 QuantLib::Real recoveryRate = QuantLib::Null<QuantLib::Real>()) override {
136 return CDSEngineKey(creditCurveId, ccy, recoveryRate);
137 }
138};
139
140//! Midpoint engine builder class for credit default swaps
141/*! This class creates a MidPointCdsEngine
142 \ingroup builders
143*/
145public:
146 MidPointCdsEngineBuilder() : CreditDefaultSwapEngineBuilder("DiscountedCashflows", "MidPointCdsEngine") {}
147
148protected:
149 QuantLib::ext::shared_ptr<PricingEngine>
150 engineImpl(QuantLib::Currency ccy, std::string creditCurveId,
151 QuantLib::Real recoveryRate = QuantLib::Null<QuantLib::Real>()) override {
152
154 auto yts = market_->discountCurve(ccy.code(), cfg);
155 auto dpts = market_->defaultCurve(creditCurveId, cfg);
156
157 if (recoveryRate == QuantLib::Null<QuantLib::Real>()) {
158 // If recovery rate is null, get it from the market for the given reference entity
159 recoveryRate = market_->recoveryRate(creditCurveId, cfg)->value();
160 }
161
162 return QuantLib::ext::make_shared<MidPointCdsEngine>(dpts->curve(), recoveryRate, yts);
163 }
164};
165
166//! Multi State Engine Builder class for CDS
167/*! This creates a CreditDefaultSwapEngineMultiState
168 \ingroup portfolio
169*/
170
172public:
174 : CreditDefaultSwapEngineBuilder("DiscountedCashflows", "MidPointCdsEngineMultiState") {}
175
176protected:
177 virtual QuantLib::ext::shared_ptr<PricingEngine>
178 engineImpl(QuantLib::Currency ccy, std::string creditCurveId,
179 QuantLib::Real recoveryRate = QuantLib::Null<QuantLib::Real>()) override {
180 Handle<YieldTermStructure> yts = market_->discountCurve(ccy.code(), configuration(MarketContext::pricing));
181 // build state curves and recovery rates
182 // big overlap with BondMultiStateEngineBuilder
183 std::vector<Handle<DefaultProbabilityTermStructure>> dpts;
184 std::vector<Handle<Quote>> recovery;
185 Size mainResultState = Null<Size>();
186 Size i = 0;
187 for (; true; ++i) {
188 std::ostringstream rule_s;
189 rule_s << "Rule_" << i;
190 if (engineParameters_.count(rule_s.str()) == 0)
191 break;
192 std::vector<std::string> tokens;
193 std::string rule = engineParameters_[rule_s.str()];
194 std::string stateCreditCurveId;
195 // if rule is empty, we use the initial curve for this state
196 // TODO computation should be optimised in this case, so that only different
197 // curves are recomputed in the engine
198 if (rule.empty()) {
199 stateCreditCurveId = creditCurveId;
200 DLOG("Rule " << rule_s.str() << " is empty, use initial curve " << stateCreditCurveId
201 << " for this state.");
202 } else {
203 boost::split(tokens, rule, boost::is_any_of(","));
204 QL_REQUIRE(tokens.size() == 2, "invalid rule: " << rule);
205 stateCreditCurveId = regex_replace(creditCurveId, std::regex(tokens[0]), tokens[1]);
206 DLOG("Apply " << rule_s.str() << " => " << tokens[0] << " in " << creditCurveId << " yields state #"
207 << i << " creditCurve id " << stateCreditCurveId);
208 }
209 if (stateCreditCurveId == creditCurveId) {
210 mainResultState = i;
211 DLOG("State #" << i << " is the main result state (overwriting previous choice)");
212 }
213 dpts.push_back(market_->defaultCurve(stateCreditCurveId, configuration(MarketContext::pricing))->curve());
214 recovery.push_back(recoveryRate == Null<Real>()
215 ? market_->recoveryRate(stateCreditCurveId, configuration(MarketContext::pricing))
216 : Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(recoveryRate)));
217 }
218 // If there were no rules at all we take the original creditCurveId as the only state
219 if (i == 0) {
220 dpts.push_back(market_->defaultCurve(creditCurveId, configuration(MarketContext::pricing))->curve());
221 recovery.push_back(recoveryRate == Null<Real>()
222 ? market_->recoveryRate(creditCurveId, configuration(MarketContext::pricing))
223 : Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(recoveryRate)));
224 mainResultState = 0;
225 DLOG("No rules given, only states are " << creditCurveId << " and default");
226 }
227 // check we have a main result state
228 QL_REQUIRE(mainResultState != Null<Size>(),
229 "CreditDefaultSwapMultiStateEngineBuilder: No main state found for " << creditCurveId);
230 // return engine
231 return QuantLib::ext::make_shared<QuantExt::MidPointCdsEngineMultiState>(dpts, recovery, yts, mainResultState);
232 }
233};
234
235} // namespace data
236} // namespace ore
Abstract template engine builder class.
QuantLib::Real recoveryRate() const
Return the recovery rate if it is set, otherwise Null<Real>()
const std::string & creditCurveId() const
Return the credit curve Id.
const QuantLib::Currency & currency() const
Return the currency.
CDSEngineKey(const std::string &creditCurveId, const QuantLib::Currency &ccy, QuantLib::Real recoveryRate=QuantLib::Null< QuantLib::Real >())
Abstract template EngineBuilder class that can cache engines and coupon pricers.
Engine builder base class for credit default swaps.
CDSEngineKey keyImpl(QuantLib::Currency ccy, std::string creditCurveId, QuantLib::Real recoveryRate=QuantLib::Null< QuantLib::Real >()) override
CreditDefaultSwapEngineBuilder(const std::string &model, const std::string &engine)
QuantLib::ext::shared_ptr< Market > market_
const string & engine() const
Return the engine name.
map< string, string > engineParameters_
const string & model() const
Return the model name.
const string & configuration(const MarketContext &key)
Return a configuration (or the default one if key not found)
Midpoint engine builder class for credit default swaps.
QuantLib::ext::shared_ptr< PricingEngine > engineImpl(QuantLib::Currency ccy, std::string creditCurveId, QuantLib::Real recoveryRate=QuantLib::Null< QuantLib::Real >()) override
Multi State Engine Builder class for CDS.
virtual QuantLib::ext::shared_ptr< PricingEngine > engineImpl(QuantLib::Currency ccy, std::string creditCurveId, QuantLib::Real recoveryRate=QuantLib::Null< QuantLib::Real >()) override
Pricing Engine Factory.
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
bool operator<(const Dividend &d1, const Dividend &d2)
bool operator!=(const Filter &a, const Filter &b)
Filter operator>=(const RandomVariable &x, const RandomVariable &y)
bool operator==(const Dividend &d1, const Dividend &d)
bool operator>(const Distributionpair &p1, const Distributionpair &p2)
Filter operator<=(const RandomVariable &x, const RandomVariable &y)
Serializable Credit Default Swap.
Definition: namespaces.docs:23