Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cdo.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/cdo.hpp
20 \brief Mid point CDO engines cached by currency
21 \ingroup portfolio
22*/
23
24#pragma once
25
27
28// avoid compile error from homogeneouspooldef.hpp
29#include <boost/algorithm/string.hpp>
30
35
38
43#include <ql/quotes/simplequote.hpp>
44
45#include <boost/make_shared.hpp>
46
47namespace ore {
48namespace data {
49using namespace std;
50
51//! Engine Builder base class for CDOs
52/*! Pricing engines are cached by currency
53 \ingroup portfolio
54*/
55
56std::vector<QuantLib::Handle<QuantLib::DefaultProbabilityTermStructure>>
57buildPerformanceOptimizedDefaultCurves(const std::vector<QuantLib::Handle<QuantLib::DefaultProbabilityTermStructure>>& curves);
58
60 : public CachingPricingEngineBuilder<vector<string>, const Currency&, bool, const vector<string>&,
61 const QuantLib::ext::shared_ptr<QuantLib::SimpleQuote>&,
62 const QuantLib::Real> {
63public:
64 CdoEngineBuilder(const std::string& model, const std::string& engine)
65 : CachingEngineBuilder(model, engine, {"SyntheticCDO"}) {}
66
67 virtual QuantLib::ext::shared_ptr<QuantExt::DefaultLossModel>
68 lossModel(const string& qualifier, const vector<Real>& recoveryRates, const Real& detachmentPoint,
69 const QuantLib::Date& trancheMaturity, bool homogeneous) = 0;
70
73 engineParameter("SensitivityDecomposition", {}, false, "Underlying"));
74 }
75
77 return parseBool(engineParameter("calibrateConstituentCurves", {}, false, "false"));
78 }
79
80 std::vector<QuantLib::Period> calibrationIndexTerms() const {
81 return parseListOfValues<QuantLib::Period>(engineParameter("calibrationIndexTerms", {}, false, ""),
83 }
84
86 auto rt = globalParameters_.find("RunType");
88 (rt != globalParameters_.end() &&
89 (rt->second == "SensitivityDelta" || rt->second == "SensitivityDeltaGamma"));
90 }
91
92protected:
93 virtual vector<string> keyImpl(const Currency& ccy, bool isIndexCDS, const vector<string>& creditCurves,
94 const QuantLib::ext::shared_ptr<QuantLib::SimpleQuote>& calibrationFactor,
95 const QuantLib::Real fixedRecovery) override {
96 vector<string> res;
97 res.reserve(creditCurves.size() + 4);
98 res.emplace_back(ccy.code());
99 if (isIndexCDS)
100 res.emplace_back("_indexCDS");
101 res.insert(res.end(), creditCurves.begin(), creditCurves.end());
102 if (!close_enough(calibrationFactor->value(), 1.0) && calibrationFactor->value() != QuantLib::Null<Real>()) {
103 res.emplace_back(to_string(calibrationFactor->value()));
104 }
105 if (fixedRecovery != QuantLib::Null<QuantLib::Real>()) {
106 res.emplace_back(to_string(fixedRecovery));
107 }
108 return res;
109 }
110};
111
113public:
115
116 QuantLib::ext::shared_ptr<QuantExt::DefaultLossModel> lossModel(const string& qualifier, const vector<Real>& recoveryRates,
117 const Real& detachmentPoint,
118 const QuantLib::Date& trancheMaturity,
119 bool homogeneous) override {
120
121 Size poolSize = recoveryRates.size();
122
123 Handle<QuantExt::BaseCorrelationTermStructure> bcts =
124 market_->baseCorrelation(qualifier, configuration(MarketContext::pricing));
125
126 // Create the base correlation quote.
127 RelinkableHandle<Quote> correlation;
128 if (detachmentPoint < 1.0) {
129 const Date& bctsRd = bcts->referenceDate();
130 QL_REQUIRE(trancheMaturity >= bctsRd, "Tranche maturity ("
131 << io::iso_date(trancheMaturity) << ") must be "
132 << " on or after base correlation structure's reference date ("
133 << io::iso_date(bctsRd) << ").");
134 Period ttm = (trancheMaturity - bctsRd) * Days;
135 correlation.linkTo(
136 QuantLib::ext::make_shared<QuantExt::BaseCorrelationQuote>(bcts, ttm, detachmentPoint, true));
137 } else {
138 correlation.linkTo(QuantLib::ext::make_shared<SimpleQuote>(0.0));
139 }
140 DLOG("Base correlation quote value is " << correlation->value() << " at detachment point " << detachmentPoint);
141
142 // Optional flag, set to false if omitted, i.e. we use determinsitic recovery by default
143 bool useStochasticRecovery = parseBool(modelParameter("useStochasticRecovery", {}, false, "false"));
144
145 // Compile default recovery rate grids and probabilities for each name:
146 // Recovery rate grids have three pillars, centered around market recovery, DECREASING order : [ 2*RR - 0.1, RR, 0.1 ]
147 // Probabilities for the three pillars are symmetric around the center of the distribution and independent of the concrete rate grid
148 std::vector<std::vector<Real>> recoveryProbabilities, recoveryGrids;
149 if (useStochasticRecovery) {
150 string rrProbString = modelParameter("recoveryRateProbabilities");
151 string rrGridString = modelParameter("recoveryRateGrid");
152 vector<string> rrProbStringTokens;
153 boost::split(rrProbStringTokens, rrProbString, boost::is_any_of(","));
154 vector<Real> rrProb = parseVectorOfValues<Real>(rrProbStringTokens, &parseReal);
155 for (Size i = 0; i < recoveryRates.size(); ++i) {
156 // Use the same recovery rate probabilities across all entites
157 recoveryProbabilities.push_back(rrProb);
158 // recovery rate grid dependent on market recovery rate
159 std::vector<Real> rrGrid(3, recoveryRates[i]); // constant recovery by default
160 QL_REQUIRE(rrProb.size() == rrGrid.size(), "recovery grid size mismatch");
161 if (rrGridString == "Markit2020") {
162 if (recoveryRates[i] >= 0.1 && recoveryRates[i] <= 0.55) {
163 rrGrid[0] = 2.0 * recoveryRates[i] - 0.1;
164 rrGrid[1] = recoveryRates[i];
165 rrGrid[2] = 0.1;
166 LOG("Using recovery rate grid for entity " << i << ": " << rrGrid[0] << " " << rrGrid[1] << " " << rrGrid[2]);
167 }
168 else
169 ALOG("Market recovery rate " << recoveryRates[i] << " for entity " << i << " out of range [0.1, 0.55], using constant recovery");
170 recoveryGrids.push_back(rrGrid);
171 }
172 else if (rrGridString != "Constant") {
173 QL_FAIL("recovery rate model code " << rrGridString << " not recognized");
174 }
175 }
176 }
177
178 DLOG("Build ExtendedGaussianConstantLossLM");
179 QuantLib::ext::shared_ptr<QuantExt::ExtendedGaussianConstantLossLM> gaussLM(new QuantExt::ExtendedGaussianConstantLossLM(
180 correlation, recoveryRates, recoveryProbabilities, recoveryGrids, LatentModelIntegrationType::GaussianQuadrature, poolSize,
181 GaussianCopulaPolicy::initTraits()));
182 Real gaussCopulaMin = parseReal(modelParameter("min"));
183 Real gaussCopulaMax = parseReal(modelParameter("max"));
184 Size gaussCopulaSteps = parseInteger(modelParameter("steps"));
185 bool useQuadrature = parseBool(modelParameter("useQuadrature", {}, false, "false"));
186 Size nBuckets = parseInteger(engineParameter("buckets"));
187 bool homogeneousPoolWhenJustified = parseBool(engineParameter("homogeneousPoolWhenJustified"));
188
189 homogeneous = homogeneous && homogeneousPoolWhenJustified;
190 LOG("Use " << (homogeneous ? "" : "in") << "homogeneous pool loss model for qualifier " << qualifier);
191 DLOG("useQuadrature is set to " << std::boolalpha << useQuadrature);
192 return QuantLib::ext::make_shared<QuantExt::GaussPoolLossModel>(homogeneous, gaussLM, nBuckets, gaussCopulaMax,
193 gaussCopulaMin, gaussCopulaSteps, useQuadrature,
194 useStochasticRecovery);
195 }
196
197protected:
198 virtual QuantLib::ext::shared_ptr<PricingEngine>
199 engineImpl(const Currency& ccy, bool isIndexCDS, const vector<string>& creditCurves,
200 const QuantLib::ext::shared_ptr<QuantLib::SimpleQuote>& calibrationFactor,
201 const QuantLib::Real fixedRecovery = QuantLib::Null<QuantLib::Real>()) override;
202};
203
204} // namespace data
205} // namespace ore
Abstract template engine builder class.
Abstract template EngineBuilder class that can cache engines and coupon pricers.
virtual vector< string > keyImpl(const Currency &ccy, bool isIndexCDS, const vector< string > &creditCurves, const QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > &calibrationFactor, const QuantLib::Real fixedRecovery) override
Definition: cdo.hpp:93
CdoEngineBuilder(const std::string &model, const std::string &engine)
Definition: cdo.hpp:64
std::vector< QuantLib::Period > calibrationIndexTerms() const
Definition: cdo.hpp:80
virtual QuantLib::ext::shared_ptr< QuantExt::DefaultLossModel > lossModel(const string &qualifier, const vector< Real > &recoveryRates, const Real &detachmentPoint, const QuantLib::Date &trancheMaturity, bool homogeneous)=0
bool optimizedSensitivityCalculation() const
Definition: cdo.hpp:85
CreditPortfolioSensitivityDecomposition sensitivityDecomposition() const
Definition: cdo.hpp:71
bool calibrateConstituentCurve() const
Definition: cdo.hpp:76
QuantLib::ext::shared_ptr< Market > market_
const string & engine() const
Return the engine name.
const string & model() const
Return the model name.
std::string modelParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
std::string engineParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
const string & configuration(const MarketContext &key)
Return a configuration (or the default one if key not found)
std::map< std::string, std::string > globalParameters_
QuantLib::ext::shared_ptr< QuantExt::DefaultLossModel > lossModel(const string &qualifier, const vector< Real > &recoveryRates, const Real &detachmentPoint, const QuantLib::Date &trancheMaturity, bool homogeneous) override
Definition: cdo.hpp:116
virtual QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const Currency &ccy, bool isIndexCDS, const vector< string > &creditCurves, const QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > &calibrationFactor, const QuantLib::Real fixedRecovery=QuantLib::Null< QuantLib::Real >()) override
Definition: cdo.cpp:83
Pricing Engine Factory.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
Definition: parsers.cpp:136
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
CreditPortfolioSensitivityDecomposition parseCreditPortfolioSensitivityDecomposition(const std::string &s)
Convert text to CreditPortfolioSensitivitiyDecomposition.
Definition: parsers.cpp:1374
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
std::vector< Handle< DefaultProbabilityTermStructure > > buildPerformanceOptimizedDefaultCurves(const std::vector< Handle< DefaultProbabilityTermStructure > > &curves)
Definition: cdo.cpp:40
CreditPortfolioSensitivityDecomposition
Enumeration CreditPortfolioSensitivityDecomposition.
Definition: parsers.hpp:568
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
string conversion utilities