Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
correlationcurveconfig.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 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#include <ql/time/calendars/nullcalendar.hpp>
26#include <ql/time/daycounters/actualactual.hpp>
27namespace ore {
28namespace data {
29
30std::ostream& operator<<(std::ostream& out, CorrelationCurveConfig::CorrelationType t) {
31 switch (t) {
33 return out << "CMSSpread";
35 return out << "Generic";
36 default:
37 QL_FAIL("unknown QuoteType(" << Integer(t) << ")");
38 }
39}
40std::ostream& operator<<(std::ostream& out, CorrelationCurveConfig::Dimension t) {
41 switch (t) {
43 return out << "ATM";
45 return out << "Constant";
46 default:
47 QL_FAIL("unknown Dimension(" << Integer(t) << ")");
48 }
49}
50
51CorrelationCurveConfig::CorrelationCurveConfig(const string& curveID, const string& curveDescription,
52 const Dimension& dimension, const CorrelationType& corrType,
53 const string& convention, const MarketDatum::QuoteType& quoteType,
54 const bool extrapolate, const vector<string>& optionTenors,
55 const DayCounter& dayCounter, const Calendar& calendar,
56 const BusinessDayConvention& businessDayConvention, const string& index1,
57 const string& index2, const string& currency, const string& swaptionVol,
58 const string& discountCurve)
59 : CurveConfig(curveID, curveDescription), dimension_(dimension), correlationType_(corrType),
60 conventions_(convention), quoteType_(quoteType), extrapolate_(extrapolate), optionTenors_(optionTenors),
61 dayCounter_(dayCounter), calendar_(calendar), businessDayConvention_(businessDayConvention), index1_(index1),
62 index2_(index2), currency_(currency), swaptionVol_(swaptionVol), discountCurve_(discountCurve) {
63
64 QL_REQUIRE(dimension == Dimension::ATM || dimension == Dimension::Constant, "Invalid dimension");
65
67 QL_REQUIRE(optionTenors.size() == 1,
68 "Only one tenor should be supplied for a constant correlation termstructure");
69 }
70
72}
73
75 if (!swaptionVolatility().empty())
77 if (!discountCurve().empty())
79}
80
81const vector<string>& CorrelationCurveConfig::quotes() {
82
83 if (quotes_.size() == 0) {
84
85 std::stringstream ssBase;
86 ssBase << "CORRELATION/" << quoteType_ << "/" << index1_ << "/" << index2_;
87 string base = ssBase.str();
88
89 for (auto o : optionTenors_) {
90 std::stringstream ss;
91 ss << base << "/" << o << "/ATM";
92 quotes_.push_back(ss.str());
93 }
94 }
95 return quotes_;
96}
97
99 XMLUtils::checkNode(node, "Correlation");
100
101 curveID_ = XMLUtils::getChildValue(node, "CurveId", true);
102 curveDescription_ = XMLUtils::getChildValue(node, "CurveDescription", true);
103
104 string corrType = XMLUtils::getChildValue(node, "CorrelationType", true);
105 if (corrType == "CMSSpread") {
107 } else if (corrType == "Generic") {
109 } else {
110 QL_FAIL("Correlation type " << corrType << " not recognized");
111 }
112
113 string quoteType = XMLUtils::getChildValue(node, "QuoteType", true);
114 // For QuoteType, we use an insensitive compare because we previously used "Rate" here
115 // But now we want to be consistent with the market datum name
116 if (boost::iequals(quoteType, "RATE")) {
118 } else if (boost::iequals(quoteType, "PRICE")) {
120 } else if (boost::iequals(quoteType, "NULL")) {
122 } else {
123 QL_FAIL("Quote type " << quoteType << " not recognized");
124 }
125
126 string cal, dc;
128
129 cal = XMLUtils::getChildValue(node, "Calendar", false);
130 cal == "" ? calendar_ = QuantLib::NullCalendar() : calendar_ = parseCalendar(cal);
131
132 dc = XMLUtils::getChildValue(node, "DayCounter", false);
133 dc == "" ? dayCounter_ = QuantLib::ActualActual(ActualActual::ISDA) : dayCounter_ = parseDayCounter(dc);
134 } else { // Compulsory information for Rate and Price QuoteTypes
135 cal = XMLUtils::getChildValue(node, "Calendar", true);
137
138 dc = XMLUtils::getChildValue(node, "DayCounter", true);
140
141 optionTenors_ = XMLUtils::getChildrenValuesAsStrings(node, "OptionTenors", true);
142 QL_REQUIRE(optionTenors_.size() > 0, "no option tenors supplied");
143
144 string dim = XMLUtils::getChildValue(node, "Dimension", true);
145 QL_REQUIRE(dim == "ATM" || dim == "Constant", "Dimension " << dim << " not recognised");
146
147 if (dim == "Constant") {
149 QL_REQUIRE(optionTenors_.size() == 1, "Only one tenor should be supplied for a constant correlation termstructure");
150 } else {
152 }
153
154 if (dimension_ == Dimension::ATM) {
155 string bdc = XMLUtils::getChildValue(node, "BusinessDayConvention", true);
157 }
158
159 string extr = XMLUtils::getChildValue(node, "Extrapolation", true);
160 extrapolate_ = parseBool(extr);
161
163 QL_REQUIRE(quoteType_ == MarketDatum::QuoteType::RATE, "For CorrelationType::Generic calibration is not supported!");
164 }
165 // needed for Rate and Price QuoteTyope to build the quote string
166 index1_ = XMLUtils::getChildValue(node, "Index1", true);
167 index2_ = XMLUtils::getChildValue(node, "Index2", true);
168
169 swaptionVol_ = "";
170
171 // Index1, Index2, Currency, Conventions, SwaptionVolatility, DiscountCurve are relevant for calibration which
172 // is only supported for
173 // CMSSpread type correlation
175 currency_ = XMLUtils::getChildValue(node, "Currency", true);
176 conventions_ = XMLUtils::getChildValue(node, "Conventions");
177 swaptionVol_ = XMLUtils::getChildValue(node, "SwaptionVolatility", true);
178 discountCurve_ = XMLUtils::getChildValue(node, "DiscountCurve", true);
179 }
180 }
182}
183
185 XMLNode* node = doc.allocNode("Correlation");
186 XMLUtils::addChild(doc, node, "CurveId", curveID_);
187 XMLUtils::addChild(doc, node, "CurveDescription", curveDescription_);
188 XMLUtils::addChild(doc, node, "CorrelationType", to_string(correlationType_));
189 XMLUtils::addChild(doc, node, "Index1", index1_);
190 XMLUtils::addChild(doc, node, "Index2", index2_);
191 XMLUtils::addChild(doc, node, "Conventions", conventions_);
192
194 XMLUtils::addChild(doc, node, "SwaptionVolatility", swaptionVol_);
195 XMLUtils::addChild(doc, node, "DiscountCurve", discountCurve_);
196 XMLUtils::addChild(doc, node, "Currency", currency_);
197 }
199 XMLUtils::addChild(doc, node, "Dimension", to_string(dimension_));
200 }
201
202 XMLUtils::addChild(doc, node, "QuoteType", to_string(quoteType_));
203
205
206 XMLUtils::addChild(doc, node, "Extrapolation", extrapolate_);
207 XMLUtils::addChild(doc, node, "DayCounter", to_string(dayCounter_));
208 XMLUtils::addChild(doc, node, "Calendar", to_string(calendar_));
209
211 XMLUtils::addChild(doc, node, "BusinessDayConvention", to_string(businessDayConvention_));
212
213 XMLUtils::addGenericChildAsList(doc, node, "OptionTenors", optionTenors_);
214 }
215
217 XMLUtils::addChild(doc, node, "DayCounter", to_string(dayCounter_));
218 XMLUtils::addChild(doc, node, "Calendar", to_string(calendar_));
219 }
220
221 return node;
222}
223
224bool indexNameLessThan(const std::string& index1, const std::string& index2) {
225 vector<string> tokens1;
226 boost::split(tokens1, index1, boost::is_any_of("-"));
227 vector<string> tokens2;
228 boost::split(tokens2, index2, boost::is_any_of("-"));
229
230 QL_REQUIRE(tokens1.size() >= 2, "at least two tokens expected in " << index1);
231 QL_REQUIRE(tokens2.size() >= 2, "at least two tokens expected in " << index2);
232
233 Size s1, s2;
234
235 if (tokens1[1] == "CMS")
236 s1 = 4;
237 else if (tokens1[0] == "FX")
238 s1 = 2;
239 else if (tokens1[0] == "EQ")
240 s1 = 1;
241 else if (tokens1[0] == "COMM")
242 s1 = 0;
243 else
244 s1 = 3; // assume Ibor
245
246 if (tokens2[1] == "CMS")
247 s2 = 4;
248 else if (tokens2[0] == "FX")
249 s2 = 2;
250 else if (tokens2[0] == "EQ")
251 s2 = 1;
252 else if (tokens2[0] == "COMM")
253 s2 = 0;
254 else
255 s2 = 3; // assume Ibor
256
257 if (s1 < s2)
258 return true;
259 else if (s2 < s1)
260 return false;
261
262 // both EQ or both COM
263 if (s1 == 0 || s1 == 1)
264 return tokens1[1] < tokens2[1];
265
266 QL_REQUIRE(tokens1.size() >= 3, "at least three tokens expected in " << index1);
267 QL_REQUIRE(tokens2.size() >= 3, "at least three tokens expected in " << index2);
268
269 // both CMS or both Ibor, tenor is the last token (3rd or even 4th for customised CMS indices)
270 if (s1 == 3 || s1 == 4)
271 return parsePeriod(tokens1.back()) < parsePeriod(tokens2.back());
272
273 QL_REQUIRE(tokens1.size() >= 4, "at least four tokens expected in " << index1);
274 QL_REQUIRE(tokens2.size() >= 4, "at least four tokens expected in " << index2);
275
276 // both FX, compare CCY1 then CCY2 alphabetical
277 if (s1 == 2) {
278 return (tokens1[2] + "-" + tokens1[3]) < (tokens2[2] + "-" + tokens2[3]);
279 }
280
281 QL_FAIL("indexNameLessThan(): internal error");
282}
283
284} // namespace data
285} // namespace ore
const vector< string > & optionTenors() const
const MarketDatum::QuoteType & quoteType() const
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
const vector< string > & quotes() override
Return all the market quotes required for this config.
CorrelationType
supported Correlation types
Dimension
supported Correlation dimensions
Base curve configuration.
Definition: curveconfig.hpp:41
vector< string > quotes_
Definition: curveconfig.hpp:74
map< CurveSpec::CurveType, set< string > > requiredCurveIds_
Definition: curveconfig.hpp:75
QuoteType
Supported market quote types.
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
static void addGenericChildAsList(XMLDocument &doc, XMLNode *n, const string &name, const vector< T > &values, const string &attrName="", const string &attr="")
Definition: xmlutils.hpp:144
static void checkNode(XMLNode *n, const string &expectedName)
Definition: xmlutils.cpp:175
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
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
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Definition: parsers.cpp:173
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
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Definition: parsers.cpp:209
Map text representations to QuantLib/QuantExt types.
@ data
Definition: log.hpp:77
Calendar calendar
Definition: utilities.cpp:441
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
bool indexNameLessThan(const std::string &index1, const std::string &index2)
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