31 auto builder = QuantLib::ext::dynamic_pointer_cast<ScriptedTradeEngineBuilder>(factory->builder(
"ScriptedTrade"));
63 "FixedAccrualSchedule must be specified for accruing fixed coupons.");
70 defaultName = s.second.second;
71 if (defaultName.empty()) {
72 QL_REQUIRE(ed.
hasData(),
"Could not find mandatory node " <<
name <<
".");
80 defaultName = s.second.second;
81 if (!defaultName.empty() && !ed.
hasData()) {
82 auto defaultEventData =
schedules_.find(defaultName);
83 QL_REQUIRE(defaultEventData !=
schedules_.end(),
"Could not find node " << defaultName);
116 QL_REQUIRE(u->type() == type,
"All of Underlyings must be from the same asset class.");
119 auto ois = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(floatingIndex);
122 DLOG(
"building WorstOfBasketSwap scripted trade wrapper using (internal) script \'Overnight\'")
124 DLOG(
"building WorstOfBasketSwap scripted trade wrapper using (internal) script \'Standard\'");
129 "KnockInDeterminationSchedule must be specified for a Bermudan knock-in.");
134 "FixedAccrualSchedule must be specified for accruing fixed coupons.");
138 QuantLib::Date newKnockInPayDate =
makeSchedule(
schedules_[
"FloatingPayDates"].first.schedule()).dates().back();
143 QuantLib::Date newInitialFixedPayDate =
makeSchedule(
schedules_[
"FloatingPayDates"].first.schedule()).dates().front();
168 "FloatingLookback (" <<
floatingLookback_ <<
") should be given with units days.");
195 if (type ==
"InterestRate") {
206 const std::string fixingScriptStandard =
207 " fixing = FloatingIndex(FloatingFixingSchedule[d-1]) + FloatingSpread;\n";
208 const std::string fixingScriptOvernight =
209 std::string(
" fixing = FWD") + (
isAveraged_ ?
"AVG" :
"COMP") + std::string(
"(FloatingIndex, FloatingPeriodSchedule[d-1], FloatingPeriodSchedule[d-1], FloatingPeriodSchedule[d], FloatingSpread, 1, FloatingLookback, FloatingRateCutoff, 0, IncludeSpread);\n");
211 const std::string floatingFixingScript = ois ? fixingScriptOvernight : fixingScriptStandard;
219 "NUMBER alive, couponAccumulation, fixing, n, indexInitial;\n"
220 "NUMBER allAssetsTriggered, indexFinal, performance, worstPerformance, d, payoff, u, knockedIn;\n"
221 "NUMBER floatingAccrualFraction, fixedAccrualFraction;\n"
222 "NUMBER lastIdx, accrualPeriodIdx, accrualFractions[SIZE(FixedTriggerLevels)], totalDays;\n"
223 "NUMBER ad, cd, dd, ed, fd;\n"
225 "Option = Option + LOGPAY(LongShort * Quantity * InitialFixedRate, InitialFixedPayDate,\n"
226 " InitialFixedPayDate, Currency, 0, InitialFixedAmount);\n"
228 "n = SIZE(FloatingPeriodSchedule);\n"
229 "REQUIRE n - SIZE(FloatingPayDates) <= 1;\n"
230 "REQUIRE n - SIZE(FloatingFixingSchedule) <= 1;\n"
231 "REQUIRE n - SIZE(FixedDeterminationSchedule) <= 1;\n"
232 "REQUIRE n - SIZE(KnockInDeterminationSchedule) <= 1;\n"
233 "REQUIRE n - SIZE(KnockOutDeterminationSchedule) <= 1;\n"
234 "REQUIRE n - SIZE(FixedPayDates) <= 1;\n"
236 "IF SIZE(FloatingPayDates) == n THEN ad = 0; ELSE ad = -1; END;\n"
237 "IF SIZE(FixedDeterminationSchedule) == n THEN cd = 0; ELSE cd = -1; END;\n"
238 "IF SIZE(KnockInDeterminationSchedule) == n THEN dd = 0; ELSE dd = -1; END;\n"
239 "IF SIZE(KnockOutDeterminationSchedule) == n THEN ed = 0; ELSE ed = -1; END;\n"
240 "IF SIZE(FixedPayDates) == n THEN fd = 0; ELSE fd = -1; END;\n"
242 "couponAccumulation = 1;\n"
244 "IF BermudanKnockIn == 1 THEN\n"
245 " FOR d IN (1, SIZE(KnockInDeterminationSchedule), 1) DO\n"
246 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
247 " IF Underlyings[u](KnockInDeterminationSchedule[d+dd]) < KnockInLevel * InitialPrices[u] THEN\n"
254 "IF AccruingFixedCoupons == 1 THEN\n"
256 " FOR d IN (1, SIZE(FixedAccrualSchedule), 1) DO \n"
257 " accrualPeriodIdx = DATEINDEX(FixedAccrualSchedule[d], FixedDeterminationSchedule, GEQ) - 1;\n"
258 " IF accrualPeriodIdx > 0 AND accrualPeriodIdx < SIZE(FixedDeterminationSchedule) THEN\n"
259 " IF lastIdx != accrualPeriodIdx THEN\n"
260 " accrualFractions[lastIdx] = accrualFractions[lastIdx] / totalDays;\n"
261 " lastIdx = accrualPeriodIdx;\n"
265 " allAssetsTriggered = 1;"
266 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
267 " IF Underlyings[u](FixedAccrualSchedule[d]) < FixedTriggerLevels[accrualPeriodIdx] * InitialPrices[u] THEN\n"
268 " allAssetsTriggered = 0;\n"
271 " accrualFractions[accrualPeriodIdx] = accrualFractions[accrualPeriodIdx] + allAssetsTriggered;\n"
272 " totalDays = totalDays + 1;\n"
273 " IF d == SIZE(FixedAccrualSchedule) THEN\n"
274 " accrualFractions[SIZE(FixedTriggerLevels)] = accrualFractions[SIZE(FixedTriggerLevels)] / totalDays;\n"
280 "FOR d IN (2, n, 1) DO\n"
281 + floatingFixingScript +
282 " floatingAccrualFraction = dcf(FloatingDayCountFraction, FloatingPeriodSchedule[d-1], FloatingPeriodSchedule[d]);\n"
283 " Option = Option + LOGPAY(-1 * LongShort * Quantity * alive * fixing * floatingAccrualFraction,\n"
284 " FloatingFixingSchedule[d-1], FloatingPayDates[d+ad], Currency, 1, FloatingLeg);\n"
286 " allAssetsTriggered = 1;\n"
287 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
288 " IF Underlyings[u](FixedDeterminationSchedule[d+cd]) < FixedTriggerLevels[d-1] * InitialPrices[u] THEN\n"
289 " allAssetsTriggered = 0;\n"
292 " IF AccruingFixedCoupons == 1 THEN\n"
293 " fixedAccrualFraction = allAssetsTriggered * accrualFractions[d-1] + (1-allAssetsTriggered) * fixedAccrualFraction;\n"
295 " fixedAccrualFraction = allAssetsTriggered + (1-allAssetsTriggered) * fixedAccrualFraction;\n"
297 " Option = Option + LOGPAY(allAssetsTriggered * LongShort * Quantity * alive * FixedRate * couponAccumulation * fixedAccrualFraction,\n"
298 " FixedDeterminationSchedule[d+cd], FixedPayDates[d+fd], Currency, 2, FixedCouponLeg);\n"
299 " couponAccumulation = allAssetsTriggered + (1-allAssetsTriggered) * couponAccumulation;\n"
300 " IF AccumulatingFixedCoupons == 1 THEN\n"
301 " couponAccumulation = couponAccumulation + (1 - allAssetsTriggered);\n"
305 " worstPerformance = 999999.9;\n"
306 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
307 " indexInitial = InitialPrices[u];\n"
308 " indexFinal = Underlyings[u](FloatingPeriodSchedule[n]);\n"
309 " performance = indexFinal / indexInitial;\n"
311 " IF performance < worstPerformance THEN\n"
312 " worstPerformance = performance;\n"
316 " IF worstPerformance < KnockInLevel THEN\n"
320 " IF worstPerformance < Strike THEN\n"
321 " payoff = worstPerformance - Strike;\n"
322 " Option = Option + LOGPAY(LongShort * Quantity * alive * payoff * knockedIn, FloatingPeriodSchedule[n],\n"
323 " KnockInPayDate, Currency, 3, EquityAmountPayoff);\n"
328 " allAssetsTriggered = 1;\n"
329 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
330 " IF Underlyings[u](KnockOutDeterminationSchedule[d+ed]) < KnockOutLevels[d-1] * InitialPrices[u] THEN\n"
331 " allAssetsTriggered = 0;\n"
334 " alive = alive * (1 - allAssetsTriggered);\n"
339 {{
"currentNotional",
"Quantity"},
340 {
"notionalCurrency",
"Currency"}},
354 std::string assetClass = boost::any_cast<std::string>(
additionalData_[
"isdaAssetClass"]);
355 if (assetClass ==
"Equity") {
357 additionalData_[
"isdaSubProduct"] = string(
"Price Return Basic Performance");
358 }
else if (assetClass ==
"Commodity") {
361 additionalData_[
"isdaSubProduct"] = string(
"Price Return Basic Performance");
362 }
else if (assetClass ==
"Foreign Exchange") {
372 std::vector<string> underlyings;
376 indices_.emplace_back(
"Index",
"Underlyings", underlyings);
387 shift = shift.empty() ?
"0D" : shift;
393 convention = convention.empty() ?
"Unadjusted" : convention;
409 QL_REQUIRE(tradeDataNode,
"WorstOfBasketSwapData node not found");
417 QL_REQUIRE(initialPricesNode,
"Could not find an InitialPrices node.");
419 for (
auto const& p : initialPrices)
423 QL_REQUIRE(fixedTriggerLevelsNode,
"Could not find a FixedTriggerLevels node.");
425 for (
auto const& level : fixedTriggerLevels)
429 QL_REQUIRE(knockOutLevelsNode,
"Could not find a KnockOutLevels node.");
431 for (
auto const& level : knockOutLevels)
444 if (knockOutDeterminationSchedule)
460 QL_REQUIRE(underlyingsNode,
"Could not find an Underlyings node.");
462 for (
auto const& u : underlyings) {
514 vector<ScheduleDates> scheduleDates = eventData.
schedule().
dates();
515 for (
auto& d : scheduleDates)
518 vector<ScheduleRules> scheduleRules = eventData.
schedule().
rules();
519 for (
auto& r : scheduleRules)
525 QL_FAIL(
":writeEventData(): unexpected ScriptedTradeEventData::Type");
Serializable schedule data.
const vector< ScheduleDates > & dates() const
virtual void fromXML(XMLNode *node) override
const vector< ScheduleRules > & rules() const
const std::string & convention() const
const ScheduleData & schedule() const
const std::string & name() const
const std::string & shift() const
const std::string & baseSchedule() const
const std::string & calendar() const
std::vector< ScriptedTradeValueTypeData > daycounters_
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > indices_
virtual void setIsdaTaxonomyFields()
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
std::map< std::string, boost::any > additionalData_
const QuantLib::ext::shared_ptr< Underlying > & underlying()
void fromXML(XMLNode *node) override
bool accumulatingFixedCoupons_
vector< QuantLib::ext::shared_ptr< Underlying > > underlyings_
vector< string > initialPrices_
void setIsdaTaxonomyFields() override
vector< string > fixedTriggerLevels_
map< string, pair< ScriptedTradeEventData, string > > schedules_
string floatingRateCutoff_
ScriptedTradeEventData floatingPeriodSchedule_
vector< string > knockOutLevels_
ScriptedTradeEventData fixedDeterminationSchedule_
string initialFixedPayDate_
ScriptedTradeEventData floatingFixingSchedule_
void fromXML(XMLNode *node) override
ScriptedTradeEventData fixedAccrualSchedule_
XMLNode * toXML(XMLDocument &doc) const override
ScriptedTradeEventData floatingPayDates_
DayCounter floatingDayCountFraction_
bool accruingFixedCoupons_
ScriptedTradeEventData knockOutDeterminationSchedule_
ScriptedTradeEventData fixedPayDates_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
ScriptedTradeEventData knockInDeterminationSchedule_
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 getNodeName(XMLNode *n)
Get and set a node's name.
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
static bool getChildValueAsBool(XMLNode *node, const string &name, bool mandatory=false, bool defaultValue=true)
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static string getNodeValue(XMLNode *node)
Get a node's value.
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
string internalIndexName(const string &indexName)
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
bool parseBool(const string &s)
Convert text to bool.
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
QL_DEPRECATED_ENABLE_WARNING std::string scriptedIndexName(const QuantLib::ext::shared_ptr< Underlying > &underlying)
std::string to_string(const LocationInfo &l)
ScriptedTradeEventData readEventData(XMLNode *node)
XMLNode * writeEventData(XMLDocument &doc, ScriptedTradeEventData &eventData)
Schedule makeSchedule(const ScheduleDates &data)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
trade schedule data model and serialization
string conversion utilities