Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
portfolio.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 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
28#include <ql/errors.hpp>
29#include <ql/time/date.hpp>
30
31using namespace QuantLib;
32using namespace std;
33
34namespace ore {
35namespace data {
36
37using namespace data;
38
40 trades_.clear();
42}
43
45 LOG("Reset portfolio of size " << trades_.size());
46 for (auto [id, t] : trades_)
47 t->reset();
48}
49
51 XMLUtils::checkNode(node, "Portfolio");
52 vector<XMLNode*> nodes = XMLUtils::getChildrenNodes(node, "Trade");
53 for (Size i = 0; i < nodes.size(); i++) {
54 string tradeType = XMLUtils::getChildValue(nodes[i], "TradeType", true);
55
56 // Get the id attribute
57 string id = XMLUtils::getAttribute(nodes[i], "id");
58 QL_REQUIRE(id != "", "No id attribute in Trade Node");
59 DLOG("Parsing trade id:" << id);
60
61 QuantLib::ext::shared_ptr<Trade> trade;
62 bool failedToLoad = true;
63 try {
64 trade = TradeFactory::instance().build(tradeType);
65 trade->fromXML(nodes[i]);
66 trade->id() = id;
67 add(trade);
68 DLOG("Added Trade " << id << " (" << trade->id() << ")"
69 << " type:" << tradeType);
70 failedToLoad = false;
71 } catch (std::exception& ex) {
72 StructuredTradeErrorMessage(id, tradeType, "Error parsing Trade XML", ex.what()).log();
73 }
74
75 // If trade loading failed, then insert a dummy trade with same id and envelope
76 if (failedToLoad && buildFailedTrades_) {
77 try {
78 trade = TradeFactory::instance().build("Failed");
79 // this loads only type, id and envelope, but type will be set to the original trade's type
80 trade->fromXML(nodes[i]);
81 // create a dummy trade of type "Dummy"
82 QuantLib::ext::shared_ptr<FailedTrade> failedTrade = QuantLib::ext::make_shared<FailedTrade>();
83 // copy id and envelope
84 failedTrade->id() = id;
85 failedTrade->setUnderlyingTradeType(tradeType);
86 failedTrade->setEnvelope(trade->envelope());
87 // and add it to the portfolio
88 add(failedTrade);
89 WLOG("Added trade id " << failedTrade->id() << " type " << failedTrade->tradeType()
90 << " for original trade type " << trade->tradeType());
91 } catch (std::exception& ex) {
92 StructuredTradeErrorMessage(id, tradeType, "Error parsing type and envelope", ex.what()).log();
93 }
94 }
95 }
96 LOG("Finished Parsing XML doc");
97}
98
100 XMLNode* node = doc.allocNode("Portfolio");
101 for (auto& t : trades_)
102 XMLUtils::appendNode(node, t.second->toXML(doc));
103 return node;
104}
105
106bool Portfolio::remove(const std::string& tradeID) {
108 return trades_.erase(tradeID) > 0;
109}
110
111void Portfolio::removeMatured(const Date& asof) {
112 for (auto it = trades_.begin(); it != trades_.end(); /* manual */) {
113 if ((*it).second->isExpired(asof)) {
114 StructuredTradeWarningMessage((*it).second, "", "Trade is Matured").log();
115 it=trades_.erase(it);
116 } else {
117 ++it;
118 }
119 }
120}
121
122void Portfolio::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, const std::string& context,
123 const bool emitStructuredError) {
124 LOG("Building Portfolio of size " << trades_.size() << " for context = '" << context << "'");
125 auto trade = trades_.begin();
126 Size initialSize = trades_.size();
127 Size failedTrades = 0;
128 while (trade != trades_.end()) {
129 auto [ft, success] = buildTrade((*trade).second, engineFactory, context, ignoreTradeBuildFail(),
130 buildFailedTrades(), emitStructuredError);
131 if (success) {
132 ++trade;
133 } else if (ft) {
134 (*trade).second = ft;
135 ++failedTrades;
136 ++trade;
137 } else {
138 trade = trades_.erase(trade);
139 }
140 }
141 LOG("Built Portfolio. Initial size = " << initialSize << ", size now " << trades_.size() << ", built "
142 << failedTrades << " failed trades, context is " + context);
143
144 QL_REQUIRE(trades_.size() > 0, "Portfolio does not contain any built trades, context is '" + context + "'");
145}
146
148 QL_REQUIRE(trades_.size() > 0, "Cannot get maturity of an empty portfolio");
149 Date mat = Date::minDate();
150 for (const auto& t : trades_)
151 mat = std::max(mat, t.second->maturity());
152 return mat;
153}
154
155set<string> Portfolio::ids() const {
156 set<string> ids;
157 for (const auto& [tradeId, _] : trades_)
158 ids.insert(tradeId);
159 return ids;
160}
161
162const std::map<std::string, QuantLib::ext::shared_ptr<Trade>>& Portfolio::trades() const { return trades_; }
163
164map<string, string> Portfolio::nettingSetMap() const {
165 map<string, string> nettingSetMap;
166 for (const auto& t : trades_)
167 nettingSetMap[t.second->id()] = t.second->envelope().nettingSetId();
168 return nettingSetMap;
169}
170
171std::set<std::string> Portfolio::counterparties() const {
172 set<string> counterparties;
173 for (const auto& t : trades_)
174 counterparties.insert(t.second->envelope().counterparty());
175 return counterparties;
176}
177
178map<string, set<string>> Portfolio::counterpartyNettingSets() const {
179 map<string, set<string>> cpNettingSets;
180 for (const auto& [tradeId, trade] : trades()) {
181 cpNettingSets[trade->envelope().counterparty()].insert(trade->envelope().nettingSetId());
182 }
183 return cpNettingSets;
184}
185
186void Portfolio::add(const QuantLib::ext::shared_ptr<Trade>& trade) {
187 QL_REQUIRE(!has(trade->id()), "Attempted to add a trade to the portfolio with an id, which already exists.");
189 trades_[trade->id()] = trade;
190}
191
192bool Portfolio::has(const string& id) { return trades_.find(id) != trades_.end(); }
193
194QuantLib::ext::shared_ptr<Trade> Portfolio::get(const string& id) const {
195 auto it = trades_.find(id);
196 if (it != trades_.end())
197 return it->second;
198 else
199 return nullptr;
200}
201
202std::set<std::string> Portfolio::portfolioIds() const {
203 std::set<std::string> portfolioIds;
204 for (const auto& [tradeId, trade] : trades()) {
205 portfolioIds.insert(trade->portfolioIds().begin(), trade->portfolioIds().end());
206 }
207 return portfolioIds;
208}
209
211 bool hasNettingSetDetails = false;
212 for (const auto& t : trades_)
213 if (!t.second->envelope().nettingSetDetails().emptyOptionalFields()) {
215 break;
216 }
218}
219
220map<string, RequiredFixings::FixingDates> Portfolio::fixings(const Date& settlementDate) const {
221 map<string, RequiredFixings::FixingDates> result;
222 for (const auto& t : trades_) {
223 auto fixings = t.second->fixings(settlementDate);
224 for (const auto& [index, fixingDates] : fixings) {
225 if (!fixingDates.empty()) {
226 result[index].addDates(fixingDates);
227 }
228 }
229 }
230 return result;
231}
232
233std::map<AssetClass, std::set<std::string>>
234Portfolio::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) {
235
236 if (!underlyingIndicesCache_.empty())
238
239 map<AssetClass, std::set<std::string>> result;
240
241 for (const auto& t : trades_) {
242 try {
243 auto underlyings = t.second->underlyingIndices(referenceDataManager);
244 for (const auto& kv : underlyings) {
245 result[kv.first].insert(kv.second.begin(), kv.second.end());
246 }
247 } catch (const std::exception& e) {
248 StructuredTradeErrorMessage(t.second->id(), t.second->tradeType(), "Error retrieving underlying indices",
249 e.what())
250 .log();
251 }
252 }
255}
256
257std::set<std::string>
259 const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) {
260
261 std::map<AssetClass, std::set<std::string>> indices = underlyingIndices(referenceDataManager);
262 auto it = indices.find(assetClass);
263 if (it != indices.end()) {
264 return it->second;
265 }
266 return std::set<std::string>();
267}
268
269std::pair<QuantLib::ext::shared_ptr<Trade>, bool> buildTrade(QuantLib::ext::shared_ptr<Trade>& trade,
270 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory,
271 const std::string& context, const bool ignoreTradeBuildFail,
272 const bool buildFailedTrades, const bool emitStructuredError) {
273 try {
274 trade->reset();
275 trade->build(engineFactory);
276 TLOG("Required Fixings for trade " << trade->id() << ":");
277 TLOGGERSTREAM(trade->requiredFixings());
278 return std::make_pair(nullptr, true);
279 } catch (std::exception& e) {
280 if (emitStructuredError) {
281 StructuredTradeErrorMessage(trade, "Error building trade for context '" + context + "'", e.what()).log();
282 } else {
283 ALOG("Error building trade '" << trade->id() << "' for context '" + context + "': " + e.what());
284 }
285 if (ignoreTradeBuildFail) {
286 return std::make_pair(trade, false);
287 } else if (buildFailedTrades) {
288 QuantLib::ext::shared_ptr<FailedTrade> failed = QuantLib::ext::make_shared<FailedTrade>();
289 failed->id() = trade->id();
290 failed->setUnderlyingTradeType(trade->tradeType());
291 failed->setEnvelope(trade->envelope());
292 failed->build(engineFactory);
293 failed->resetPricingStats(trade->getNumberOfPricings(), trade->getCumulativePricingTime());
294 LOG("Built failed trade with id " << failed->id());
295 return std::make_pair(failed, false);
296 } else {
297 return std::make_pair(nullptr, false);
298 }
299 }
300}
301
302} // namespace data
303} // namespace ore
void log() const
generate Boost log record to pass to corresponding sinks
Definition: log.cpp:491
QuantLib::Date maturity() const
Calculates the maturity of the portfolio.
Definition: portfolio.cpp:147
const std::map< std::string, QuantLib::ext::shared_ptr< Trade > > & trades() const
Return the map tradeId -> trade.
Definition: portfolio.cpp:162
std::set< std::string > counterparties() const
Build a set of all counterparties in the portfolio.
Definition: portfolio.cpp:171
void add(const QuantLib::ext::shared_ptr< Trade > &trade)
Add a trade to the portfolio.
Definition: portfolio.cpp:186
std::map< std::string, RequiredFixings::FixingDates > fixings(const QuantLib::Date &settlementDate=QuantLib::Date()) const
Definition: portfolio.cpp:220
void removeMatured(const QuantLib::Date &asof)
Remove matured trades from portfolio for a given date, each removal is logged with an Alert.
Definition: portfolio.cpp:111
std::map< std::string, QuantLib::ext::shared_ptr< Trade > > trades_
Definition: portfolio.hpp:133
std::map< std::string, std::string > nettingSetMap() const
Build a map from trade Ids to NettingSet.
Definition: portfolio.cpp:164
bool ignoreTradeBuildFail() const
Keep trade in the portfolio even after build fail.
Definition: portfolio.hpp:114
void fromXML(XMLNode *node) override
XMLSerializable interface.
Definition: portfolio.cpp:50
void build(const QuantLib::ext::shared_ptr< EngineFactory > &, const std::string &context="unspecified", const bool emitStructuredError=true)
Call build on all trades in the portfolio, the context is included in error messages.
Definition: portfolio.cpp:122
std::set< std::string > portfolioIds() const
Compute set of portfolios.
Definition: portfolio.cpp:202
XMLNode * toXML(XMLDocument &doc) const override
Definition: portfolio.cpp:99
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr)
Definition: portfolio.cpp:234
bool hasNettingSetDetails() const
Check if at least one trade in the portfolio uses the NettingSetDetails node, and not just NettingSet...
Definition: portfolio.cpp:210
bool remove(const std::string &tradeID)
Remove specified trade from the portfolio.
Definition: portfolio.cpp:106
bool buildFailedTrades() const
Does this portfolio build failed trades?
Definition: portfolio.hpp:111
std::map< AssetClass, std::set< std::string > > underlyingIndicesCache_
Definition: portfolio.hpp:134
void clear()
Clear the portfolio.
Definition: portfolio.cpp:39
void reset()
Reset all trade data.
Definition: portfolio.cpp:44
std::map< std::string, std::set< std::string > > counterpartyNettingSets() const
Build a map from counterparty to NettingSet.
Definition: portfolio.cpp:178
bool has(const string &id)
Check if a trade id is already in the portfolio.
Definition: portfolio.cpp:192
QuantLib::ext::shared_ptr< Trade > get(const std::string &id) const
Definition: portfolio.cpp:194
std::set< std::string > ids() const
Build a set of tradeIds.
Definition: portfolio.cpp:155
Utility class for Structured Trade errors, contains the Trade ID and Type.
Utility classes for Structured warnings, 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 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 string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
Definition: xmlutils.cpp:277
static void appendNode(XMLNode *parent, XMLNode *child)
Definition: xmlutils.cpp:406
Skeleton trade generated when trade loading/building fails.
FX Forward data model and serialization.
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
#define TLOGGERSTREAM(text)
Definition: log.hpp:633
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
std::pair< QuantLib::ext::shared_ptr< Trade >, bool > buildTrade(QuantLib::ext::shared_ptr< Trade > &trade, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const std::string &context, const bool ignoreTradeBuildFail, const bool buildFailedTrades, const bool emitStructuredError)
Definition: portfolio.cpp:269
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Portfolio class.
Structured Trade Error class.
Classes for structured trade warnings.
Swap trade data model and serialization.
Swaption data model and serialization.
XML utility functions.