Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cdsvolcurveconfig.cpp
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#include <boost/algorithm/string.hpp>
24#include <ql/errors.hpp>
25
27using QuantLib::Real;
28using std::string;
29
30namespace ore {
31namespace data {
32
33CDSVolatilityCurveConfig::CDSVolatilityCurveConfig(const string& curveId, const string& curveDescription,
34 const QuantLib::ext::shared_ptr<VolatilityConfig>& volatilityConfig,
35 const string& dayCounter, const string& calendar,
36 const string& strikeType, const string& quoteName, Real strikeFactor,
37 const std::vector<QuantLib::Period>& terms,
38 const std::vector<std::string>& termCurves)
39 : CurveConfig(curveId, curveDescription), volatilityConfig_(volatilityConfig), dayCounter_(dayCounter),
40 calendar_(calendar), strikeType_(strikeType), quoteName_(quoteName), strikeFactor_(strikeFactor), terms_(terms),
41 termCurves_(termCurves) {
42
43 QL_REQUIRE(terms_.size() == termCurves_.size(),
44 "CDSVolatilityCurveConfig: " << curveId
45 << " specifies different number of terms / curves (built via constructor)");
46 populateQuotes();
47 populateRequiredCurveIds();
48}
49
50const QuantLib::ext::shared_ptr<VolatilityConfig>& CDSVolatilityCurveConfig::volatilityConfig() const {
51 return volatilityConfig_;
52}
53
54const string& CDSVolatilityCurveConfig::dayCounter() const { return dayCounter_; }
55
56const string& CDSVolatilityCurveConfig::calendar() const { return calendar_; }
57
58const string& CDSVolatilityCurveConfig::strikeType() const { return strikeType_; }
59
60const string& CDSVolatilityCurveConfig::quoteName() const { return quoteName_; }
61
62Real CDSVolatilityCurveConfig::strikeFactor() const { return strikeFactor_; }
63
64const std::vector<QuantLib::Period>& CDSVolatilityCurveConfig::terms() const { return terms_; }
65
66const std::vector<std::string>& CDSVolatilityCurveConfig::termCurves() const { return termCurves_; }
67
68void CDSVolatilityCurveConfig::fromXML(XMLNode* node) {
69
70 XMLUtils::checkNode(node, "CDSVolatility");
71
72 curveID_ = XMLUtils::getChildValue(node, "CurveId", true);
73 curveDescription_ = XMLUtils::getChildValue(node, "CurveDescription", true);
74
75 terms_.clear();
76 termCurves_.clear();
77 if (auto n = XMLUtils::getChildNode(node, "Terms")) {
78 terms_.clear();
79 termCurves_.clear();
80 for (auto c : XMLUtils::getChildrenNodes(n, "Term")) {
81 terms_.push_back(XMLUtils::getChildValueAsPeriod(c, "Label", true));
82 termCurves_.push_back(XMLUtils::getChildValue(c, "Curve", true));
83 }
84 }
85
86 quoteName_ = "";
87 if (auto n = XMLUtils::getChildNode(node, "QuoteName"))
88 quoteName_ = XMLUtils::getNodeValue(n);
89
90 if (XMLUtils::getChildNode(node, "Expiries")) {
91
92 // Giving just an Expiries node is allowed to be backwards compatible but is discouraged.
93 WLOG("Using an Expiries node only in CDSVolatilityCurveConfig is deprecated. "
94 << "A volatility configuration node should be used instead.");
95
96 // Get the expiries
97 vector<string> expiries = XMLUtils::getChildrenValuesAsStrings(node, "Expiries", true);
98 QL_REQUIRE(expiries.size() > 0, "Need at least one expiry in the Expiries node.");
99
100 // Build the quotes by appending the expiries and terms to the quote stem.
101 std::vector<std::string> quotes;
102 string stem = quoteStem();
103 for (const string& exp : expiries) {
104 for (auto const& p : terms_) {
105 quotes.push_back(stem + exp + "/" + ore::data::to_string(p));
106 }
107 }
108
109 // If we have at most 1 term specified, we add quotes without term as well
110 for (const string& exp : expiries) {
111 quotes.push_back(stem + exp);
112 }
113
114 // Create the relevant volatilityConfig_ object.
115 if (quotes.size() == 1) {
116 volatilityConfig_ = QuantLib::ext::make_shared<ConstantVolatilityConfig>(quotes[0]);
117 } else {
118 volatilityConfig_ = QuantLib::ext::make_shared<VolatilityCurveConfig>(quotes, "Linear", "Flat");
119 }
120
121 } else {
122 XMLNode* n;
123 if ((n = XMLUtils::getChildNode(node, "Constant"))) {
124 volatilityConfig_ = QuantLib::ext::make_shared<ConstantVolatilityConfig>();
125 } else if ((n = XMLUtils::getChildNode(node, "Curve"))) {
126 volatilityConfig_ = QuantLib::ext::make_shared<VolatilityCurveConfig>();
127 } else if ((n = XMLUtils::getChildNode(node, "StrikeSurface"))) {
128 volatilityConfig_ = QuantLib::ext::make_shared<VolatilityStrikeSurfaceConfig>();
129 } else if ((n = XMLUtils::getChildNode(node, "DeltaSurface"))) {
130 QL_FAIL("CDSVolatilityCurveConfig does not yet support a DeltaSurface.");
131 } else if ((n = XMLUtils::getChildNode(node, "MoneynessSurface"))) {
132 QL_FAIL("CDSVolatilityCurveConfig does not yet support a MoneynessSurface.");
133 } else if ((n = XMLUtils::getChildNode(node, "ProxySurface"))) {
134 volatilityConfig_ = QuantLib::ext::make_shared<CDSProxyVolatilityConfig>();
135 } else {
136 QL_FAIL("CDSVolatility node expects one child node with name in list: Constant,"
137 << " Curve, StrikeSurface, ProxySurface.");
138 }
139 volatilityConfig_->fromXML(n);
140 }
141
142 dayCounter_ = "A365";
143 if (auto n = XMLUtils::getChildNode(node, "DayCounter"))
144 dayCounter_ = XMLUtils::getNodeValue(n);
145
146 calendar_ = "NullCalendar";
147 if (auto n = XMLUtils::getChildNode(node, "Calendar"))
148 calendar_ = XMLUtils::getNodeValue(n);
149
150 strikeType_ = "";
151 if (auto n = XMLUtils::getChildNode(node, "StrikeType"))
152 strikeType_ = XMLUtils::getNodeValue(n);
153
154 strikeFactor_ = 1.0;
155 if (auto n = XMLUtils::getChildNode(node, "StrikeFactor"))
156 strikeFactor_ = parseReal(XMLUtils::getNodeValue(n));
157
158 populateQuotes();
159 populateRequiredCurveIds();
160}
161
162XMLNode* CDSVolatilityCurveConfig::toXML(XMLDocument& doc) const {
163
164 XMLNode* node = doc.allocNode("CDSVolatility");
165
166 XMLUtils::addChild(doc, node, "CurveId", curveID_);
167 XMLUtils::addChild(doc, node, "CurveDescription", curveDescription_);
168
169 if (!terms_.empty()) {
170 QL_REQUIRE(terms_.size() == termCurves_.size(),
171 "CDSVolatilityCurveConfig::toXML(): internal error, terms size ("
172 << terms_.size() << ") != termCurves size (" << termCurves_.size() << "), curveId = curveID_");
173 auto termsNode = XMLUtils::addChild(doc, node, "Terms");
174 for (Size i = 0; i < terms_.size(); ++i) {
175 auto tmp = XMLUtils::addChild(doc, termsNode, "Term");
176 XMLUtils::addChild(doc, tmp, "Label", ore::data::to_string(terms_[i]));
177 XMLUtils::addChild(doc, tmp, "Curve", ore::data::to_string(termCurves_[i]));
178 }
179 }
180
181 XMLNode* n = volatilityConfig_->toXML(doc);
182 XMLUtils::appendNode(node, n);
183
184 XMLUtils::addChild(doc, node, "DayCounter", dayCounter_);
185 XMLUtils::addChild(doc, node, "Calendar", calendar_);
186 if (!strikeType_.empty())
187 XMLUtils::addChild(doc, node, "StrikeType", strikeType_);
188 if (!quoteName_.empty())
189 XMLUtils::addChild(doc, node, "QuoteName", quoteName_);
190 XMLUtils::addChild(doc, node, "StrikeFactor", strikeFactor_);
191
192 return node;
193}
194
195void CDSVolatilityCurveConfig::populateQuotes() {
196
197 // The quotes depend on the type of volatility structure that has been configured.
198 if (auto vc = QuantLib::ext::dynamic_pointer_cast<ConstantVolatilityConfig>(volatilityConfig_)) {
199 quotes_ = {vc->quote()};
200 } else if (auto vc = QuantLib::ext::dynamic_pointer_cast<VolatilityCurveConfig>(volatilityConfig_)) {
201 quotes_ = vc->quotes();
202 } else if (auto vc = QuantLib::ext::dynamic_pointer_cast<VolatilitySurfaceConfig>(volatilityConfig_)) {
203
204 // Clear the quotes_ if necessary and populate with surface quotes
205 quotes_.clear();
206
207 string stem = quoteStem();
208 for (const pair<string, string>& p : vc->quotes()) {
209 // build quotes of the form .../TERM/EXPIRY/STRIKE
210 for (auto const& t : terms_) {
211 quotes_.push_back(stem + ore::data::to_string(t) + "/" + p.first + "/" + p.second);
212 }
213 // if only one or even no term is configured, also build quotes of the form .../EXPIRY/STRIKE
214 if (terms_.size() <= 1) {
215 quotes_.push_back(stem + p.first + "/" + p.second);
216 }
217 }
218
219 } else if (auto vc = QuantLib::ext::dynamic_pointer_cast<CDSProxyVolatilityConfig>(volatilityConfig_)) {
220 // no quotes required in this case
221 } else {
222 QL_FAIL("CDSVolatilityCurveConfig expected a constant, curve or surface");
223 }
224}
225
226void CDSVolatilityCurveConfig::populateRequiredCurveIds() {
227 if (auto vc = QuantLib::ext::dynamic_pointer_cast<CDSProxyVolatilityConfig>(volatilityConfig_)) {
228 requiredCurveIds_[CurveSpec::CurveType::CDSVolatility].insert(vc->cdsVolatilityCurve());
229 }
230 for (auto const& c : termCurves_) {
231 auto spec = parseCurveSpec(c);
232 requiredCurveIds_[CurveSpec::CurveType::Default].insert(spec->curveConfigID());
233 }
234}
235
236string CDSVolatilityCurveConfig::quoteStem() const {
237
238 string stem{"INDEX_CDS_OPTION/RATE_LNVOL/"};
239
240 if (!quoteName_.empty()) {
241 // If an explicit quote name has been provided use this.
242 stem += quoteName_;
243 } else {
244 // If not, fallback to just using the curveID_.
245 stem += curveID_;
246 }
247 stem += "/";
248 return stem;
249}
250
251} // namespace data
252} // namespace ore
CDS and index CDS volatility configuration.
CDSVolatilityCurveConfig()
Default constructor.
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
XML Utilities Class.
Definition: xmlutils.hpp:119
static void checkNode(XMLNode *n, const string &expectedName)
Definition: xmlutils.cpp:175
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
Definition: xmlutils.cpp:428
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
static XMLNode * getChildNode(XMLNode *n, const string &name="")
Definition: xmlutils.cpp:387
static string getNodeValue(XMLNode *node)
Get a node's value.
Definition: xmlutils.cpp:489
static Period getChildValueAsPeriod(XMLNode *node, const string &name, bool mandatory=false, const QuantLib::Period &defaultValue=0 *QuantLib::Days)
Definition: xmlutils.cpp:301
static vector< string > getChildrenValuesAsStrings(XMLNode *node, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:342
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
CurveSpec parser.
QuantLib::ext::shared_ptr< CurveSpec > parseCurveSpec(const string &s)
function to convert a string into a curve spec
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
@ data
Definition: log.hpp:77
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
Calendar calendar
Definition: utilities.cpp:441
RandomVariable exp(RandomVariable x)
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
string conversion utilities