Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
formulabasedlegdata.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2018 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
20
25
27#include <qle/cashflows/formulabasedcoupon.hpp>
29
34
35#include <ql/cashflows/capflooredcoupon.hpp>
36#include <ql/cashflows/cashflowvectors.hpp>
37#include <ql/cashflows/cmscoupon.hpp>
38#include <ql/cashflows/cpicoupon.hpp>
39#include <ql/cashflows/fixedratecoupon.hpp>
40#include <ql/cashflows/iborcoupon.hpp>
41#include <ql/cashflows/overnightindexedcoupon.hpp>
42#include <ql/cashflows/simplecashflow.hpp>
43#include <ql/cashflows/yoyinflationcoupon.hpp>
44#include <ql/experimental/coupons/strippedcapflooredcoupon.hpp>
45
46#include <boost/make_shared.hpp>
47
48namespace ore {
49namespace data {
50
52 XMLNode* node = doc.allocNode(legNodeName());
53 XMLUtils::addChild(doc, node, "Index", formulaBasedIndex_);
54 XMLUtils::addChild(doc, node, "IsInArrears", isInArrears_);
55 XMLUtils::addChild(doc, node, "FixingDays", fixingDays_);
56 XMLUtils::addChild(doc, node, "FixingCalendar", fixingCalendar_);
57 return node;
58}
59
62 formulaBasedIndex_ = XMLUtils::getChildValue(node, "Index", true);
63 fixingDays_ = XMLUtils::getChildValueAsInt(node, "FixingDays", true);
64 // These are all optional
65 XMLNode* arrNode = XMLUtils::getChildNode(node, "IsInArrears");
66 if (arrNode)
67 isInArrears_ = XMLUtils::getChildValueAsBool(node, "IsInArrears", true);
68 else
69 isInArrears_ = false; // default to fixing-in-advance
70 fixingCalendar_ = XMLUtils::getChildValue(node, "FixingCalendar"); // defaults to empty string
72}
73
75 std::vector<std::string> variables;
76 QuantExt::CompiledFormula compiledFormula = parseFormula(formulaBasedIndex_, variables);
77 indices_.insert(variables.begin(), variables.end());
78}
79
80namespace {
81QuantLib::ext::shared_ptr<QuantLib::FloatingRateCouponPricer>
82getFormulaBasedCouponPricer(const QuantLib::ext::shared_ptr<QuantExt::FormulaBasedIndex>& formulaBasedIndex,
83 const Currency& paymentCurrency, const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory,
84 const std::map<std::string, QuantLib::ext::shared_ptr<QuantLib::InterestRateIndex>>& indexMaps) {
85 auto builder =
86 QuantLib::ext::dynamic_pointer_cast<FormulaBasedCouponPricerBuilder>(engineFactory->builder("FormulaBasedCoupon"));
87 QL_REQUIRE(builder != nullptr, "makeFormulaBasedLeg(): no builder found for FormulaBasedCoupon");
88
89 std::map<std::string, QuantLib::ext::shared_ptr<IborCouponPricer>> iborPricers;
90 std::map<std::string, QuantLib::ext::shared_ptr<CmsCouponPricer>> cmsPricers;
91 for (auto const& i : formulaBasedIndex->indices()) {
92 // add ibor pricer for index
93 if (auto ibor = QuantLib::ext::dynamic_pointer_cast<QuantLib::IborIndex>(i)) {
94 auto iborBuilder = QuantLib::ext::dynamic_pointer_cast<CapFlooredIborLegEngineBuilder>(
95 engineFactory->builder("CapFlooredIborLeg"));
96 QL_REQUIRE(iborBuilder != nullptr, "makeFormulaBasedLeg(): No builder found for CapFlooredIborLeg");
97 auto pricerKey = IndexNameTranslator::instance().oreName(ibor->name());
98 auto iborPricer = QuantLib::ext::dynamic_pointer_cast<IborCouponPricer>(iborBuilder->engine(pricerKey));
99 QL_REQUIRE(iborPricer != nullptr, "makeFormulaBasedLeg(): expected ibor coupon pricer");
100 iborPricers[i->name()] = iborPricer;
101 }
102 // add cms pricer for index
103 if (auto cms = QuantLib::ext::dynamic_pointer_cast<QuantLib::SwapIndex>(i)) {
104 auto cmsBuilder = QuantLib::ext::dynamic_pointer_cast<CmsCouponPricerBuilder>(engineFactory->builder("CMS"));
105 QL_REQUIRE(cmsBuilder, "makeFormulaBasedLeg(): No builder found for CmsLeg");
106 auto pricerKey = IndexNameTranslator::instance().oreName(cms->iborIndex()->name());
107 auto cmsPricer = QuantLib::ext::dynamic_pointer_cast<CmsCouponPricer>(cmsBuilder->engine(pricerKey));
108 QL_REQUIRE(cmsPricer != nullptr, "makeFormulaBasedLeg(): expected cms coupon pricer");
109 cmsPricers[cms->iborIndex()->name()] = cmsPricer;
110 }
111 }
112
113 return builder->engine(paymentCurrency.code(), iborPricers, cmsPricers, indexMaps);
114}
115} // namespace
116
117Leg makeFormulaBasedLeg(const LegData& data, const QuantLib::ext::shared_ptr<QuantExt::FormulaBasedIndex>& formulaBasedIndex,
118 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory,
119 const std::map<std::string, QuantLib::ext::shared_ptr<QuantLib::InterestRateIndex>>& indexMaps,
120 const QuantLib::Date& openEndDateReplacement) {
121 auto formulaBasedData = QuantLib::ext::dynamic_pointer_cast<FormulaBasedLegData>(data.concreteLegData());
122 QL_REQUIRE(formulaBasedData, "Wrong LegType, expected FormulaBased, got " << data.legType());
123 Currency paymentCurrency = parseCurrency(data.currency());
124 Schedule schedule = makeSchedule(data.schedule(), openEndDateReplacement);
125 if (schedule.size() < 2)
126 return Leg();
127 Calendar paymentCalendar;
128 if (data.paymentCalendar().empty())
129 paymentCalendar = schedule.calendar();
130 else
131 paymentCalendar = parseCalendar(data.paymentCalendar());
132 PaymentLag paymentLag = parsePaymentLag(data.paymentLag());
133 // day counter is optional in leg data in general, but here we need it
134 QL_REQUIRE(data.dayCounter() != "", "makeFormulaBasedLeg(): day counter must be given");
135 DayCounter dc = parseDayCounter(data.dayCounter());
136 // bdc is optional too, but all the other legs just do this, too ?!
137 // FIXME, to be solved for all leg types, here we do as in the other legs
138 BusinessDayConvention bdc = parseBusinessDayConvention(data.paymentConvention());
139 auto formulaBasedLegData = QuantLib::ext::dynamic_pointer_cast<FormulaBasedLegData>(data.concreteLegData());
140 vector<double> notionals = buildScheduledVector(data.notionals(), data.notionalDates(), schedule);
141
142 ore::data::applyAmortization(notionals, data, schedule);
143 // amortization type annuity is not allowed, check this
144 for (auto const& amort : data.amortizationData()) {
145 if (!amort.initialized())
146 continue;
147 AmortizationType amortizationType = parseAmortizationType(amort.type());
148 QL_REQUIRE(amortizationType != AmortizationType::Annuity,
149 "AmortizationType " << amort.type() << " not supported for Formula based legs");
150 }
151
152 QuantExt::FormulaBasedLeg formulaBasedLeg =
153 QuantExt::FormulaBasedLeg(paymentCurrency, schedule, formulaBasedIndex)
154 .withNotionals(notionals)
155 .withPaymentCalendar(paymentCalendar)
156 .withPaymentLag(boost::apply_visitor(PaymentLagInteger(), paymentLag))
157 .withPaymentDayCounter(dc)
158 .withPaymentAdjustment(bdc)
159 .withFixingDays(formulaBasedData->fixingDays())
160 .inArrears(formulaBasedData->isInArrears());
161
162 auto couponPricer = getFormulaBasedCouponPricer(formulaBasedIndex, paymentCurrency, engineFactory, indexMaps);
163
164 // make sure leg is built before pricers are set...
165 Leg tmp = formulaBasedLeg;
166 QuantExt::setCouponPricer(tmp, couponPricer);
167 return tmp;
168}
169
170} // namespace data
171} // namespace ore
builder that returns an engine to price capped floored ibor legs
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
std::set< std::string > indices_
Definition: legdata.hpp:77
const string & legNodeName() const
Definition: legdata.hpp:70
Serializable object holding leg data.
Definition: legdata.hpp:844
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 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 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 int getChildValueAsInt(XMLNode *node, const string &name, bool mandatory=false, int defaultValue=0)
Definition: xmlutils.cpp:291
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
builder that returns an engine to price capped floored ibor legs
formula based index builder
leg data for formula based leg types
generic formula parser
void setCouponPricer(const Leg &leg, const boost::shared_ptr< FloatingRateCouponPricer > &)
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Definition: parsers.cpp:173
PaymentLag parsePaymentLag(const string &s)
Convert text to PaymentLag.
Definition: parsers.cpp:628
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Definition: parsers.cpp:209
translates between QuantLib::Index::name() and ORE names
leg data model and serialization
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
QuantExt::CompiledFormula parseFormula(const std::string &text, std::vector< std::string > &variables)
void applyAmortization(std::vector< Real > &notionals, const LegData &data, const Schedule &schedule, const bool annuityAllowed, const std::vector< Real > &rates)
Definition: legdata.cpp:2593
vector< T > buildScheduledVector(const vector< T > &values, const vector< string > &dates, const Schedule &schedule, const bool checkAllValuesAppearInResult=false)
Definition: legdata.hpp:1061
AmortizationType parseAmortizationType(const std::string &s)
Definition: parsers.cpp:651
boost::variant< QuantLib::Period, QuantLib::Natural > PaymentLag
Definition: types.hpp:32
Leg makeFormulaBasedLeg(const LegData &data, const QuantLib::ext::shared_ptr< QuantExt::FormulaBasedIndex > &formulaBasedIndex, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const std::map< std::string, QuantLib::ext::shared_ptr< QuantLib::InterestRateIndex > > &indexMaps, const QuantLib::Date &openEndDateReplacement)
Schedule makeSchedule(const ScheduleDates &data)
Definition: schedule.cpp:263
AmortizationType
Definition: parsers.hpp:346
Serializable Credit Default Swap.
Definition: namespaces.docs:23