Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
yieldcurveconfig.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 Copyright (C) 2023 Oleg Kulkov
4 All rights reserved.
5
6 This file is part of ORE, a free-software/open-source library
7 for transparent pricing and risk analysis - http://opensourcerisk.org
8
9 ORE is free software: you can redistribute it and/or modify it
10 under the terms of the Modified BSD License. You should have received a
11 copy of the license along with this program.
12 The license is also available online at <http://opensourcerisk.org>
13
14 This program is distributed on the basis that it will form a useful
15 contribution to risk analytics and model standardisation, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/errors.hpp>
21
29
30#include <boost/algorithm/string/predicate.hpp>
31
32using boost::iequals;
34using QuantLib::Size;
35using QuantLib::Visitor;
36
37namespace ore {
38namespace data {
39
41 if (iequals(s, "Zero"))
43 else if (iequals(s, "Zero Spread"))
45 else if (iequals(s, "Discount"))
47 else if (iequals(s, "Deposit"))
49 else if (iequals(s, "FRA"))
51 else if (iequals(s, "Future"))
53 else if (iequals(s, "OIS"))
55 else if (iequals(s, "Swap"))
57 else if (iequals(s, "Average OIS"))
59 else if (iequals(s, "Tenor Basis Swap"))
61 else if (iequals(s, "Tenor Basis Two Swaps"))
63 else if (iequals(s, "BMA Basis Swap"))
65 else if (iequals(s, "FX Forward"))
67 else if (iequals(s, "Cross Currency Basis Swap"))
69 else if (iequals(s, "Cross Currency Fix Float Swap"))
71 else if (iequals(s, "Discount Ratio"))
73 else if (iequals(s, "FittedBond"))
75 else if (iequals(s, "Yield Plus Default"))
77 else if (iequals(s, "Weighted Average"))
79 else if (iequals(s, "Ibor Fallback"))
81 else if (iequals(s, "Bond Yield Shifted"))
83 QL_FAIL("Yield curve segment type " << s << " not recognized");
84}
85
86class SegmentIDGetter : public AcyclicVisitor,
87 public Visitor<YieldCurveSegment>,
88 public Visitor<SimpleYieldCurveSegment>,
89 public Visitor<AverageOISYieldCurveSegment>,
90 public Visitor<TenorBasisYieldCurveSegment>,
91 public Visitor<CrossCcyYieldCurveSegment>,
92 public Visitor<ZeroSpreadedYieldCurveSegment>,
93 public Visitor<DiscountRatioYieldCurveSegment>,
94 public Visitor<FittedBondYieldCurveSegment>,
95 public Visitor<WeightedAverageYieldCurveSegment>,
96 public Visitor<YieldPlusDefaultYieldCurveSegment>,
97 public Visitor<BondYieldShiftedYieldCurveSegment>,
98 public Visitor<IborFallbackCurveSegment> {
99
100public:
101 SegmentIDGetter(const string& curveID, map<CurveSpec::CurveType, set<string>>& requiredCurveIds)
102 : curveID_(curveID), requiredCurveIds_(requiredCurveIds) {}
103
104 void visit(YieldCurveSegment&) override;
105 void visit(SimpleYieldCurveSegment& s) override;
106 void visit(AverageOISYieldCurveSegment& s) override;
107 void visit(TenorBasisYieldCurveSegment& s) override;
108 void visit(CrossCcyYieldCurveSegment& s) override;
109 void visit(ZeroSpreadedYieldCurveSegment& s) override;
110 void visit(DiscountRatioYieldCurveSegment& s) override;
111 void visit(FittedBondYieldCurveSegment& s) override;
112 void visit(WeightedAverageYieldCurveSegment& s) override;
113 void visit(YieldPlusDefaultYieldCurveSegment& s) override;
114 void visit(BondYieldShiftedYieldCurveSegment& s) override;
115 void visit(IborFallbackCurveSegment& s) override;
116
117private:
118 string curveID_;
119 map<CurveSpec::CurveType, set<string>>& requiredCurveIds_;
120};
121
122void SegmentIDGetter::visit(YieldCurveSegment&) {
123 // Do nothing
124}
125
126void SegmentIDGetter::visit(SimpleYieldCurveSegment& s) {
127 string aCurveID = s.projectionCurveID();
128 if (curveID_ != aCurveID && !aCurveID.empty()) {
129 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
130 }
131}
132
133void SegmentIDGetter::visit(AverageOISYieldCurveSegment& s) {
134 string aCurveID = s.projectionCurveID();
135 if (curveID_ != aCurveID && !aCurveID.empty()) {
136 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
137 }
138}
139
140void SegmentIDGetter::visit(TenorBasisYieldCurveSegment& s) {
141 string aCurveID = s.receiveProjectionCurveID();
142 if (curveID_ != aCurveID && !aCurveID.empty()) {
143 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
144 }
145 aCurveID = s.payProjectionCurveID();
146 if (curveID_ != aCurveID && !aCurveID.empty()) {
147 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
148 }
149}
150
151void SegmentIDGetter::visit(CrossCcyYieldCurveSegment& s) {
152 string aCurveID = s.foreignDiscountCurveID();
153 if (curveID_ != aCurveID && !aCurveID.empty()) {
154 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
155 }
156 aCurveID = s.domesticProjectionCurveID();
157 if (curveID_ != aCurveID && !aCurveID.empty()) {
158 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
159 }
160 aCurveID = s.foreignProjectionCurveID();
161 if (curveID_ != aCurveID && !aCurveID.empty()) {
162 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
163 }
164}
165
166void SegmentIDGetter::visit(ZeroSpreadedYieldCurveSegment& s) {
167 string aCurveID = s.referenceCurveID();
168 if (curveID_ != aCurveID && !aCurveID.empty()) {
169 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID);
170 }
171}
172
173void SegmentIDGetter::visit(DiscountRatioYieldCurveSegment& s) {
174 if (curveID_ != s.baseCurveId() && !s.baseCurveId().empty()) {
175 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(s.baseCurveId());
176 }
177 if (curveID_ != s.numeratorCurveId() && !s.numeratorCurveId().empty()) {
178 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(s.numeratorCurveId());
179 }
180 if (curveID_ != s.denominatorCurveId() && !s.denominatorCurveId().empty()) {
181 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(s.denominatorCurveId());
182 }
183}
184
185void SegmentIDGetter::visit(FittedBondYieldCurveSegment& s) {
186 for (auto const& c : s.iborIndexCurves())
187 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(c.second);
188}
189
190void SegmentIDGetter::visit(BondYieldShiftedYieldCurveSegment& s) {
191 for (auto const& c : s.iborIndexCurves())
192 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(c.second);
193 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(s.referenceCurveID());
194}
195
196void SegmentIDGetter::visit(WeightedAverageYieldCurveSegment& s) {
197 string aCurveID1 = s.referenceCurveID1();
198 string aCurveID2 = s.referenceCurveID2();
199 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID1);
200 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(aCurveID2);
201}
202
203void SegmentIDGetter::visit(YieldPlusDefaultYieldCurveSegment& s) {
204 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(s.referenceCurveID());
205 for (auto const& i : s.defaultCurveIDs()) {
206 requiredCurveIds_[CurveSpec::CurveType::Default].insert(parseCurveSpec(i)->curveConfigID());
207 }
208}
209
210void SegmentIDGetter::visit(IborFallbackCurveSegment& s) {
211 requiredCurveIds_[CurveSpec::CurveType::Yield].insert(parseCurveSpec(s.rfrCurve())->curveConfigID());
212}
213
214// YieldCurveConfig
215YieldCurveConfig::YieldCurveConfig(const string& curveID, const string& curveDescription, const string& currency,
216 const string& discountCurveID,
217 const vector<QuantLib::ext::shared_ptr<YieldCurveSegment>>& curveSegments,
218 const string& interpolationVariable, const string& interpolationMethod,
219 const string& zeroDayCounter, bool extrapolation,
220 const BootstrapConfig& bootstrapConfig, const Size mixedInterpolationCutoff)
221 : CurveConfig(curveID, curveDescription), currency_(currency), discountCurveID_(discountCurveID),
222 curveSegments_(curveSegments), interpolationVariable_(interpolationVariable),
223 interpolationMethod_(interpolationMethod), zeroDayCounter_(zeroDayCounter), extrapolation_(extrapolation),
224 bootstrapConfig_(bootstrapConfig), mixedInterpolationCutoff_(mixedInterpolationCutoff) {
226}
227
228const vector<string>& YieldCurveConfig::quotes() {
229 if (quotes_.size() == 0) {
230 bool addedFxSpot = false;
231 for (auto c : curveSegments_) {
232 for (auto segmentQuote : c->quotes())
233 quotes_.push_back(segmentQuote.first);
234
235 // Check if the segment is a CrossCcyYieldCurveSegment and add the FX spot rate to the
236 // set of quotes needed for the YieldCurveConfig if it has not already been added.
237 if (auto xccySegment = QuantLib::ext::dynamic_pointer_cast<CrossCcyYieldCurveSegment>(c)) {
238 if (!addedFxSpot)
239 quotes_.push_back(xccySegment->spotRateID());
240 }
241 }
242 }
243 return quotes_;
244}
245
247
248 XMLUtils::checkNode(node, "YieldCurve");
249
250 // Read in the mandatory nodes.
251 curveID_ = XMLUtils::getChildValue(node, "CurveId", true);
252 curveDescription_ = XMLUtils::getChildValue(node, "CurveDescription", true);
253 currency_ = XMLUtils::getChildValue(node, "Currency", true);
254 discountCurveID_ = XMLUtils::getChildValue(node, "DiscountCurve", true);
255
256 // Read in the segments.
257 XMLNode* segmentsNode = XMLUtils::getChildNode(node, "Segments");
258 if (segmentsNode) {
259 for (XMLNode* child = XMLUtils::getChildNode(segmentsNode); child; child = XMLUtils::getNextSibling(child)) {
260
261 QuantLib::ext::shared_ptr<YieldCurveSegment> segment;
262 string childName = XMLUtils::getNodeName(child);
263
264 if (childName == "Direct") {
265 segment.reset(new DirectYieldCurveSegment());
266 } else if (childName == "Simple") {
267 segment.reset(new SimpleYieldCurveSegment());
268 } else if (childName == "AverageOIS") {
269 segment.reset(new AverageOISYieldCurveSegment());
270 } else if (childName == "TenorBasis") {
271 segment.reset(new TenorBasisYieldCurveSegment());
272 } else if (childName == "CrossCurrency") {
273 segment.reset(new CrossCcyYieldCurveSegment());
274 } else if (childName == "ZeroSpread") {
275 segment.reset(new ZeroSpreadedYieldCurveSegment());
276 } else if (childName == "DiscountRatio") {
277 segment.reset(new DiscountRatioYieldCurveSegment());
278 } else if (childName == "FittedBond") {
279 segment.reset(new FittedBondYieldCurveSegment());
280 } else if (childName == "BondYieldShifted") {
281 segment.reset(new BondYieldShiftedYieldCurveSegment());
282 } else if (childName == "WeightedAverage") {
283 segment.reset(new WeightedAverageYieldCurveSegment());
284 } else if (childName == "YieldPlusDefault") {
285 segment.reset(new YieldPlusDefaultYieldCurveSegment());
286 } else if(childName == "IborFallback"){
287 segment.reset(new IborFallbackCurveSegment());
288 } else {
289 QL_FAIL("Yield curve segment node name '" << childName << "' not recognized.");
290 }
291
292 if (segment) {
293 try {
294 segment->fromXML(child);
295 } catch (std::exception& ex) {
296 QL_FAIL("Exception parsing yield curve segment XML Node, name = "
297 << childName << " and curveID = " << curveID_ << " : " << ex.what());
298 }
299 } else {
300 QL_FAIL("Unable to build yield curve segment for name = " << childName
301 << " and curveID = " << curveID_);
302 }
303 curveSegments_.push_back(segment);
304 }
305 } else {
306 QL_FAIL("No Segments node in XML doc for yield curve ID = " << curveID_);
307 }
308
309 // Read in the optional nodes.
310
311 // Empty strings if not there (or if there and empty).
312 interpolationVariable_ = XMLUtils::getChildValue(node, "InterpolationVariable", false, "Discount");
313 interpolationMethod_ = XMLUtils::getChildValue(node, "InterpolationMethod", false, interpolationVariable_ == "Zero" ? "Linear" : "LogLinear");
314 mixedInterpolationCutoff_ = XMLUtils::getChildValueAsInt(node, "MixedInterpolationCutoff", false, 1);
315 zeroDayCounter_ = XMLUtils::getChildValue(node, "YieldCurveDayCounter", false, "A365");
316 extrapolation_ = XMLUtils::getChildValueAsBool(node, "Extrapolation", false, true);
317
318 // Optional bootstrap configuration
319 if (XMLNode* n = XMLUtils::getChildNode(node, "BootstrapConfig")) {
321 }
322
323 // Tolerance is deprecated in favour of Accuracy in BootstrapConfig. However, if it is
324 // still provided, use it as the accuracy and global accuracy in the bootstrap.
325 if (XMLUtils::getChildNode(node, "Tolerance")) {
326 Real accuracy = XMLUtils::getChildValueAsDouble(node, "Tolerance", false);
330 }
331
333}
334
336 // Allocate a node.
337 XMLNode* node = doc.allocNode("YieldCurve");
338
339 // Add the mandatory members.
340 XMLUtils::addChild(doc, node, "CurveId", curveID_);
341 XMLUtils::addChild(doc, node, "CurveDescription", curveDescription_);
342 XMLUtils::addChild(doc, node, "Currency", currency_);
343 XMLUtils::addChild(doc, node, "DiscountCurve", discountCurveID_);
344
345 // Add the segments node.
346 XMLNode* segmentsNode = doc.allocNode("Segments");
347 XMLUtils::appendNode(node, segmentsNode);
348 for (Size i = 0; i < curveSegments_.size(); ++i) {
349 XMLUtils::appendNode(segmentsNode, curveSegments_[i]->toXML(doc));
350 }
351
352 // Add the defaultable elements.
353 XMLUtils::addChild(doc, node, "InterpolationVariable", interpolationVariable_);
354 XMLUtils::addChild(doc, node, "InterpolationMethod", interpolationMethod_);
355 XMLUtils::addChild(doc, node, "MixedInterpolationCutoff", (int)mixedInterpolationCutoff_);
356 XMLUtils::addChild(doc, node, "YieldCurveDayCounter", zeroDayCounter_);
357 XMLUtils::addChild(doc, node, "Tolerance", bootstrapConfig_.accuracy());
358 XMLUtils::addChild(doc, node, "Extrapolation", extrapolation_);
360
361 return node;
362}
363
365
366 requiredCurveIds_.clear();
367
368 if (curveID_ != discountCurveID_ && !discountCurveID_.empty()) {
370 }
371
372 SegmentIDGetter segmentIDGetter(curveID_, requiredCurveIds_);
373 for (Size i = 0; i < curveSegments_.size(); i++) {
374 curveSegments_[i]->accept(segmentIDGetter);
375 }
376}
377
378YieldCurveSegment::YieldCurveSegment(const string& typeID, const string& conventionsID,
379 const vector<string>& quoteNames)
380 : type_(parseYieldCurveSegment(typeID)), typeID_(typeID), conventionsID_(conventionsID) {
381 for (auto q : quoteNames)
382 quotes_.emplace_back(quote(q));
383}
384
386 typeID_ = XMLUtils::getChildValue(node, "Type", true);
387 string name = XMLUtils::getNodeName(node);
388
389 // Check if curve type is valid for the given segment name
390 std::map<std::string, std::list<std::string>> validSegmentTypes = {
391 {"Direct", {"Zero", "Discount"}},
392 {"Simple", {"Deposit", "FRA", "Future", "OIS", "Swap", "BMA Basis Swap"}},
393 {"AverageOIS", {"Average OIS"}},
394 {"TenorBasis", {"Tenor Basis Swap", "Tenor Basis Two Swaps"}},
395 {"CrossCurrency", {"FX Forward", "Cross Currency Basis Swap", "Cross Currency Fix Float Swap"}},
396 {"ZeroSpread", {"Zero Spread"}},
397 {"FittedBond", {"FittedBond"}},
398 {"YieldPlusDefault", {"Yield Plus Default"}},
399 {"WeightedAverage", {"Weighted Average"}},
400 {"DiscountRatio", {"Discount Ratio"}},
401 {"IborFallback", {"Ibor Fallback"}},
402 {"BondYieldShifted", {"Bond Yield Shifted"}}
403 };
404
405 std::list<std::string> validTypes = validSegmentTypes.at(name);
406 QL_REQUIRE(std::find(validTypes.begin(), validTypes.end(), typeID_) != validTypes.end(),
407 "The curve type " << typeID_ << " is not a valid " << name << " curve segment type");
408
409 quotes_.clear();
410 if (name == "AverageOIS") {
411 XMLNode* quotesNode = XMLUtils::getChildNode(node, "Quotes");
412 if (quotesNode) {
413 for (XMLNode* child = XMLUtils::getChildNode(quotesNode, "CompositeQuote"); child;
414 child = XMLUtils::getNextSibling(child)) {
415 quotes_.push_back(quote(XMLUtils::getChildValue(child, "RateQuote", true)));
416 quotes_.push_back(quote(XMLUtils::getChildValue(child, "SpreadQuote", true)));
417 }
418 } else {
419 QL_FAIL("No Quotes in segment. Remove segment or add quotes.");
420 }
421 } else {
422 XMLNode* quotesNode = XMLUtils::getChildNode(node, "Quotes");
423 if (quotesNode) {
424 for (auto n : XMLUtils::getChildrenNodes(quotesNode, "Quote")) {
425 string attr = XMLUtils::getAttribute(n, "optional"); // return "" if not present
426 bool opt = (!attr.empty() && parseBool(attr));
427 quotes_.emplace_back(quote(XMLUtils::getNodeValue(n), opt));
428 }
429 }
430 }
432 conventionsID_ = XMLUtils::getChildValue(node, "Conventions", false);
433 pillarChoice_ = parsePillarChoice(XMLUtils::getChildValue(node, "PillarChoice", false, "LastRelevantDate"));
434 QL_REQUIRE(pillarChoice_ == QuantLib::Pillar::MaturityDate || pillarChoice_ == QuantLib::Pillar::LastRelevantDate,
435 "PillarChoice " << pillarChoice_ << " not supported, expected MaturityDate, LastRelevantDate");
436 priority_ = XMLUtils::getChildValueAsInt(node, "Priority", false, 0);
437 minDistance_ = XMLUtils::getChildValueAsInt(node, "MinDistance", false, 1);
438}
439
441 XMLNode* node = doc.allocNode("Segment");
442 XMLUtils::addChild(doc, node, "Type", typeID_);
443 if (!quotes_.empty()) {
444 XMLNode* quotesNode = doc.allocNode("Quotes");
445 // Special case handling for AverageOIS where the quotes are stored as pairs
446 // Spread and Rate.
448 QL_REQUIRE(quotes_.size() % 2 == 0, "Invalid quotes vector should be even");
449 for (Size i = 0; i < quotes_.size(); i = i + 2) {
450 string rateQuote = quotes_[i].first;
451 string spreadQuote = quotes_[i + 1].first;
452
453 XMLNode* compositeQuoteNode = doc.allocNode("CompositeQuote");
454 XMLUtils::addChild(doc, compositeQuoteNode, "SpreadQuote", spreadQuote);
455 XMLUtils::addChild(doc, compositeQuoteNode, "RateQuote", rateQuote);
456 XMLUtils::appendNode(quotesNode, compositeQuoteNode);
457 }
458 } else {
459 for (auto q : quotes_) {
460 XMLNode* qNode = doc.allocNode("Quote", q.first);
461 if (q.second)
462 XMLUtils::addAttribute(doc, qNode, "optional", "true");
463 XMLUtils::appendNode(quotesNode, qNode);
464 }
465 }
466 XMLUtils::appendNode(node, quotesNode);
467 }
468
469 if (!conventionsID_.empty())
470 XMLUtils::addChild(doc, node, "Conventions", conventionsID_);
471 XMLUtils::addChild(doc, node, "PillarChoice", ore::data::to_string(pillarChoice_));
472 XMLUtils::addChild(doc, node, "Priority", (int)priority_);
473 XMLUtils::addChild(doc, node, "MinDistance", (int)minDistance_);
474 return node;
475}
476
477void YieldCurveSegment::accept(AcyclicVisitor& v) {
478 Visitor<YieldCurveSegment>* v1 = dynamic_cast<Visitor<YieldCurveSegment>*>(&v);
479 if (v1 != 0)
480 v1->visit(*this);
481 else
482 QL_FAIL("Not a YieldCurveSegment visitor.");
483}
484
485DirectYieldCurveSegment::DirectYieldCurveSegment(const string& typeID, const string& conventionsID,
486 const vector<string>& quotes)
487 : YieldCurveSegment(typeID, conventionsID, quotes) {}
488
490 XMLUtils::checkNode(node, "Direct");
492}
493
496 XMLUtils::setNodeName(doc, node, "Direct");
497 return node;
498}
499
500void DirectYieldCurveSegment::accept(AcyclicVisitor& v) {
501 Visitor<DirectYieldCurveSegment>* v1 = dynamic_cast<Visitor<DirectYieldCurveSegment>*>(&v);
502 if (v1 != 0)
503 v1->visit(*this);
504 else
506}
507
508SimpleYieldCurveSegment::SimpleYieldCurveSegment(const string& typeID, const string& conventionsID,
509 const vector<string>& quotes, const string& projectionCurveID)
510 : YieldCurveSegment(typeID, conventionsID, quotes), projectionCurveID_(projectionCurveID) {}
511
513 XMLUtils::checkNode(node, "Simple");
515 projectionCurveID_ = XMLUtils::getChildValue(node, "ProjectionCurve", false);
516}
517
520 XMLUtils::setNodeName(doc, node, "Simple");
521 if (!projectionCurveID_.empty())
522 XMLUtils::addChild(doc, node, "ProjectionCurve", projectionCurveID_);
523 return node;
524}
525
526void SimpleYieldCurveSegment::accept(AcyclicVisitor& v) {
527 Visitor<SimpleYieldCurveSegment>* v1 = dynamic_cast<Visitor<SimpleYieldCurveSegment>*>(&v);
528 if (v1 != 0)
529 v1->visit(*this);
530 else
532}
533
534AverageOISYieldCurveSegment::AverageOISYieldCurveSegment(const string& typeID, const string& conventionsID,
535 const vector<string>& quotes, const string& projectionCurveID)
536 : YieldCurveSegment(typeID, conventionsID, quotes), projectionCurveID_(projectionCurveID) {}
537
539 XMLUtils::checkNode(node, "AverageOIS");
541 projectionCurveID_ = XMLUtils::getChildValue(node, "ProjectionCurve", false);
542}
543
546 XMLUtils::setNodeName(doc, node, "AverageOIS");
547 if (!projectionCurveID_.empty())
548 XMLUtils::addChild(doc, node, "ProjectionCurve", projectionCurveID_);
549 return node;
550}
551
552void AverageOISYieldCurveSegment::accept(AcyclicVisitor& v) {
553 Visitor<AverageOISYieldCurveSegment>* v1 = dynamic_cast<Visitor<AverageOISYieldCurveSegment>*>(&v);
554 if (v1 != 0)
555 v1->visit(*this);
556 else
558}
559
560TenorBasisYieldCurveSegment::TenorBasisYieldCurveSegment(const string& typeID, const string& conventionsID,
561 const vector<string>& quotes,
562 const string& receiveProjectionCurveID,
563 const string& payProjectionCurveID)
564 : YieldCurveSegment(typeID, conventionsID, quotes), receiveProjectionCurveID_(receiveProjectionCurveID),
565 payProjectionCurveID_(payProjectionCurveID) {}
566
568 XMLUtils::checkNode(node, "TenorBasis");
570 receiveProjectionCurveID_ = XMLUtils::getChildValue(node, "ProjectionCurveReceive", false);
571 payProjectionCurveID_ = XMLUtils::getChildValue(node, "ProjectionCurvePay", false);
572
573 // handle deprecated fields...
574 XMLNode* projectionCurveShort = XMLUtils::getChildNode(node, "ProjectionCurveShort");
575 if (projectionCurveShort) {
576 ALOG("TenorBasisYieldCurveSegment: ProjectionCurveShort is deprecated, fill empty receiveProjectionCurveID");
577 if (receiveProjectionCurveID_.empty())
579 }
580
581 XMLNode* projectionCurveLong = XMLUtils::getChildNode(node, "ProjectionCurveLong");
582 if (projectionCurveLong) {
583 ALOG("TenorBasisYieldCurveSegment: projectionCurveLong is deprecated, fill empty payProjectionCurveID");
584 if (payProjectionCurveID_.empty())
585 payProjectionCurveID_ = XMLUtils::getNodeValue(projectionCurveLong);
586 }
587}
588
591 XMLUtils::setNodeName(doc, node, "TenorBasis");
592 if (!payProjectionCurveID_.empty())
593 XMLUtils::addChild(doc, node, "ProjectionCurvePay", payProjectionCurveID_);
594 if (!receiveProjectionCurveID_.empty())
595 XMLUtils::addChild(doc, node, "ProjectionCurveReceive", receiveProjectionCurveID_);
596 return node;
597}
598
599void TenorBasisYieldCurveSegment::accept(AcyclicVisitor& v) {
600 Visitor<TenorBasisYieldCurveSegment>* v1 = dynamic_cast<Visitor<TenorBasisYieldCurveSegment>*>(&v);
601 if (v1 != 0)
602 v1->visit(*this);
603 else
605}
606
607CrossCcyYieldCurveSegment::CrossCcyYieldCurveSegment(const string& type, const string& conventionsID,
608 const vector<string>& quotes, const string& spotRateID,
609 const string& foreignDiscountCurveID,
610 const string& domesticProjectionCurveID,
611 const string& foreignProjectionCurveID)
612 : YieldCurveSegment(type, conventionsID, quotes), spotRateID_(spotRateID),
613 foreignDiscountCurveID_(foreignDiscountCurveID), domesticProjectionCurveID_(domesticProjectionCurveID),
614 foreignProjectionCurveID_(foreignProjectionCurveID) {}
615
617 XMLUtils::checkNode(node, "CrossCurrency");
619 foreignDiscountCurveID_ = XMLUtils::getChildValue(node, "DiscountCurve", true);
620 spotRateID_ = XMLUtils::getChildValue(node, "SpotRate", true);
621 domesticProjectionCurveID_ = XMLUtils::getChildValue(node, "ProjectionCurveDomestic", false);
622 foreignProjectionCurveID_ = XMLUtils::getChildValue(node, "ProjectionCurveForeign", false);
623}
624
627 XMLUtils::setNodeName(doc, node, "CrossCurrency");
628 XMLUtils::addChild(doc, node, "DiscountCurve", foreignDiscountCurveID_);
629 XMLUtils::addChild(doc, node, "SpotRate", spotRateID_);
630 if (!domesticProjectionCurveID_.empty())
631 XMLUtils::addChild(doc, node, "ProjectionCurveDomestic", domesticProjectionCurveID_);
632 if (!foreignProjectionCurveID_.empty())
633 XMLUtils::addChild(doc, node, "ProjectionCurveForeign", foreignProjectionCurveID_);
634 return node;
635}
636
637void CrossCcyYieldCurveSegment::accept(AcyclicVisitor& v) {
638 Visitor<CrossCcyYieldCurveSegment>* v1 = dynamic_cast<Visitor<CrossCcyYieldCurveSegment>*>(&v);
639 if (v1 != 0)
640 v1->visit(*this);
641 else
643}
644
645ZeroSpreadedYieldCurveSegment::ZeroSpreadedYieldCurveSegment(const string& typeID, const string& conventionsID,
646 const vector<string>& quotes,
647 const string& referenceCurveID)
648 : YieldCurveSegment(typeID, conventionsID, quotes), referenceCurveID_(referenceCurveID) {}
649
651 XMLUtils::checkNode(node, "ZeroSpread");
653 referenceCurveID_ = XMLUtils::getChildValue(node, "ReferenceCurve", false);
654}
655
658 XMLUtils::setNodeName(doc, node, "ZeroSpread");
659 XMLUtils::addChild(doc, node, "ReferenceCurve", referenceCurveID_);
660 return node;
661}
662
664 Visitor<ZeroSpreadedYieldCurveSegment>* v1 = dynamic_cast<Visitor<ZeroSpreadedYieldCurveSegment>*>(&v);
665 if (v1 != 0)
666 v1->visit(*this);
667 else
669}
670
672 const string& typeId, const string& baseCurveId, const string& baseCurveCurrency, const string& numeratorCurveId,
673 const string& numeratorCurveCurrency, const string& denominatorCurveId, const string& denominatorCurveCurrency)
674 : YieldCurveSegment(typeId, "", vector<string>()), baseCurveId_(baseCurveId), baseCurveCurrency_(baseCurveCurrency),
675 numeratorCurveId_(numeratorCurveId), numeratorCurveCurrency_(numeratorCurveCurrency),
676 denominatorCurveId_(denominatorCurveId), denominatorCurveCurrency_(denominatorCurveCurrency) {}
677
679 XMLUtils::checkNode(node, "DiscountRatio");
681
682 XMLNode* aNode = XMLUtils::getChildNode(node, "BaseCurve");
683 QL_REQUIRE(aNode, "Discount ratio segment needs a BaseCurve node");
685 baseCurveCurrency_ = XMLUtils::getAttribute(aNode, "currency");
686
687 aNode = XMLUtils::getChildNode(node, "NumeratorCurve");
688 QL_REQUIRE(aNode, "Discount ratio segment needs a NumeratorCurve node");
691
692 aNode = XMLUtils::getChildNode(node, "DenominatorCurve");
693 QL_REQUIRE(aNode, "Discount ratio segment needs a DenominatorCurve node");
696}
697
700 XMLUtils::setNodeName(doc, node, "DiscountRatio");
701
702 XMLNode* baseCurveNode = doc.allocNode("BaseCurve", baseCurveId_);
703 XMLUtils::appendNode(node, baseCurveNode);
704 XMLUtils::addAttribute(doc, baseCurveNode, "currency", baseCurveCurrency_);
705
706 XMLNode* numCurveNode = doc.allocNode("NumeratorCurve", numeratorCurveId_);
707 XMLUtils::appendNode(node, numCurveNode);
708 XMLUtils::addAttribute(doc, numCurveNode, "currency", numeratorCurveCurrency_);
709
710 XMLNode* denCurveNode = doc.allocNode("DenominatorCurve", denominatorCurveId_);
711 XMLUtils::appendNode(node, denCurveNode);
712 XMLUtils::addAttribute(doc, denCurveNode, "currency", denominatorCurveCurrency_);
713
714 return node;
715}
716
718 if (Visitor<DiscountRatioYieldCurveSegment>* v1 = dynamic_cast<Visitor<DiscountRatioYieldCurveSegment>*>(&v))
719 v1->visit(*this);
720 else
722}
723
724FittedBondYieldCurveSegment::FittedBondYieldCurveSegment(const string& typeID, const vector<string>& quotes,
725 const map<string, string>& iborIndexCurves,
726 const bool extrapolateFlat)
727 : YieldCurveSegment(typeID, "", quotes), iborIndexCurves_(iborIndexCurves), extrapolateFlat_(extrapolateFlat) {}
728
730 XMLUtils::checkNode(node, "FittedBond");
732
733 vector<string> iborIndexNames;
735 node, "IborIndexCurves", "IborIndexCurve", "iborIndex", iborIndexNames, false);
736 for (Size i = 0; i < iborIndexNames.size(); ++i) {
737 iborIndexCurves_[iborIndexNames[i]] = iborIndexCurves[i];
738 }
739
740 if (auto n = XMLUtils::getChildNode(node, "ExtrapolateFlat")) {
742 } else {
743 extrapolateFlat_ = false;
744 }
745}
746
749 XMLUtils::setNodeName(doc, node, "FittedBond");
750
751 vector<string> iborIndexNames;
752 vector<string> iborIndexCurves;
753 for (auto const& c : iborIndexCurves_) {
754 iborIndexNames.push_back(c.first);
755 iborIndexCurves.push_back(c.second);
756 }
757 XMLUtils::addChildrenWithAttributes(doc, node, "IborIndexCurves", "IborIndexCurve", iborIndexCurves, "iborIndex",
758 iborIndexNames);
759
760 XMLUtils::addChild(doc, node, "ExtrapolateFlat", extrapolateFlat_);
761 return node;
762}
763
764void FittedBondYieldCurveSegment::accept(AcyclicVisitor& v) {
765 Visitor<FittedBondYieldCurveSegment>* v1 = dynamic_cast<Visitor<FittedBondYieldCurveSegment>*>(&v);
766 if (v1 != 0)
767 v1->visit(*this);
768 else
770}
771
773 const string& referenceCurveID1,
774 const string& referenceCurveID2, const Real weight1,
775 const Real weight2)
776 : YieldCurveSegment(typeID, "", {}), referenceCurveID1_(referenceCurveID1), referenceCurveID2_(referenceCurveID2),
777 weight1_(weight1), weight2_(weight2) {}
778
780 XMLUtils::checkNode(node, "WeightedAverage");
782 referenceCurveID1_ = XMLUtils::getChildValue(node, "ReferenceCurve1", true);
783 referenceCurveID2_ = XMLUtils::getChildValue(node, "ReferenceCurve2", true);
784 weight1_ = XMLUtils::getChildValueAsDouble(node, "Weight1", true);
785 weight2_ = XMLUtils::getChildValueAsDouble(node, "Weight2", true);
786}
787
790 XMLUtils::setNodeName(doc, node, "WeightedAverage");
791 XMLUtils::addChild(doc, node, "ReferenceCurve1", referenceCurveID1_);
792 XMLUtils::addChild(doc, node, "ReferenceCurve2", referenceCurveID2_);
793 XMLUtils::addChild(doc, node, "Weight1", weight1_);
794 XMLUtils::addChild(doc, node, "Weight2", weight2_);
795 return node;
796}
797
799 Visitor<WeightedAverageYieldCurveSegment>* v1 = dynamic_cast<Visitor<WeightedAverageYieldCurveSegment>*>(&v);
800 if (v1 != 0)
801 v1->visit(*this);
802 else
804}
805
807 const string& referenceCurveID,
808 const std::vector<std::string>& defaultCurveIDs,
809 const std::vector<Real>& weights)
810 : YieldCurveSegment(typeID, "", {}), referenceCurveID_(referenceCurveID), defaultCurveIDs_(defaultCurveIDs),
811 weights_(weights) {}
812
814 XMLUtils::checkNode(node, "YieldPlusDefault");
816 referenceCurveID_ = XMLUtils::getChildValue(node, "ReferenceCurve", true);
817 defaultCurveIDs_ = XMLUtils::getChildrenValues(node, "DefaultCurves", "DefaultCurve", true);
818 weights_ = XMLUtils::getChildrenValuesAsDoubles(node, "Weights", "Weight", true);
819}
820
823 XMLUtils::setNodeName(doc, node, "YieldPlusDefault");
824 XMLUtils::addChild(doc, node, "ReferenceCurve", referenceCurveID_);
825 XMLUtils::addChildren(doc, node, "DefaultCurves", "DefaultCurve", defaultCurveIDs_);
826 XMLUtils::addChildren(doc, node, "Weights", "Weight", weights_);
827 return node;
828}
829
831 Visitor<YieldPlusDefaultYieldCurveSegment>* v1 = dynamic_cast<Visitor<YieldPlusDefaultYieldCurveSegment>*>(&v);
832 if (v1 != 0)
833 v1->visit(*this);
834 else
836}
837
838IborFallbackCurveSegment::IborFallbackCurveSegment(const string& typeID, const string& iborIndex,
839 const string& rfrCurve, const boost::optional<string>& rfrIndex,
840 const boost::optional<Real>& spread)
841 : YieldCurveSegment(typeID, "", {}), iborIndex_(iborIndex), rfrCurve_(rfrCurve), rfrIndex_(rfrIndex),
842 spread_(spread) {}
843
845 XMLUtils::checkNode(node, "IborFallback");
847 iborIndex_ = XMLUtils::getChildValue(node, "IborIndex", true);
848 rfrCurve_ = XMLUtils::getChildValue(node, "RfrCurve", true);
849 rfrIndex_ = boost::none;
850 spread_ = boost::none;
851 if (auto n = XMLUtils::getChildNode(node, "RfrIndex"))
853 if (auto n = XMLUtils::getChildNode(node, "Spread"))
855}
856
859 XMLUtils::setNodeName(doc, node, "IborFallback");
860 XMLUtils::addChild(doc, node, "IborIndex", iborIndex_);
861 XMLUtils::addChild(doc, node, "RfrCurve", rfrCurve_);
862 if (rfrIndex_)
863 XMLUtils::addChild(doc, node, "RfrIndex", *rfrIndex_);
864 if (spread_)
865 XMLUtils::addChild(doc, node, "Spread", *spread_);
866 return node;
867}
868
869void IborFallbackCurveSegment::accept(AcyclicVisitor& v) {
870 Visitor<IborFallbackCurveSegment>* v1 = dynamic_cast<Visitor<IborFallbackCurveSegment>*>(&v);
871 if (v1 != 0)
872 v1->visit(*this);
873 else
875}
876
877BondYieldShiftedYieldCurveSegment::BondYieldShiftedYieldCurveSegment(const string& typeID, const string& referenceCurveID, const vector<string>& quotes,
878 const map<string, string>& iborIndexCurves, const bool extrapolateFlat)
879 : YieldCurveSegment(typeID, "", quotes), referenceCurveID_(referenceCurveID), iborIndexCurves_(iborIndexCurves),
880 extrapolateFlat_(extrapolateFlat) {}
881
883 XMLUtils::checkNode(node, "BondYieldShifted");
885
886 referenceCurveID_ = XMLUtils::getChildValue(node, "ReferenceCurve", true);
887
888 vector<string> iborIndexNames;
890 node, "IborIndexCurves", "IborIndexCurve", "iborIndex", iborIndexNames, false);
891 for (Size i = 0; i < iborIndexNames.size(); ++i) {
892 iborIndexCurves_[iborIndexNames[i]] = iborIndexCurves[i];
893 }
894
895 if (auto n = XMLUtils::getChildNode(node, "ExtrapolateFlat")) {
897 } else {
898 extrapolateFlat_ = false;
899 }
900}
901
904 XMLUtils::setNodeName(doc, node, "BondYieldShifted");
905 XMLUtils::addChild(doc, node, "ReferenceCurve", referenceCurveID_);
906 return node;
907}
908
910 Visitor<BondYieldShiftedYieldCurveSegment>* v1 = dynamic_cast<Visitor<BondYieldShiftedYieldCurveSegment>*>(&v);
911 if (v1 != 0)
912 v1->visit(*this);
913 else
915}
916
917
918} // namespace data
919} // namespace ore
Average OIS yield curve segment.
AverageOISYieldCurveSegment()
Default constructor.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Bond yield shifted yield curve segment.
const map< string, string > & iborIndexCurves() const
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
QuantLib::Real maxFactor() const
QuantLib::Real accuracy() const
void fromXML(ore::data::XMLNode *node) override
QuantLib::Real minFactor() const
ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
QuantLib::Size maxAttempts() const
Cross Currency yield curve segment.
CrossCcyYieldCurveSegment()
Default constructor.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Base curve configuration.
Definition: curveconfig.hpp:41
vector< string > quotes_
Definition: curveconfig.hpp:74
map< CurveSpec::CurveType, set< string > > requiredCurveIds_
Definition: curveconfig.hpp:75
CurveType
Supported curve types.
Definition: curvespec.hpp:43
Direct yield curve segment.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
DirectYieldCurveSegment()
Default constructor.
Discount ratio yield curve segment.
void accept(QuantLib::AcyclicVisitor &v) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
FittedBond yield curve segment.
FittedBondYieldCurveSegment()
Default constructor.
const map< string, string > & iborIndexCurves() const
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Ibor Fallback yield curve segment.
boost::optional< string > rfrIndex_
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
IborFallbackCurveSegment()
Default constructor.
Simple yield curve segment.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
SimpleYieldCurveSegment()
Default constructor.
Tenor Basis yield curve segment.
TenorBasisYieldCurveSegment()
Default constructor.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Weighted average yield curve segment.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual 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
XML Utilities Class.
Definition: xmlutils.hpp:119
static void addChildrenWithAttributes(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values, const string &attrName, const vector< string > &attrs)
Definition: xmlutils.cpp:510
static void addAttribute(XMLDocument &doc, XMLNode *node, const string &attrName, const string &attrValue)
Definition: xmlutils.cpp:412
static vector< Real > getChildrenValuesAsDoubles(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:319
static void addChildren(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values)
Definition: xmlutils.cpp:502
static string getAttribute(XMLNode *node, const string &attrName)
Definition: xmlutils.cpp:419
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 Real getChildValueAsDouble(XMLNode *node, const string &name, bool mandatory=false, double defaultValue=0.0)
Definition: xmlutils.cpp:286
static string getNodeName(XMLNode *n)
Get and set a node's name.
Definition: xmlutils.cpp:473
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
static bool getChildValueAsBool(XMLNode *node, const string &name, bool mandatory=false, bool defaultValue=true)
Definition: xmlutils.cpp:296
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 int getChildValueAsInt(XMLNode *node, const string &name, bool mandatory=false, int defaultValue=0)
Definition: xmlutils.cpp:291
static XMLNode * getNextSibling(XMLNode *node, const string &name="")
Get a node's next sibling node.
Definition: xmlutils.cpp:484
static vector< string > getChildrenValuesWithAttributes(XMLNode *node, const string &names, const string &name, const string &attrName, vector< string > &attrs, bool mandatory=false)
Definition: xmlutils.cpp:563
static vector< string > getChildrenValues(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:306
static void setNodeName(XMLDocument &doc, XMLNode *node, const string &name)
Definition: xmlutils.cpp:478
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
YieldCurveConfig()
Default constructor.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const vector< string > & quotes() override
Return all the market quotes required for this config.
vector< QuantLib::ext::shared_ptr< YieldCurveSegment > > curveSegments_
Base class for yield curve segments.
QuantLib::Pillar::Choice pillarChoice_
Type
supported segment types
virtual void accept(AcyclicVisitor &)
vector< pair< string, bool > > quotes_
Quote and optional flag pair.
YieldCurveSegment()
Default constructor.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
pair< string, bool > quote(const string &name, bool opt=false)
Utility to build a quote, optional flag defaults to false.
Yield plus default curves segment.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Zero Spreaded yield curve segment.
virtual void accept(AcyclicVisitor &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Curve requirements specification.
CurveSpec parser.
QuantLib::ext::shared_ptr< CurveSpec > parseCurveSpec(const string &s)
function to convert a string into a curve spec
QuantLib::Pillar::Choice parsePillarChoice(const std::string &s)
Convert text to QuantLib::Pillar::Choice.
Definition: parsers.cpp:1403
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
SimpleQuote & spread_
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
Market Datum parser.
YieldCurveSegment::Type parseYieldCurveSegment(const string &s)
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
string name
Yield curve configuration classes.