Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
creditlinkedswap.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
19/*! \file portfolio/creditlinkedswap.hpp
20 \brief credit linked swap data model
21 \ingroup portfolio
22*/
23
25
27
28namespace ore {
29namespace data {
30
32 Trade::fromXML(node);
33 XMLNode* n = XMLUtils::getChildNode(node, "CreditLinkedSwapData");
34 creditCurveId_ = XMLUtils::getChildValue(n, "CreditCurveId");
35 settlesAccrual_ = XMLUtils::getChildValueAsBool(n, "SettlesAccrual", false, true);
36 fixedRecoveryRate_ = XMLUtils::getChildValueAsDouble(n, "FixedRecoveryRate", false, Null<Real>());
37 defaultPaymentTime_ = QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atDefault;
38 if (auto c = XMLUtils::getChildNode(n, "DefaultPaymentTime")) {
39 if (XMLUtils::getNodeValue(c) == "atDefault")
40 defaultPaymentTime_ = QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atDefault;
41 else if (XMLUtils::getNodeValue(c) == "atPeriodEnd")
42 defaultPaymentTime_ = QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atPeriodEnd;
43 else if (XMLUtils::getNodeValue(c) == "atMaturity")
44 defaultPaymentTime_ = QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atMaturity;
45 else {
46 QL_FAIL("default payment time '" << XMLUtils::getNodeValue(c)
47 << "' not known, expected atDefault, atPeriodEnd, atMaturity");
48 }
49 }
50 if (auto tmp = XMLUtils::getChildNode(n, "IndependentPayments")) {
51 for (auto const& d : XMLUtils::getChildrenNodes(tmp, "LegData")) {
52 independentPayments_.push_back(LegData());
53 independentPayments_.back().fromXML(d);
54 }
55 }
56 if (auto tmp = XMLUtils::getChildNode(n, "ContingentPayments")) {
57 for (auto const& d : XMLUtils::getChildrenNodes(tmp, "LegData")) {
58 contingentPayments_.push_back(LegData());
59 contingentPayments_.back().fromXML(d);
60 }
61 }
62 if (auto tmp = XMLUtils::getChildNode(n, "DefaultPayments")) {
63 for (auto const& d : XMLUtils::getChildrenNodes(tmp, "LegData")) {
64 defaultPayments_.push_back(LegData());
65 defaultPayments_.back().fromXML(d);
66 }
67 }
68 if (auto tmp = XMLUtils::getChildNode(n, "RecoveryPayments")) {
69 for (auto const& d : XMLUtils::getChildrenNodes(tmp, "LegData")) {
70 recoveryPayments_.push_back(LegData());
71 recoveryPayments_.back().fromXML(d);
72 }
73 }
74}
75
76XMLNode* CreditLinkedSwap::toXML(ore::data::XMLDocument& doc) const {
77 XMLNode* n = Trade::toXML(doc);
78 XMLNode* d = doc.allocNode("CreditLinkedSwapData");
79 XMLUtils::appendNode(n, d);
80 XMLUtils::addChild(doc, d, "CreditCurveId", creditCurveId_);
81 XMLUtils::addChild(doc, d, "SettlesAccrual", settlesAccrual_);
82 XMLUtils::addChild(doc, d, "FixedRecoveryRate", fixedRecoveryRate_);
83 if (defaultPaymentTime_ == QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atDefault) {
84 XMLUtils::addChild(doc, d, "DefaultPaymentTime", "atDefault");
85 } else if (defaultPaymentTime_ == QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atPeriodEnd) {
86 XMLUtils::addChild(doc, d, "DefaultPaymentTime", "atPeriodEnd");
87 } else if (defaultPaymentTime_ == QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atMaturity) {
88 XMLUtils::addChild(doc, d, "DefaultPaymentTime", "atMaturity");
89 } else {
90 QL_FAIL("toXML(): unexpected DefaultPaymentTime");
91 }
92 XMLNode* d1 = doc.allocNode("IndependentPayments");
93 XMLUtils::appendNode(d, d1);
94 for (auto& l : independentPayments_) {
95 XMLUtils::appendNode(d1, l.toXML(doc));
96 }
97 XMLNode* d2 = doc.allocNode("ContingentPayments");
98 XMLUtils::appendNode(d, d2);
99 for (auto& l : contingentPayments_) {
100 XMLUtils::appendNode(d2, l.toXML(doc));
101 }
102 XMLNode* d3 = doc.allocNode("DefaultPayments");
103 XMLUtils::appendNode(d, d3);
104 for (auto& l : defaultPayments_) {
105 XMLUtils::appendNode(d3, l.toXML(doc));
106 }
107 XMLNode* d4 = doc.allocNode("RecoveryPayments");
108 XMLUtils::appendNode(d, d4);
109 for (auto& l : recoveryPayments_) {
110 XMLUtils::appendNode(d4, l.toXML(doc));
111 }
112 return n;
113}
114
115void CreditLinkedSwap::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
116
117 DLOG("Building credit linked swap " << id());
118
119 // ISDA taxonomy
120
121 additionalData_["isdaAssetClass"] = string("Interest Rate");
122 additionalData_["isdaBaseProduct"] = string("Exotic");
123 additionalData_["isdaSubProduct"] = string("");
124 additionalData_["isdaTransaction"] = string("");
125
126 // checks, set npv currency (= single currency allowed in all legs)
127
128 npvCurrency_.clear();
129 for (auto const& l : independentPayments_) {
130 QL_REQUIRE(npvCurrency_ == "" || l.currency() == npvCurrency_,
131 "CreditLinkedSwap: all leg currencies must be the same, found " << npvCurrency_ << " and "
132 << l.currency());
133 npvCurrency_ = l.currency();
134 }
135
136 // get engine builder
137
138 auto builder = QuantLib::ext::dynamic_pointer_cast<CreditLinkedSwapEngineBuilder>(engineFactory->builder(tradeType()));
139 QL_REQUIRE(builder, "CreditLinkedSwap: wrong builder, expected CreditLinkedSwapEngineBuilder");
140 auto configuration = builder->configuration(MarketContext::pricing);
141
142 // build underlying legs
143
144 std::vector<QuantExt::CreditLinkedSwap::LegType> legTypes;
145 for (auto const& l : independentPayments_) {
146 auto legBuilder = engineFactory->legBuilder(l.legType());
147 legs_.push_back(legBuilder->buildLeg(l, engineFactory, requiredFixings_, configuration));
148 legPayers_.push_back(l.isPayer());
149 legTypes.push_back(QuantExt::CreditLinkedSwap::LegType::IndependentPayments);
150 }
151 for (auto const& l : contingentPayments_) {
152 auto legBuilder = engineFactory->legBuilder(l.legType());
153 legs_.push_back(legBuilder->buildLeg(l, engineFactory, requiredFixings_, configuration));
154 legPayers_.push_back(l.isPayer());
155 legTypes.push_back(QuantExt::CreditLinkedSwap::LegType::ContingentPayments);
156 }
157 for (auto const& l : defaultPayments_) {
158 auto legBuilder = engineFactory->legBuilder(l.legType());
159 legs_.push_back(legBuilder->buildLeg(l, engineFactory, requiredFixings_, configuration));
160 legPayers_.push_back(l.isPayer());
161 legTypes.push_back(QuantExt::CreditLinkedSwap::LegType::DefaultPayments);
162 }
163 for (auto const& l : recoveryPayments_) {
164 auto legBuilder = engineFactory->legBuilder(l.legType());
165 legs_.push_back(legBuilder->buildLeg(l, engineFactory, requiredFixings_, configuration));
166 legPayers_.push_back(l.isPayer());
167 legTypes.push_back(QuantExt::CreditLinkedSwap::LegType::RecoveryPayments);
168 }
169
170 // build ql instrument
171
172 auto qlInstr =
173 QuantLib::ext::make_shared<QuantExt::CreditLinkedSwap>(legs_, legPayers_, legTypes, settlesAccrual_, fixedRecoveryRate_,
174 defaultPaymentTime_, parseCurrency(npvCurrency_));
175
176 // wrap instrument
177
178 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(qlInstr);
179
180 // set trade members
181
182 notionalCurrency_ = npvCurrency_;
183 legCurrencies_ = std::vector<std::string>(legs_.size(), npvCurrency_);
184 maturity_ = qlInstr->maturity();
185
186 // set pricing engine
187
188 qlInstr->setPricingEngine(builder->engine(npvCurrency_, creditCurveId_));
189 setSensitivityTemplate(*builder);
190
191 // log
192
193 DLOG("Finished building credit linked swap " << id());
194 DLOG("Currency : " << npvCurrency_);
195 DLOG("IndependentPayments legs: " << independentPayments_.size());
196 DLOG("ContingentPayments legs: " << contingentPayments_.size());
197 DLOG("DefaultPayments legs: " << defaultPayments_.size());
198 DLOG("RecoveryPayments legs: " << recoveryPayments_.size());
199}
200
201QuantLib::Real CreditLinkedSwap::notional() const {
202 Real notional = 0.0;
203 for (auto const& l : legs_)
204 notional = std::max(notional, currentNotional(l));
205 return notional;
206}
207
208} // namespace data
209} // namespace ore
std::vector< bool > legPayers_
std::vector< Leg > legs_
QuantExt::CreditDefaultSwap::ProtectionPaymentTime defaultPaymentTime_
void fromXML(XMLNode *node) override
Serializable object holding leg data.
Definition: legdata.hpp:844
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
credit linked swap data model
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Real currentNotional(const Leg &leg)
Definition: legdata.cpp:2435
Serializable Credit Default Swap.
Definition: namespaces.docs:23