Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
nettingsetdefinition.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
23#include <ql/utilities/dataparsers.hpp>
24#include <utility>
25
26namespace ore {
27namespace data {
28
29CSA::Type parseCsaType(const string& s) {
30 static map<string, CSA::Type> t = {
31 {"Bilateral", CSA::Bilateral}, {"CallOnly", CSA::CallOnly}, {"PostOnly", CSA::PostOnly}};
32
33 auto it = t.find(s);
34 if (it != t.end()) {
35 return it->second;
36 } else {
37 QL_FAIL("Cannot convert \"" << s << "\" to CSA::Type");
38 }
39}
40
41std::ostream& operator<<(std::ostream& out, CSA::Type t) {
42 switch (t) {
43 case CSA::Bilateral:
44 return out << "Bilateral";
45 case CSA::CallOnly:
46 return out << "CallOnly";
47 case CSA::PostOnly:
48 return out << "PostOnly";
49 default:
50 QL_FAIL("csa type not covered");
51 }
52}
53
55 if (type_ != Bilateral) {
57 }
60 }
62 std::swap(thresholdPay_, thresholdRcv_);
63 std::swap(mtaPay_, mtaRcv_);
64 iaHeld_ *= -1;
66}
67
69 QL_REQUIRE(csaCurrency_.size() == 3, "NettingSetDefinition build error;"
70 << " CSA currency should be a three-letter ISO code");
71
72 QL_REQUIRE(thresholdPay_ >= 0, "NettingSetDefinition build error; negative thresholdPay");
73 QL_REQUIRE(thresholdRcv_ >= 0, "NettingSetDefinition build error; negative thresholdRcv");
74 QL_REQUIRE(mtaPay_ >= 0, "NettingSetDefinition build error; negative mtaPay");
75 QL_REQUIRE(mtaRcv_ >= 0, "NettingSetDefinition build error; negative mtaRcv");
76 QL_REQUIRE(iaType_ == "FIXED", "NettingSetDefinition build error;"
77 << " unsupported independent amount type; " << iaType_);
78
79 QL_REQUIRE(marginCallFreq_ > Period(0, Days) && marginPostFreq_ > Period(0, Days),
80 "NettingSetDefinition build error;"
81 << " non-positive margining frequency");
82 QL_REQUIRE(mpr_ >= Period(0, Days), "NettingSetDefinition build error;"
83 << " negative margin period of risk");
85 LOG("NettingSetDefinition has CSA margining frequency ("
86 << marginCallFreq_ << ", " << marginPostFreq_ << ") longer than assumed margin period of risk " << mpr_);
87 }
88
89 for (Size i = 0; i < eligCollatCcys_.size(); i++) {
90 QL_REQUIRE(eligCollatCcys_[i].size() == 3,
91 "NettingSetDefinition build error;"
92 << "EligibleCollaterals currency should be a three-letter ISO code");
93 }
94
95 // unilateral CSA - set threshold near infinity to disable margining
96 switch (type_) {
97 case CallOnly: {
98 thresholdPay_ = std::numeric_limits<double>::max();
99 break;
100 }
101 case PostOnly: {
102 thresholdRcv_ = std::numeric_limits<double>::max();
103 }
104 default:
105 break;
106 }
107}
108
110 fromXML(node);
111 DLOG(nettingSetDetails_ << ": NettingSetDefinition built from XML... ");
112}
113
115 : nettingSetDetails_(nettingSetDetails), activeCsaFlag_(false) {
116 validate();
117 DLOG(nettingSetDetails_ << ": uncollateralised NettingSetDefinition built.");
118}
119
120NettingSetDefinition::NettingSetDefinition(const NettingSetDetails& nettingSetDetails, const string& bilateral,
121 const string& csaCurrency, const string& index, const Real& thresholdPay,
122 const Real& thresholdRcv, const Real& mtaPay, const Real& mtaRcv,
123 const Real& iaHeld, const string& iaType, const string& marginCallFreq,
124 const string& marginPostFreq, const string& mpr, const Real& collatSpreadPay,
125 const Real& collatSpreadRcv, const vector<string>& eligCollatCcys,
126 bool applyInitialMargin, const string& initialMarginType,
127 const bool calculateIMAmount, const bool calculateVMAmount,
128 const string& nonExemptIMRegulations)
129 : nettingSetDetails_(nettingSetDetails), activeCsaFlag_(true) {
130
131 csa_ = QuantLib::ext::make_shared<CSA>(
132 parseCsaType(bilateral), csaCurrency, index, thresholdPay, thresholdRcv, mtaPay, mtaRcv, iaHeld, iaType,
133 parsePeriod(marginCallFreq), parsePeriod(marginPostFreq), parsePeriod(mpr), collatSpreadPay, collatSpreadRcv,
134 eligCollatCcys, applyInitialMargin, parseCsaType(initialMarginType), calculateIMAmount, calculateVMAmount,
135 nonExemptIMRegulations);
136
137 validate();
138 DLOG(nettingSetDetails_ << ": collateralised NettingSetDefinition built. ");
139}
140
142 XMLUtils::checkNode(node, "NettingSet");
143
144 // Read in the mandatory nodes.
145 XMLNode* nettingSetDetailsNode = XMLUtils::getChildNode(node, "NettingSetDetails");
146 if (nettingSetDetailsNode) {
147 nettingSetDetails_.fromXML(nettingSetDetailsNode);
148 } else {
149 nettingSetId_ = XMLUtils::getChildValue(node, "NettingSetId", false);
150 nettingSetDetails_ = NettingSetDetails(nettingSetId_);
151 }
152
153 activeCsaFlag_ = XMLUtils::getChildValueAsBool(node, "ActiveCSAFlag", false, true);
154
155 // Load "CSA" information, if necessary
156 if (activeCsaFlag_) {
157 XMLNode* csaChild = XMLUtils::getChildNode(node, "CSADetails");
158 XMLUtils::checkNode(csaChild, "CSADetails");
159
160 string csaTypeStr = XMLUtils::getChildValue(csaChild, "Bilateral", false);
161 if (csaTypeStr.empty())
162 csaTypeStr = "Bilateral";
163 string csaCurrency = XMLUtils::getChildValue(csaChild, "CSACurrency", false);
164 string index = XMLUtils::getChildValue(csaChild, "Index", false);
165 Real thresholdPay = XMLUtils::getChildValueAsDouble(csaChild, "ThresholdPay", false, 0.0);
166 Real thresholdRcv = XMLUtils::getChildValueAsDouble(csaChild, "ThresholdReceive", false, 0.0);
167 Real mtaPay = XMLUtils::getChildValueAsDouble(csaChild, "MinimumTransferAmountPay", false, 0.0);
168 Real mtaRcv = XMLUtils::getChildValueAsDouble(csaChild, "MinimumTransferAmountReceive", false, 0.0);
169 string mprStr = XMLUtils::getChildValue(csaChild, "MarginPeriodOfRisk", false);
170 if (mprStr.empty())
171 mprStr = "2W";
172 Real collatSpreadRcv =
173 XMLUtils::getChildValueAsDouble(csaChild, "CollateralCompoundingSpreadReceive", false, 0.0);
174 Real collatSpreadPay = XMLUtils::getChildValueAsDouble(csaChild, "CollateralCompoundingSpreadPay", false, 0.0);
175
176 string marginCallFreqStr, marginPostFreqStr;
177 if (XMLNode* freqChild = XMLUtils::getChildNode(csaChild, "MarginingFrequency")) {
178 marginCallFreqStr = XMLUtils::getChildValue(freqChild, "CallFrequency", false);
179 marginPostFreqStr = XMLUtils::getChildValue(freqChild, "PostFrequency", false);
180 }
181 if (marginCallFreqStr.empty())
182 marginCallFreqStr = "1D";
183 if (marginPostFreqStr.empty())
184 marginPostFreqStr = "1D";
185
186 Real iaHeld = 0.0;
187 string iaType;
188 if (XMLNode* iaChild = XMLUtils::getChildNode(csaChild, "IndependentAmount")) {
189 iaHeld = XMLUtils::getChildValueAsDouble(iaChild, "IndependentAmountHeld", false, 0.0);
190 iaType = XMLUtils::getChildValue(iaChild, "IndependentAmountType", false);
191 }
192 if (iaType.empty())
193 iaType = "FIXED";
194
195 vector<string> eligCollatCcys;
196 if (XMLNode* collatChild = XMLUtils::getChildNode(csaChild, "EligibleCollaterals")) {
197 eligCollatCcys = XMLUtils::getChildrenValues(collatChild, "Currencies", "Currency", false);
198 }
199
200 bool applyInitialMargin = XMLUtils::getChildValueAsBool(csaChild, "ApplyInitialMargin", false, false);
201
202 string initialMarginType = XMLUtils::getChildValue(csaChild, "InitialMarginType", false);
203 if (initialMarginType.empty())
204 initialMarginType = "Bilateral";
205
206 bool calculateIMAmount = XMLUtils::getChildValueAsBool(csaChild, "CalculateIMAmount", false, false);
207 bool calculateVMAmount = XMLUtils::getChildValueAsBool(csaChild, "CalculateVMAmount", false, false);
208
209 string nonExemptIMRegulations = XMLUtils::getChildValue(csaChild, "NonExemptIMRegulations", false);
210
211 csa_ = QuantLib::ext::make_shared<CSA>(parseCsaType(csaTypeStr), csaCurrency, index, thresholdPay, thresholdRcv, mtaPay,
212 mtaRcv, iaHeld, iaType, parsePeriod(marginCallFreqStr),
213 parsePeriod(marginPostFreqStr), parsePeriod(mprStr), collatSpreadPay,
214 collatSpreadRcv, eligCollatCcys, applyInitialMargin,
215 parseCsaType(initialMarginType), calculateIMAmount, calculateVMAmount,
216 nonExemptIMRegulations);
217 }
218
219 validate();
220}
221
223 // Allocate a node.
224 XMLNode* node = doc.allocNode("NettingSet");
225
226 // Add the mandatory members.
227 if (nettingSetDetails_.emptyOptionalFields()) {
228 XMLUtils::addChild(doc, node, "NettingSetId", nettingSetId_);
229 } else {
230 XMLUtils::appendNode(node, nettingSetDetails_.toXML(doc));
231 }
232 XMLUtils::addChild(doc, node, "ActiveCSAFlag", activeCsaFlag_);
233
234 XMLNode* csaSubNode = doc.allocNode("CSADetails");
235 XMLUtils::appendNode(node, csaSubNode);
236
237 if (activeCsaFlag_) {
238 QL_REQUIRE(csa_, "CSA details not defined");
239
240 XMLUtils::addChild(doc, csaSubNode, "Bilateral", to_string(csa_->type()));
241 XMLUtils::addChild(doc, csaSubNode, "CSACurrency", csa_->csaCurrency());
242 XMLUtils::addChild(doc, csaSubNode, "ThresholdPay", csa_->thresholdPay());
243 XMLUtils::addChild(doc, csaSubNode, "ThresholdReceive", csa_->thresholdRcv());
244 XMLUtils::addChild(doc, csaSubNode, "MinimumTransferAmountPay", csa_->mtaPay());
245 XMLUtils::addChild(doc, csaSubNode, "MinimumTransferAmountReceive", csa_->mtaRcv());
246 XMLUtils::addChild(doc, csaSubNode, "MarginPeriodOfRisk", to_string(csa_->marginPeriodOfRisk()));
247 XMLUtils::addChild(doc, csaSubNode, "CollateralCompoundingSpreadPay", csa_->collatSpreadPay());
248 XMLUtils::addChild(doc, csaSubNode, "CollateralCompoundingSpreadReceive", csa_->collatSpreadRcv());
249
250 XMLNode* freqSubNode = doc.allocNode("MarginingFrequency");
251 XMLUtils::appendNode(csaSubNode, freqSubNode);
252 XMLUtils::addChild(doc, freqSubNode, "CallFrequency", to_string(csa_->marginCallFrequency()));
253 XMLUtils::addChild(doc, freqSubNode, "PostFrequency", to_string(csa_->marginPostFrequency()));
254
255 XMLNode* iaSubNode = doc.allocNode("IndependentAmount");
256 XMLUtils::appendNode(csaSubNode, iaSubNode);
257 XMLUtils::addChild(doc, iaSubNode, "IndependentAmountHeld", csa_->independentAmountHeld());
258 XMLUtils::addChild(doc, iaSubNode, "IndependentAmountType", csa_->independentAmountType());
259
260 XMLNode* collatSubNode = doc.allocNode("EligibleCollaterals");
261 XMLUtils::appendNode(csaSubNode, collatSubNode);
262 XMLUtils::addChildren(doc, collatSubNode, "Currencies", "Currency", csa_->eligCollatCcys());
263
264 XMLUtils::addChild(doc, csaSubNode, "ApplyInitialMargin", csa_->applyInitialMargin());
265 XMLUtils::addChild(doc, csaSubNode, "InitialMarginType", to_string(csa_->initialMarginType()));
266 XMLUtils::addChild(doc, csaSubNode, "CalculateIMAmount", csa_->calculateIMAmount());
267 XMLUtils::addChild(doc, csaSubNode, "CalculateVMAmount", csa_->calculateVMAmount());
268 XMLUtils::addChild(doc, csaSubNode, "NonExemptIMRegulations", csa_->nonExemptIMRegulations());
269 }
270
271 return node;
272}
273
275 string nettingSetLog = nettingSetDetails_.empty() ? nettingSetId_ : ore::data::to_string(nettingSetDetails_);
276 LOG(nettingSetLog << ": Validating netting set definition");
277 QL_REQUIRE(nettingSetId_.size() > 0 || !nettingSetDetails_.empty(),
278 "NettingSetDefinition build error; no netting set ID or netting set details");
279
280 if (activeCsaFlag_) {
281 QL_REQUIRE(csa_, "CSA not defined yet");
282 string nettingSetLog = nettingSetDetails_.empty() ? nettingSetId_ : ore::data::to_string(nettingSetDetails_);
283 LOG(nettingSetLog << ": Validating netting set definition's CSA details");
284 csa_->validate();
285 }
286}
287} // namespace data
288} // namespace ore
vector< string > eligCollatCcys_
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
Serializable object holding netting set identification data.
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 addChildren(XMLDocument &doc, XMLNode *n, const string &names, const string &name, const vector< T > &values)
Definition: xmlutils.cpp:502
static void checkNode(XMLNode *n, const string &expectedName)
Definition: xmlutils.cpp:175
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 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
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
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
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
CSA::Type parseCsaType(const string &s)
Size size(const ValueType &v)
Definition: value.cpp:145
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Netting Set Definition - including CSA information where available.
Map text representations to QuantLib/QuantExt types.
string conversion utilities