21#include <qle/instruments/balanceguaranteedswap.hpp>
28#include <ql/cashflows/fixedratecoupon.hpp>
29#include <ql/cashflows/floatingratecoupon.hpp>
41 notionals_ = XMLUtils::getChildrenValuesWithAttributes<Real>(node,
"Notionals",
"Notional",
"startDate",
56 LOG(
"BalanceGuaranteedSwap::build() for id \"" <<
id() <<
"\" called.");
66 std::vector<BGSTrancheData> sortedTranches(
tranches());
67 std::sort(sortedTranches.begin(), sortedTranches.end(),
69 std::vector<std::vector<Real>> trancheNotionals;
70 Size referencedTranche = Null<Size>(), counter = 0;
71 for (
auto const& t : sortedTranches) {
73 QL_REQUIRE(referencedTranche == Null<Size>(),
75 referencedTranche = counter;
80 QL_REQUIRE(referencedTranche != Null<Size>(),
"referenced tranche not found");
82 QL_REQUIRE(
swap_.size() == 2,
"swap must have 2 legs");
83 QL_REQUIRE(
swap_[0].currency() ==
swap_[1].currency(),
"swap must be single currency");
85 string ccy_str =
swap_[0].currency();
88 Size fixedLegIndex, floatingLegIndex;
89 if (
swap_[0].legType() ==
"Floating" &&
swap_[1].legType() ==
"Fixed") {
92 }
else if (
swap_[1].legType() ==
"Floating" &&
swap_[0].legType() ==
"Fixed") {
96 QL_FAIL(
"Invalid leg types " <<
swap_[0].legType() <<
" + " <<
swap_[1].legType());
99 QuantLib::ext::shared_ptr<FixedLegData> fixedLegData =
100 QuantLib::ext::dynamic_pointer_cast<FixedLegData>(
swap_[fixedLegIndex].concreteLegData());
101 QuantLib::ext::shared_ptr<FloatingLegData> floatingLegData =
102 QuantLib::ext::dynamic_pointer_cast<FloatingLegData>(
swap_[floatingLegIndex].concreteLegData());
104 QL_REQUIRE(fixedLegData !=
nullptr,
"expected fixed leg data");
105 QL_REQUIRE(floatingLegData !=
nullptr,
"expected floating leg data");
107 QuantLib::ext::shared_ptr<EngineBuilder> tmp = engineFactory->builder(
"BalanceGuaranteedSwap");
108 auto builder = QuantLib::ext::dynamic_pointer_cast<FlexiSwapBGSEngineBuilderBase>(tmp);
109 QL_REQUIRE(builder,
"No BGS Builder found for \"" <<
id() <<
"\"");
113 vector<Real> fixedRate =
116 floatingSchedule, 0.0);
118 floatingSchedule, 1.0);
120 floatingSchedule, (Real)Null<Real>());
122 floatingSchedule, (Real)Null<Real>());
123 std::string floatingIndex = floatingLegData->index();
125 Handle<IborIndex> index =
129 VanillaSwap::Type type =
swap_[fixedLegIndex].isPayer() ? VanillaSwap::Payer : VanillaSwap::Receiver;
131 auto bgSwap = QuantLib::ext::make_shared<QuantExt::BalanceGuaranteedSwap>(
132 type, trancheNotionals,
schedule, referencedTranche, fixedSchedule, fixedRate, fixedDayCounter,
133 floatingSchedule, *index, gearings, spreads, caps, floors, floatingDayCounter, paymentConvention);
135 auto fixLeg = bgSwap->leg(0);
136 auto fltLeg = bgSwap->leg(1);
139 Size legRatio = fltLeg.size() / fixLeg.size();
141 swap_[fixedLegIndex].notionals(),
swap_[fixedLegIndex].notionalDates(), fixedSchedule, 0.0);
143 swap_[floatingLegIndex].notionals(),
swap_[floatingLegIndex].notionalDates(), floatingSchedule, 0.0);
144 for (Size i = 0; i < legFixedNominal.size(); ++i) {
145 QL_REQUIRE(
close_enough(bgSwap->trancheNominal(referencedTranche, fixedSchedule[i]), legFixedNominal[i]),
146 "fixed leg notional at " << i <<
" (" << legFixedNominal[i] <<
") does not match tranche notional ("
147 << bgSwap->trancheNominal(referencedTranche, fixedSchedule[i])
148 <<
"), referenced tranche is " << referencedTranche);
150 for (Size i = 0; i < legFloatingNominal.size(); ++i) {
153 QL_REQUIRE(
close_enough(legFloatingNominal[i], legFixedNominal[i / legRatio]),
154 "floating leg notional at " << i <<
" (" << legFloatingNominal[i]
155 <<
") does not match fixed leg notional at " << (i / legRatio) <<
" ("
156 << legFixedNominal[i / legRatio] <<
")");
161 bool hasCapsFloors =
false;
162 for (
auto const& k : caps) {
163 if (k != Null<Real>())
164 hasCapsFloors =
true;
166 for (
auto const& k : floors) {
167 if (k != Null<Real>())
168 hasCapsFloors =
true;
171 QuantLib::ext::shared_ptr<EngineBuilder> cfBuilder = engineFactory->builder(
"CapFlooredIborLeg");
172 QL_REQUIRE(cfBuilder,
"No builder found for CapFlooredIborLeg");
173 QuantLib::ext::shared_ptr<CapFlooredIborLegEngineBuilder> cappedFlooredIborBuilder =
174 QuantLib::ext::dynamic_pointer_cast<CapFlooredIborLegEngineBuilder>(cfBuilder);
175 QL_REQUIRE(cappedFlooredIborBuilder !=
nullptr,
"expected CapFlooredIborLegEngineBuilder");
176 QuantLib::ext::shared_ptr<FloatingRateCouponPricer> couponPricer =
177 cappedFlooredIborBuilder->engine(IndexNameTranslator::instance().oreName(index->name()));
178 QuantLib::setCouponPricer(fltLeg, couponPricer);
183 std::vector<Date> expiryDates;
185 Date today = Settings::instance().evaluationDate();
186 for (Size i = 0; i < fltLeg.size(); ++i) {
187 auto fltcpn = QuantLib::ext::dynamic_pointer_cast<FloatingRateCoupon>(fltLeg[i]);
188 if (fltcpn !=
nullptr && fltcpn->fixingDate() > today && i % legRatio == 0) {
189 expiryDates.push_back(fltcpn->fixingDate());
190 auto fixcpn = QuantLib::ext::dynamic_pointer_cast<FixedRateCoupon>(fixLeg[i]);
191 QL_REQUIRE(fixcpn !=
nullptr,
"BalanceGuaranteedSwap Builder: expected fixed rate coupon");
192 strikes.push_back(fixcpn->rate() - fltcpn->spread());
198 bgSwap->setPricingEngine(
206 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(bgSwap);
212 legs_ = {fixLeg, fltLeg};
220 QL_REQUIRE(swapNode,
"BalanceGuaranteedSwap::fromXML(): BalanceGuaranteedSwapData not found");
225 QL_REQUIRE(tranchesNode,
"BalanceGuaranteedSwap::fromXML(): Tranches node not found");
228 for (Size i = 0; i < trancheNodes.size(); ++i) {
239 for (Size i = 0; i < nodes.size(); ++i) {
252 for (Size i = 0; i <
tranches_.size(); ++i) {
260 for (Size i = 0; i <
swap_.size(); ++i)
Balance Guaranteed Swap data model and serialization.
builder that returns an engine to price capped floored ibor legs
Serializable Tranche for use in Balance Guaranteed Swaps.
std::vector< std::string > notionalDates_
std::vector< QuantLib::Real > notionals_
virtual void fromXML(ore::data::XMLNode *node) override
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::string referenceSecurity_
ore::data::ScheduleData schedule_
const std::string & referenceSecurity() const
std::vector< ore::data::LegData > swap_
std::vector< BGSTrancheData > tranches_
virtual void fromXML(ore::data::XMLNode *node) override
const ore::data::ScheduleData schedule() const
const std::vector< BGSTrancheData > & tranches() const
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
void build(const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &) override
Serializable object holding leg data.
virtual void fromXML(XMLNode *node) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const 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 void checkNode(XMLNode *n, const string &expectedName)
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 int getChildValueAsInt(XMLNode *node, const string &name, bool mandatory=false, int defaultValue=0)
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.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
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)
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.