27#include <ql/cashflows/capflooredcoupon.hpp>
28#include <ql/cashflows/floatingratecoupon.hpp>
30#include <boost/make_shared.hpp>
39 DLOG(
"Building MultiLegOption " <<
id());
41 QL_REQUIRE(!underlyingData_.empty(),
"MultiLegOption: no underlying given");
43 Position::Type positionType = Position::Long;
44 Settlement::Type settleType = Settlement::Cash;
47 QL_REQUIRE(exerciseType == Exercise::Bermudan || exerciseType == Exercise::European,
48 "MultiLegOption: exercise type must be bermudan or european");
53 Date today = Settings::instance().evaluationDate();
54 Real multiplier = positionType == Position::Long ? 1.0 : -1.0;
57 QuantLib::ext::dynamic_pointer_cast<MultiLegOptionEngineBuilderBase>(engineFactory->builder(
"MultiLegOption"));
58 QL_REQUIRE(builder !=
nullptr,
"wrong builder, expected multi leg option engine builder");
63 vector<Leg> underlyingLegs;
64 vector<bool> underlyingPayers;
65 vector<Currency> underlyingCurrencies;
66 legCurrencies_.clear();
68 for (Size i = 0; i < underlyingData_.size(); ++i) {
69 auto legBuilder = engineFactory->legBuilder(underlyingData_[i].legType());
70 underlyingLegs.push_back(legBuilder->buildLeg(underlyingData_[i], engineFactory, requiredFixings_,
71 builder->configuration(MarketContext::pricing)));
72 underlyingCurrencies.push_back(
parseCurrency(underlyingData_[i].currency()));
73 legCurrencies_.push_back(underlyingData_[i].currency());
74 underlyingPayers.push_back(underlyingData_[i].isPayer());
75 DLOG(
"Added leg of type " << underlyingData_[i].legType() <<
" in currency " << underlyingData_[i].currency()
76 <<
" is payer " << underlyingData_[i].isPayer());
81 QuantLib::ext::shared_ptr<Exercise> exercise;
84 for (Size i = 0; i < optionData_.exerciseDates().
size(); ++i) {
85 Date exDate =
parseDate(optionData_.exerciseDates()[i]);
86 if (exDate > Settings::instance().evaluationDate())
87 exDates.push_back(exDate);
90 if (!exDates.empty()) {
91 std::sort(exDates.begin(), exDates.end());
92 exercise = QuantLib::ext::make_shared<BermudanExercise>(exDates);
93 DLOG(
"Added exercise with " << exDates.size() <<
" alive exercise dates.");
95 DLOG(
"No exercise added, instrument is equal to the underlying");
100 auto multiLegOption = QuantLib::ext::make_shared<QuantExt::MultiLegOption>(underlyingLegs, underlyingPayers,
101 underlyingCurrencies, exercise, settleType);
103 DLOG(
"QLE Instrument built.")
107 vector<Date> underlyingFixingDates;
108 vector<QuantLib::ext::shared_ptr<InterestRateIndex>> underlyingIndices;
109 vector<Currency> allCurrencies;
110 for (
auto const& c : underlyingCurrencies) {
111 if (std::find(allCurrencies.begin(), allCurrencies.end(), c) == allCurrencies.end()) {
112 allCurrencies.push_back(c);
115 for (
auto const& l : underlyingLegs) {
116 for (
auto const& c : l) {
117 auto flr = QuantLib::ext::dynamic_pointer_cast<QuantLib::FloatingRateCoupon>(c);
118 auto cfc = QuantLib::ext::dynamic_pointer_cast<QuantLib::CappedFlooredCoupon>(c);
120 flr = cfc->underlying();
121 if (flr !=
nullptr) {
122 if (flr->fixingDate() > today) {
123 underlyingFixingDates.push_back(flr->fixingDate());
124 underlyingIndices.push_back(flr->index());
125 if (std::find(allCurrencies.begin(), allCurrencies.end(), flr->index()->currency()) ==
127 allCurrencies.push_back(flr->index()->currency());
133 DLOG(
"Extracted underlying currencies, indices and fixing dates.")
135 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
136 std::vector<Real> additionalMultipliers;
137 Date lastPremiumDate = addPremiums(additionalInstruments, additionalMultipliers, multiplier,
138 optionData_.premiumData(), -multiplier,
parseCurrency(legCurrencies_.front()),
139 engineFactory, builder->configuration(MarketContext::pricing));
143 std::sort(allCurrencies.begin(), allCurrencies.end(),
144 [](
const Currency& a,
const Currency& b) { return a.code() < b.code(); });
145 auto engine = builder->engine(
id(), exDates, multiLegOption->maturityDate(), allCurrencies, underlyingFixingDates,
147 multiLegOption->setPricingEngine(engine);
148 setSensitivityTemplate(*builder);
150 DLOG(
"Pricing engine set.")
155 QuantLib::ext::make_shared<VanillaInstrument>(multiLegOption, multiplier, additionalInstruments, additionalMultipliers);
159 legs_ = underlyingLegs;
160 legPayers_ = underlyingPayers;
162 maturity_ = std::max(lastPremiumDate, multiLegOption->maturityDate());
164 auto moe = QuantLib::ext::dynamic_pointer_cast<McMultiLegOptionEngine>(engine);
165 QL_REQUIRE(moe !=
nullptr,
"MultiLegOption::build(): expected McMultiLegOptionEngine from engine builder");
166 npvCurrency_ = moe->model()->irlgm1f(0)->currency().code();
168 DLOG(
"Building MultiLegOption done");
172 Trade::fromXML(node);
173 underlyingData_.clear();
176 XMLNode* n0 = XMLUtils::getChildNode(node,
"MultiLegOptionData");
177 XMLNode* n1 = XMLUtils::getChildNode(n0,
"OptionData");
179 optionData_.fromXML(n1);
182 vector<XMLNode*> nodes = XMLUtils::getChildrenNodes(n0,
"LegData");
183 for (
auto const n : nodes) {
186 underlyingData_.push_back(ld);
191 XMLNode* node = Trade::toXML(doc);
193 XMLUtils::appendNode(node, n0);
195 XMLUtils::appendNode(n0, optionData_.toXML(doc));
196 for (
auto& d : underlyingData_) {
197 XMLUtils::appendNode(n0, d.toXML(doc));
multi leg option engine builder
const std::vector< Leg > legs_
Serializable object holding leg data.
virtual void fromXML(XMLNode *node) override
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Serializable object holding option data.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Logic for calculating required fixing dates on legs.
Exercise::Type parseExerciseType(const std::string &s)
Convert text to QuantLib::Exercise::Type.
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.
Settlement::Type parseSettlementType(const std::string &s)
Convert text to QuantLib::Settlement::Type.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
Multileg Option data model.
Real currentNotional(const Leg &leg)
Size size(const ValueType &v)
Serializable Credit Default Swap.