Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
bondposition.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2021 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
21
22namespace ore {
23namespace data {
24
26 XMLUtils::checkNode(node, "BondBasketData");
27 quantity_ = XMLUtils::getChildValueAsDouble(node, "Quantity", true);
28 identifier_ = XMLUtils::getChildValue(node, "Identifier", true);
29 auto c = XMLUtils::getChildrenNodes(node, "Underlying");
30 underlyings_.clear();
31 for (auto const n : c) {
32 underlyings_.push_back(BondUnderlying());
33 underlyings_.back().fromXML(n);
34 }
35}
36
38 XMLNode* n = doc.allocNode("BondBasketData");
39 XMLUtils::addChild(doc, n, "Quantity", quantity_);
40 XMLUtils::addChild(doc, n, "Identifier", identifier_);
41 for (auto& u : underlyings_) {
42 XMLUtils::appendNode(n, u.toXML(doc));
43 }
44 return n;
45}
46
47void BondPositionData::populateFromBondBasketReferenceData(const QuantLib::ext::shared_ptr<ReferenceDataManager>& ref) {
48 QL_REQUIRE(!identifier_.empty(), "BondPositionData::populateFromBondBasketReferenceData(): no identifier given");
49 if (!ref || !ref->hasData(BondBasketReferenceDatum::TYPE, identifier_)) {
50 DLOG("could not get BondBasketReferenceDatum for '" << identifier_ << "' leave data in trade unchanged");
51 } else {
52 DLOG("got BondBasketReferenceDatum for '" << identifier_ << "':");
53 auto r = QuantLib::ext::dynamic_pointer_cast<BondBasketReferenceDatum>(
55 QL_REQUIRE(r, "BondPositionData::populateFromBondBasketReferenceData(): internal error, could not cast "
56 "reference datum to expected type.");
57 underlyings_ = r->underlyingData();
58 DLOG("updated " << underlyings_.size() << " Underlying nodes.");
59 }
60}
61
62void BondPosition::build(const QuantLib::ext::shared_ptr<ore::data::EngineFactory>& engineFactory) {
63 DLOG("BondPosition::build() called for " << id());
64
65 // ISDA taxonomy: not a derivative, but define the asset class at least
66 // so that we can determine a TRS asset class that has a Bond position underlying
67 additionalData_["isdaAssetClass"] = string("Credit");
68 additionalData_["isdaBaseProduct"] = string("");
69 additionalData_["isdaSubProduct"] = string("");
70 additionalData_["isdaTransaction"] = string("");
71
72 bonds_.clear();
73 weights_.clear();
74 bidAskAdjustments_.clear();
75 fxConversion_.clear();
76
78 data_.populateFromBondBasketReferenceData(engineFactory->referenceData());
79
80 QL_REQUIRE(!data_.underlyings().empty(), "BondPosition::build(): no underlyings given");
81
82 maturity_ = Date::minDate();
83 for (auto const& u : data_.underlyings()) {
84 try {
85 bonds_.push_back(BondFactory::instance().build(engineFactory, engineFactory->referenceData(), u.name()));
86 } catch (const std::exception& e) {
87 QL_FAIL("Build failed for underlying " << u.type() << " (" << u.name() << "): " << e.what());
88 }
89 weights_.push_back(u.weight());
90 bidAskAdjustments_.push_back(u.bidAskAdjustment());
91 maturity_ = std::max(bonds_.back().bond->maturityDate(), maturity_);
92 }
93
94 // get fx quotes
95
96 isSingleCurrency_ = true;
97 npvCurrency_ = bonds_.front().currency;
98 for (auto const& b : bonds_) {
99 fxConversion_.push_back(engineFactory->market()->fxSpot(b.currency + npvCurrency_,
100 engineFactory->configuration(MarketContext::pricing)));
101 if (npvCurrency_ != b.currency)
102 isSingleCurrency_ = false;
103 }
104
105 // set instrument
106 std::vector<QuantLib::ext::shared_ptr<QuantLib::Bond>> qlbonds;
107 std::transform(bonds_.begin(), bonds_.end(), std::back_inserter(qlbonds),
108 [](const BondBuilder::Result& d) { return d.bond; });
109 instrument_ = QuantLib::ext::make_shared<BondPositionInstrumentWrapper>(data_.quantity(), qlbonds, weights_,
111
112 // leave legs empty, leave notional empty for the time being
113 notional_ = Null<Real>();
115
116 setSensitivityTemplate(std::string());
117}
118
119void BondPosition::setNpvCurrencyConversion(const std::string& ccy, const Handle<Quote>& conversion) {
120 npvCurrency_ = ccy;
121 QuantLib::ext::static_pointer_cast<BondPositionInstrumentWrapper>(instrument_)->setNpvCurrencyConversion(conversion);
122}
123
125 Trade::fromXML(node);
126 originalData_.fromXML(XMLUtils::getChildNode(node, "BondBasketData"));
128}
129
131 XMLNode* node = Trade::toXML(doc);
133 return node;
134}
135
136std::map<AssetClass, std::set<std::string>>
137BondPosition::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
138 std::map<AssetClass, std::set<std::string>> result;
139 for (auto const& u : data_.underlyings()) {
140 result[AssetClass::BOND].insert(u.name());
141 }
142 result[AssetClass::BOND_INDEX].insert(data().identifier());
143 return result;
144}
145
147 const Real quantity, const std::vector<QuantLib::ext::shared_ptr<QuantLib::Bond>>& bonds, const std::vector<Real>& weights,
148 const std::vector<Real>& bidAskAdjustments, const std::vector<Handle<Quote>>& fxConversion)
149 : quantity_(quantity), bonds_(bonds), weights_(weights), bidAskAdjustments_(bidAskAdjustments),
150 fxConversion_(fxConversion) {
151 QL_REQUIRE(bonds_.size() == weights_.size(), "BondPositionInstrumentWrapper: bonds size ("
152 << bonds_.size() << ") must match weights size ("
153 << weights_.size() << ")");
154 QL_REQUIRE(bonds_.size() == bidAskAdjustments_.size(),
155 "BondPositionInstrumentWrapper: bonds size (" << bonds_.size() << ") must match bidAskAdjustment size ("
156 << weights_.size() << ")");
157 QL_REQUIRE(fxConversion_.empty() || fxConversion_.size() == bonds_.size(),
158 "BondPositionInstrumentWrapper: fxConversion size ("
159 << fxConversion_.size() << ") must match bonds size (" << bonds_.size() << ")");
160}
161
162void BondPositionInstrumentWrapper::setNpvCurrencyConversion(const Handle<Quote>& npvCcyConversion) {
163 npvCcyConversion_ = npvCcyConversion;
164}
165
167 Real result = 0.0;
168 for (Size i = 0; i < bonds_.size(); ++i) {
169 // - divide by current notional, because weights are supposed to include any amortization factors
170 // - add bid ask adjustment to relative price in bond ccy
171 Real tmp = quantity_ * (bonds_[i]->NPV() / bonds_[i]->notional() + bidAskAdjustments_[i]);
172 if (!fxConversion_[i].empty()) {
173 tmp *= fxConversion_[i]->value();
174 }
175 result += tmp * weights_[i];
176 }
177 if (!npvCcyConversion_.empty()) {
178 result *= npvCcyConversion_->value();
179 }
180 return result;
181}
182
183const std::map<std::string, boost::any>& BondPositionInstrumentWrapper::additionalResults() const {
184 static std::map<std::string, boost::any> emptyMap;
185 return emptyMap;
186}
187
188} // namespace data
189} // namespace ore
Bond Position trade data model and serialization.
static constexpr const char * TYPE
std::vector< BondUnderlying > underlyings_
void populateFromBondBasketReferenceData(const QuantLib::ext::shared_ptr< ReferenceDataManager > &ref)
const std::vector< BondUnderlying > & underlyings() const
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
BondPositionData originalData_
BondPositionData data_
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
const BondPositionData & data() const
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< Real > weights_
void build(const QuantLib::ext::shared_ptr< ore::data::EngineFactory > &) override
std::vector< Real > bidAskAdjustments_
std::vector< BondBuilder::Result > bonds_
BondPositionInstrumentWrapper(const Real quantity, const std::vector< QuantLib::ext::shared_ptr< QuantLib::Bond > > &bonds, const std::vector< Real > &weights, const std::vector< Real > &bidAskAdjstments, const std::vector< Handle< Quote > > &fxConversion={})
QuantLib::Real NPV() const override
Return the NPV of this instrument.
const std::map< std::string, boost::any > & additionalResults() const override
Return the additional results of this instrument.
std::vector< Handle< Quote > > fxConversion_
std::vector< QuantLib::ext::shared_ptr< QuantLib::Bond > > bonds_
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 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 XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
Definition: xmlutils.cpp:181
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Reference data model and serialization.