Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
worstofbasketswap.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17 */
18
25
26namespace ore {
27namespace data {
28
29void WorstOfBasketSwap::build(const QuantLib::ext::shared_ptr<EngineFactory>& factory) {
30
31 auto builder = QuantLib::ext::dynamic_pointer_cast<ScriptedTradeEngineBuilder>(factory->builder("ScriptedTrade"));
32
33 // set script parameters
34
35 clear();
37
38 // Manually defined map that specifies which schedules should be mandatory, and which ones should be optional.
39 // Mandatory schedules are specified with a blank string (""). For optional schedules, the default schedule
40 // that they will be derived from must be specified.
41 // clang-format off
42 schedules_ = {
43 // schedule name ST event data fallback schedule
44 // mandatory schedules
45 {"FloatingPeriodSchedule", {floatingPeriodSchedule_, ""}},
46 {"FloatingPayDates", {floatingPayDates_, ""}},
47 // optional schedules
48 {"FloatingFixingSchedule", {floatingFixingSchedule_, "FloatingPeriodSchedule"}},
49 {"FixedDeterminationSchedule", {fixedDeterminationSchedule_, "FloatingPeriodSchedule"}},
50 {"KnockInDeterminationSchedule", {knockInDeterminationSchedule_, "FloatingPeriodSchedule"}},
51 {"KnockOutDeterminationSchedule", {knockOutDeterminationSchedule_, "FloatingPeriodSchedule"}},
52 {"FixedAccrualSchedule", {fixedAccrualSchedule_, "FloatingPeriodSchedule"}},
53 {"FixedPayDates", {fixedPayDates_, "FloatingPayDates"}}
54 };
55 // clang-format on
56
57 string name;
58 string defaultName;
60
62 QL_REQUIRE(fixedAccrualSchedule_.hasData(),
63 "FixedAccrualSchedule must be specified for accruing fixed coupons.");
64 }
65
66 // First, we check the schedule dates that are mandatory
67 for (auto s : schedules_) {
68 name = s.first;
69 ed = s.second.first;
70 defaultName = s.second.second;
71 if (defaultName.empty()) {
72 QL_REQUIRE(ed.hasData(), "Could not find mandatory node " << name << ".");
73 }
74 }
75
76 // Next, we ensure that each optional schedule has a valid EventData schedule
77 for (auto s : schedules_) {
78 name = s.first;
79 ed = s.second.first;
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);
84
85 auto n = schedules_[defaultName].first;
86 ScriptedTradeEventData newEventData;
87
89 newEventData = ScriptedTradeEventData(name, n.schedule());
90 } else if (n.type() == ScriptedTradeEventData::Type::Derived) {
91 newEventData = ScriptedTradeEventData(name, n.baseSchedule(), n.shift(), n.calendar(), n.convention());
92 }
93 schedules_[name].first = newEventData;
94 }
95 }
96
97 // We build the schedules first that are defined by a ScheduleData node
98 for (auto s : schedules_) {
99 ed = s.second.first;
101 events_.emplace_back(ed);
102 }
103 }
104
105 // And then we build the schedules that are defined by a DerivedSchedule node, i.e. are dependent on the above
106 for (auto s : schedules_) {
107 ed = s.second.first;
109 events_.emplace_back(ed);
110 }
111 }
112
113 // check underlying types
114 string type = underlyings_.front()->type();
115 for (auto u : underlyings_) {
116 QL_REQUIRE(u->type() == type, "All of Underlyings must be from the same asset class.");
117 }
118 auto floatingIndex = *factory->market()->iborIndex(floatingIndex_, builder->configuration(MarketContext::pricing));
119 auto ois = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(floatingIndex);
120
121 if (ois) {
122 DLOG("building WorstOfBasketSwap scripted trade wrapper using (internal) script \'Overnight\'")
123 } else {
124 DLOG("building WorstOfBasketSwap scripted trade wrapper using (internal) script \'Standard\'");
125 }
126
127 if (bermudanKnockIn_) {
129 "KnockInDeterminationSchedule must be specified for a Bermudan knock-in.");
130 }
131
133 QL_REQUIRE(fixedAccrualSchedule_.hasData(),
134 "FixedAccrualSchedule must be specified for accruing fixed coupons.");
135 }
136
137 if (knockInPayDate_.empty()) {
138 QuantLib::Date newKnockInPayDate = makeSchedule(schedules_["FloatingPayDates"].first.schedule()).dates().back();
139 knockInPayDate_ = ore::data::to_string(newKnockInPayDate);
140 }
141 events_.emplace_back("KnockInPayDate", knockInPayDate_);
142 if (initialFixedPayDate_.empty()) {
143 QuantLib::Date newInitialFixedPayDate = makeSchedule(schedules_["FloatingPayDates"].first.schedule()).dates().front();
144 initialFixedPayDate_ = ore::data::to_string(newInitialFixedPayDate);
145 }
146 events_.emplace_back("InitialFixedPayDate", initialFixedPayDate_);
147
148 // numbers
149 numbers_.emplace_back("Number", "Quantity", quantity_);
150 strike_ = strike_.empty() ? "1.0" : strike_;
151 numbers_.emplace_back("Number", "Strike", strike_);
153 numbers_.emplace_back("Number", "InitialFixedRate", initialFixedRate_);
154 numbers_.emplace_back("Number", "FixedRate", fixedRate_);
155 numbers_.emplace_back("Number", "InitialPrices", initialPrices_);
156 numbers_.emplace_back("Number", "FixedTriggerLevels", fixedTriggerLevels_);
157 numbers_.emplace_back("Number", "KnockOutLevels", knockOutLevels_);
158 knockInLevel_ = knockInLevel_.empty() ? "1.0" : knockInLevel_;
159 numbers_.emplace_back("Number", "KnockInLevel", knockInLevel_);
161 numbers_.emplace_back("Number", "FloatingSpread", floatingSpread_);
163 if (ois)
164 QL_REQUIRE(parseInteger(floatingRateCutoff_) >= 0, "FloatingRateCutoff should be a non-negative whole number.");
165 numbers_.emplace_back("Number", "FloatingRateCutoff", floatingRateCutoff_);
166 if (ois)
167 QL_REQUIRE(floatingLookback_.units() == TimeUnit::Days,
168 "FloatingLookback (" << floatingLookback_ << ") should be given with units days.");
169 numbers_.emplace_back("Number", "FloatingLookback", std::to_string(floatingLookback_.length()));
170
171 // booleans
172 numbers_.emplace_back("Number", "BermudanKnockIn", bermudanKnockIn_ ? "1" : "-1");
173 numbers_.emplace_back("Number", "AccumulatingFixedCoupons", accumulatingFixedCoupons_ ? "1" : "-1");
174 numbers_.emplace_back("Number", "AccruingFixedCoupons", accruingFixedCoupons_ ? "1" : "-1");
175 numbers_.emplace_back("Number", "LongShort", parsePositionType(longShort_) == Position::Long ? "1" : "-1");
176 numbers_.emplace_back("Number", "IsAveraged", isAveraged_ ? "1" : "-1");
177 numbers_.emplace_back("Number", "IncludeSpread", includeSpread_ ? "1" : "-1");
178
179 //bool inArrears;
180 //if (inArrears_.empty()) {
181 // // If left blank or omitted, default to true if OIS, otherwise (e.g. ibor) default to false
182 // inArrears = ois ? true : false;
183 //} else {
184 // inArrears = parseBool(inArrears_);
185 //}
186 //numbers_.emplace_back("Number", "IsInArrears", inArrears ? "1" : "-1");
187
188 // daycounters
189 daycounters_.emplace_back("DayCounter", "FloatingDayCountFraction", floatingDayCountFraction_.name());
190
191 // currencies
192 currencies_.emplace_back("Currency", "Currency", currency_);
193
194 // set product tag accordingly
195 if (type == "InterestRate") {
196 productTag_ = "MultiUnderlyingIrOption";
197 } else {
198 productTag_ = "MultiAssetOptionAD({AssetClass})";
199 }
200
201 LOG("ProductTag=" << productTag_);
202
203 // set script
204
205 // clang-format off
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");
210
211 const std::string floatingFixingScript = ois ? fixingScriptOvernight : fixingScriptStandard;
212
213 // clang-format on
214
215 script_ = {
216 // clang-format off
217 {"",
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"
224 "\n"
225 "Option = Option + LOGPAY(LongShort * Quantity * InitialFixedRate, InitialFixedPayDate,\n"
226 " InitialFixedPayDate, Currency, 0, InitialFixedAmount);\n"
227 "\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"
235 "\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"
241 "\n"
242 "couponAccumulation = 1;\n"
243 "alive = 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"
248 " knockedIn = 1;\n"
249 " END;\n"
250 " END;\n"
251 " END;\n"
252 "END;\n"
253 "\n"
254 "IF AccruingFixedCoupons == 1 THEN\n"
255 " lastIdx = 1;\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"
262 " totalDays = 1;\n"
263 " END;\n"
264 "\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"
269 " END;\n"
270 " END;\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"
275 " END;\n"
276 " END;\n"
277 " END;\n"
278 "END;\n"
279 "\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"
285 "\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"
290 " END;\n"
291 " END;\n"
292 " IF AccruingFixedCoupons == 1 THEN\n"
293 " fixedAccrualFraction = allAssetsTriggered * accrualFractions[d-1] + (1-allAssetsTriggered) * fixedAccrualFraction;\n"
294 " ELSE\n"
295 " fixedAccrualFraction = allAssetsTriggered + (1-allAssetsTriggered) * fixedAccrualFraction;\n"
296 " END;\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"
302 " END;\n"
303 "\n"
304 " IF d == n THEN\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"
310 "\n"
311 " IF performance < worstPerformance THEN\n"
312 " worstPerformance = performance;\n"
313 " END;\n"
314 " END;\n"
315 "\n"
316 " IF worstPerformance < KnockInLevel THEN\n"
317 " knockedIn = 1;\n"
318 " END;\n"
319 "\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"
324 " END;\n"
325 " END;\n"
326 "\n"
327 " IF d != n THEN\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"
332 " END;\n"
333 " END;\n"
334 " alive = alive * (1 - allAssetsTriggered);\n"
335 " END;\n"
336 "END;\n",
337 //
338 "Option",
339 {{"currentNotional", "Quantity"},
340 {"notionalCurrency", "Currency"}},
341 {})}};
342 // clang-format on
343
344 // build trade
345
346 ScriptedTrade::build(factory);
347}
348
351
352 // ISDA taxonomy
353 // asset class set in the base class already
354 std::string assetClass = boost::any_cast<std::string>(additionalData_["isdaAssetClass"]);
355 if (assetClass == "Equity") {
356 additionalData_["isdaBaseProduct"] = string("Other");
357 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
358 } else if (assetClass == "Commodity") {
359 // isda taxonomy missing for this class, using the same as equity
360 additionalData_["isdaBaseProduct"] = string("Other");
361 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
362 } else if (assetClass == "Foreign Exchange") {
363 additionalData_["isdaBaseProduct"] = string("Exotic");
364 additionalData_["isdaSubProduct"] = string("Generic");
365 }
366 additionalData_["isdaTransaction"] = string("Basket");
367}
368
370 indices_.emplace_back("Index", "FloatingIndex", floatingIndex_);
371
372 std::vector<string> underlyings;
373 for (auto const& u : underlyings_) {
374 underlyings.push_back(scriptedIndexName(u));
375 }
376 indices_.emplace_back("Index", "Underlyings", underlyings);
377}
378
380 ScriptedTradeEventData eventData;
381
382 string name = XMLUtils::getNodeName(node);
383 if (XMLNode* sch = XMLUtils::getChildNode(node, "DerivedSchedule")) {
384 string baseSchedule = XMLUtils::getChildValue(sch, "BaseSchedule", true);
385
386 string shift = XMLUtils::getChildValue(sch, "Shift", false);
387 shift = shift.empty() ? "0D" : shift;
388
389 string calendar = XMLUtils::getChildValue(sch, "Calendar", false);
390 calendar = calendar.empty() ? "NullCalendar" : calendar;
391
392 string convention = XMLUtils::getChildValue(sch, "Convention", false);
393 convention = convention.empty() ? "Unadjusted" : convention;
394
395 eventData = ScriptedTradeEventData(name, baseSchedule, shift, calendar, convention);
396
397 } else {
398 ScheduleData scheduleData = ScheduleData();
399 scheduleData.fromXML(node);
400 eventData = ScriptedTradeEventData(name, scheduleData);
401 }
402
403 return eventData;
404}
405
407 Trade::fromXML(node);
408 XMLNode* tradeDataNode = XMLUtils::getChildNode(node, tradeType() + "Data");
409 QL_REQUIRE(tradeDataNode, "WorstOfBasketSwapData node not found");
410 longShort_ = XMLUtils::getChildValue(tradeDataNode, "LongShort", true);
411 quantity_ = XMLUtils::getChildValue(tradeDataNode, "Quantity", true);
412 strike_ = XMLUtils::getChildValue(tradeDataNode, "Strike", false);
413 initialFixedRate_ = XMLUtils::getChildValue(tradeDataNode, "InitialFixedRate", false);
414 fixedRate_ = XMLUtils::getChildValue(tradeDataNode, "FixedRate", true);
415
416 XMLNode* initialPricesNode = XMLUtils::getChildNode(tradeDataNode, "InitialPrices");
417 QL_REQUIRE(initialPricesNode, "Could not find an InitialPrices node.");
418 auto initialPrices = XMLUtils::getChildrenNodes(initialPricesNode, "InitialPrice");
419 for (auto const& p : initialPrices)
421
422 XMLNode* fixedTriggerLevelsNode = XMLUtils::getChildNode(tradeDataNode, "FixedTriggerLevels");
423 QL_REQUIRE(fixedTriggerLevelsNode, "Could not find a FixedTriggerLevels node.");
424 auto fixedTriggerLevels = XMLUtils::getChildrenNodes(fixedTriggerLevelsNode, "FixedTriggerLevel");
425 for (auto const& level : fixedTriggerLevels)
427
428 XMLNode* knockOutLevelsNode = XMLUtils::getChildNode(tradeDataNode, "KnockOutLevels");
429 QL_REQUIRE(knockOutLevelsNode, "Could not find a KnockOutLevels node.");
430 auto knockOutLevels = XMLUtils::getChildrenNodes(knockOutLevelsNode, "KnockOutLevel");
431 for (auto const& level : knockOutLevels)
432 knockOutLevels_.push_back(XMLUtils::getNodeValue(level));
433
434 if (XMLNode* floatingPeriodSchedule = XMLUtils::getChildNode(tradeDataNode, "FloatingPeriodSchedule"))
435 floatingPeriodSchedule_ = readEventData(floatingPeriodSchedule);
436
437 if (XMLNode* floatingFixingSchedule = XMLUtils::getChildNode(tradeDataNode, "FloatingFixingSchedule"))
438 floatingFixingSchedule_ = readEventData(floatingFixingSchedule);
439
440 if (XMLNode* fixedDeterminationSchedule = XMLUtils::getChildNode(tradeDataNode, "FixedDeterminationSchedule"))
441 fixedDeterminationSchedule_ = readEventData(fixedDeterminationSchedule);
442
443 XMLNode* knockOutDeterminationSchedule = XMLUtils::getChildNode(tradeDataNode, "KnockOutDeterminationSchedule");
444 if (knockOutDeterminationSchedule)
445 knockOutDeterminationSchedule_ = readEventData(knockOutDeterminationSchedule);
446
447 if (XMLNode* knockInDeterminationSchedule = XMLUtils::getChildNode(tradeDataNode, "KnockInDeterminationSchedule"))
448 knockInDeterminationSchedule_ = readEventData(knockInDeterminationSchedule);
449
450 if (XMLNode* fixedAccrualSchedule = XMLUtils::getChildNode(tradeDataNode, "FixedAccrualSchedule"))
451 fixedAccrualSchedule_ = readEventData(fixedAccrualSchedule);
452
453 if (XMLNode* floatingPayDates = XMLUtils::getChildNode(tradeDataNode, "FloatingPayDates"))
454 floatingPayDates_ = readEventData(floatingPayDates);
455
456 if (XMLNode* fixedPayDates = XMLUtils::getChildNode(tradeDataNode, "FixedPayDates"))
457 fixedPayDates_ = readEventData(fixedPayDates);
458
459 XMLNode* underlyingsNode = XMLUtils::getChildNode(tradeDataNode, "Underlyings");
460 QL_REQUIRE(underlyingsNode, "Could not find an Underlyings node.");
461 auto underlyings = XMLUtils::getChildrenNodes(underlyingsNode, "Underlying");
462 for (auto const& u : underlyings) {
463 UnderlyingBuilder underlyingBuilder;
464 underlyingBuilder.fromXML(u);
465 underlyings_.push_back(underlyingBuilder.underlying());
466 }
467
468 knockInPayDate_ = XMLUtils::getChildValue(tradeDataNode, "KnockInPayDate", false);
469 initialFixedPayDate_ = XMLUtils::getChildValue(tradeDataNode, "InitialFixedPayDate", false);
470
471 string bermudanKnockIn = XMLUtils::getChildValue(tradeDataNode, "BermudanKnockIn", false);
472 bermudanKnockIn_ = bermudanKnockIn.empty() ? false : parseBool(bermudanKnockIn);
473
474 string accumulatingFixedCoupons = XMLUtils::getChildValue(tradeDataNode, "AccumulatingFixedCoupons", false);
475 accumulatingFixedCoupons_ = accumulatingFixedCoupons.empty() ? false : parseBool(accumulatingFixedCoupons);
476
477 string accruingFixedCoupons = XMLUtils::getChildValue(tradeDataNode, "AccruingFixedCoupons", false);
478 accruingFixedCoupons_ = accruingFixedCoupons.empty() ? false : parseBool(accruingFixedCoupons);
479
480 floatingIndex_ = internalIndexName(XMLUtils::getChildValue(tradeDataNode, "FloatingIndex", true));
481
482 floatingSpread_ = XMLUtils::getChildValue(tradeDataNode, "FloatingSpread", false);
483 string floatingDayCountFraction = XMLUtils::getChildValue(tradeDataNode, "FloatingDayCountFraction", true);
484 floatingDayCountFraction_ = parseDayCounter(floatingDayCountFraction);
485
486 string floatingLookback = XMLUtils::getChildValue(tradeDataNode, "FloatingLookback", false);
487 floatingLookback_ = floatingLookback.empty() ? 0 * Days : parsePeriod(floatingLookback);
488
489 floatingRateCutoff_ = XMLUtils::getChildValue(tradeDataNode, "FloatingRateCutoff", false);
490
491 isAveraged_ = XMLUtils::getChildValueAsBool(tradeDataNode, "IsAveraged", false, false);
492
493 //inArrears_ = XMLUtils::getChildValue(tradeDataNode, "IsInArrears", false);
494
495 includeSpread_ = XMLUtils::getChildValueAsBool(tradeDataNode, "IncludeSpread", false, false);
496
497 knockInLevel_ = XMLUtils::getChildValue(tradeDataNode, "KnockInLevel", false);
498 currency_ = XMLUtils::getChildValue(tradeDataNode, "Currency", true);
499
500 initIndices();
501}
502
504 XMLNode* n = doc.allocNode(eventData.name());
505 if (eventData.type() == ScriptedTradeEventData::Type::Derived) {
506 XMLNode* derivedSchedule = doc.allocNode("DerivedSchedule");
507 XMLUtils::addChild(doc, derivedSchedule, "BaseSchedule", eventData.baseSchedule());
508 XMLUtils::addChild(doc, derivedSchedule, "Shift", eventData.shift());
509 XMLUtils::addChild(doc, derivedSchedule, "Calendar", eventData.calendar());
510 XMLUtils::addChild(doc, derivedSchedule, "Convention", eventData.convention());
511 XMLUtils::appendNode(n, derivedSchedule);
512 } else if (eventData.type() == ScriptedTradeEventData::Type::Array) {
513 if (!eventData.schedule().dates().empty()) {
514 vector<ScheduleDates> scheduleDates = eventData.schedule().dates();
515 for (auto& d : scheduleDates)
516 XMLUtils::appendNode(n, d.toXML(doc));
517 } else {
518 vector<ScheduleRules> scheduleRules = eventData.schedule().rules();
519 for (auto& r : scheduleRules)
520 XMLUtils::appendNode(n, r.toXML(doc));
521 }
522 //ScheduleData scheduleData = eventData.schedule();
523 //XMLUtils::appendNode(n, scheduleData.toXML(doc));
524 } else {
525 QL_FAIL(":writeEventData(): unexpected ScriptedTradeEventData::Type");
526 }
527 return n;
528}
529
531 XMLNode* node = Trade::toXML(doc);
532 XMLNode* tradeNode = doc.allocNode(tradeType() + "Data");
533 XMLUtils::appendNode(node, tradeNode);
534 XMLUtils::addChild(doc, tradeNode, "LongShort", longShort_);
535 XMLUtils::addChild(doc, tradeNode, "Currency", currency_);
536 XMLUtils::addChild(doc, tradeNode, "Quantity", quantity_);
537 XMLUtils::addChild(doc, tradeNode, "Strike", strike_);
538 XMLUtils::addChild(doc, tradeNode, "InitialFixedRate", initialFixedRate_);
539 XMLUtils::addChild(doc, tradeNode, "InitialFixedPayDate", initialFixedPayDate_);
540 XMLUtils::addChild(doc, tradeNode, "FixedRate", fixedRate_);
541
542 XMLNode* underlyingsNode = doc.allocNode("Underlyings");
543 for (auto const& u : underlyings_)
544 XMLUtils::appendNode(underlyingsNode, u->toXML(doc));
545 XMLUtils::appendNode(tradeNode, underlyingsNode);
546
547 XMLNode* initialPricesNode = doc.allocNode("InitialPrices");
548 for (auto const& p : initialPrices_)
549 XMLUtils::addChild(doc, initialPricesNode, "InitialPrice", p);
550 XMLUtils::appendNode(tradeNode, initialPricesNode);
551
552 XMLUtils::addChild(doc, tradeNode, "BermudanKnockIn", bermudanKnockIn_);
553 XMLUtils::addChild(doc, tradeNode, "KnockInLevel", knockInLevel_);
554
555 XMLNode* fixedTriggerLevelsNode = doc.allocNode("FixedTriggerLevels");
556 for (auto const& level : fixedTriggerLevels_)
557 XMLUtils::addChild(doc, fixedTriggerLevelsNode, "FixedTriggerLevel", level);
558 XMLUtils::appendNode(tradeNode, fixedTriggerLevelsNode);
559
560 XMLNode* knockOutLevelsNode = doc.allocNode("KnockOutLevels");
561 for (auto const& p : knockOutLevels_)
562 XMLUtils::addChild(doc, knockOutLevelsNode, "KnockOutLevel", p);
563 XMLUtils::appendNode(tradeNode, knockOutLevelsNode);
564
565 for (auto sch : schedules_) {
566 XMLNode* tmp = writeEventData(doc, sch.second.first);
567 XMLUtils::appendNode(tradeNode, tmp);
568 }
569
570 XMLUtils::addChild(doc, tradeNode, "KnockInPayDate", knockInPayDate_);
571 XMLUtils::addChild(doc, tradeNode, "AccruingFixedCoupons", accruingFixedCoupons_);
572 XMLUtils::addChild(doc, tradeNode, "AccumulatingFixedCoupons", accumulatingFixedCoupons_);
573 XMLUtils::addChild(doc, tradeNode, "FloatingIndex", floatingIndex_);
574 if (!floatingSpread_.empty())
575 XMLUtils::addChild(doc, tradeNode, "FloatingSpread", floatingSpread_);
576 XMLUtils::addChild(doc, tradeNode, "FloatingDayCountFraction", floatingDayCountFraction_.name());
577
578 XMLUtils::addChild(doc, tradeNode, "FloatingLookback", floatingLookback_);
579 if (!floatingRateCutoff_.empty())
580 XMLUtils::addChild(doc, tradeNode, "FloatingRateCutoff", floatingRateCutoff_);
581 XMLUtils::addChild(doc, tradeNode, "IsAveraged", isAveraged_);
582 //if (!inArrears_.empty())
583 // XMLUtils::addChild(doc, tradeNode, "IsInArrears", inArrears_);
584 XMLUtils::addChild(doc, tradeNode, "IncludeSpread", includeSpread_);
585
586 return node;
587}
588
589} // namespace data
590} // namespace ore
Serializable schedule data.
Definition: schedule.hpp:202
const vector< ScheduleDates > & dates() const
Definition: schedule.hpp:228
virtual void fromXML(XMLNode *node) override
Definition: schedule.cpp:179
const vector< ScheduleRules > & rules() const
Definition: schedule.hpp:229
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
Definition: trade.cpp:34
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
const string & tradeType() const
Definition: trade.hpp:133
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
const QuantLib::ext::shared_ptr< Underlying > & underlying()
Definition: underlying.hpp:266
void fromXML(XMLNode *node) override
Definition: underlying.cpp:305
vector< QuantLib::ext::shared_ptr< Underlying > > underlyings_
map< string, pair< ScriptedTradeEventData, string > > schedules_
ScriptedTradeEventData floatingPeriodSchedule_
ScriptedTradeEventData fixedDeterminationSchedule_
ScriptedTradeEventData floatingFixingSchedule_
void fromXML(XMLNode *node) override
ScriptedTradeEventData fixedAccrualSchedule_
XMLNode * toXML(XMLDocument &doc) const override
ScriptedTradeEventData floatingPayDates_
ScriptedTradeEventData knockOutDeterminationSchedule_
ScriptedTradeEventData fixedPayDates_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
ScriptedTradeEventData knockInDeterminationSchedule_
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
Definition: xmlutils.cpp:428
static string getNodeName(XMLNode *n)
Get and set a node's name.
Definition: xmlutils.cpp:473
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
static bool getChildValueAsBool(XMLNode *node, const string &name, bool mandatory=false, bool defaultValue=true)
Definition: xmlutils.cpp:296
static XMLNode * getChildNode(XMLNode *n, const string &name="")
Definition: xmlutils.cpp:387
static string getNodeValue(XMLNode *node)
Get a node's value.
Definition: xmlutils.cpp:489
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
string internalIndexName(const string &indexName)
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Definition: parsers.cpp:404
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
Definition: parsers.cpp:136
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Definition: parsers.cpp:209
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Calendar calendar
Definition: utilities.cpp:441
QL_DEPRECATED_ENABLE_WARNING std::string scriptedIndexName(const QuantLib::ext::shared_ptr< Underlying > &underlying)
Definition: utilities.cpp:614
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
ScriptedTradeEventData readEventData(XMLNode *node)
XMLNode * writeEventData(XMLDocument &doc, ScriptedTradeEventData &eventData)
Schedule makeSchedule(const ScheduleDates &data)
Definition: schedule.cpp:263
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
trade schedule data model and serialization
some utility functions
string conversion utilities
string name