Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
accumulator.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 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
21
24
25#include <boost/lexical_cast.hpp>
26
27namespace ore {
28namespace data {
29
30// clang-format off
31
32 static const std::string accumulator01_script =
33 " REQUIRE SIZE(FixingDates) == SIZE(SettlementDates);\n"
34 " REQUIRE KnockOutType == 3 OR KnockOutType == 4;\n"
35 " NUMBER Payoff, fix, d, r, Alive, currentNotional, Factor, ThisPayout, Fixing[SIZE(FixingDates)], dailyMult;\n"
36 " Alive = 1;\n"
37 " dailyMult = 1;\n"
38 " FOR d IN (1, SIZE(FixingDates), 1) DO\n"
39 " fix = Underlying(FixingDates[d]);\n"
40 " Fixing[d] = fix;\n"
41 "\n"
42 " IF DailyFixingAmount == 1 THEN\n"
43 " IF d == 1 THEN\n"
44 " dailyMult = days(DailyFixingAmountDayCounter, StartDate, FixingDates[d]);\n"
45 " ELSE\n"
46 " dailyMult = days(DailyFixingAmountDayCounter, FixingDates[d-1], FixingDates[d]);\n"
47 " END;\n"
48 " END;\n"
49 "\n"
50 " IF AmericanKO == 1 THEN\n"
51 " IF KnockOutType == 4 THEN\n"
52 " IF FixingDates[d] >= StartDate THEN\n"
53 " IF d == 1 OR FixingDates[d-1] <= StartDate THEN\n"
54 " Alive = Alive * (1 - ABOVEPROB(Underlying, StartDate, FixingDates[d], KnockOutLevel));\n"
55 " ELSE\n"
56 " Alive = Alive * (1 - ABOVEPROB(Underlying, FixingDates[d-1], FixingDates[d], KnockOutLevel));\n"
57 " END;\n"
58 " END;\n"
59 " ELSE\n"
60 " IF FixingDates[d] >= StartDate THEN\n"
61 " IF d == 1 OR FixingDates[d-1] <= StartDate THEN\n"
62 " Alive = Alive * (1 - BELOWPROB(Underlying, StartDate, FixingDates[d], KnockOutLevel));\n"
63 " ELSE\n"
64 " Alive = Alive * (1 - BELOWPROB(Underlying, FixingDates[d-1], FixingDates[d], KnockOutLevel));\n"
65 " END;\n"
66 " END;\n"
67 " END;\n"
68 " ELSE\n"
69 " IF {KnockOutType == 4 AND fix >= KnockOutLevel} OR\n"
70 " {KnockOutType == 3 AND fix <= KnockOutLevel} THEN\n"
71 " Alive = 0;\n"
72 " END;\n"
73 " END;\n"
74 "\n"
75 " IF d <= GuaranteedFixings THEN\n"
76 " Factor = 1;\n"
77 " ELSE\n"
78 " Factor = Alive;\n"
79 " END;\n"
80 "\n"
81 " FOR r IN (1, SIZE(RangeUpperBounds), 1) DO\n"
82 " IF fix > RangeLowerBounds[r] AND fix <= RangeUpperBounds[r] THEN\n"
83 " IF NakedOption == 1 THEN\n"
84 " ThisPayout = abs(RangeLeverages[r]) * FixingAmount * dailyMult * max(0, OptionType * (fix - Strike[r])) * Factor;\n"
85 " ELSE\n"
86 " ThisPayout = RangeLeverages[r] * FixingAmount * dailyMult * (fix - Strike[r]) * Factor;\n"
87 " END;\n"
88 " IF d > GuaranteedFixings OR ThisPayout >= 0 THEN\n"
89 " Payoff = Payoff + LOGPAY(ThisPayout, FixingDates[d], SettlementDates[d], PayCcy);\n"
90 " END;\n"
91 " END;\n"
92 " END;\n"
93 " END;\n"
94 " value = LongShort * Payoff;\n"
95 " currentNotional = FixingAmount * dailyMult * Strike[1];";
96
97
98 static const std::string accumulator02_script =
99 " REQUIRE SIZE(ObservationDates) == SIZE(KnockOutSettlementDates);\n"
100 " REQUIRE SIZE(ObservationPeriodEndDates) == SIZE(SettlementDates);\n"
101 " REQUIRE SIZE(RangeUpperBounds) == SIZE(RangeLowerBounds);\n"
102 " REQUIRE SIZE(RangeUpperBounds) == SIZE(RangeLeverages);\n"
103 " REQUIRE ObservationPeriodEndDates[SIZE(ObservationPeriodEndDates)] >= ObservationDates[SIZE(ObservationDates)];\n"
104 " NUMBER Payoff, fix, d, dd, KnockedOut, currentNotional, Days[SIZE(RangeUpperBounds)], knockOutDays, Fixing[SIZE(ObservationPeriodEndDates)];\n"
105 " NUMBER currentPeriod, r, ThisPayout;\n"
106 " currentPeriod = 1;\n"
107 " FOR d IN (1, SIZE(ObservationDates), 1) DO\n"
108 " fix = Underlying(ObservationDates[d]);\n"
109 "\n"
110 " knockOutDays = max(DATEINDEX(GuaranteedPeriodEndDate, ObservationDates, GT) - 1 - d, 0);\n"
111 "\n"
112 " IF KnockedOut == 0 THEN\n"
113 " IF {KnockOutType == 4 AND fix >= KnockOutLevel} OR\n"
114 " {KnockOutType == 3 AND fix <= KnockOutLevel} THEN\n"
115 " KnockedOut = 1;\n"
116 " Days[DefaultRange] = Days[DefaultRange] + knockOutDays;\n"
117 " FOR r IN (1, SIZE(RangeUpperBounds), 1) DO\n"
118 " IF NakedOption == 1 THEN\n"
119 " ThisPayout = LongShort * FixingAmount * abs(RangeLeverages[r]) * Days[r] * max(0, OptionType * (fix - Strike) );\n"
120 " ELSE\n"
121 " ThisPayout = LongShort * FixingAmount * RangeLeverages[r] * Days[r] * ( fix - Strike );\n"
122 " END;\n"
123 " value = value + PAY( ThisPayout, ObservationDates[d], KnockOutSettlementDates[d], PayCcy );\n"
124 " END;\n"
125 " END;\n"
126 " END;\n"
127 "\n"
128 " IF KnockedOut == 0 THEN\n"
129 " FOR r IN (1, SIZE(RangeUpperBounds), 1) DO\n"
130 " IF fix > RangeLowerBounds[r] AND fix <= RangeUpperBounds[r] THEN\n"
131 " Days[r] = Days[r] + 1;\n"
132 " END;\n"
133 " END;\n"
134 " IF ObservationDates[d] >= ObservationPeriodEndDates[currentPeriod] THEN\n"
135 " FOR r IN (1, SIZE(RangeUpperBounds), 1) DO\n"
136 " IF NakedOption == 1 THEN\n"
137 " ThisPayout = LongShort * FixingAmount * abs(RangeLeverages[r]) * Days[r] * max(0, OptionType * (fix - Strike) );\n"
138 " ELSE\n"
139 " ThisPayout = LongShort * FixingAmount * RangeLeverages[r] * Days[r] * ( fix - Strike );\n"
140 " END;\n"
141 " value = value + LOGPAY( ThisPayout, ObservationDates[d], SettlementDates[currentPeriod], PayCcy );\n"
142 " END;\n"
143 " END;\n"
144 " END;\n"
145 " IF ObservationDates[d] >= ObservationPeriodEndDates[currentPeriod] THEN\n"
146 " Fixing[currentPeriod] = fix;\n"
147 " currentPeriod = currentPeriod + 1;\n"
148 " FOR r IN (1, SIZE(RangeUpperBounds), 1) DO\n"
149 " Days[r] = 0;\n"
150 " END;\n"
151 " END;\n"
152 " END;\n"
153 " currentNotional = FixingAmount * Strike;";
154
155
156 static const std::string accumulator02_script_fd =
157 " REQUIRE SIZE(ObservationDates) == SIZE(KnockOutSettlementDates);\n"
158 " REQUIRE SIZE(ObservationPeriodEndDates) == SIZE(SettlementDates);\n"
159 " REQUIRE SIZE(RangeUpperBounds) == SIZE(RangeLowerBounds);\n"
160 " REQUIRE SIZE(RangeUpperBounds) == SIZE(RangeLeverages);\n"
161 " REQUIRE ObservationPeriodEndDates[SIZE(ObservationPeriodEndDates)] >= ObservationDates[SIZE(ObservationDates)];\n"
162 "\n"
163 " NUMBER currentPeriod, referencePayout, fix, d, r, dd, currentNotional, Fixing[SIZE(ObservationPeriodEndDates)], ThisPayout;\n"
164 "\n"
165 " currentPeriod = DATEINDEX(ObservationDates[SIZE(ObservationDates)], ObservationPeriodEndDates, GEQ);\n"
166 " IF NakedOption == 1 THEN\n"
167 " ThisPayout = max(0, OptionType * (Underlying(ObservationDates[SIZE(ObservationDates)]) - Strike) );\n"
168 " ELSE\n"
169 " ThisPayout = Underlying(ObservationDates[SIZE(ObservationDates)]) - Strike;\n"
170 " END;\n"
171 " referencePayout = PAY( LongShort * FixingAmount * ThisPayout, ObservationDates[SIZE(ObservationDates)],\n"
172 " SettlementDates[currentPeriod], PayCcy );\n"
173 " value = 0 * referencePayout;\n"
174 "\n"
175 " FOR d IN (SIZE(ObservationDates), 1, -1) DO\n"
176 "\n"
177 " IF ObservationDates[d] >= TODAY THEN\n"
178 " value = NPV(value, ObservationDates[d]);\n"
179 " referencePayout = NPV(referencePayout, ObservationDates[d]);\n"
180 " ELSE\n"
181 " value = NPV(value, TODAY);\n"
182 " referencePayout = NPV(referencePayout, TODAY);\n"
183 " END;\n"
184 "\n"
185 " fix = Underlying(ObservationDates[d]);\n"
186 " IF NakedOption == 1 THEN\n"
187 " ThisPayout = LongShort * FixingAmount * max(0, OptionType * (fix - Strike));\n"
188 " ELSE\n"
189 " ThisPayout = LongShort * FixingAmount * (fix - Strike);\n"
190 " END;\n"
191 "\n"
192 " IF d > 1 AND currentPeriod > 0 AND ObservationDates[d-1] < ObservationPeriodEndDates[currentPeriod] THEN\n"
193 " referencePayout = PAY( ThisPayout, ObservationDates[d], SettlementDates[currentPeriod], PayCcy );\n"
194 " Fixing[currentPeriod] = fix;\n"
195 " currentPeriod = currentPeriod - 1;\n"
196 " END;\n"
197 "\n"
198 " IF {KnockOutType == 4 AND fix >= KnockOutLevel} OR\n"
199 " {KnockOutType == 3 AND fix <= KnockOutLevel} THEN\n"
200 " IF NakedOption == 1 THEN\n"
201 " ThisPayout = ThisPayout * abs(RangeLeverages[DefaultRange]);\n"
202 " ELSE\n"
203 " ThisPayout = ThisPayout * RangeLeverages[DefaultRange];\n"
204 " END;\n"
205 " referencePayout = PAY( ThisPayout, ObservationDates[d], KnockOutSettlementDates[d], PayCcy );\n"
206 " value = referencePayout * max(DATEINDEX(GuaranteedPeriodEndDate, ObservationDates, GT) - 1 - d, 0);\n"
207 " ELSE\n"
208 " FOR r IN (1, SIZE(RangeUpperBounds), 1) DO\n"
209 " IF fix > RangeLowerBounds[r] AND fix <= RangeUpperBounds[r] THEN\n"
210 " IF NakedOption == 1 THEN\n"
211 " value = value + abs(RangeLeverages[r]) * referencePayout;\n"
212 " ELSE\n"
213 " value = value + RangeLeverages[r] * referencePayout;\n"
214 " END;\n"
215 " END;\n"
216 " END;\n"
217 " END;\n"
218 " END;\n"
219 " currentNotional = FixingAmount * Strike;";
220
221// clang-format on
222
223void Accumulator::build(const QuantLib::ext::shared_ptr<EngineFactory>& factory) {
224
225 // set script parameters
226
227 clear();
228 initIndices();
229
230 enum class AccumulatorScript { Accumulator01, Accumulator02 };
231 AccumulatorScript scriptToUse;
232 if (!pricingDates_.hasData()) {
233 scriptToUse = AccumulatorScript::Accumulator01;
234 DLOG("building scripted trade wrapper using (internal) script Accumulator01");
235 } else {
236 scriptToUse = AccumulatorScript::Accumulator02;
237 DLOG("building scripted trade wrapper using (internal) script Accumulator02");
238 }
239
240 Real leverageMultiplier;
241 if (optionData_.payoffType() == "Accumulator")
242 leverageMultiplier = 1.0;
243 else if (optionData_.payoffType() == "Decumulator")
244 leverageMultiplier = -1.0;
245 else {
246 QL_FAIL("invalid payoff type, expected Accumulator or Decumulator");
247 }
248
249 if (strike_.currency().empty())
251 Real globalStrike = strike_.value();
252
253 QL_REQUIRE(scriptToUse == AccumulatorScript::Accumulator01 || globalStrike != Null<Real>(),
254 "For accumulator type 02 a global strike must be given");
255
256 std::vector<std::string> rangeUpperBounds, rangeLowerBounds, rangeLeverages, rangeStrikes;
257 for (auto const& r : rangeBounds_) {
258 rangeLowerBounds.push_back(
259 boost::lexical_cast<std::string>(r.from() == Null<Real>() ? -QL_MAX_REAL : r.from()));
260 rangeUpperBounds.push_back(boost::lexical_cast<std::string>(r.to() == Null<Real>() ? QL_MAX_REAL : r.to()));
261 rangeLeverages.push_back(
262 boost::lexical_cast<std::string>(leverageMultiplier * (r.leverage() == Null<Real>() ? 1.0 : r.leverage())));
263 if (scriptToUse == AccumulatorScript::Accumulator01) {
264 if (r.strike() != Null<Real>()) {
265 rangeStrikes.push_back(boost::lexical_cast<std::string>(r.strike()));
266 } else if (r.strikeAdjustment() != Null<Real>() && globalStrike != Null<Real>()) {
267 rangeStrikes.push_back(boost::lexical_cast<std::string>(globalStrike + r.strikeAdjustment()));
268 } else if (globalStrike != Null<Real>()) {
269 rangeStrikes.push_back(boost::lexical_cast<std::string>(globalStrike));
270 } else {
271 QL_FAIL(
272 "insufficient strike information: either a global strike or a range-specific strike must be given");
273 }
274 }
275 }
276
277 bool initPositive = false;
278 for (Size i = 0; i < rangeLeverages.size(); i++) {
279 Real rl = parseReal(rangeLeverages.at(i));
280 if (i == 0)
281 initPositive = rl >= 0.0;
282 else {
283 bool nextPositive = rl >= 0.0;
284 QL_REQUIRE(nextPositive == initPositive, "Range leverages must all have the same sign.");
285 }
286 }
287 numbers_.emplace_back("Number", "NakedOption", nakedOption_ ? "1" : "-1");
288 if (nakedOption_)
289 numbers_.emplace_back("Number", "OptionType", initPositive ? "1" : "-1");
290
291 numbers_.emplace_back("Number", "RangeLowerBounds", rangeLowerBounds);
292 numbers_.emplace_back("Number", "RangeUpperBounds", rangeUpperBounds);
293 numbers_.emplace_back("Number", "RangeLeverages", rangeLeverages);
294 if (scriptToUse == AccumulatorScript::Accumulator02) {
295 numbers_.emplace_back("Number", "DefaultRange", "1");
296 }
297
298 numbers_.emplace_back("Number", "FixingAmount", fixingAmount_);
299 numbers_.emplace_back("Number", "LongShort",
300 parsePositionType(optionData_.longShort()) == Position::Long ? "1" : "-1");
301
302 currencies_.emplace_back("Currency", "PayCcy", currency_);
303 if (scriptToUse == AccumulatorScript::Accumulator01) {
304 numbers_.emplace_back("Number", "Strike", rangeStrikes);
305 } else {
306 numbers_.emplace_back("Number", "Strike", boost::lexical_cast<std::string>(globalStrike));
307 }
308
309 if (scriptToUse == AccumulatorScript::Accumulator01) {
310 events_.emplace_back("FixingDates", observationDates_);
312 events_.emplace_back("SettlementDates", settlementDates_);
313 } else {
314 events_.emplace_back("SettlementDates", "FixingDates", settlementLag_.empty() ? "0D" : settlementLag_,
315 settlementCalendar_.empty() ? "NullCalendar" : settlementCalendar_,
317 }
318 } else {
319 events_.emplace_back("ObservationDates", observationDates_);
320 events_.emplace_back("KnockOutSettlementDates", "ObservationDates",
321 settlementLag_.empty() ? "0D" : settlementLag_,
322 settlementCalendar_.empty() ? "NullCalendar" : settlementCalendar_,
324 events_.emplace_back("ObservationPeriodEndDates", pricingDates_);
326 events_.emplace_back("SettlementDates", settlementDates_);
327 } else {
328 events_.emplace_back("SettlementDates", "ObservationPeriodEndDates",
329 settlementLag_.empty() ? "0D" : settlementLag_,
330 settlementCalendar_.empty() ? "NullCalendar" : settlementCalendar_,
332 }
333 }
334
335 std::string knockOutLevel = boost::lexical_cast<std::string>(QL_MAX_REAL), knockOutType = "4",
336 guaranteedFixings = "0";
337 bool barrierSet = false;
338 bool americanKO = false;
339 for (auto const& b : barriers_) {
340 QL_REQUIRE(b.style().empty() || b.style() == "European" || b.style() == "American",
341 "expected barrier style American or European, got " << b.style());
342 QL_REQUIRE(b.style() != "European" || scriptToUse == AccumulatorScript::Accumulator01,
343 "European barrier style not allowed if PricingDates are given (Accumulator02 script variant)");
344 if (b.type() == "UpAndOut" && !b.levels().empty()) {
345 knockOutType = "4";
346 knockOutLevel = boost::lexical_cast<std::string>(b.levels().front().value());
347 QL_REQUIRE(!barrierSet, "multiple barrier definitions");
348 barrierSet = true;
349 americanKO = !(b.style() == "European");
350 } else if (b.type() == "DownAndOut" && !b.levels().empty()) {
351 knockOutType = "3";
352 knockOutLevel = boost::lexical_cast<std::string>(b.levels().front().value());
353 QL_REQUIRE(!barrierSet, "multiple barrier definitions");
354 barrierSet = true;
355 americanKO = !(b.style() == "European");
356 } else if (b.type() == "FixingFloor" && !b.levels().empty()) {
357 guaranteedFixings = boost::lexical_cast<std::string>(b.levels().front().value());
358 } else
359 QL_FAIL("invalid barrier definition, expected UpAndOut, DownAndOut, FixingFloor (with exactly one level)");
360 }
361
362 numbers_.emplace_back("Number", "KnockOutLevel", knockOutLevel);
363 numbers_.emplace_back("Number", "KnockOutType", knockOutType);
364
365 if (scriptToUse == AccumulatorScript::Accumulator01) {
366 QL_REQUIRE((!americanKO && !dailyFixingAmount_) || !startDate_.empty(),
367 "For american knock out or when using a daily fixing amount StartDate must be given.");
368 events_.emplace_back("StartDate", startDate_);
369 numbers_.emplace_back("Number", "AmericanKO", americanKO ? "1" : "-1");
370 numbers_.emplace_back("Number", "GuaranteedFixings", guaranteedFixings);
371 numbers_.emplace_back("Number", "DailyFixingAmount", dailyFixingAmount_ ? "1" : "-1");
372 daycounters_.emplace_back("Daycounter", "DailyFixingAmountDayCounter", "ACT/ACT.ISDA");
373
374 } else {
375 Schedule pd = makeSchedule(pricingDates_);
376 Size gf = parseInteger(guaranteedFixings);
377 QL_REQUIRE(gf <= pd.size(),
378 "guaranteed fixings (" << gf << ") > pricing dates schedule size (" << pd.size() << ")");
379 Date gpend = gf == 0 ? Date::minDate() : pd.date(gf - 1);
380 events_.emplace_back("GuaranteedPeriodEndDate", ore::data::to_string(gpend));
381 }
382
383 // set product tag
384
385 productTag_ = scriptToUse == AccumulatorScript::Accumulator01 ? "SingleAssetOptionCG({AssetClass})"
386 : "SingleAssetOptionBwd({AssetClass})";
387
388 // set script
389
390 if (scriptToUse == AccumulatorScript::Accumulator01) {
392 accumulator01_script, "value",
393 {{"currentNotional", "currentNotional"},
394 {"notionalCurrency", "PayCcy"},
395 {"Alive", "Alive"},
396 {"Fixing", "Fixing"}},
397 {}, {}, {ScriptedTradeScriptData::CalibrationData("Underlying", {"Strike", "KnockOutLevel"})});
398 } else {
400 accumulator02_script, "value",
401 {{"currentNotional", "currentNotional"},
402 {"notionalCurrency", "PayCcy"},
403 {"KnockedOut", "KnockedOut"},
404 {"Fixing", "Fixing"}},
405 {}, {}, {ScriptedTradeScriptData::CalibrationData("Underlying", {"Strike", "KnockOutLevel"})});
407 accumulator02_script_fd, "value",
408 {{"currentNotional", "currentNotional"}, {"notionalCurrency", "PayCcy"}, {"Fixing", "Fixing"}}, {}, {},
409 {ScriptedTradeScriptData::CalibrationData("Underlying", {"Strike", "KnockOutLevel"})});
410 }
411
412 // build trade
413
414 ScriptedTrade::build(factory);
415}
416
419
420 // ISDA taxonomy, asset class set in the base class build
421 // asset class set in the base class already
422 std::string assetClass = boost::any_cast<std::string>(additionalData_["isdaAssetClass"]);
423 if (assetClass == "Equity") {
424 additionalData_["isdaBaseProduct"] = string("Other");
425 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
426 } else if (assetClass == "Commodity") {
427 // isda taxonomy missing for this class, using the same as equity
428 additionalData_["isdaBaseProduct"] = string("Other");
429 additionalData_["isdaSubProduct"] = string("Price Return Basic Performance");
430 } else if (assetClass == "Foreign Exchange") {
431 additionalData_["isdaBaseProduct"] = string("Exotic");
432 additionalData_["isdaSubProduct"] = string("Target");
433 } else {
434 WLOG("ISDA taxonomy incomplete for trade " << id());
435 }
436
437 additionalData_["isdaTransaction"] = string("");
438}
439
440void Accumulator::initIndices() { indices_.emplace_back("Index", "Underlying", scriptedIndexName(underlying_)); }
441
443 Trade::fromXML(node);
444 XMLNode* dataNode = XMLUtils::getChildNode(node, tradeType() + "Data");
445 QL_REQUIRE(dataNode, tradeType() + "Data node not found");
446 fixingAmount_ = XMLUtils::getChildValue(dataNode, "FixingAmount", true);
447 dailyFixingAmount_ = XMLUtils::getChildValueAsBool(dataNode, "DailyFixingAmount", false, false);
448
449 currency_ = XMLUtils::getChildValue(dataNode, "Currency", false);
450 strike_.fromXML(dataNode, false, false);
451
452 XMLNode* tmp = XMLUtils::getChildNode(dataNode, "Underlying");
453 if (!tmp)
454 tmp = XMLUtils::getChildNode(dataNode, "Name");
455 UnderlyingBuilder underlyingBuilder;
456 underlyingBuilder.fromXML(tmp);
457 underlying_ = underlyingBuilder.underlying();
458
459 optionData_.fromXML(XMLUtils::getChildNode(dataNode, "OptionData"));
460 startDate_ = XMLUtils::getChildValue(dataNode, "StartDate", false);
461 observationDates_.fromXML(XMLUtils::getChildNode(dataNode, "ObservationDates"));
462 if (XMLNode* n = XMLUtils::getChildNode(dataNode, "PricingDates"))
464 if (XMLNode* n = XMLUtils::getChildNode(dataNode, "SettlementDates"))
466 settlementLag_ = XMLUtils::getChildValue(dataNode, "SettlementLag", false);
467 settlementCalendar_ = XMLUtils::getChildValue(dataNode, "SettlementCalendar", false);
468 settlementConvention_ = XMLUtils::getChildValue(dataNode, "SettlementConvention", false);
469 nakedOption_ = XMLUtils::getChildValueAsBool(dataNode, "NakedOption", false, false);
470 auto rangeBoundsNode = XMLUtils::getChildNode(dataNode, "RangeBounds");
471 QL_REQUIRE(rangeBoundsNode, "No RangeBounds node");
472 auto rangeBounds = XMLUtils::getChildrenNodes(rangeBoundsNode, "RangeBound");
473 for (auto const& n : rangeBounds) {
474 rangeBounds_.push_back(RangeBound());
475 rangeBounds_.back().fromXML(n);
476 }
477 auto barriersNode = XMLUtils::getChildNode(dataNode, "Barriers");
478 QL_REQUIRE(barriersNode, "No Barriers node");
479 auto barriers = XMLUtils::getChildrenNodes(barriersNode, "BarrierData");
480 for (auto const& n : barriers) {
481 barriers_.push_back(BarrierData());
482 barriers_.back().fromXML(n);
483 }
484 initIndices();
485}
486
488 XMLNode* node = Trade::toXML(doc);
489 XMLNode* dataNode = doc.allocNode(tradeType() + "Data");
490 XMLUtils::appendNode(node, dataNode);
491 XMLUtils::addChild(doc, dataNode, "FixingAmount", fixingAmount_);
492 XMLUtils::addChild(doc, dataNode, "DailyFixingAmount", dailyFixingAmount_);
493 XMLUtils::addChild(doc, dataNode, "Currency", currency_);
494
495 if (strike_.value() != Null<Real>()) {
496 XMLUtils::appendNode(dataNode, strike_.toXML(doc));
497 }
498
499 XMLUtils::appendNode(dataNode, underlying_->toXML(doc));
500 XMLUtils::appendNode(dataNode, optionData_.toXML(doc));
501 if (!startDate_.empty())
502 XMLUtils::addChild(doc, dataNode, "StartDate", startDate_);
503 XMLNode* tmp = observationDates_.toXML(doc);
504 XMLUtils::setNodeName(doc, tmp, "ObservationDates");
505 XMLUtils::appendNode(dataNode, tmp);
506 if (pricingDates_.hasData()) {
507 XMLNode* tmp = pricingDates_.toXML(doc);
508 XMLUtils::setNodeName(doc, tmp, "PricingDates");
509 XMLUtils::appendNode(dataNode, tmp);
510 }
512 XMLNode* tmp = settlementDates_.toXML(doc);
513 XMLUtils::setNodeName(doc, tmp, "SettlementDates");
514 XMLUtils::appendNode(dataNode, tmp);
515 }
516 if (!settlementLag_.empty())
517 XMLUtils::addChild(doc, dataNode, "SettlementLag", settlementLag_);
518 if (!settlementCalendar_.empty())
519 XMLUtils::addChild(doc, dataNode, "SettlementCalendar", settlementCalendar_);
520 if (!settlementConvention_.empty())
521 XMLUtils::addChild(doc, dataNode, "SettlementConvention", settlementConvention_);
522 XMLUtils::addChild(doc, dataNode, "NakedOption", nakedOption_);
523 XMLNode* rangeBounds = doc.allocNode("RangeBounds");
524 for (auto& n : rangeBounds_) {
525 XMLUtils::appendNode(rangeBounds, n.toXML(doc));
526 }
527 XMLUtils::appendNode(dataNode, rangeBounds);
528 XMLNode* barriers = doc.allocNode("Barriers");
529 for (auto& n : barriers_) {
530 XMLUtils::appendNode(barriers, n.toXML(doc));
531 }
532 XMLUtils::appendNode(dataNode, barriers);
533 return node;
534}
535
536} // namespace data
537} // namespace ore
accumulator wrapper for scripted trade
std::string settlementConvention_
Definition: accumulator.hpp:72
ScheduleData settlementDates_
Definition: accumulator.hpp:71
void setIsdaTaxonomyFields() override
void fromXML(XMLNode *node) override
QuantLib::ext::shared_ptr< Underlying > underlying_
Definition: accumulator.hpp:68
XMLNode * toXML(XMLDocument &doc) const override
std::string settlementLag_
Definition: accumulator.hpp:72
ScheduleData observationDates_
Definition: accumulator.hpp:71
ScheduleData pricingDates_
Definition: accumulator.hpp:71
std::vector< BarrierData > barriers_
Definition: accumulator.hpp:77
std::string fixingAmount_
Definition: accumulator.hpp:66
std::string settlementCalendar_
Definition: accumulator.hpp:72
std::vector< RangeBound > rangeBounds_
Definition: accumulator.hpp:76
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Serializable obejct holding barrier data.
Definition: barrierdata.hpp:34
const string & payoffType() const
Definition: optiondata.hpp:72
const string & longShort() const
Definition: optiondata.hpp:70
virtual void fromXML(XMLNode *node) override
Definition: optiondata.cpp:32
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: optiondata.cpp:86
Serializable obejct holding range bound data.
Definition: rangebound.hpp:39
bool hasData() const
Check if has any dates/rules/derived schedules.
Definition: schedule.hpp:223
virtual void fromXML(XMLNode *node) override
Definition: schedule.cpp:179
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: schedule.cpp:198
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
XMLNode * toXML(XMLDocument &doc) const
Definition: tradestrike.cpp:86
void setCurrency(const std::string &currency)
void fromXML(XMLNode *node, const bool isRequired=true, const bool allowYieldStrike=false)
Definition: tradestrike.cpp:50
std::string currency()
QuantLib::Real value() const
const QuantLib::ext::shared_ptr< Underlying > & underlying()
Definition: underlying.hpp:266
void fromXML(XMLNode *node) override
Definition: underlying.cpp:305
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 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 void setNodeName(XMLDocument &doc, XMLNode *node, const string &name)
Definition: xmlutils.cpp:478
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
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Definition: parsers.cpp:404
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
Definition: parsers.cpp:136
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
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
Schedule makeSchedule(const ScheduleDates &data)
Definition: schedule.cpp:263
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
some utility functions
string conversion utilities