Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
scriptedtrade.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 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
24
29
30#include <boost/algorithm/string/replace.hpp>
31
32using namespace QuantLib;
33using namespace QuantExt;
34using namespace std::placeholders;
35
36namespace ore {
37namespace data {
38
39void ScriptedTrade::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, const PremiumData& premiumData,
40 const Real premiumMultiplier) {
41
42 DLOG("ScriptedTrade::build() called for trade " << id());
43
44 auto builder = QuantLib::ext::dynamic_pointer_cast<ScriptedTradeEngineBuilder>(engineFactory->builder("ScriptedTrade"));
45
46 QL_REQUIRE(builder, "no builder found for ScriptedTrade");
47 auto engine = builder->engine(id(), *this, engineFactory->referenceData(), engineFactory->iborFallbackConfig());
48
49 simmProductClass_ = builder->simmProductClass();
50 scheduleProductClass_ = builder->scheduleProductClass();
51
53
54 auto qleInstr = QuantLib::ext::make_shared<ScriptedInstrument>(builder->lastRelevantDate());
55 qleInstr->setPricingEngine(engine);
56
57 npvCurrency_ = builder->npvCurrency();
58 maturity_ = builder->lastRelevantDate();
59 notional_ = Null<Real>(); // is handled by override of notional()
60 notionalCurrency_ = ""; // is handled by override of notionalCurrency()
61 legs_.clear();
62 legCurrencies_.clear();
63 legPayers_.clear();
64
65 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
66 std::vector<Real> additionalMultipliers;
67 maturity_ = std::max(maturity_, addPremiums(additionalInstruments, additionalMultipliers, 1.0, premiumData,
68 premiumMultiplier, parseCurrencyWithMinors(npvCurrency_), engineFactory,
69 builder->configuration(MarketContext::pricing)));
70
71 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(qleInstr, 1.0, additionalInstruments, additionalMultipliers);
72
73 // add required fixings
74 for (auto const& f : builder->fixings()) {
75 for (auto const& d : f.second) {
76 IndexInfo info(f.first);
77 if (info.isInf()) {
78 QL_DEPRECATED_DISABLE_WARNING
79 requiredFixings_.addZeroInflationFixingDate(d, info.infName(), info.inf()->interpolated(),
80 info.inf()->frequency(), info.inf()->availabilityLag(),
81 CPI::AsIndex, info.inf()->frequency(), Date::maxDate(), false, false);
82 QL_DEPRECATED_ENABLE_WARNING
83 } else if (info.isFx()) {
84 // for FX we do not know if FX-TAG-CCY1-CCY2 or FX-TAG-CCY2-CCY1 is in the history, require both
85 requiredFixings_.addFixingDate(d, f.first, Date::maxDate(), false, false);
86 requiredFixings_.addFixingDate(d, inverseFxIndex(f.first), Date::maxDate(), false, false);
87 } else {
88 requiredFixings_.addFixingDate(d, f.first, Date::maxDate(), false, false);
89 }
90 }
91 }
92
93 // set sensitivity template
94 setSensitivityTemplate(builder->sensitivityTemplate());
95}
96
97void ScriptedTrade::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
98 ScriptedTrade::build(engineFactory, PremiumData(), 1.0);
99}
100
102 // ISDA taxonomy, can be overwritten in derived classes
103 if (scheduleProductClass_ == "FX") {
104 additionalData_["isdaAssetClass"] = string("Foreign Exchange");
105 additionalData_["isdaBaseProduct"] = string("Complex Exotic");
106 additionalData_["isdaSubProduct"] = string("Generic");
107 additionalData_["isdaTransaction"] = string("");
108 } else if (scheduleProductClass_ == "Rates") {
109 additionalData_["isdaAssetClass"] = string("Interest Rate");
110 additionalData_["isdaBaseProduct"] = string("Exotic");
111 additionalData_["isdaSubProduct"] = string("");
112 additionalData_["isdaTransaction"] = string("");
113 } else if (scheduleProductClass_ == "Equity") {
114 additionalData_["isdaAssetClass"] = string("Equity");
115 additionalData_["isdaBaseProduct"] = string("Other");
116 additionalData_["isdaSubProduct"] = string("");
117 additionalData_["isdaTransaction"] = string("");
118 } else if (scheduleProductClass_ == "Credit") {
119 additionalData_["isdaAssetClass"] = string("Credit");
120 additionalData_["isdaBaseProduct"] = string("Exotic");
121 additionalData_["isdaSubProduct"] = string("Other");
122 additionalData_["isdaTransaction"] = string("");
123 } else if (scheduleProductClass_ == "Commodity") {
124 DLOG("ISDA taxonomy for trade " << id() << " and product class " << scheduleProductClass_
125 << " follows the Equity template");
126 additionalData_["isdaAssetClass"] = string("Commodity");
127 additionalData_["isdaBaseProduct"] = string("Other");
128 additionalData_["isdaSubProduct"] = string("");
129 additionalData_["isdaTransaction"] = string("");
130 } else {
131 DLOG("ISDA taxonomy not set for trade " << id() << " and product class " << scheduleProductClass_);
132 }
133}
134
135QuantLib::Real ScriptedTrade::notional() const {
136 if (instrument_->qlInstrument()->isExpired())
137 return 0.0;
138 // try to get the notional from the additional results of the instrument
139 auto st = QuantLib::ext::dynamic_pointer_cast<ScriptedInstrument>(instrument_->qlInstrument(true));
140 QL_REQUIRE(st, "internal error: could not cast to ScriptedInstrument");
141 try {
142 return st->result<Real>("currentNotional");
143 } catch (const std::exception& e) {
144 if (st->lastCalculationWasValid()) {
145 // calculation was valid, just the result is not provided
146 DLOG("notional was not retrieved: " << e.what() << ", return null");
147 } else {
148 // calculation threw an error, propagate this
149 QL_FAIL(e.what());
150 }
151 }
152 // if not provided, return null
153 return Null<Real>();
154}
155
157 if (instrument_->qlInstrument()->isExpired())
158 return npvCurrency_;
159 // try to get the notional ccy from the additional results of the instrument
160 auto st = QuantLib::ext::dynamic_pointer_cast<ScriptedInstrument>(instrument_->qlInstrument(true));
161 QL_REQUIRE(st, "internal error: could not cast to ScriptedInstrument");
162 try {
163 return instrument_->qlInstrument()->result<std::string>("notionalCurrency");
164 } catch (const std::exception& e) {
165 if (st->lastCalculationWasValid()) {
166 // calculation was valid, just the result is not provided
167 DLOG("notional ccy was not retrieved: " << e.what() << ", return empty string");
168 } else {
169 // calculation threw an error, propagate this
170 QL_FAIL(e.what());
171 }
172 }
173 // if not provided, return an empty string
174 return std::string();
175}
176
178 events_.clear();
179 numbers_.clear();
180 indices_.clear();
181 currencies_.clear();
182 daycounters_.clear();
184 script_.clear();
185}
186
187namespace {
188
189// some helper functions for freestyle parsing
190
191enum class NodeType { Event, Number, Index, Currency, Daycounter };
192
193std::pair<NodeType, std::string> getNativeTypeAndValue(const std::string& value, const std::string& type) {
194
195 static std::map<std::string, std::map<std::string, std::string>> mappings = {
196 {"bool", {{"true", "1"}, {"false", "-1"}}},
197 {"optionType", {{"Call", "1"}, {"Put", "-1"}, {"Cap", "1"}, {"Floor", "-1"}}},
198 {"longShort", {{"Long", "1"}, {"Short", "-1"}}},
199 {"barrierType", {{"DownIn", "1"}, {"UpIn", "2"}, {"DownOut", "3"}, {"UpOut", "4"}}},
200 };
201
202 // native types
203 if (type == "event")
204 return std::make_pair(NodeType::Event, value);
205 else if (type == "number")
206 return std::make_pair(NodeType::Number, value);
207 else if (type == "index")
208 return std::make_pair(NodeType::Index, value);
209 else if (type == "currency")
210 return std::make_pair(NodeType::Currency, value);
211 else if (type == "dayCounter")
212 return std::make_pair(NodeType::Daycounter, value);
213 else {
214 // type that maps to number
215 auto t = mappings.find(type);
216 QL_REQUIRE(t != mappings.end(), "type '" << type << "' not known");
217 auto v = t->second.find(value);
218 QL_REQUIRE(v != t->second.end(), "value '" << value << "' for type '" << type << "' not known");
219 return std::make_pair(NodeType::Number, v->second);
220 }
221}
222
223} // namespace
224
225std::map<ore::data::AssetClass, std::set<std::string>>
226ScriptedTrade::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
227
228 map<ore::data::AssetClass, set<string>> result;
229
230 for (const auto& p : indices_) {
231 vector<string> vals;
232 if (!p.value().empty())
233 vals.push_back(p.value());
234 else
235 vals = p.values();
236
237 for (auto v : vals) {
238 if (!v.empty()) {
239 IndexInfo ind(v);
240 if (ind.isComm()) {
241 result[ore::data::AssetClass::COM].insert(ind.commName());
242 } else if (ind.isEq()) {
243 result[ore::data::AssetClass::EQ].insert(ind.eq()->name());
244 }
245 }
246 }
247 }
248
249 return result;
250}
251
253 clear();
254 Trade::fromXML(node);
255
256 // if we find a ScriptedTradeData node we use this (native format)
257
258 XMLNode* tradeDataNode = XMLUtils::getChildNode(node, "ScriptedTradeData");
259 if (tradeDataNode) {
260 XMLNode* dataNode = XMLUtils::getChildNode(tradeDataNode, "Data");
261 QL_REQUIRE(dataNode, "ScriptedTradeData/Data node not found");
262 vector<XMLNode*> nodes = XMLUtils::getChildrenNodes(dataNode, "");
263 for (auto const n : nodes) {
264 if (XMLUtils::getNodeName(n) == "Event") {
265 events_.push_back(ScriptedTradeEventData());
266 events_.back().fromXML(n);
267 } else if (XMLUtils::getNodeName(n) == "Number") {
268 numbers_.push_back(ScriptedTradeValueTypeData("Number"));
269 numbers_.back().fromXML(n);
270 } else if (XMLUtils::getNodeName(n) == "Index") {
271 indices_.push_back(ScriptedTradeValueTypeData("Index"));
272 indices_.back().fromXML(n);
273 } else if (XMLUtils::getNodeName(n) == "Currency") {
274 currencies_.push_back(ScriptedTradeValueTypeData("Currency"));
275 currencies_.back().fromXML(n);
276 } else if (XMLUtils::getNodeName(n) == "Daycounter") {
277 daycounters_.push_back(ScriptedTradeValueTypeData("Daycounter"));
278 daycounters_.back().fromXML(n);
279 }
280 }
281 if (XMLNode* scriptName = XMLUtils::getChildNode(tradeDataNode, "ScriptName")) {
283 } else if (XMLUtils::getChildNode(tradeDataNode, "Script")) {
284 productTag_ = XMLUtils::getChildValue(tradeDataNode, "ProductTag", false);
285 auto sn = XMLUtils::getChildrenNodes(tradeDataNode, "Script");
286 for (auto const& n : sn) {
288 s.fromXML(n);
289 std::string purpose = XMLUtils::getAttribute(n, "purpose");
290 script_[purpose] = s;
291 }
292 } else {
293 QL_FAIL("either Script or ScriptName expected");
294 }
295 return;
296 }
297
298 // otherwise we look for a xxxData node and interpret the xxx as the script name (freestyle parsing)
299
300 for (XMLNode* child = XMLUtils::getChildNode(node); child; child = XMLUtils::getNextSibling(child)) {
301 std::string name = XMLUtils::getNodeName(child);
302 if (name.size() > 4 && name.substr(name.size() - 4, 4) == "Data") {
303 QL_REQUIRE(!tradeDataNode, "multiple child nodes xxxData found");
304 tradeDataNode = child;
305 scriptName_ = name.substr(0, name.size() - 4);
306 }
307 }
308
309 QL_REQUIRE(tradeDataNode, "expected ScriptedTradeData or xxxData node");
310
311 // now loop over the child nodes and populate the script data
312 for (XMLNode* child = XMLUtils::getChildNode(tradeDataNode); child; child = XMLUtils::getNextSibling(child)) {
313
314 // the name of the node will be the name of the script variable
315 std::string varName = XMLUtils::getNodeName(child);
316 std::string type = XMLUtils::getAttribute(child, "type");
317 QL_REQUIRE(!type.empty(), "no type given for node '" << varName << "'");
318
319 std::string scalarValue = XMLUtils::getNodeValue(child);
320 if (!scalarValue.empty()) {
321 // if we have a value, this is a scalar
322 auto native = getNativeTypeAndValue(scalarValue, type);
323 if (native.first == NodeType::Event) {
324 events_.push_back(ScriptedTradeEventData(varName, native.second));
325 } else if (native.first == NodeType::Number) {
326 numbers_.push_back(ScriptedTradeValueTypeData("Number", varName, native.second));
327 } else if (native.first == NodeType::Index) {
328 indices_.push_back(ScriptedTradeValueTypeData("Index", varName, native.second));
329 } else if (native.first == NodeType::Currency) {
330 currencies_.push_back(ScriptedTradeValueTypeData("Currency", varName, native.second));
331 } else if (native.first == NodeType::Daycounter) {
332 daycounters_.push_back(ScriptedTradeValueTypeData("Daycounter", varName, native.second));
333 } else {
334 QL_FAIL("unexpected node type");
335 }
336 } else {
337 // if we don't have a value, this is a vector given by some sub node
338 if (XMLNode* v = XMLUtils::getChildNode(child, "ScheduleData")) {
339 ScheduleData sched;
340 sched.fromXML(v);
341 events_.push_back(ScriptedTradeEventData(varName, sched));
342 } else if (XMLNode* v = XMLUtils::getChildNode(child, "DerivedSchedule")) {
343 events_.push_back(ScriptedTradeEventData(varName, XMLUtils::getChildValue(v, "BaseSchedule", true),
344 XMLUtils::getChildValue(v, "Shift", true),
345 XMLUtils::getChildValue(v, "Calendar", true),
346 XMLUtils::getChildValue(v, "Convention", true)));
347 } else if (XMLNode* v = XMLUtils::getChildNode(child, "Value")) {
348 auto native = getNativeTypeAndValue(XMLUtils::getNodeValue(v), type);
349 QL_REQUIRE(native.first != NodeType::Event, "unexpected even array under node '" << varName << "'");
350 std::vector<std::string> arrayValues;
351 for (XMLNode* val = XMLUtils::getChildNode(child, "Value"); val;
352 val = XMLUtils::getNextSibling(val, "Value")) {
353 auto v = getNativeTypeAndValue(XMLUtils::getNodeValue(val), type);
354 arrayValues.push_back(v.second);
355 }
356 if (native.first == NodeType::Number) {
357 numbers_.push_back(ScriptedTradeValueTypeData("Number", varName, arrayValues));
358 } else if (native.first == NodeType::Index) {
359 indices_.push_back(ScriptedTradeValueTypeData("Index", varName, arrayValues));
360 } else if (native.first == NodeType::Currency) {
361 currencies_.push_back(ScriptedTradeValueTypeData("Currency", varName, arrayValues));
362 } else if (native.first == NodeType::Daycounter) {
363 daycounters_.push_back(ScriptedTradeValueTypeData("Daycounter", varName, arrayValues));
364 } else {
365 QL_FAIL("unexpected node type");
366 }
367 } else {
368 QL_FAIL("unexpected content under node '" << varName << "'");
369 }
370 }
371 }
372}
373
375 XMLNode* node = Trade::toXML(doc);
376 XMLNode* tradeDataNode = doc.allocNode("ScriptedTradeData");
377 XMLUtils::appendNode(node, tradeDataNode);
378 if (!scriptName_.empty())
379 XMLUtils::addChild(doc, tradeDataNode, "ScriptName", scriptName_);
380 else {
381 XMLUtils::addChild(doc, tradeDataNode, "ProductTag", productTag_);
382 for (auto& s : script_) {
383 XMLNode* n = s.second.toXML(doc);
384 XMLUtils::addAttribute(doc, n, "purpose", s.first);
385 XMLUtils::appendNode(tradeDataNode, n);
386 }
387 }
388 XMLNode* dataNode = doc.allocNode("Data");
389 XMLUtils::appendNode(tradeDataNode, dataNode);
390 for (auto& x : events_)
391 XMLUtils::appendNode(dataNode, x.toXML(doc));
392 for (auto& x : numbers_)
393 XMLUtils::appendNode(dataNode, x.toXML(doc));
394 for (auto& x : indices_)
395 XMLUtils::appendNode(dataNode, x.toXML(doc));
396 for (auto& x : currencies_)
397 XMLUtils::appendNode(dataNode, x.toXML(doc));
398 for (auto& x : daycounters_)
399 XMLUtils::appendNode(dataNode, x.toXML(doc));
400 return node;
401}
402
403const ScriptedTradeScriptData& ScriptedTrade::script(const std::string& purpose,
404 const bool fallBackOnEmptyPurpose) const {
405 auto s1 = script_.find(purpose);
406 if (s1 != script_.end())
407 return s1->second;
408 if (fallBackOnEmptyPurpose) {
409 auto s2 = script_.find("");
410 if (s2 != script_.end())
411 return s2->second;
412 }
413 QL_FAIL("ScriptedTrade::script(): script with purpose '"
414 << purpose << "' not found, fall back on empty purpose was " << std::boolalpha << fallBackOnEmptyPurpose);
415}
416
418 XMLUtils::checkNode(node, "Event");
419 name_ = XMLUtils::getChildValue(node, "Name", true);
420 if (XMLNode* v = XMLUtils::getChildNode(node, "Value")) {
423 } else if (XMLNode* v = XMLUtils::getChildNode(node, "ScheduleData")) {
426 } else if (XMLNode* v = XMLUtils::getChildNode(node, "DerivedSchedule")) {
428 baseSchedule_ = XMLUtils::getChildValue(v, "BaseSchedule", true);
429 shift_ = XMLUtils::getChildValue(v, "Shift", true);
430 calendar_ = XMLUtils::getChildValue(v, "Calendar", true);
431 convention_ = XMLUtils::getChildValue(v, "Convention", true);
432 } else {
433 QL_FAIL("Expected Value or ScheduleData node");
434 }
435}
436
438 XMLNode* n = doc.allocNode("Event");
439 XMLUtils::addChild(doc, n, "Name", name_);
440 if (type_ == Type::Value) {
441 XMLUtils::addChild(doc, n, "Value", value_);
442 } else if (type_ == Type::Array) {
444 } else if (type_ == Type::Derived) {
445 XMLNode* d = doc.allocNode("DerivedSchedule");
446 XMLUtils::addChild(doc, d, "BaseSchedule", baseSchedule_);
447 XMLUtils::addChild(doc, d, "Shift", shift_);
448 XMLUtils::addChild(doc, d, "Calendar", calendar_);
449 XMLUtils::addChild(doc, d, "Convention", convention_);
451 } else {
452 QL_FAIL("ScriptedTradeEventData::toXML(): unexpected ScriptedTradeEventData::Type");
453 }
454 return n;
455}
456
458 if (type_ == Type::Array) {
459 return schedule_.hasData();
460 } else if (type_ == Type::Derived) {
461 return !baseSchedule_.empty() && !shift_.empty() && !calendar_.empty() && !convention_.empty();
462 } else if (type_ == Type::Value) {
463 return !value_.empty();
464 } else {
465 // If type_ is not defined, then the ScriptedTradeEventData object is not defined
466 return false;
467 }
468}
469
472 name_ = XMLUtils::getChildValue(node, "Name", true);
473 if (XMLNode* v = XMLUtils::getChildNode(node, "Value")) {
474 isArray_ = false;
476 } else if (XMLUtils::getChildNode(node, "Values")) {
477 isArray_ = true;
478 values_ = XMLUtils::getChildrenValues(node, "Values", "Value");
479 } else {
480 QL_FAIL("Expected Value or Values node");
481 }
482}
483
485 XMLNode* n = doc.allocNode(nodeName_);
486 XMLUtils::addChild(doc, n, "Name", name_);
487 if (!isArray_) {
488 XMLUtils::addChild(doc, n, "Value", value_);
489 } else {
490 XMLUtils::addChildren(doc, n, "Values", "Value", values_);
491 }
492 return n;
493}
494
496 XMLUtils::checkNode(node, "NewSchedule");
497 name_ = XMLUtils::getChildValue(node, "Name", true);
498 operation_ = XMLUtils::getChildValue(node, "Operation", true);
499 sourceSchedules_ = XMLUtils::getChildrenValues(node, "Schedules", "Schedule");
500}
501
503 XMLNode* n = doc.allocNode("NewSchedule");
504 XMLUtils::addChild(doc, n, "Name", name_);
505 XMLUtils::addChild(doc, n, "Operation", operation_);
506 XMLUtils::addChildren(doc, n, "Schedules", "Schedule", sourceSchedules_);
507 return n;
508}
509
511 XMLUtils::checkNode(node, "Calibration");
512 index_ = XMLUtils::getChildValue(node, "Index", true);
513 strikes_ = XMLUtils::getChildrenValues(node, "Strikes", "Strike", true);
514}
515
517 XMLNode* n = doc.allocNode("Calibration");
518 XMLUtils::addChild(doc, n, "Index", index_);
519 XMLUtils::addChildren(doc, n, "Strikes", "Strike", strikes_);
520 return n;
521}
522
524 XMLUtils::checkNode(node, "Script");
525 code_ = XMLUtils::getChildValue(node, "Code", true);
526 formatCode();
527 npv_ = XMLUtils::getChildValue(node, "NPV", true);
528 std::vector<std::string> attributes;
529 std::vector<std::string> values =
530 XMLUtils::getChildrenValuesWithAttributes(node, "Results", "Result", "rename", attributes);
531 for (Size i = 0; i < values.size(); ++i) {
532 // result name is identical to script variable expect the rename attribute is filled
533 results_.push_back(std::make_pair(attributes[i].empty() ? values[i] : attributes[i], values[i]));
534 }
535 schedulesEligibleForCoarsening_ = XMLUtils::getChildrenValues(node, "ScheduleCoarsening", "EligibleSchedule");
536 if (XMLNode* ns = XMLUtils::getChildNode(node, "NewSchedules")) {
537 std::vector<XMLNode*> newSchedules = XMLUtils::getChildrenNodes(ns, "NewSchedule");
538 for (auto const& n : newSchedules) {
539 NewScheduleData tmp;
540 tmp.fromXML(n);
541 newSchedules_.push_back(tmp);
542 }
543 }
544 if (XMLNode* ns = XMLUtils::getChildNode(node, "CalibrationSpec")) {
545 std::vector<XMLNode*> calibrations = XMLUtils::getChildrenNodes(ns, "Calibration");
546 for (auto const& n : calibrations) {
547 CalibrationData tmp;
548 tmp.fromXML(n);
549 calibrationSpec_.push_back(tmp);
550 }
551 }
552 stickyCloseOutStates_ = XMLUtils::getChildrenValues(node, "StickyCloseOutStates", "StickyCloseOutState");
553 if (XMLNode* ns = XMLUtils::getChildNode(node, "ConditionalExpectation")) {
554 conditionalExpectationModelStates_ = XMLUtils::getChildrenValues(ns, "ModelStates", "ModelState", false);
555 }
556}
557
559 XMLNode* n = doc.allocNode("Script");
560 XMLUtils::addChildAsCdata(doc, n, "Code", code_);
561 XMLUtils::addChild(doc, n, "NPV", npv_);
562 std::vector<std::string> values, attributes;
563 for (auto const& r : results_) {
564 attributes.push_back(r.first);
565 values.push_back(r.second);
566 }
567 XMLUtils::addChildrenWithAttributes(doc, n, "Results", "Result", values, "rename", attributes);
568 XMLUtils::addChildren(doc, n, "ScheduleCoarsening", "EligibleSchedule", schedulesEligibleForCoarsening_);
569 XMLNode* newSchedules = doc.allocNode("NewSchedules");
571 for (auto& s : newSchedules_) {
572 XMLUtils::appendNode(newSchedules, s.toXML(doc));
573 }
574 XMLNode* calibrations = doc.allocNode("CalibrationSpec");
575 XMLUtils::appendNode(n, calibrations);
576 for (auto& c : calibrationSpec_) {
577 XMLUtils::appendNode(calibrations, c.toXML(doc));
578 }
579 XMLUtils::addChildren(doc, n, "StickyCloseOutStates", "StickyCloseOutState", stickyCloseOutStates_);
580 XMLNode* condExp = doc.allocNode("ConditionalExpectation");
581 XMLUtils::appendNode(n, condExp);
582 XMLUtils::addChildren(doc, condExp, "ModelStates", "ModelState", conditionalExpectationModelStates_);
583 return n;
584}
585
587 // remove carriage returns (e.g. DOS uses \r\n as a line ending, but we want \n only)
588 boost::replace_all(code_, "\r", "");
589 // untabify
590 boost::replace_all(code_, "\t", " ");
591}
592
594
595ScriptLibraryData::ScriptLibraryData(ScriptLibraryData&& d) { scripts_ = std::move(d.scripts_); }
596
598 scripts_ = d.scripts_;
599 return *this;
600}
601
603 scripts_ = std::move(d.scripts_);
604 return *this;
605}
606
607bool ScriptLibraryData::has(const std::string& scriptName, const std::string& purpose,
608 const bool fallBackOnEmptyPurpose) const {
609 auto s = scripts_.find(scriptName);
610 if (s != scripts_.end()) {
611 return s->second.second.find(purpose) != s->second.second.end() ||
612 (fallBackOnEmptyPurpose && has(scriptName, "", false));
613 }
614 return false;
615}
616
617std::pair<std::string, ScriptedTradeScriptData> ScriptLibraryData::get(const std::string& scriptName,
618 const std::string& purpose,
619 const bool fallBackOnEmptyPurpose) const {
620 auto s = scripts_.find(scriptName);
621 if (s != scripts_.end()) {
622 auto f = s->second.second.find(purpose);
623 if (f != s->second.second.end()) {
624 return std::make_pair(s->second.first, f->second);
625 } else if (fallBackOnEmptyPurpose) {
626 auto f = s->second.second.find("");
627 if (f != s->second.second.end())
628 return std::make_pair(s->second.first, f->second);
629 }
630 }
631 QL_FAIL("ScriptedTradeScriptData::get(): script '" << scriptName << "' with purpose '" << purpose
632 << "' not found, fallBackOnEmptyPurpose was " << std::boolalpha
633 << fallBackOnEmptyPurpose);
634}
635
637 XMLUtils::checkNode(node, "ScriptLibrary");
638 auto childs = XMLUtils::getChildrenNodes(node, "Script");
639 std::set<std::string> loadedNames;
640 for (auto c : childs) {
641 std::string name = XMLUtils::getChildValue(c, "Name");
642 QL_REQUIRE(std::find(loadedNames.begin(), loadedNames.end(), name) == loadedNames.end(),
643 "duplicate script with name '" << name << "'");
644 loadedNames.insert(name);
645 std::string productTag = XMLUtils::getChildValue(c, "ProductTag", false);
646 scripts_[name].first = productTag;
647 auto sn = XMLUtils::getChildrenNodes(c, "Script");
648 QL_REQUIRE(!sn.empty(), "no node Script found for '" << name << "'");
649 for (auto& n : sn) {
651 d.fromXML(n);
652 std::string purpose = XMLUtils::getAttribute(n, "purpose");
653 scripts_[name].second[purpose] = d;
654 TLOG("loaded script '" << name << "' (purpose='" << purpose << "', productTag='" << productTag << "')");
655 }
656 }
657}
658
660 XMLNode* n = doc.allocNode("ScriptLibrary");
661 for (auto& s : scripts_) {
662 XMLNode* c = XMLUtils::addChild(doc, n, "Script");
663 XMLUtils::addChild(doc, c, "Name", s.first);
664 XMLUtils::addChild(doc, c, "ProductTag", s.second.first);
665 for (auto& t : s.second.second) {
666 XMLNode* n = t.second.toXML(doc);
667 XMLUtils::addAttribute(doc, n, "purpose", t.first);
669 }
670 }
671 return n;
672}
673
675 boost::shared_lock<boost::shared_mutex> lock(mutex_);
676 return data_;
677}
678
680 boost::unique_lock<boost::shared_mutex> lock(mutex_);
681 data_ = data;
682}
683
685 boost::unique_lock<boost::shared_mutex> lock(mutex_);
686 data_ = std::move(data);
687}
688
690 boost::unique_lock<boost::shared_mutex> lock(mutex_);
691 data_ = ScriptLibraryData();
692}
693
694} // namespace data
695} // namespace ore
std::string infName() const
Definition: utilities.cpp:479
bool isComm() const
Definition: utilities.hpp:102
QuantLib::ext::shared_ptr< ZeroInflationIndex > inf() const
Definition: utilities.hpp:123
QuantLib::ext::shared_ptr< EquityIndex2 > eq() const
Definition: utilities.hpp:110
bool isFx() const
Definition: utilities.hpp:100
bool isEq() const
Definition: utilities.hpp:101
std::string commName() const
Definition: utilities.cpp:474
bool isInf() const
Definition: utilities.hpp:106
Serializable object holding premium data.
Definition: premiumdata.hpp:37
void addZeroInflationFixingDate(const QuantLib::Date &fixingDate, const std::string &indexName, const bool indexInterpolated, const Frequency indexFrequency, const Period &indexAvailabilityLag, const CPI::InterpolationType coupopnInterpolation, const Frequency couponFrequency, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false, const bool mandatoryFixing=true)
void addFixingDate(const QuantLib::Date &fixingDate, const std::string &indexName, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false, const bool mandatoryFixing=true)
Serializable schedule data.
Definition: schedule.hpp:202
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
ScriptLibraryData & operator=(const ScriptLibraryData &d)
std::pair< std::string, ScriptedTradeScriptData > get(const std::string &scriptName, const std::string &purpose, const bool fallBackOnEmptyPurpose=true) const
std::map< std::string, std::pair< std::string, std::map< std::string, ScriptedTradeScriptData > > > scripts_
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(ore::data::XMLDocument &doc) const override
bool has(const std::string &scriptName, const std::string &purpose, const bool fallBackOnEmptyPurpose=true) const
void set(const ScriptLibraryData &data)
const ScriptLibraryData & get() const
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::string notionalCurrency() const override
const std::map< std::string, ScriptedTradeScriptData > & script() const
std::vector< ScriptedTradeValueTypeData > daycounters_
std::vector< ScriptedTradeEventData > events_
const std::string & scriptName() const
std::vector< ScriptedTradeValueTypeData > currencies_
std::map< ore::data::AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
QuantLib::Real notional() const override
Return the current notional in npvCurrency. See individual sub-classes for the precise definition.
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
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(ore::data::XMLDocument &doc) const override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::vector< std::string > conditionalExpectationModelStates_
std::vector< CalibrationData > calibrationSpec_
std::vector< NewScheduleData > newSchedules_
std::vector< std::string > schedulesEligibleForCoarsening_
virtual void fromXML(XMLNode *node) override
std::vector< std::pair< std::string, std::string > > results_
virtual XMLNode * toXML(ore::data::XMLDocument &doc) const override
const std::vector< NewScheduleData > & newSchedules() const
std::vector< std::string > stickyCloseOutStates_
std::vector< std::string > values_
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(ore::data::XMLDocument &doc) const override
string npvCurrency_
Definition: trade.hpp:201
std::vector< bool > legPayers_
Definition: trade.hpp:200
std::vector< string > legCurrencies_
Definition: trade.hpp:199
std::vector< QuantLib::Leg > legs_
Definition: trade.hpp:198
QuantLib::Real notional_
Definition: trade.hpp:202
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
Date addPremiums(std::vector< QuantLib::ext::shared_ptr< Instrument > > &instruments, std::vector< Real > &multipliers, const Real tradeMultiplier, const PremiumData &premiumData, const Real premiumMultiplier, const Currency &tradeCurrency, const QuantLib::ext::shared_ptr< EngineFactory > &factory, const string &configuration)
Definition: trade.cpp:58
void setSensitivityTemplate(const EngineBuilder &builder)
Definition: trade.cpp:295
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
RequiredFixings requiredFixings_
Definition: trade.hpp:223
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
Definition: trade.hpp:197
string notionalCurrency_
Definition: trade.hpp:203
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
static void addChildrenWithAttributes(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values, const string &attrName, const vector< string > &attrs)
Definition: xmlutils.cpp:510
static void addAttribute(XMLDocument &doc, XMLNode *node, const string &attrName, const string &attrValue)
Definition: xmlutils.cpp:412
static void addChildren(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values)
Definition: xmlutils.cpp:502
static string getAttribute(XMLNode *node, const string &attrName)
Definition: xmlutils.cpp:419
static void checkNode(XMLNode *n, const string &expectedName)
Definition: xmlutils.cpp:175
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
Definition: xmlutils.cpp:428
static void addChildAsCdata(XMLDocument &doc, XMLNode *n, const string &name, const string &value)
Definition: xmlutils.cpp:202
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 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 * getNextSibling(XMLNode *node, const string &name="")
Get a node's next sibling node.
Definition: xmlutils.cpp:484
static vector< string > getChildrenValuesWithAttributes(XMLNode *node, const string &names, const string &name, const string &attrName, vector< string > &attrs, bool mandatory=false)
Definition: xmlutils.cpp:563
static vector< string > getChildrenValues(XMLNode *node, const string &names, const string &name, bool mandatory=false)
Definition: xmlutils.cpp:306
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
SafeStack< ValueType > value
script engine context holding variable names and values
Pricing Engine Factory.
Currency parseCurrencyWithMinors(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:310
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
std::string inverseFxIndex(const std::string &indexName)
Serializable Credit Default Swap.
Definition: namespaces.docs:23
trade schedule data model and serialization
scripted instrument
scripted instrument pricing engine
scripted trade data model
string name