Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
genericyieldvolcurveconfig.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>
26#include <ql/errors.hpp>
27
28namespace ore {
29namespace data {
30
32 switch (t) {
34 return out << "RATE_LNVOL";
36 return out << "RATE_NVOL";
38 return out << "RATE_SLNVOL";
39 default:
40 QL_FAIL("unknown VolatilityType(" << Integer(t) << ")");
41 }
42}
43
45 const std::string& underlyingLabel, const std::string& rootNodeLabel, const std::string& marketDatumInstrumentLabel,
46 const std::string& qualifierLabel, const string& curveID, const string& curveDescription,
47 const std::string& qualifier, const Dimension dimension, const VolatilityType volatilityType,
48 const VolatilityType outputVolatilityType, const Interpolation interpolation, const Extrapolation extrapolation,
49 const vector<string>& optionTenors, const vector<string>& underlyingTenors, const DayCounter& dayCounter,
50 const Calendar& calendar, const BusinessDayConvention& businessDayConvention, const string& shortSwapIndexBase,
51 const string& swapIndexBase, const vector<string>& smileOptionTenors, const vector<string>& smileUnderlyingTenors,
52 const vector<string>& smileSpreads,
53 const boost::optional<ParametricSmileConfiguration>& parametricSmileConfiguration)
54 : CurveConfig(curveID, curveDescription), underlyingLabel_(underlyingLabel), rootNodeLabel_(rootNodeLabel),
55 marketDatumInstrumentLabel_(marketDatumInstrumentLabel), qualifierLabel_(qualifierLabel), allowSmile_(true),
56 requireSwapIndexBases_(false), qualifier_(qualifier), dimension_(dimension), volatilityType_(volatilityType),
57 interpolation_(interpolation), extrapolation_(extrapolation), optionTenors_(optionTenors),
58 underlyingTenors_(underlyingTenors), dayCounter_(dayCounter), calendar_(calendar),
59 businessDayConvention_(businessDayConvention), shortSwapIndexBase_(shortSwapIndexBase),
60 swapIndexBase_(swapIndexBase), smileOptionTenors_(smileOptionTenors),
61 smileUnderlyingTenors_(smileUnderlyingTenors), smileSpreads_(smileSpreads),
62 parametricSmileConfiguration_(parametricSmileConfiguration) {
63
64 QL_REQUIRE(dimension == Dimension::ATM || dimension == Dimension::Smile, "Invalid dimension");
65
67 QL_REQUIRE(smileOptionTenors.size() == 0 && smileUnderlyingTenors.size() == 0 && smileSpreads.size() == 0,
68 "Smile tenors/strikes/spreads should only be set when dim=Smile");
69 }
70
71 if (qualifier_.empty()) {
73 }
74}
75
77 const std::string& underlyingLabel, const std::string& rootNodeLabel, const std::string& qualifierLabel,
78 const string& curveID, const string& curveDescription, const string& qualifier,
79 const std::string& proxySourceCurveId, const std::string& proxySourceShortSwapIndexBase,
80 const std::string& proxySourceSwapIndexBase, const std::string& proxyTargetShortSwapIndexBase,
81 const std::string& proxyTargetSwapIndexBase)
82 : CurveConfig(curveID, curveDescription), underlyingLabel_(underlyingLabel), rootNodeLabel_(rootNodeLabel),
83 qualifierLabel_(qualifierLabel), allowSmile_(true), requireSwapIndexBases_(false),
84 proxySourceShortSwapIndexBase_(proxySourceShortSwapIndexBase),
85 proxySourceSwapIndexBase_(proxySourceSwapIndexBase),
86 proxyTargetShortSwapIndexBase_(proxyTargetShortSwapIndexBase),
87 proxyTargetSwapIndexBase_(proxyTargetSwapIndexBase) {
88
89 if (qualifier_.empty()) {
91 }
92
94}
95
97 if (!proxySourceCurveId_.empty()) {
99 parseCurveSpec(proxySourceCurveId_)->curveConfigID());
100 }
101}
102
104
105 if (quotes_.size() == 0 && proxySourceCurveId_.empty()) {
106 std::stringstream ssBase;
107 ssBase << marketDatumInstrumentLabel_ << "/" << volatilityType_ << "/" << qualifier_ << "/";
108 if (!quoteTag_.empty())
109 ssBase << quoteTag_ << "/";
110 string base = ssBase.str();
111
112 // add atm vols (always required)
113 for (auto o : optionTenors_) {
114 for (auto s : underlyingTenors_) {
115 std::stringstream ss;
116 ss << base << o << "/" << s << "/ATM";
117 quotes_.push_back(ss.str());
118 }
119 }
120
121 // add Smile Spreads, if dimension is Smile
123 for (auto o : smileOptionTenors_) {
124 for (auto s : smileUnderlyingTenors_) {
125 for (auto sp : smileSpreads_) {
126 std::stringstream ss;
127 ss << base << o << "/" << s << "/Smile/" << sp;
128 quotes_.push_back(ss.str());
129 }
130 }
131 }
132 }
133 // add SHIFT quotes, if vol type is SLN
134 for (auto s : underlyingTenors_) {
136 std::stringstream ss;
137 ss << marketDatumInstrumentLabel_ << "/SHIFT/" << qualifier_ << "/"
138 << (quoteTag_.empty() ? "" : quoteTag_ + "/") << s;
139 quotes_.push_back(ss.str());
140 }
141 }
142 }
143 return quotes_;
144}
145
146string GenericYieldVolatilityCurveConfig::ccyFromSwapIndexBase(const std::string& swapIndexBase) {
147 std::vector<string> tokens;
148 split(tokens, swapIndexBase, boost::is_any_of("-"));
149 QL_REQUIRE(!tokens.empty() && tokens[0] != "",
150 "GenericYieldVolatilityCurveConfig::fromXML(): can not derive qualifier from SwapIndexBase ("
151 << swapIndexBase << ")");
152 return tokens[0];
153}
154
157
158 curveID_ = XMLUtils::getChildValue(node, "CurveId", true);
159 curveDescription_ = XMLUtils::getChildValue(node, "CurveDescription", true);
160
161 if (auto p = XMLUtils::getChildNode(node, "ProxyConfig")) {
162 // read in proxy config
163
164 auto source = XMLUtils::getChildNode(p, "Source");
165 QL_REQUIRE(source != nullptr,
166 "GenericYieldVolatilityCurveConfig::fromXML(): ProxyConfig requires child node 'Source'");
167 proxySourceCurveId_ = XMLUtils::getChildValue(source, "CurveId");
168 proxySourceShortSwapIndexBase_ = XMLUtils::getChildValue(source, "ShortSwapIndexBase");
169 proxySourceSwapIndexBase_ = XMLUtils::getChildValue(source, "SwapIndexBase");
170
171 auto target = XMLUtils::getChildNode(p, "Target");
172 QL_REQUIRE(target != nullptr,
173 "GenericYieldVolatilityCurveConfig::fromXML(): ProxyConfig requires child node 'Target'");
174 proxyTargetShortSwapIndexBase_ = XMLUtils::getChildValue(target, "ShortSwapIndexBase");
175 proxyTargetSwapIndexBase_ = XMLUtils::getChildValue(target, "SwapIndexBase");
176
178
179 } else {
180 // read in quote-based config
181 if (allowSmile_) {
182 string dim = XMLUtils::getChildValue(node, "Dimension", true);
183 if (dim == "ATM") {
185 } else if (dim == "Smile") {
187 } else {
188 QL_FAIL("Dimension " << dim << " not recognized");
189 }
190 } else {
192 }
193
194 string volType = XMLUtils::getChildValue(node, "VolatilityType", true);
195 if (volType == "Normal") {
197 } else if (volType == "Lognormal") {
199 } else if (volType == "ShiftedLognormal") {
201 } else {
202 QL_FAIL(
203 "VolatilityType '" << volType
204 << "' not recognized. Expected one of 'Normal', 'Lognormal', 'ShiftedLognormal'.");
205 }
206
207 string outVolType = XMLUtils::getChildValue(node, "OutputVolatilityType", false);
208 if (outVolType.empty())
210 else if (outVolType == "Normal") {
212 } else if (outVolType == "Lognormal") {
214 } else if (outVolType == "ShiftedLognormal") {
216 } else {
217 QL_FAIL("OutputVolatilityType '"
218 << outVolType << "' not recognized. Expected one of 'Normal', 'Lognormal', 'ShiftedLognormal'.");
219 }
220
221 string interp = XMLUtils::getChildValue(node, "Interpolation", false, "Linear");
222 if (interp == "Linear") {
224 } else {
225 try {
227 } catch (const std::exception& e) {
228 QL_FAIL("Interpolation '" << interp << "' not recognized. Expected 'Linear' or a SABR variant ("
229 << e.what() << ")");
230 }
231 }
232
233 string extr = XMLUtils::getChildValue(node, "Extrapolation", false, "Flat");
234 if (extr == "Linear") {
236 } else if (extr == "Flat") {
238 } else if (extr == "None") {
240 } else {
241 QL_FAIL("Extrapolation " << extr << " not recognized, expected one of 'Linear', 'Flat', 'None'.");
242 }
243
244 optionTenors_ = XMLUtils::getChildrenValuesAsStrings(node, "OptionTenors", true);
246
247 string cal = XMLUtils::getChildValue(node, "Calendar", true);
249
250 string dc = XMLUtils::getChildValue(node, "DayCounter", true);
252
253 string bdc = XMLUtils::getChildValue(node, "BusinessDayConvention", true);
255
257 shortSwapIndexBase_ = XMLUtils::getChildValue(node, "ShortSwapIndexBase", true);
258 swapIndexBase_ = XMLUtils::getChildValue(node, "SwapIndexBase", true);
259 }
260
261 // smile data
263 smileOptionTenors_ = XMLUtils::getChildrenValuesAsStrings(node, "SmileOptionTenors", true);
265 XMLUtils::getChildrenValuesAsStrings(node, "Smile" + underlyingLabel_ + "Tenors", true);
266 smileSpreads_ = XMLUtils::getChildrenValuesAsStrings(node, "SmileSpreads", true);
267 }
268
269 // read qualifier from explicit field
270 if (qualifierLabel_ != "")
272
273 // derive qualifier (=ccy) from swapIndexBase if not given explicitly
274 if (qualifier_ == "")
276
277 // optional quote tag to include
278 quoteTag_ = XMLUtils::getChildValue(node, "QuoteTag", false);
279
280 // Optional parametric smile configuration
281 if(XMLNode* n = XMLUtils::getChildNode(node, "ParametricSmileConfiguration")) {
284 }
285 }
286
287 if (auto tmp = XMLUtils::getChildNode(node, "Report")) {
289 }
290}
291
293 XMLNode* node = doc.allocNode(rootNodeLabel_);
294 XMLUtils::addChild(doc, node, "CurveId", curveID_);
295 XMLUtils::addChild(doc, node, "CurveDescription", curveDescription_);
296
297 if (!proxySourceCurveId_.empty()) {
298 // write out proxy config
299 auto proxy = XMLUtils::addChild(doc, node, "ProxyConfig");
300 auto source = XMLUtils::addChild(doc, proxy, "Source");
301 auto target = XMLUtils::addChild(doc, proxy, "Target");
302 XMLUtils::addChild(doc, source, "CurveId", proxySourceCurveId_);
303 XMLUtils::addChild(doc, source, "ShortSwapIndexBase", proxySourceShortSwapIndexBase_);
304 XMLUtils::addChild(doc, source, "SwapIndexBase", proxySourceSwapIndexBase_);
305 XMLUtils::addChild(doc, target, "ShortSwapIndexBase", proxyTargetShortSwapIndexBase_);
306 XMLUtils::addChild(doc, target, "SwapIndexBase", proxyTargetSwapIndexBase_);
307 } else {
308 // write out quote based config
309 if (qualifierLabel_ != "")
311
312 if (dimension_ == Dimension::ATM) {
313 XMLUtils::addChild(doc, node, "Dimension", "ATM");
314 } else if (dimension_ == Dimension::Smile) {
315 XMLUtils::addChild(doc, node, "Dimension", "Smile");
316 } else {
317 QL_FAIL("Unknown Dimension in GenericYieldVolatilityCurveConfig::toXML()");
318 }
319
321 XMLUtils::addChild(doc, node, "VolatilityType", "Normal");
323 XMLUtils::addChild(doc, node, "VolatilityType", "Lognormal");
325 XMLUtils::addChild(doc, node, "VolatilityType", "ShiftedLognormal");
326 } else {
327 QL_FAIL("Unknown VolatilityType in GenericYieldVolatilityCurveConfig::toXML()");
328 }
329
331 XMLUtils::addChild(doc, node, "OutputVolatilityType", "Normal");
333 XMLUtils::addChild(doc, node, "OutputVolatilityType", "Lognormal");
335 XMLUtils::addChild(doc, node, "OutputVolatilityType", "ShiftedLognormal");
336 } else {
337 QL_FAIL("Unknown OutputVolatilityType in GenericYieldVolatilityCurveConfig::toXML()");
338 }
339
340 std::string extr_string;
342 extr_string = "None";
344 extr_string = "Linear";
345 } else if (extrapolation_ == Extrapolation::Flat) {
346 extr_string = "Flat";
347 }
348 XMLUtils::addChild(doc, node, "Extrapolation", extr_string);
349
350 XMLUtils::addChild(doc, node, "DayCounter", to_string(dayCounter_));
351 XMLUtils::addChild(doc, node, "Calendar", to_string(calendar_));
352 XMLUtils::addChild(doc, node, "BusinessDayConvention", to_string(businessDayConvention_));
353 XMLUtils::addGenericChildAsList(doc, node, "OptionTenors", optionTenors_);
355
357 XMLUtils::addChild(doc, node, "ShortSwapIndexBase", shortSwapIndexBase_);
358 XMLUtils::addChild(doc, node, "SwapIndexBase", swapIndexBase_);
359 }
360
362 XMLUtils::addGenericChildAsList(doc, node, "SmileOptionTenors", smileOptionTenors_);
364 XMLUtils::addGenericChildAsList(doc, node, "SmileSpreads", smileSpreads_);
365 }
366
367 if (!quoteTag_.empty()) {
368 XMLUtils::addChild(doc, node, "QuoteTag", quoteTag_);
369 }
370 }
371
373
374 return node;
375}
376
377} // namespace data
378} // namespace ore
Base curve configuration.
Definition: curveconfig.hpp:41
vector< string > quotes_
Definition: curveconfig.hpp:74
map< CurveSpec::CurveType, set< string > > requiredCurveIds_
Definition: curveconfig.hpp:75
GenericYieldVolatilityCurveConfig(const std::string &underlyingLabel, const std::string &rootNodeLabel, const std::string &marketDatumInstrumentLabel, const std::string &qualifierLabel, const bool allowSmile, const bool requireSwapIndexBases)
Default constructor.
string ccyFromSwapIndexBase(const std::string &swapIndexBase)
XMLNode * toXML(XMLDocument &doc) const override
const vector< string > & quotes() override
Return all the market quotes required for this config.
boost::optional< ParametricSmileConfiguration > parametricSmileConfiguration_
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
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 XMLNode * getChildNode(XMLNode *n, const string &name="")
Definition: xmlutils.cpp:387
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.
Swaption volatility curve configuration classes.
QuantLib::ext::shared_ptr< CurveSpec > parseCurveSpec(const string &s)
function to convert a string into a curve spec
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
SabrParametricVolatility::ModelVariant parseSabrParametricVolatilityModelVariant(const std::string &s)
Parse SabrParametricVolatility::ModelVariant.
Definition: parsers.cpp:1458
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Definition: parsers.cpp:173
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)
VolatilityType volatilityType(CapFloorVolatilityCurveConfig::VolatilityType type)
Imply QuantLib::VolatilityType from CapFloorVolatilityCurveConfig::VolatilityType.
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
XML utility functions.