Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
referencedata.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
25
26using std::function;
27
28namespace ore {
29namespace data {
30
32 XMLUtils::checkNode(node, "ReferenceDatum");
33 type_ = XMLUtils::getChildValue(node, "Type", true);
34 id_ = XMLUtils::getAttribute(node, "id");
35 std::string dateStr = XMLUtils::getAttribute(node, "validFrom");
36 if (!dateStr.empty()) {
37 validFrom_ = parseDate(dateStr);
38 } else {
39 validFrom_ = QuantLib::Date::minDate();
40 }
41}
42
44 XMLNode* node = doc.allocNode("ReferenceDatum");
45 QL_REQUIRE(node, "Failed to create ReferenceDatum node");
46 XMLUtils::addAttribute(doc, node, "id", id_);
47 XMLUtils::addChild(doc, node, "Type", type_);
48 if (validFrom_ > QuantLib::Date::minDate()) {
49 XMLUtils::addAttribute(doc, node, "validFrom", to_string(validFrom_));
50 }
51 return node;
52}
53
55 QL_REQUIRE(node, "BondReferenceDatum::BondData::fromXML(): no node given");
56 issuerId = XMLUtils::getChildValue(node, "IssuerId", true);
57 creditCurveId = XMLUtils::getChildValue(node, "CreditCurveId", false);
58 creditGroup = XMLUtils::getChildValue(node, "CreditGroup", false);
59 referenceCurveId = XMLUtils::getChildValue(node, "ReferenceCurveId", true);
60 incomeCurveId = XMLUtils::getChildValue(node, "IncomeCurveId", false);
61 volatilityCurveId = XMLUtils::getChildValue(node, "VolatilityCurveId", false);
62 settlementDays = XMLUtils::getChildValue(node, "SettlementDays", true);
63 calendar = XMLUtils::getChildValue(node, "Calendar", true);
64 issueDate = XMLUtils::getChildValue(node, "IssueDate", true);
65 priceQuoteMethod = XMLUtils::getChildValue(node, "PriceQuoteMethod", false);
66 priceQuoteBaseValue = XMLUtils::getChildValue(node, "PriceQuoteBaseValue", false);
67 subType = XMLUtils::getChildValue(node, "SubType", false);
68
69 legData.clear();
70 XMLNode* legNode = XMLUtils::getChildNode(node, "LegData");
71 while (legNode != nullptr) {
72 LegData ld;
73 ld.fromXML(legNode);
74 legData.push_back(ld);
75 legNode = XMLUtils::getNextSibling(legNode, "LegData");
76 }
77}
78
80 XMLNode* node = doc.allocNode("BondData");
81 XMLUtils::addChild(doc, node, "IssuerId", issuerId);
82 XMLUtils::addChild(doc, node, "CreditCurveId", creditCurveId);
83 XMLUtils::addChild(doc, node, "CreditGroup", creditGroup);
84 XMLUtils::addChild(doc, node, "ReferenceCurveId", referenceCurveId);
85 XMLUtils::addChild(doc, node, "IncomeCurveId", incomeCurveId);
86 XMLUtils::addChild(doc, node, "VolatilityCurveId", volatilityCurveId);
87 XMLUtils::addChild(doc, node, "SettlementDays", settlementDays);
88 XMLUtils::addChild(doc, node, "Calendar", calendar);
89 XMLUtils::addChild(doc, node, "IssueDate", issueDate);
90 XMLUtils::addChild(doc, node, "PriceQuoteMethod", priceQuoteMethod);
91 XMLUtils::addChild(doc, node, "PriceQuoteBaseValue", priceQuoteBaseValue);
92 XMLUtils::addChild(doc, node, "SubType", subType);
93 for (auto& bd : legData)
94 XMLUtils::appendNode(node, bd.toXML(doc));
95 return node;
96}
97
100 bondData_.fromXML(XMLUtils::getChildNode(node, "BondReferenceData"));
101}
102
104 XMLNode* node = ReferenceDatum::toXML(doc);
105 XMLNode* dataNode = bondData_.toXML(doc);
106 XMLUtils::setNodeName(doc, dataNode, "BondReferenceData");
107 XMLUtils::appendNode(node, dataNode);
108 return node;
109}
110
112 : weight_(Null<Real>()), priorWeight_(Null<Real>()), recovery_(Null<Real>()) {}
113
114CreditIndexConstituent::CreditIndexConstituent(const string& name, Real weight, Real priorWeight, Real recovery,
115 const Date& auctionDate, const Date& auctionSettlementDate, const Date& defaultDate,
116 const Date& eventDeterminationDate)
117 : name_(name), weight_(weight), priorWeight_(priorWeight), recovery_(recovery), auctionDate_(auctionDate),
118 auctionSettlementDate_(auctionSettlementDate), defaultDate_(defaultDate),
119 eventDeterminationDate_(eventDeterminationDate) {}
120
122
123 name_ = XMLUtils::getChildValue(node, "Name", true);
124 weight_ = XMLUtils::getChildValueAsDouble(node, "Weight", true);
125
126 if (close(weight_, 0.0)) {
127 priorWeight_ = Null<Real>();
128 if (auto n = XMLUtils::getChildNode(node, "PriorWeight"))
130
131 recovery_ = Null<Real>();
132 if (auto n = XMLUtils::getChildNode(node, "RecoveryRate"))
134
135 auctionDate_ = Date();
136 if (auto n = XMLUtils::getChildNode(node, "AuctionDate"))
138
139 auctionSettlementDate_ = Date();
140 if (auto n = XMLUtils::getChildNode(node, "AuctionSettlementDate"))
142
143 defaultDate_ = Date();
144 if (auto n = XMLUtils::getChildNode(node, "DefaultDate"))
146
148 if (auto n = XMLUtils::getChildNode(node, "EventDeterminationDate"))
150 }
151}
152
154
155 XMLNode* node = doc.allocNode("Underlying");
156
157 XMLUtils::addChild(doc, node, "Name", name_);
158 XMLUtils::addChild(doc, node, "Weight", weight_);
159
160 if (close(weight_, 0.0)) {
161 if (priorWeight_ != Null<Real>())
162 XMLUtils::addChild(doc, node, "PriorWeight", priorWeight_);
163
164 if (recovery_ != Null<Real>())
165 XMLUtils::addChild(doc, node, "RecoveryRate", recovery_);
166
167 if (auctionDate_ != Date())
168 XMLUtils::addChild(doc, node, "AuctionDate", to_string(auctionDate_));
169
170 if (auctionSettlementDate_ != Date())
171 XMLUtils::addChild(doc, node, "AuctionSettlementDate", to_string(auctionSettlementDate_));
172
173 if (defaultDate_ != Date())
174 XMLUtils::addChild(doc, node, "DefaultDate", to_string(defaultDate_));
175
176 if (eventDeterminationDate_ != Date())
177 XMLUtils::addChild(doc, node, "EventDeterminationDate", to_string(eventDeterminationDate_));
178 }
179
180 return node;
181}
182
183const string& CreditIndexConstituent::name() const { return name_; }
184
186
188
190
192
194
196
198
199bool operator<(const CreditIndexConstituent& lhs, const CreditIndexConstituent& rhs) { return lhs.name() < rhs.name(); }
200
202
204
205CreditIndexReferenceDatum::CreditIndexReferenceDatum(const string& name, const QuantLib::Date& validFrom)
206 : ReferenceDatum(TYPE, name, validFrom) {}
207
209
211
212 XMLNode* cird = XMLUtils::getChildNode(node, "CreditIndexReferenceData");
213 QL_REQUIRE(cird, "Expected a CreditIndexReferenceData node.");
214
215 indexFamily_ = XMLUtils::getChildValue(cird, "IndexFamily", false);
216
217 constituents_.clear();
218
219 for (XMLNode* child = XMLUtils::getChildNode(cird, "Underlying"); child;
220 child = XMLUtils::getNextSibling(child, "Underlying")) {
222 c.fromXML(child);
223 add(c);
224 }
225}
226
228
229 XMLNode* node = ReferenceDatum::toXML(doc);
230 XMLNode* cird = XMLUtils::addChild(doc, node, "CreditIndexReferenceData");
231
232 XMLUtils::addChild(doc, cird, "IndexFamily", indexFamily_);
233
234 for (auto c : constituents_) {
235 auto cNode = c.toXML(doc);
236 XMLUtils::appendNode(cird, cNode);
237 }
238
239 return node;
240}
241
243 auto it = constituents_.find(c);
244 if (it != constituents_.end()) {
245 DLOG("Constituent " << c.name() << " not added to credit index " << id() << " because already present.");
246 } else {
247 constituents_.insert(c);
248 DLOG("Constituent " << c.name() << " added to credit index " << id() << ".");
249 }
250}
251
252const set<CreditIndexConstituent>& CreditIndexReferenceDatum::constituents() const { return constituents_; }
253
254// Index
257 XMLNode* innerNode = XMLUtils::getChildNode(node, type() + "ReferenceData");
258 QL_REQUIRE(innerNode, "No " + type() + "ReferenceData node");
259
260 // clear map
261 data_.clear();
262
263 // and populate it...
264 for (XMLNode* child = XMLUtils::getChildNode(innerNode, "Underlying"); child;
265 child = XMLUtils::getNextSibling(child, "Underlying")) {
266 string name = XMLUtils::getChildValue(child, "Name", true);
267 double weight = XMLUtils::getChildValueAsDouble(child, "Weight", true);
268 addUnderlying(name, weight);
269 }
270}
271
273 XMLNode* node = ReferenceDatum::toXML(doc);
274 XMLNode* rdNode = XMLUtils::addChild(doc, node, type() + "ReferenceData");
275
276 for (auto d : data_) {
277 XMLNode* underlyingNode = XMLUtils::addChild(doc, rdNode, "Underlying");
278 XMLUtils::addChild(doc, underlyingNode, "Name", d.first);
279 XMLUtils::addChild(doc, underlyingNode, "Weight", d.second);
280 }
281
282 return node;
283}
284// Currency Hedged Equity Indexes
285/*
286<ReferenceDatum id="RIC:.SPXEURHedgedMonthly">
287 <Type>CurrencyHedgedEquityIndex</Type>
288 <CurrencyHedgedEquityIndexReferenceDatum>
289 <UnderlyingIndex>RIC:.SPX</UnderlyingIndex>
290 <UnderlyingIndexCurrency>USD</UnderlyingIndexCurrency>
291 <HedgeCurrency>EUR</HedgeCurrency>
292 <RebalancingStrategy>EndOfMonth</RebalancingStrategy>
293 <ReferenceDateOffset>1</ReferenceDateOffset>
294 <HedgeAdjustment>None|Daily</HedgeAdjustment>
295 <HedgeCalendar>EUR,USD</HedgeCalendar>
296 <FxIndex>ECB-EUR-USD</FxIndex>
297 <IndexWeightsAtLastRebalancingDate>
298 <Underlying>
299 <Name>Apple</Name>
300 <Weight>0.1</Weight>
301 </Underlying>
302 ...
303 </IndexWeightsAtLastRebalancingDate>
304 </CurrencyHedgedEquityIndexReferenceDatum>
305</ReferenceDatum>
306*/
307
310 XMLNode* innerNode = XMLUtils::getChildNode(node, type() + "ReferenceData");
311 QL_REQUIRE(innerNode, "No " + type() + "ReferenceData node");
312
313 underlyingIndexName_ = XMLUtils::getChildValue(innerNode, "UnderlyingIndex", true);
314
315 auto rebalancingStr = XMLUtils::getChildValue(innerNode, "RebalancingStrategy", false, "EndOfMonth");
316 if (rebalancingStr == "EndOfMonth") {
318 } else {
319 QL_FAIL("unexpected rebalancing strategy " << rebalancingStr);
320 }
321
322 std::string hedgeCalendarStr = XMLUtils::getChildValue(innerNode, "HedgeCalendar", true);
323 hedgeCalendar_ = parseCalendar(hedgeCalendarStr);
324
325 XMLNode* fxIndexesNode = XMLUtils::getChildNode(innerNode, "FxIndexes");
326 if (fxIndexesNode) {
327 for (XMLNode* child = XMLUtils::getChildNode(fxIndexesNode, "FxIndex"); child;
328 child = XMLUtils::getNextSibling(child, "FxIndex")) {
329 string currency = XMLUtils::getChildValue(child, "Currency", true);
330 string indexFamily = XMLUtils::getChildValue(child, "IndexName", true);
331 fxIndexes_[currency] = indexFamily;
332 }
333 }
334 // Optional Fields
335 referenceDateOffset_ = XMLUtils::getChildValueAsInt(innerNode, "ReferenceDateOffset", false, 0);
336 auto hedgeAdjStr = XMLUtils::getChildValue(innerNode, "HedgeAdjustment", false, "None");
337
338 if (hedgeAdjStr == "None") {
340 } else if (hedgeAdjStr == "Daily") {
342 } else {
343 QL_FAIL("unexpected rebalancing strategy " << hedgeAdjStr);
344 }
345 // clear map
346 data_.clear();
347
348 // and populate it...
349 XMLNode* currencyWeightNode = XMLUtils::getChildNode(innerNode, "IndexWeightsAtLastRebalancingDate");
350 if (currencyWeightNode) {
351 double totalWeight = 0.0;
352 for (XMLNode* child = XMLUtils::getChildNode(currencyWeightNode, "Underlying"); child;
353 child = XMLUtils::getNextSibling(child, "Underlying")) {
354 string name = XMLUtils::getChildValue(child, "Name", true);
355 double weight = XMLUtils::getChildValueAsDouble(child, "Weight", true);
356 QL_REQUIRE(weight > 0 || QuantLib::close_enough(weight, 0.0),
357 "Try to add negtive weight for Underlying" << name);
358 data_[name] += weight;
359 totalWeight += weight;
360 }
361 QL_REQUIRE(data_.empty() || QuantLib::close_enough(totalWeight, 1.0),
362 "Sum of underlying weights at last rebalancing date (" << totalWeight << ") is not 1.0");
363 }
364}
365
367 XMLNode* node = ReferenceDatum::toXML(doc);
368 XMLNode* rdNode = XMLUtils::addChild(doc, node, type() + "ReferenceData");
369
370 XMLUtils::addChild(doc, rdNode, "UnderlyingIndex", underlyingIndexName_);
371 XMLUtils::addChild(doc, rdNode, "RebalancingStrategy", "EndOfMonth");
372 XMLUtils::addChild(doc, rdNode, "HedgeCalendar", to_string(hedgeCalendar_));
373 if (referenceDateOffset_ != 0)
374 XMLUtils::addChild(doc, rdNode, "ReferenceDateOffset", to_string(referenceDateOffset_));
376 XMLUtils::addChild(doc, rdNode, "HedgeAdjustment", "Daily");
377 }
378
379 if (!fxIndexes_.empty()) {
380 XMLNode* currencyWeightNode = XMLUtils::addChild(doc, rdNode, "FxIndexes");
381 for (auto d : fxIndexes_) {
382 XMLNode* underlyingNode = XMLUtils::addChild(doc, currencyWeightNode, "FxIndex");
383 XMLUtils::addChild(doc, underlyingNode, "Currency", d.first);
384 XMLUtils::addChild(doc, underlyingNode, "IndexName", d.second);
385 }
386 }
387
388 if (!data_.empty()) {
389 XMLNode* currencyWeightNode = XMLUtils::addChild(doc, rdNode, "IndexWeightsAtLastRebalancingDate");
390 for (auto d : data_) {
391 XMLNode* underlyingNode = XMLUtils::addChild(doc, currencyWeightNode, "Underlying");
392 XMLUtils::addChild(doc, underlyingNode, "Name", d.first);
393 XMLUtils::addChild(doc, underlyingNode, "Weight", d.second);
394 }
395 }
396 return node;
397}
398
399// Portfolio Basket
400/*
401<ReferenceDatum id="MSFDSJP">
402 <PortfolioBasketReferenceData>
403 <Components>
404 <Trade>
405 <TradeType>EquityPosition</TradeType>
406 <Envelope>
407 <CounterParty>{{netting_set_id}}</CounterParty>
408 <NettingSetId>{{netting_set_id}}</NettingSetId>
409 <AdditionalFields>
410 <valuation_date>2023-11-07</valuation_date>
411 <im_model>SIMM</im_model>
412 <post_regulations>SEC</post_regulations>
413 <collect_regulations>SEC</collect_regulations>
414 </AdditionalFields>
415 </Envelope>
416 <EquityPositionData>
417 <Quantity>7006.0</Quantity>
418 <Underlying>
419 <Type>Equity</Type>
420 <Name>CR.N</Name>
421 <IdentifierType>RIC</IdentifierType>
422 </Underlying>
423 </EquityPositionData>
424 </Trade>
425 <Trade id="CashSWAP_USD.CASH">
426 <TradeType>Swap</TradeType>
427 <Envelope>
428 <CounterParty>{{netting_set_id}}</CounterParty>
429 <NettingSetId>{{netting_set_id}}</NettingSetId>
430 <AdditionalFields>
431 <valuation_date>2023-11-07</valuation_date>
432 <im_model>SIMM</im_model>
433 <post_regulations>SEC</post_regulations>
434 <collect_regulations>SEC</collect_regulations>
435 </AdditionalFields>
436 </Envelope>
437 <SwapData>
438 <LegData>
439 <Payer>true</Payer>
440 <LegType>Cashflow</LegType>
441 <Currency>USD</Currency>
442 <CashflowData>
443 <Cashflow>
444 <Amount date="2023-11-08">28641475.824680243</Amount>
445 </Cashflow>
446 </CashflowData>
447 </LegData>
448 </SwapData>
449 </Trade>
450 </Components>
451 </PortfolioBasketReferenceData>
452</ReferenceDatum>
453*/
454
457 XMLNode* innerNode = XMLUtils::getChildNode(node, type() + "ReferenceData");
458 QL_REQUIRE(innerNode, "No " + type() + "ReferenceData node");
459
460 // Get the "Components" node
461 XMLNode* componentsNode = XMLUtils::getChildNode(innerNode, "Components");
462 QL_REQUIRE(componentsNode, "No Components node");
463
464 tradecomponents_.clear();
465 auto c = XMLUtils::getChildrenNodes(componentsNode, "Trade");
466 int k = 0;
467 for (auto const n : c) {
468
469 string tradeType = XMLUtils::getChildValue(n, "TradeType", true);
470 string id = XMLUtils::getAttribute(n, "id");
471 if (id == "") {
472 id = std::to_string(k);
473 }
474
475 DLOG("Parsing composite trade " << this->id() << " node " << k << " with id: " << id);
476
477 QuantLib::ext::shared_ptr<Trade> trade;
478 try {
479 trade = TradeFactory::instance().build(tradeType);
480 trade->id() = id;
481 Envelope componentEnvelope;
482 if (XMLNode* envNode = XMLUtils::getChildNode(n, "Envelope")) {
483 componentEnvelope.fromXML(envNode);
484 }
485 Envelope env;
486 // the component trade's envelope is the main trade's envelope with possibly overwritten add fields
487 for (auto const& [k, v] : componentEnvelope.fullAdditionalFields()) {
488 env.setAdditionalField(k, v);
489 }
490
491 trade->setEnvelope(env);
492 trade->fromXML(n);
493 tradecomponents_.push_back(trade);
494 DLOG("Added Trade " << id << " (" << trade->id() << ")"
495 << " type:" << tradeType << " to composite trade " << this->id() << ".");
496 k += 1;
497 } catch (const std::exception& e) {
499 id, tradeType,
500 "Failed to build subtrade with id '" + id + "' inside composite trade: ", e.what())
501 .log();
502 }
503
504 }
505}
506
508 XMLNode* node = ReferenceDatum::toXML(doc);
509 XMLNode* rdNode = XMLUtils::addChild(doc, node, type() + "ReferenceData");
510 XMLUtils::appendNode(node, rdNode);
511 XMLNode* cNode = XMLUtils::addChild(doc, rdNode, "Components");
512 for (auto& u : tradecomponents_) {
513 auto test = u->toXML(doc);
514 XMLUtils::appendNode(cNode, test);
515 }
516
517 return node;
518 }
519
520// Credit
523 XMLNode* innerNode = XMLUtils::getChildNode(node, "CreditReferenceData");
524 QL_REQUIRE(innerNode, "No CreditReferenceData node");
525
526 creditData_.name = XMLUtils::getChildValue(innerNode, "Name", true);
527 creditData_.group = XMLUtils::getChildValue(innerNode, "Group", false);
528 creditData_.successor = XMLUtils::getChildValue(innerNode, "Successor", false);
529 creditData_.predecessor = XMLUtils::getChildValue(innerNode, "Predecessor", false);
531 parseDate(XMLUtils::getChildValue(innerNode, "SuccessorImplementationDate", false));
533 parseDate(XMLUtils::getChildValue(innerNode, "PredecessorImplementationDate", false));
534 creditData_.entityType = (XMLUtils::getChildValue(innerNode, "EntityType", false) == "Corp."||
535 XMLUtils::getChildValue(innerNode, "EntityType", false) == "Corp")
536 ? "Corporate"
537 : XMLUtils::getChildValue(innerNode, "EntityType", false);
538}
539
541 XMLNode* node = ReferenceDatum::toXML(doc);
542 XMLNode* creditNode = doc.allocNode("CreditReferenceData");
543 XMLUtils::appendNode(node, creditNode);
544 XMLUtils::addChild(doc, creditNode, "Name", creditData_.name);
545 XMLUtils::addChild(doc, creditNode, "Group", creditData_.group);
546 XMLUtils::addChild(doc, creditNode, "Successor", creditData_.successor);
547 XMLUtils::addChild(doc, creditNode, "Predecessor", creditData_.predecessor);
549 XMLUtils::addChild(doc, creditNode, "SuccessorImplementationDate",
552 XMLUtils::addChild(doc, creditNode, "PredecessorImplementationDate",
554 XMLUtils::addChild(doc, creditNode, "EntityType", creditData_.entityType);
555 return node;
556}
557
558// Equity
561 XMLNode* innerNode = XMLUtils::getChildNode(node, "EquityReferenceData");
562 QL_REQUIRE(innerNode, "No EquityReferenceData node");
563
564 equityData_.equityId = XMLUtils::getChildValue(innerNode, "EquityId", true);
565 equityData_.equityName = XMLUtils::getChildValue(innerNode, "EquityName", true);
566 equityData_.currency = XMLUtils::getChildValue(innerNode, "Currency", true);
567 equityData_.scalingFactor = XMLUtils::getChildValueAsInt(innerNode, "ScalingFactor", true);
568 equityData_.exchangeCode = XMLUtils::getChildValue(innerNode, "ExchangeCode", true);
569 equityData_.isIndex = XMLUtils::getChildValueAsBool(innerNode, "IsIndex", true);
570 equityData_.equityStartDate = parseDate(XMLUtils::getChildValue(innerNode, "EquityStartDate", true));
571 equityData_.proxyIdentifier = XMLUtils::getChildValue(innerNode, "ProxyIdentifier", true);
572 equityData_.simmBucket = XMLUtils::getChildValue(innerNode, "SimmBucket", true);
573 equityData_.crifQualifier = XMLUtils::getChildValue(innerNode, "CrifQualifier", true);
574 equityData_.proxyVolatilityId = XMLUtils::getChildValue(innerNode, "ProxyVolatilityId", true);
575}
576
578 XMLNode* node = ReferenceDatum::toXML(doc);
579 XMLNode* equityNode = doc.allocNode("EquityReferenceData");
580 XMLUtils::appendNode(node, equityNode);
581 XMLUtils::addChild(doc, equityNode, "EquityId", equityData_.equityId);
582 XMLUtils::addChild(doc, equityNode, "EquityName", equityData_.equityName);
583 XMLUtils::addChild(doc, equityNode, "Currency", equityData_.currency);
584 XMLUtils::addChild(doc, equityNode, "ScalingFactor", int(equityData_.scalingFactor));
585 XMLUtils::addChild(doc, equityNode, "ExchangeCode", equityData_.exchangeCode);
586 XMLUtils::addChild(doc, equityNode, "IsIndex", equityData_.isIndex);
587 XMLUtils::addChild(doc, equityNode, "EquityStartDate", to_string(equityData_.equityStartDate));
588 XMLUtils::addChild(doc, equityNode, "ProxyIdentifier", equityData_.proxyIdentifier);
589 XMLUtils::addChild(doc, equityNode, "SimmBucket", equityData_.simmBucket);
590 XMLUtils::addChild(doc, equityNode, "CrifQualifier", equityData_.crifQualifier);
591 XMLUtils::addChild(doc, equityNode, "ProxyVolatilityId", equityData_.proxyVolatilityId);
592 return node;
593}
594
595// Bond Basket
598 XMLNode* b = XMLUtils::getChildNode(node, "BondBasketData");
599 QL_REQUIRE(b, "No BondBasketData node");
600 underlyingData_.clear();
601 auto c = XMLUtils::getChildrenNodes(b, "Underlying");
602 for (auto const n : c) {
603 underlyingData_.push_back(BondUnderlying());
604 underlyingData_.back().fromXML(n);
605 }
606}
607
609 XMLNode* res = ReferenceDatum::toXML(doc);
610 XMLNode* node = doc.allocNode("BondBasketData");
611 XMLUtils::appendNode(res, node);
612 for (auto& u : underlyingData_) {
613 XMLUtils::appendNode(node, u.toXML(doc));
614 }
615 return res;
616}
617
618// BasicReferenceDataManager
619
621 XMLUtils::checkNode(node, "ReferenceData");
622 for (XMLNode* child = XMLUtils::getChildNode(node, "ReferenceDatum"); child;
623 child = XMLUtils::getNextSibling(child, "ReferenceDatum")) {
624 addFromXMLNode(child);
625 }
626}
627
628void BasicReferenceDataManager::add(const QuantLib::ext::shared_ptr<ReferenceDatum>& rd) {
629 // Add reference datum, it is overwritten if it is already present.
630 data_[make_pair(rd->type(), rd->id())][rd->validFrom()] = rd;
631}
632
633QuantLib::ext::shared_ptr<ReferenceDatum> BasicReferenceDataManager::addFromXMLNode(XMLNode* node, const std::string& inputId,
634 const QuantLib::Date& inputValidFrom) {
635 string refDataType = XMLUtils::getChildValue(node, "Type", false);
636 QuantLib::ext::shared_ptr<ReferenceDatum> refData;
637
638 if (refDataType.empty()) {
639 ALOG("Found referenceDatum without Type - skipping");
640 return refData;
641 }
642
643 string id = inputId.empty() ? XMLUtils::getAttribute(node, "id") : inputId;
644
645 string validFromStr = XMLUtils::getAttribute(node, "validFrom");
646 QuantLib::Date validFrom;
647 if (validFromStr.empty()) {
648 validFrom = QuantLib::Date::minDate();
649 } else {
650 validFrom = ore::data::parseDate(validFromStr);
651 }
652
653 validFrom = inputValidFrom == QuantLib::Null<QuantLib::Date>() ? validFrom : inputValidFrom;
654
655 if (id.empty()) {
656 ALOG("Found referenceDatum without id - skipping");
657 return refData;
658 }
659
660 if (auto it = data_.find(make_pair(refDataType, id)); it != data_.end()) {
661 if (it->second.count(validFrom) > 0) {
662 duplicates_.insert(make_tuple(refDataType, id, validFrom));
663 ALOG("Found duplicate referenceDatum for type='" << refDataType << "', id='" << id << "', validFrom='"
664 << validFrom << "'");
665 return refData;
666 }
667 }
668
669 try {
670 refData = buildReferenceDatum(refDataType);
671 refData->fromXML(node);
672 // set the type and id at top level (is this needed?)
673 refData->setType(refDataType);
674 refData->setId(id);
675 refData->setValidFrom(validFrom);
676 data_[make_pair(refDataType, id)][validFrom] = refData;
677 TLOG("added referenceDatum for type='" << refDataType << "', id='" << id << "', validFrom='" << validFrom
678 << "'");
679 } catch (const std::exception& e) {
680 buildErrors_[make_pair(refDataType, id)][validFrom] = e.what();
681 ALOG("Error building referenceDatum for type='" << refDataType << "', id='" << id << "', validFrom='" << validFrom
682 << "': " << e.what());
683 }
684
685 return refData;
686}
687
688QuantLib::ext::shared_ptr<ReferenceDatum> BasicReferenceDataManager::buildReferenceDatum(const string& refDataType) {
689 auto refData = ReferenceDatumFactory::instance().build(refDataType);
690 QL_REQUIRE(refData,
691 "Reference data type " << refDataType << " has not been registered with the reference data factory.");
692 return refData;
693}
694
696 XMLNode* node = doc.allocNode("ReferenceData");
697 for (const auto& kv : data_) {
698 for (const auto& [_, refData] : kv.second) {
699 XMLUtils::appendNode(node, refData->toXML(doc));
700 }
701 }
702 return node;
703}
704
705std::tuple<QuantLib::Date, QuantLib::ext::shared_ptr<ReferenceDatum>> BasicReferenceDataManager::latestValidFrom(const string& type, const string& id,
706 const QuantLib::Date& asof) const {
707 auto it = data_.find(make_pair(type, id));
708 if (it != data_.end() && !it->second.empty()){
709 auto uB = it->second.upper_bound(asof);
710 if (uB != it->second.begin()) {
711 return *(--uB);
712 }
713 }
714 return {QuantLib::Date(), nullptr};
715}
716
717void BasicReferenceDataManager::check(const string& type, const string& id, const QuantLib::Date& validFrom) const {
718 auto key = make_tuple(type, id, validFrom);
719 if (duplicates_.find(key) != duplicates_.end())
720 ALOG("BasicReferenceDataManager: duplicate entries for type='" << type << "', id='" << id << "', validFrom='"
721 << validFrom << "'");
722 auto err = buildErrors_.find(make_pair(type, id));
723 if (err != buildErrors_.end()) {
724 for (const auto& [validFrom, error] : err->second) {
725 ALOG("BasicReferenceDataManager: Build error for type='" << type << "', id='" << id << "', validFrom='"
726 << validFrom << "': " << error);
727 }
728 }
729
730}
731
732bool BasicReferenceDataManager::hasData(const string& type, const string& id, const QuantLib::Date& asof) {
733 Date asofDate = asof;
734 if (asofDate == QuantLib::Null<QuantLib::Date>()) {
735 asofDate = Settings::instance().evaluationDate();
736 }
737 auto [validFrom, refData] = latestValidFrom(type, id, asofDate);
738 check(type, id, validFrom);
739 return refData != nullptr;
740}
741
742QuantLib::ext::shared_ptr<ReferenceDatum> BasicReferenceDataManager::getData(const string& type, const string& id,
743 const QuantLib::Date& asof) {
744 Date asofDate = asof;
745 if (asofDate == QuantLib::Null<QuantLib::Date>()) {
746 asofDate = Settings::instance().evaluationDate();
747 }
748 auto [validFrom, refData] = latestValidFrom(type, id, asofDate);
749 check(type, id, validFrom);
750 QL_REQUIRE(refData != nullptr, "BasicReferenceDataManager::getData(): No Reference data for type='"
751 << type << "', id='" << id << "', asof='" << asof << "'");
752 return refData;
753}
754
755} // namespace data
756} // namespace ore
bool hasData(const string &type, const string &id, const QuantLib::Date &asof=QuantLib::Null< QuantLib::Date >()) override
map< std::pair< string, string >, std::map< QuantLib::Date, QuantLib::ext::shared_ptr< ReferenceDatum > > > data_
map< std::pair< string, string >, std::map< QuantLib::Date, string > > buildErrors_
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::tuple< QuantLib::Date, QuantLib::ext::shared_ptr< ReferenceDatum > > latestValidFrom(const string &type, const string &id, const QuantLib::Date &asof) const
QuantLib::ext::shared_ptr< ReferenceDatum > buildReferenceDatum(const string &refDataType)
void add(const QuantLib::ext::shared_ptr< ReferenceDatum > &referenceDatum) override
std::set< std::tuple< string, string, QuantLib::Date > > duplicates_
QuantLib::ext::shared_ptr< ReferenceDatum > getData(const string &type, const string &id, const QuantLib::Date &asof=QuantLib::Null< QuantLib::Date >()) override
void check(const string &type, const string &id, const QuantLib::Date &asof) const
QuantLib::ext::shared_ptr< ReferenceDatum > addFromXMLNode(XMLNode *node, const std::string &id=std::string(), const QuantLib::Date &validFrom=QuantLib::Null< QuantLib::Date >())
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::vector< BondUnderlying > underlyingData_
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
const QuantLib::Date & defaultDate() const
const QuantLib::Date & eventDeterminationDate() const
QuantLib::Real recovery() const
void fromXML(XMLNode *node) override
const QuantLib::Date & auctionDate() const
XMLNode * toXML(ore::data::XMLDocument &doc) const override
QuantLib::Real priorWeight() const
const QuantLib::Date & auctionSettlementDate() const
const std::string & name() const
const std::set< CreditIndexConstituent > & constituents() const
Get all of the underlying constituents.
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::set< CreditIndexConstituent > constituents_
void add(const CreditIndexConstituent &c)
Add a constituent. The constituent is not added if already present.
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::map< std::string, std::string > fxIndexes_
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
virtual void fromXML(XMLNode *node) override
Definition: envelope.cpp:27
void setAdditionalField(const std::string &key, const boost::any &value)
Definition: envelope.cpp:133
const map< string, boost::any > & fullAdditionalFields() const
Definition: envelope.hpp:105
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::map< std::string, double > data_
void fromXML(XMLNode *node) override
void addUnderlying(const string &name, double weight)
XMLNode * toXML(ore::data::XMLDocument &doc) const override
void log() const
generate Boost log record to pass to corresponding sinks
Definition: log.cpp:491
Serializable object holding leg data.
Definition: legdata.hpp:844
virtual void fromXML(XMLNode *node) override
Definition: legdata.cpp:759
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
vector< QuantLib::ext::shared_ptr< Trade > > tradecomponents_
Base class for reference data.
const std::string & id() const
const std::string & type() const
getters
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
Utility class for Structured Trade errors, contains the Trade ID and Type.
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 addAttribute(XMLDocument &doc, XMLNode *node, const string &attrName, const string &attrValue)
Definition: xmlutils.cpp:412
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 Real getChildValueAsDouble(XMLNode *node, const string &name, bool mandatory=false, double defaultValue=0.0)
Definition: xmlutils.cpp:286
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 int getChildValueAsInt(XMLNode *node, const string &name, bool mandatory=false, int defaultValue=0)
Definition: xmlutils.cpp:291
static XMLNode * getNextSibling(XMLNode *node, const string &name="")
Get a node's next sibling node.
Definition: xmlutils.cpp:484
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
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
leg data model and serialization
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
Calendar calendar
Definition: utilities.cpp:441
Real error
Definition: utilities.cpp:65
bool operator<(const Dividend &d1, const Dividend &d2)
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
Reference data model and serialization.
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
Structured Trade Error class.
string conversion utilities
string name
Trade Factory.