Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
equityposition.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
20
22
24
25namespace ore {
26namespace data {
27
29 XMLUtils::checkNode(node, "EquityPositionData");
30 quantity_ = XMLUtils::getChildValueAsDouble(node, "Quantity", true);
31 auto c = XMLUtils::getChildrenNodes(node, "Underlying");
32 underlyings_.clear();
33 for (auto const n : c) {
34 underlyings_.push_back(EquityUnderlying());
35 underlyings_.back().fromXML(n);
36 }
37}
38
40 XMLNode* n = doc.allocNode("EquityPositionData");
41 XMLUtils::addChild(doc, n, "Quantity", quantity_);
42 for (auto& u : underlyings_) {
43 XMLUtils::appendNode(n, u.toXML(doc));
44 }
45 return n;
46}
47
48void EquityPosition::build(const QuantLib::ext::shared_ptr<ore::data::EngineFactory>& engineFactory) {
49
50 // ISDA taxonomy: not a derivative, but define the asset class at least
51 // so that we can determine a TRS asset class that has an EQ position underlying
52 additionalData_["isdaAssetClass"] = string("Equity");
53 additionalData_["isdaBaseProduct"] = string("");
54 additionalData_["isdaSubProduct"] = string("");
55 additionalData_["isdaTransaction"] = string("");
56
57 DLOG("EquityPosition::build() called for " << id());
58 QL_REQUIRE(!data_.underlyings().empty(), "EquityPosition::build(): no underlyings given");
59 indices_.clear();
60 weights_.clear();
61 fxConversion_.clear();
62
63 std::vector<std::string> currencies;
64 for (auto const& u : data_.underlyings()) {
65 indices_.push_back(
66 *engineFactory->market()->equityCurve(u.name(), engineFactory->configuration(MarketContext::pricing)));
67 weights_.push_back(u.weight());
68 QL_REQUIRE(!indices_.back()->currency().empty(),
69 "did not get currency for equity name '" << u.name() << "', is this set up?");
70 currencies.push_back(indices_.back()->currency().code());
71 }
72
73 // get fx quotes
74
75 isSingleCurrency_ = true;
76 npvCurrency_ = currencies.front();
77 for (auto const& c : currencies) {
78 // we use fxSpot() as opposed to fxRate() here to ensure consistency between NPV() and the fixing of an
79 // equivalent index representing the same basket
80 fxConversion_.push_back(
81 engineFactory->market()->fxSpot(c + npvCurrency_, engineFactory->configuration(MarketContext::pricing)));
82 if (npvCurrency_ != c)
83 isSingleCurrency_ = false;
84 }
85
86 // set instrument
87 auto qlInstr =
88 QuantLib::ext::make_shared<EquityPositionInstrumentWrapper>(data_.quantity(), indices_, weights_, fxConversion_);
89 qlInstr->setPricingEngine(QuantLib::ext::make_shared<EquityPositionInstrumentWrapperEngine>());
90 setSensitivityTemplate(std::string());
91 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(qlInstr);
92
93 // no sensible way to set these members
94 maturity_ = Date::maxDate();
95 notional_ = Null<Real>();
97
98 // leave legs empty
99}
100
101void EquityPosition::setNpvCurrencyConversion(const std::string& ccy, const Handle<Quote>& conversion) {
102 npvCurrency_ = ccy;
103 QuantLib::ext::static_pointer_cast<EquityPositionInstrumentWrapper>(instrument_->qlInstrument())
104 ->setNpvCurrencyConversion(conversion);
105}
106
108 Trade::fromXML(node);
109 data_.fromXML(XMLUtils::getChildNode(node, "EquityPositionData"));
110}
111
113 XMLNode* node = Trade::toXML(doc);
114 XMLUtils::appendNode(node, data_.toXML(doc));
115 return node;
116}
117
118std::map<AssetClass, std::set<std::string>>
119EquityPosition::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
120 std::map<AssetClass, std::set<std::string>> result;
121 for (auto const& u : data_.underlyings()) {
122 result[AssetClass::EQ].insert(u.name());
123 }
124 return result;
125}
126
128 const Real quantity, const std::vector<QuantLib::ext::shared_ptr<QuantExt::EquityIndex2>>& equities,
129 const std::vector<Real>& weights, const std::vector<Handle<Quote>>& fxConversion)
130 : quantity_(quantity), equities_(equities), weights_(weights), fxConversion_(fxConversion) {
131 QL_REQUIRE(equities_.size() == weights_.size(), "EquityPositionInstrumentWrapper: equities size ("
132 << equities_.size() << ") must match weights size ("
133 << weights_.size() << ")");
134 QL_REQUIRE(fxConversion_.empty() || fxConversion_.size() == equities_.size(),
135 "EquityPositionInstrumentWrapper: fxConversion size ("
136 << fxConversion_.size() << ") must match equities size (" << equities_.size() << ")");
137 for (auto const& i : equities_)
138 registerWith(i);
139 for (auto const& f : fxConversion_)
140 registerWith(f);
141 registerWith(npvCcyConversion_);
142}
143
144void EquityPositionInstrumentWrapper::setNpvCurrencyConversion(const Handle<Quote>& npvCcyConversion) {
145 npvCcyConversion_ = npvCcyConversion;
146}
147
148bool EquityPositionInstrumentWrapper::isExpired() const { return false; }
149
150void EquityPositionInstrumentWrapper::setupExpired() const { Instrument::setupExpired(); }
151
152void EquityPositionInstrumentWrapper::setupArguments(PricingEngine::arguments* args) const {
154 QL_REQUIRE(a != nullptr, "wrong argument type in EquityPositionInstrumentWrapper");
155 a->quantity_ = quantity_;
156 a->equities_ = equities_;
157 a->weights_ = weights_;
160}
161
162void EquityPositionInstrumentWrapper::fetchResults(const PricingEngine::results* r) const {
163 Instrument::fetchResults(r);
164}
165
167 Real result = 0.0;
168 for (Size i = 0; i < arguments_.equities_.size(); ++i) {
169 Real tmp = arguments_.quantity_ * arguments_.equities_[i]->equitySpot()->value();
170 if (!arguments_.fxConversion_[i].empty()) {
171 tmp *= arguments_.fxConversion_[i]->value();
172 }
173 result += tmp * arguments_.weights_[i];
174 }
175 if (!arguments_.npvCcyConversion_.empty()) {
176 result *= arguments_.npvCcyConversion_->value();
177 }
178 results_.value = result;
179}
180
181} // namespace data
182} // namespace ore
const Instrument::results * results_
const std::vector< EquityUnderlying > & underlyings() const
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
std::vector< EquityUnderlying > underlyings_
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
void fromXML(XMLNode *node) override
std::vector< Handle< Quote > > fxConversion_
void setNpvCurrencyConversion(const std::string &ccy, const Handle< Quote > &conversion)
XMLNode * toXML(XMLDocument &doc) const override
std::vector< QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > > indices_
std::vector< Real > weights_
void build(const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &) override
EquityPositionData data_
std::vector< QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > > equities_
void fetchResults(const QuantLib::PricingEngine::results *) const override
EquityPositionInstrumentWrapper(const Real quantity, const std::vector< QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > > &equities, const std::vector< Real > &weights, const std::vector< Handle< Quote > > &fxConversion={})
std::vector< QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > > equities_
std::vector< Handle< Quote > > fxConversion_
void setupArguments(QuantLib::PricingEngine::arguments *) const override
void setNpvCurrencyConversion(const Handle< Quote > &npvCcyConversion)
string npvCurrency_
Definition: trade.hpp:201
QuantLib::Real notional_
Definition: trade.hpp:202
virtual void fromXML(XMLNode *node) override
Definition: trade.cpp:34
void setSensitivityTemplate(const EngineBuilder &builder)
Definition: trade.cpp:295
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: trade.cpp:46
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 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 XMLNode * getChildNode(XMLNode *n, const string &name="")
Definition: xmlutils.cpp:387
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
Equity Position trade data model and serialization.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Swap::arguments * arguments_
Trade Factory.