21#include <qle/instruments/flexiswap.hpp>
28#include <ql/cashflows/fixedratecoupon.hpp>
29#include <ql/cashflows/floatingratecoupon.hpp>
38 LOG(
"FlexiSwap::build() for id \"" <<
id() <<
"\" called.");
46 QL_REQUIRE(
swap_.size() == 2,
"swap must have 2 legs");
47 QL_REQUIRE(
swap_[0].currency() ==
swap_[1].currency(),
"swap must be single currency");
49 string ccy_str =
swap_[0].currency();
52 Size fixedLegIndex, floatingLegIndex;
53 if (
swap_[0].legType() ==
"Floating" &&
swap_[1].legType() ==
"Fixed") {
56 }
else if (
swap_[1].legType() ==
"Floating" &&
swap_[0].legType() ==
"Fixed") {
60 QL_FAIL(
"Invalid leg types " <<
swap_[0].legType() <<
" + " <<
swap_[1].legType());
63 QuantLib::ext::shared_ptr<FixedLegData> fixedLegData =
64 QuantLib::ext::dynamic_pointer_cast<FixedLegData>(
swap_[fixedLegIndex].concreteLegData());
65 QuantLib::ext::shared_ptr<FloatingLegData> floatingLegData =
66 QuantLib::ext::dynamic_pointer_cast<FloatingLegData>(
swap_[floatingLegIndex].concreteLegData());
68 QL_REQUIRE(fixedLegData !=
nullptr,
"expected fixed leg data");
69 QL_REQUIRE(floatingLegData !=
nullptr,
"expected floating leg data");
71 QuantLib::ext::shared_ptr<EngineBuilder> tmp = engineFactory->builder(
"FlexiSwap");
72 auto builder = QuantLib::ext::dynamic_pointer_cast<FlexiSwapBGSEngineBuilderBase>(tmp);
73 QL_REQUIRE(builder,
"No Flexi-Swap Builder found for \"" <<
id() <<
"\"");
78 swap_[fixedLegIndex].notionals(),
swap_[fixedLegIndex].notionalDates(), fixedSchedule, 0.0);
80 swap_[floatingLegIndex].notionals(),
swap_[floatingLegIndex].notionalDates(), floatingSchedule, 0.0);
81 vector<Real> fixedRate =
84 floatingSchedule, 0.0);
86 floatingSchedule, 1.0);
88 floatingSchedule, (Real)Null<Real>());
90 floatingSchedule, (Real)Null<Real>());
93 Handle<IborIndex> index =
97 VanillaSwap::Type type =
swap_[fixedLegIndex].isPayer() ? VanillaSwap::Payer : VanillaSwap::Receiver;
100 std::vector<bool> notionalCanBeDecreased(fixedNominal.size(),
true);
105 "can not have lower notional bounds and exercise dates / types / values specified at the same time");
112 DLOG(
"optionality is given by lower notional bounds");
122 DLOG(
"optionality is given by exercise dates, types, values");
128 notionalCanBeDecreased = std::vector<bool>(fixedNominal.size(),
false);
131 Date previousExerciseDate = Null<Date>();
135 "exercise value #" << i <<
" (" <<
exerciseValues_[i] <<
") must be non-negative");
136 QL_REQUIRE(i == 0 || previousExerciseDate < d,
"exercise dates must be strictly increasing, got "
137 << QuantLib::io::iso_date(previousExerciseDate)
138 <<
" and " << QuantLib::io::iso_date(d) <<
" as #" << i
139 <<
" and #" << i + 1);
140 previousExerciseDate = d;
142 Size exerciseIdx = std::lower_bound(fixedSchedule.dates().begin(), fixedSchedule.dates().end(), d) -
143 fixedSchedule.dates().begin();
144 if (exerciseIdx >= fixedSchedule.dates().size() - 1) {
145 DLOG(
"exercise date "
146 << QuantLib::io::iso_date(d)
147 <<
" ignored since there is no whole fixed leg period with accrual start >= exercise date");
150 notionalCanBeDecreased[exerciseIdx] =
true;
165 <<
"' unknown, expected ReductionUpToLowerBound, ReductionByAbsoluteAmount, "
166 "ReductionUpToAbsoluteAmount");
171 DLOG(
"fixedPeriod#,notional,lowerNotionalBound,canBeReduced");
174 << notionalCanBeDecreased[i]);
181 auto flexiSwap = QuantLib::ext::make_shared<QuantExt::FlexiSwap>(
182 type, fixedNominal, floatNominal, fixedSchedule, fixedRate, fixedDayCounter, floatingSchedule, *index, gearings,
186 auto fixLeg = flexiSwap->leg(0);
187 auto fltLeg = flexiSwap->leg(1);
191 bool hasCapsFloors =
false;
192 for (
auto const& k : caps) {
193 if (k != Null<Real>())
194 hasCapsFloors =
true;
196 for (
auto const& k : floors) {
197 if (k != Null<Real>())
198 hasCapsFloors =
true;
201 QuantLib::ext::shared_ptr<EngineBuilder> cfBuilder = engineFactory->builder(
"CapFlooredIborLeg");
202 QL_REQUIRE(cfBuilder,
"No builder found for CapFlooredIborLeg");
203 QuantLib::ext::shared_ptr<CapFlooredIborLegEngineBuilder> cappedFlooredIborBuilder =
204 QuantLib::ext::dynamic_pointer_cast<CapFlooredIborLegEngineBuilder>(cfBuilder);
205 QL_REQUIRE(cappedFlooredIborBuilder !=
nullptr,
"expected CapFlooredIborLegEngineBuilder");
206 QuantLib::ext::shared_ptr<FloatingRateCouponPricer> couponPricer =
207 cappedFlooredIborBuilder->engine(IndexNameTranslator::instance().oreName(index->name()));
208 QuantLib::setCouponPricer(fltLeg, couponPricer);
212 std::vector<Date> expiryDates;
214 Date today = Settings::instance().evaluationDate();
215 Size legRatio = fltLeg.size() / fixLeg.size();
216 for (Size i = 0; i < fltLeg.size(); ++i) {
217 auto fltcpn = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(fltLeg[i]);
218 if (fltcpn !=
nullptr && fltcpn->fixingDate() > today && i % legRatio == 0) {
219 expiryDates.push_back(fltcpn->fixingDate());
220 auto fixcpn = QuantLib::ext::dynamic_pointer_cast<FixedRateCoupon>(fixLeg[i / legRatio]);
221 QL_REQUIRE(fixcpn !=
nullptr,
"FlexiSwap Builder: expected fixed rate coupon");
222 strikes.push_back(fixcpn->rate() - fltcpn->spread());
228 flexiSwap->setPricingEngine(
229 builder->engine(
id(),
"", index.empty() ? ccy_str : IndexNameTranslator::instance().oreName(index->name()),
230 expiryDates, flexiSwap->maturityDate(),
strikes));
234 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(flexiSwap);
240 legs_ = {fixLeg, fltLeg};
249 QL_REQUIRE(swapNode,
"FlexiSwap::fromXML(): FlexiSwapData not found");
266 for (
auto const n : prepayOptionNodes) {
278 for (Size i = 0; i < nodes.size(); i++) {
317 for (Size i = 0; i <
swap_.size(); i++)
builder that returns an engine to price capped floored ibor legs
std::vector< double > lowerNotionalBounds_
std::vector< std::string > lowerNotionalBoundsDates_
std::string noticePeriod_
std::vector< double > exerciseValues_
std::vector< ore::data::LegData > swap_
virtual void fromXML(ore::data::XMLNode *node) override
std::string floatingIndex_
Store the name of the floating leg index.
std::string optionLongShort_
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::vector< std::string > exerciseDates_
std::string noticeConvention_
const std::vector< double > & lowerNotionalBounds() const
void build(const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &) override
std::string noticeCalendar_
const std::string & optionLongShort() const
std::vector< std::string > exerciseTypes_
Serializable object holding leg data.
virtual void fromXML(XMLNode *node) override
std::vector< bool > legPayers_
std::vector< string > legCurrencies_
std::vector< QuantLib::Leg > legs_
virtual void fromXML(XMLNode *node) override
void setSensitivityTemplate(const EngineBuilder &builder)
virtual XMLNode * toXML(XMLDocument &doc) const override
RequiredFixings requiredFixings_
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
std::map< std::string, boost::any > additionalData_
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static void addChildrenWithOptionalAttributes(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values, const string &attrName, const vector< string > &attrs)
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
Logic for calculating required fixing dates on legs.
Flexi-Swap data model and serialization.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Real parseReal(const string &s)
Convert text to Real.
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
translates between QuantLib::Index::name() and ORE names
Classes and functions for log message handling.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
vector< T > buildScheduledVectorNormalised(const vector< T > &values, const vector< string > &dates, const Schedule &schedule, const T &defaultValue, const bool checkAllValuesAppearInResult=false)
Real currentNotional(const Leg &leg)
void addToRequiredFixings(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< FixingDateGetter > &fixingDateGetter)
Schedule makeSchedule(const ScheduleDates &data)
Serializable Credit Default Swap.