24#include <boost/lexical_cast.hpp>
31 static const std::string mcscript =
32 " REQUIRE PayoffType == 0 OR PayoffType == 1;\n"
33 " REQUIRE SIZE(Underlyings) == SIZE(TransatlanticBarrierType);\n"
34 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierLevels) / SIZE(Underlyings);\n"
35 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebates);\n"
36 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebateCurrencies);\n"
37 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebatePayTimes);\n"
38 " REQUIRE ExpiryDate >= BarrierMonitoringDates[SIZE(BarrierMonitoringDates)];\n"
40 " NUMBER KnockedIn, KnockedOut, Active, rebate, TransatlanticActive;\n"
41 " NUMBER U, i, k, d, currentNotional, levelIndex;\n"
43 " FOR d IN (1, SIZE(BarrierMonitoringDates), 1) DO\n"
45 " FOR i IN (1, SIZE(BarrierTypes), 1) DO\n"
47 " FOR k IN (1, SIZE(Underlyings), 1) DO\n"
48 " U = Underlyings[k](BarrierMonitoringDates[d]);\n"
50 " levelIndex = ((k - 1) * SIZE(BarrierTypes)) + i;\n"
51 " IF {BarrierTypes[i] == 1 AND U <= BarrierLevels[levelIndex]} OR\n"
52 " {BarrierTypes[i] == 2 AND U >= BarrierLevels[levelIndex]} THEN\n"
53 " IF KnockedOut == 0 THEN\n"
58 " IF {BarrierTypes[i] == 3 AND U < BarrierLevels[levelIndex]} OR\n"
59 " {BarrierTypes[i] == 4 AND U > BarrierLevels[levelIndex]} THEN\n"
60 " IF KikoType == 1 OR { KikoType == 2 AND KnockedIn == 0 } OR { KikoType == 3 AND KnockedIn == 1 } THEN\n"
61 " IF KnockedOut == 0 THEN\n"
62 " IF BarrierRebatePayTimes[i] == 0 THEN\n"
63 " rebate = PAY( LongShort * BarrierRebates[i], BarrierMonitoringDates[d], BarrierMonitoringDates[d], BarrierRebateCurrencies[i] );\n"
65 " rebate = PAY( LongShort * BarrierRebates[i], BarrierMonitoringDates[d], SettlementDate, BarrierRebateCurrencies[i] );\n"
79 " FOR i IN (1, SIZE(BarrierTypes),1) DO\n"
80 " IF BarrierTypes[i] == 1 OR BarrierTypes[i] == 2 THEN\n"
85 " Active = max(Active, KnockedIn) * (1 - KnockedOut);\n"
87 " IF BarrierRebate != 0 THEN\n"
88 " rebate = (1 - Active) * PAY( LongShort * BarrierRebate, SettlementDate, SettlementDate, BarrierRebateCurrency );\n"
91 " TransatlanticActive = 1;\n"
92 " FOR k IN (1, SIZE(Underlyings), 1) DO\n"
93 " REQUIRE TransatlanticBarrierType[k] >= 0 AND TransatlanticBarrierType[k] <= 4;\n"
94 " IF { TransatlanticBarrierType[k] == 1 AND Underlyings[k](ExpiryDate) >= TransatlanticBarrierLevel[k] } OR\n"
95 " { TransatlanticBarrierType[k] == 2 AND Underlyings[k](ExpiryDate) <= TransatlanticBarrierLevel[k] } OR\n"
96 " { TransatlanticBarrierType[k] == 3 AND Underlyings[k](ExpiryDate) < TransatlanticBarrierLevel[k] } OR\n"
97 " { TransatlanticBarrierType[k] == 4 AND Underlyings[k](ExpiryDate) > TransatlanticBarrierLevel[k] } THEN\n"
98 " TransatlanticActive = 0;\n"
102 " rebate = rebate + Active * (1 - TransatlanticActive) * PAY( TransatlanticBarrierRebate, SettlementDate, SettlementDate, TransatlanticBarrierRebateCurrency );\n"
104 " IF PayoffType == 0 AND SIZE(Underlyings) == 1 THEN\n"
105 " value = Active * TransatlanticActive * PAY( LongShort * Quantity * max(0, PutCall * (Underlyings[1](ExpiryDate) - Strike)), ExpiryDate, SettlementDate, PayCurrency ) +\n"
108 " value = Active * TransatlanticActive * PAY( LongShort * Amount, ExpiryDate, SettlementDate, PayCurrency ) +\n"
112 " IF PayoffType == 0 THEN\n"
113 " currentNotional = Quantity * Strike;\n"
115 " currentNotional = Amount;\n"
118 static const std::string fdscript =
119 " REQUIRE PayoffType == 0 OR PayoffType == 1;\n"
120 " REQUIRE SIZE(Underlyings) == SIZE(TransatlanticBarrierType);\n"
121 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierLevels) / SIZE(Underlyings);\n"
122 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebates);\n"
123 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebateCurrencies);\n"
124 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebatePayTimes);\n"
125 " REQUIRE ExpiryDate >= BarrierMonitoringDates[SIZE(BarrierMonitoringDates)];\n"
127 " NUMBER V, V_V, V_NA, V_KI, V_KO, V_KIKO, V_KOKI;\n"
128 " NUMBER R, R_V, R_NA, R_KI, R_KO, R_KIKO, R_KOKI, rebate;\n"
129 " NUMBER U, i, k, d, currentNotional, TransatlanticActive, IsKnockedIn, IsKnockedOut, levelIndex;\n"
131 " IF PayoffType == 0 AND SIZE(Underlyings) == 1 THEN\n"
132 " V = PAY( LongShort * Quantity * max(0, PutCall * (Underlyings[1](ExpiryDate) - Strike)), ExpiryDate, SettlementDate, PayCurrency );\n"
134 " V = PAY( LongShort * Amount, ExpiryDate, SettlementDate, PayCurrency );\n"
137 " TransatlanticActive = 1;\n"
138 " FOR k IN (1, SIZE(Underlyings), 1) DO\n"
139 " REQUIRE TransatlanticBarrierType[k] >= 0 AND TransatlanticBarrierType[k] <= 4;\n"
140 " IF { TransatlanticBarrierType[k] == 1 AND Underlyings[k](ExpiryDate) >= TransatlanticBarrierLevel[k] } OR\n"
141 " { TransatlanticBarrierType[k] == 2 AND Underlyings[k](ExpiryDate) <= TransatlanticBarrierLevel[k] } OR\n"
142 " { TransatlanticBarrierType[k] == 3 AND Underlyings[k](ExpiryDate) < TransatlanticBarrierLevel[k] } OR\n"
143 " { TransatlanticBarrierType[k] == 4 AND Underlyings[k](ExpiryDate) > TransatlanticBarrierLevel[k] } THEN\n"
144 " TransatlanticActive = 0;\n"
148 " IF TransatlanticActive == 0 THEN\n"
149 " V = PAY( LongShort * TransatlanticBarrierRebate, ExpiryDate, SettlementDate, TransatlanticBarrierRebateCurrency );\n"
159 " R = PAY( LongShort * BarrierRebate, ExpiryDate, SettlementDate, BarrierRebateCurrency);\n"
167 " FOR i IN (1, SIZE(BarrierTypes), 1) DO\n"
168 " IF BarrierTypes[i] == 1 OR BarrierTypes[i] == 2 THEN\n"
174 " FOR d IN (SIZE(BarrierMonitoringDates), 1, -1) DO\n"
176 " V_V = NPV(V_V, BarrierMonitoringDates[d]);\n"
177 " V_NA = NPV(V_NA, BarrierMonitoringDates[d]);\n"
178 " V_KI = NPV(V_KI, BarrierMonitoringDates[d]);\n"
179 " V_KO = NPV(V_KO, BarrierMonitoringDates[d]);\n"
180 " V_KIKO = NPV(V_KIKO, BarrierMonitoringDates[d]);\n"
181 " V_KOKI = NPV(V_KOKI, BarrierMonitoringDates[d]);\n"
182 " R_V = NPV(R_V, BarrierMonitoringDates[d]);\n"
183 " R_NA = NPV(R_NA, BarrierMonitoringDates[d]);\n"
184 " R_KI = NPV(R_KI, BarrierMonitoringDates[d]);\n"
185 " R_KO = NPV(R_KO, BarrierMonitoringDates[d]);\n"
186 " R_KIKO = NPV(R_KIKO, BarrierMonitoringDates[d]);\n"
187 " R_KOKI = NPV(R_KOKI, BarrierMonitoringDates[d]);\n"
188 " rebate = NPV(rebate, BarrierMonitoringDates[d]);\n"
190 " FOR i IN (1, SIZE(BarrierTypes), 1) DO\n"
192 " IsKnockedIn = 0;\n"
193 " IsKnockedOut = 0;\n"
194 " FOR k IN (1, SIZE(Underlyings), 1) DO\n"
195 " U = Underlyings[k](BarrierMonitoringDates[d]);\n"
196 " levelIndex = ((k - 1) * SIZE(BarrierTypes)) + i;\n"
197 " IF {BarrierTypes[i] == 1 AND U <= BarrierLevels[levelIndex]} OR\n"
198 " {BarrierTypes[i] == 2 AND U >= BarrierLevels[levelIndex]} THEN\n"
201 " IF {BarrierTypes[i] == 3 AND U < BarrierLevels[levelIndex]} OR\n"
202 " {BarrierTypes[i] == 4 AND U > BarrierLevels[levelIndex]} THEN\n"
207 " IF {IsKnockedIn == 1} THEN\n"
208 " V_KIKO = V_KO + V_KIKO + V_KOKI;\n"
209 " V_KOKI = V_KOKI * 0;\n"
210 " V_KI = V_NA + V_KI;\n"
211 " V_KO = V_KO * 0;\n"
212 " V_NA = V_NA * 0;\n"
214 " IF KikoType == 2 THEN\n"
215 " V_V = V_V + V_KIKO;\n"
217 " R_KIKO = R_KO + R_KIKO + R_KOKI;\n"
218 " R_KOKI = R_KOKI * 0;\n"
219 " R_KI = R_NA + R_KI;\n"
220 " R_KO = R_KO * 0;\n"
221 " R_NA = R_NA * 0;\n"
223 " IF KikoType == 2 THEN\n"
224 " R_V = R_V + R_KIKO;\n"
228 " IF { IsKnockedOut == 1 } THEN\n"
229 " V_KOKI = V_KI + V_KOKI + V_KIKO;\n"
230 " V_KIKO = V_KIKO * 0;\n"
231 " V_KO = V_NA + V_KO;\n"
232 " V_KI = V_KI * 0;\n"
233 " V_NA = V_NA * 0;\n"
234 " IF KikoType == 1 OR KikoType == 2 THEN\n"
237 " R_KOKI = R_KI + R_KOKI + R_KIKO;\n"
238 " R_KIKO = R_KIKO * 0;\n"
239 " R_KO = R_NA + R_KO;\n"
240 " R_KI = R_KI * 0;\n"
241 " R_NA = R_NA * 0;\n"
242 " IF KikoType == 1 OR KikoType == 2 THEN\n"
245 " IF BarrierRebatePayTimes[i] == 0 THEN\n"
246 " rebate = PAY( LongShort * BarrierRebates[i], BarrierMonitoringDates[d], BarrierMonitoringDates[d], BarrierRebateCurrencies[i] );\n"
248 " rebate = PAY( LongShort * BarrierRebates[i], BarrierMonitoringDates[d], SettlementDate, BarrierRebateCurrencies[i] );\n"
256 " rebate = NPV(rebate, TODAY);"
257 " R_V = NPV(R_V, TODAY);"
258 " V_V = NPV(V_V, TODAY);"
261 " rebate = rebate + ( PAY( LongShort * BarrierRebate, TODAY, SettlementDate, BarrierRebateCurrency ) - R_V );\n"
262 " value = V_V + rebate;\n"
264 " IF PayoffType == 0 THEN\n"
265 " currentNotional = Quantity * Strike;\n"
267 " currentNotional = Amount;\n"
281 "Only CashOrNothing payoff allowed for mulitple underlyings");
283 std::string payoffType;
291 numbers_.emplace_back(
"Number",
"PayoffType", payoffType);
294 "Need Quantity, Strike, no Amount for PayoffType = Vanilla");
297 "Need Quantity, no Strike, no Amount for PayoffType = AssetOrNothing");
300 "Need no Quantity, no Strike, Amount for PayoffType = CashOrNothing");
302 std::vector<std::string> transatlanticBarrierType(
underlyings_.size(),
"0");
303 std::vector<std::string> transatlanticBarrierLevel(
underlyings_.size(),
"0");
304 std::string transatlanticBarrierRebate =
"0.0";
305 std::string transatlanticBarrierRebateCurrency =
payCurrency_;
307 transatlanticBarrierType.clear();
309 if (n.type() ==
"DownAndIn")
310 transatlanticBarrierType.push_back(
"1");
311 else if (n.type() ==
"UpAndIn")
312 transatlanticBarrierType.push_back(
"2");
313 else if (n.type() ==
"DownAndOut")
314 transatlanticBarrierType.push_back(
"3");
315 else if (n.type() ==
"UpAndOut")
316 transatlanticBarrierType.push_back(
"4");
318 QL_FAIL(
"Transatlantic BarrierType (" << n.type()
319 <<
") must be DownAndIn, UpAndIn, DownAndOut, UpAndOut");
322 QL_REQUIRE(transatlanticBarrierType.size() == 1 || transatlanticBarrierType.size() ==
underlyings_.size(),
323 "Transatlantic Barrier must have only 1 Barrier block or 1 block for each underlyings, got "
324 << transatlanticBarrierType.size());
325 if (transatlanticBarrierType.size() == 1 &&
underlyings_.size() > 1) {
326 transatlanticBarrierType.assign(
underlyings_.size(), transatlanticBarrierType[0]);
328 transatlanticBarrierLevel.clear();
331 "Transatlantic Barrier must have exactly 1 level for each underlying, got "
334 transatlanticBarrierLevel.push_back(boost::lexical_cast<std::string>(l.value()));
336 QL_REQUIRE(transatlanticBarrierType.size() ==
underlyings_.size(),
337 "Transatlantic Barrier must have exactly 1 level for each underlying, got "
340 QL_REQUIRE(n.levels().size() == 1,
"Number of level in each barrier block in transatlantic barriers "
341 "must be exactly 1 if more than 1 barrier blocks are provided, got "
343 transatlanticBarrierLevel.push_back(boost::lexical_cast<std::string>(n.levels()[0].value()));
350 "Rebate currency for transatlantic barriers must be identical or only given in the first "
351 "transatlantic barrier.");
358 numbers_.emplace_back(
"Number",
"TransatlanticBarrierType", transatlanticBarrierType);
359 numbers_.emplace_back(
"Number",
"TransatlanticBarrierLevel", transatlanticBarrierLevel);
360 numbers_.emplace_back(
"Number",
"TransatlanticBarrierRebate", transatlanticBarrierRebate);
361 currencies_.emplace_back(
"Currency",
"TransatlanticBarrierRebateCurrency", transatlanticBarrierRebateCurrency);
364 numbers_.emplace_back(
"Number",
"LongShort", positionType == Position::Long ?
"1" :
"-1");
368 "Payoff type must be vanilla if option type is not givien.");
369 numbers_.emplace_back(
"Number",
"PutCall",
"1.0");
371 numbers_.emplace_back(
"Number",
"PutCall",
387 "If SettlementDate is given, no SettlementLag, SettlementCalendar or SettlementConvention must be given.");
394 BusinessDayConvention conv =
401 "If ScheduleData is given, no StartDate or EndDate must be given");
407 "If no ScheduleData is given, StartDate and EndDate must be given");
408 events_.emplace_back(
"BarrierMonitoringDates",
413 std::vector<std::string> barrierTypes, barrierLevels, barrierRebates, barrierRebateCurrencies,
414 barrierRebatePayTimes;
415 bool hasKi =
false, hasKo =
false;
417 std::string barrierType;
418 if (b.type() ==
"DownAndIn") {
421 }
else if (b.type() ==
"UpAndIn") {
424 }
else if (b.type() ==
"DownAndOut") {
427 }
else if (b.type() ==
"UpAndOut") {
431 QL_FAIL(
"BarrierType (" << b.type() <<
") must be DownAndIn, UpAndIn, DownAndOut, UpAndOut");
433 barrierTypes.push_back(barrierType);
434 QL_REQUIRE(b.levels().size() ==
underlyings_.size(),
"Barrier must have exactly number of levels as underlyings, got " << b.levels().size());
435 for (
const auto& l : b.levels())
436 barrierLevels.push_back(boost::lexical_cast<std::string>(l.value()));
437 barrierRebates.push_back(boost::lexical_cast<std::string>(b.rebate()));
438 barrierRebateCurrencies.push_back(b.rebateCurrency().empty() ?
payCurrency_ : b.rebateCurrency());
439 std::string rebatePayTime;
440 if (b.rebatePayTime() ==
"atHit")
442 else if (b.rebatePayTime() ==
"atExpiry" || b.rebatePayTime().empty())
445 QL_FAIL(
"RebatePayTime (" << b.rebatePayTime() <<
") must be atHit, atExpiry");
447 barrierRebatePayTimes.push_back(rebatePayTime);
453 std::string barrierRebate =
"0.0", barrierRebateCurrency =
payCurrency_;
455 for (Size i = 1; i < barrierTypes.size(); ++i) {
457 barrierRebateCurrencies[i] == barrierRebateCurrencies[0],
458 "If Knock-In barrier is present, all rebates must be identical, found "
459 << barrierRebates[0] <<
" " << barrierRebateCurrencies[0] <<
" and " << barrierRebates[i]
460 <<
" " << barrierRebateCurrencies[i]);
462 for (Size i = 0; i < barrierTypes.size(); ++i) {
463 QL_REQUIRE(barrierRebatePayTimes[i] ==
"1",
464 "If Knock-In barrier is present, all rebate pay times must be atExpiry");
466 barrierRebate = barrierRebates[0];
467 barrierRebateCurrency = barrierRebateCurrencies[0];
468 for (Size i = 0; i < barrierTypes.size(); ++i) {
469 barrierRebates[i] =
"0.0";
474 numbers_.emplace_back(
"Number",
"BarrierTypes", barrierTypes);
475 numbers_.emplace_back(
"Number",
"BarrierLevels", barrierLevels);
476 numbers_.emplace_back(
"Number",
"BarrierRebates", barrierRebates);
477 currencies_.emplace_back(
"Currency",
"BarrierRebateCurrencies", barrierRebateCurrencies);
478 numbers_.emplace_back(
"Number",
"BarrierRebatePayTimes", barrierRebatePayTimes);
479 numbers_.emplace_back(
"Number",
"BarrierRebate", barrierRebate);
480 currencies_.emplace_back(
"Currency",
"BarrierRebateCurrency", barrierRebateCurrency);
482 std::string kikoType;
490 QL_FAIL(
"KikoType (" <<
kikoType_ <<
") must be KoAlways, KoBeforeKi, KoAfterKi");
492 numbers_.emplace_back(
"Number",
"KikoType", kikoType);
494 QL_REQUIRE((hasKi && hasKo) || kikoType ==
"1",
495 "KikoType (" <<
kikoType_ <<
") must be KoAlways if there are only Ko or only Ki barriers");
496 QL_REQUIRE(!(hasKi && hasKo) || !
kikoType_.empty(),
497 "KikoType must be given (KoAlways, KoBeforeKi, KoAfterKi) if both Ko and Ki barriers are present");
502 :
"MultiAssetOption({AssetClass})";
508 {{
"currentNotional",
"currentNotional"},
509 {
"notionalCurrency",
"PayCurrency"},
510 {
"Active",
"Active"},
511 {
"TransatlanticActive",
"TransatlanticActive"}},
514 fdscript,
"value", {{
"currentNotional",
"currentNotional"}, {
"notionalCurrency",
"PayCurrency"}}, {}, {},
523 std::vector<std::string> underlyings;
527 indices_.emplace_back(
"Index",
"Underlyings", underlyings);
532 QL_REQUIRE(
underlyings_.size() > 0,
"No underlyings provided.");
538 }
else if (ind.
isEq()) {
543 }
else if (ind.
isComm()) {
558 QL_REQUIRE(dataNode,
tradeType() +
"Data node not found");
561 QL_REQUIRE(underlyingsNode,
"No Underlyings node");
563 for (
auto const& n : underlyings) {
573 underlyingBuilder.
fromXML(tmp);
580 QL_REQUIRE(barriersNode,
"No Barriers node found");
588 for (
auto const& n : barriers) {
594 if (transatlanticBarrierNode) {
596 for (
auto const& n : b) {
Serializable obejct holding barrier data.
ScheduleData barrierMonitoringDates_
std::string settlementConvention_
std::vector< BarrierData > transatlanticBarrier_
std::vector< QuantLib::ext::shared_ptr< ore::data::Underlying > > underlyings_
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
std::string settlementLag_
std::string barrierMonitoringEndDate_
std::string barrierMonitoringStartDate_
std::vector< BarrierData > barriers_
QuantLib::Calendar getUnderlyingCalendar(const QuantLib::ext::shared_ptr< EngineFactory > &factory) const
std::string settlementDate_
std::string settlementCalendar_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
QuantLib::ext::shared_ptr< EquityIndex2 > eq() const
QuantLib::ext::shared_ptr< FxIndex > fx() const
std::string commName() const
const string & callPut() const
const string & payoffType() const
const string & longShort() const
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const PremiumData & premiumData() const
const vector< string > & exerciseDates() const
Serializable schedule data.
bool hasData() const
Check if has any dates/rules/derived schedules.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Serializable object holding schedule Rules data.
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > indices_
std::vector< ScriptedTradeValueTypeData > numbers_
std::map< std::string, ScriptedTradeScriptData > script_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const string & tradeType() const
const QuantLib::ext::shared_ptr< Underlying > & underlying()
void fromXML(XMLNode *node) override
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 XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
generic barrier option wrapper for scripted trade
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Real parseReal(const string &s)
Convert text to Real.
Option::Type parseOptionType(const std::string &s)
Convert text to QuantLib::Option::Type.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
QL_DEPRECATED_ENABLE_WARNING std::string scriptedIndexName(const QuantLib::ext::shared_ptr< Underlying > &underlying)
Size size(const ValueType &v)
std::string to_string(const LocationInfo &l)
Serializable Credit Default Swap.
string conversion utilities