272 {
273
274
275
278
281 "Only CashOrNothing payoff allowed for mulitple underlyings");
282
283 std::string payoffType;
285 payoffType = "0";
287 payoffType = "1";
288 else {
290 }
291 numbers_.emplace_back(
"Number",
"PayoffType", payoffType);
292
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");
301
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");
317 else {
318 QL_FAIL("Transatlantic BarrierType (" << n.type()
319 << ") must be DownAndIn, UpAndIn, DownAndOut, UpAndOut");
320 }
321 }
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]);
327 }
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()));
335 } else {
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()));
344 }
345 }
350 "Rebate currency for transatlantic barriers must be identical or only given in the first "
351 "transatlantic barrier.");
352 }
353 }
357 }
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);
362
364 numbers_.emplace_back(
"Number",
"LongShort", positionType == Position::Long ?
"1" :
"-1");
365
368 "Payoff type must be vanilla if option type is not givien.");
369 numbers_.emplace_back(
"Number",
"PutCall",
"1.0");
370 } else {
371 numbers_.emplace_back(
"Number",
"PutCall",
373 }
379
383
385 QL_REQUIRE(
387 "If SettlementDate is given, no SettlementLag, SettlementCalendar or SettlementConvention must be given.");
389 } else {
392 Calendar cal =
394 BusinessDayConvention conv =
397 }
398
401 "If ScheduleData is given, no StartDate or EndDate must be given");
403 } else {
404
405
407 "If no ScheduleData is given, StartDate and EndDate must be given");
408 events_.emplace_back(
"BarrierMonitoringDates",
411 }
412
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") {
419 barrierType = "1";
420 hasKi = true;
421 } else if (b.type() == "UpAndIn") {
422 barrierType = "2";
423 hasKi = true;
424 } else if (b.type() == "DownAndOut") {
425 barrierType = "3";
426 hasKo = true;
427 } else if (b.type() == "UpAndOut") {
428 barrierType = "4";
429 hasKo = true;
430 } else {
431 QL_FAIL("BarrierType (" << b.type() << ") must be DownAndIn, UpAndIn, DownAndOut, UpAndOut");
432 }
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")
441 rebatePayTime = "0";
442 else if (b.rebatePayTime() == "atExpiry" || b.rebatePayTime().empty())
443 rebatePayTime = "1";
444 else {
445 QL_FAIL("RebatePayTime (" << b.rebatePayTime() << ") must be atHit, atExpiry");
446 }
447 barrierRebatePayTimes.push_back(rebatePayTime);
448 }
449
450
451
452
453 std::string barrierRebate =
"0.0", barrierRebateCurrency =
payCurrency_;
454 if (hasKi) {
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]);
461 }
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");
465 }
466 barrierRebate = barrierRebates[0];
467 barrierRebateCurrency = barrierRebateCurrencies[0];
468 for (Size i = 0; i < barrierTypes.size(); ++i) {
469 barrierRebates[i] = "0.0";
471 }
472 }
473
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);
481
482 std::string kikoType;
484 kikoType = "1";
486 kikoType = "2";
488 kikoType = "3";
489 else {
490 QL_FAIL(
"KikoType (" <<
kikoType_ <<
") must be KoAlways, KoBeforeKi, KoAfterKi");
491 }
492 numbers_.emplace_back(
"Number",
"KikoType", kikoType);
493
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");
498
499
500
502 : "MultiAssetOption({AssetClass})";
503
504
505
506 script_[
""] = ScriptedTradeScriptData(
507 mcscript, "value",
508 {{"currentNotional", "currentNotional"},
509 {"notionalCurrency", "PayCurrency"},
510 {"Active", "Active"},
511 {"TransatlanticActive", "TransatlanticActive"}},
512 {}, {}, {ScriptedTradeScriptData::CalibrationData("Underlyings", {"Strike", "BarrierLevels"})});
513 script_[
"FD"] = ScriptedTradeScriptData(
514 fdscript, "value", {{"currentNotional", "currentNotional"}, {"notionalCurrency", "PayCurrency"}}, {}, {},
515 {ScriptedTradeScriptData::CalibrationData("Underlyings", {"Strike", "BarrierLevels"})});
516
517
518
520}
std::string settlementConvention_
std::string settlementLag_
std::string barrierMonitoringEndDate_
std::string barrierMonitoringStartDate_
QuantLib::Calendar getUnderlyingCalendar(const QuantLib::ext::shared_ptr< EngineFactory > &factory) const
std::string settlementCalendar_
const string & callPut() const
const string & payoffType() const
const string & longShort() const
const PremiumData & premiumData() const
const vector< string > & exerciseDates() const
bool hasData() const
Check if has any dates/rules/derived schedules.
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > numbers_
std::map< std::string, ScriptedTradeScriptData > script_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
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)
Size size(const ValueType &v)
std::string to_string(const LocationInfo &l)