Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
creditdefaultswap.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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
26#include <ql/time/daycounters/actual360.hpp>
27
28using namespace QuantLib;
29using namespace QuantExt;
30
31namespace ore {
32namespace data {
33
34void CreditDefaultSwap::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
35 DLOG("CreditDefaultSwap::build() called for trade " << id());
36
37 // ISDA taxonomy
38 additionalData_["isdaAssetClass"] = string("Credit");
39 additionalData_["isdaBaseProduct"] = string("Single Name");
40 // set isdaSubProduct to entityType in credit reference data
41 additionalData_["isdaSubProduct"] = string("");
43 QuantLib::ext::shared_ptr<ReferenceDataManager> refData = engineFactory->referenceData();
44 if (refData && refData->hasData("Credit", entity)) {
45 auto refDatum = refData->getData("Credit", entity);
46 QuantLib::ext::shared_ptr<CreditReferenceDatum> creditRefDatum =
47 QuantLib::ext::dynamic_pointer_cast<CreditReferenceDatum>(refDatum);
48 additionalData_["isdaSubProduct"] = creditRefDatum->creditData().entityType;
49 if (creditRefDatum->creditData().entityType == "") {
50 ALOG("EntityType is blank in credit reference data for entity " << entity);
51 }
52 } else {
53 ALOG("Credit reference data missing for entity " << entity << ", isdaSubProduct left blank");
54 }
55 // skip the transaction level mapping for now
56 additionalData_["isdaTransaction"] = string("");
57
58 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
59 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder("CreditDefaultSwap");
60
61 auto legData = swap_.leg(); // copy
62 const auto& notionals = swap_.leg().notionals();
63
64 npvCurrency_ = legData.currency();
65 notionalCurrency_ = legData.currency();
66
67 QL_REQUIRE(legData.legType() == "Fixed", "CreditDefaultSwap requires Fixed leg");
68 Schedule schedule = makeSchedule(legData.schedule());
69 QL_REQUIRE(schedule.size() > 1, "CreditDefaultSwap requires at least two dates in the schedule");
70
71 BusinessDayConvention payConvention = Following;
72 if (!legData.paymentConvention().empty()) {
73 payConvention = parseBusinessDayConvention(legData.paymentConvention());
74 }
75
76 Protection::Side prot = legData.isPayer() ? Protection::Side::Buyer : Protection::Side::Seller;
77 notional_ = notionals.front();
78
79 DayCounter dc = Actual360();
80 if (!legData.dayCounter().empty()) {
81 dc = parseDayCounter(legData.dayCounter());
82 }
83
84 // In general for CDS and CDS index trades, the standard day counter is Actual/360 and the final
85 // period coupon accrual includes the maturity date.
86 DayCounter lastPeriodDayCounter;
87 auto strLpdc = legData.lastPeriodDayCounter();
88 if (!strLpdc.empty()) {
89 lastPeriodDayCounter = parseDayCounter(strLpdc);
90 } else {
91 Actual360 standardDayCounter;
92 if (dc == standardDayCounter) {
93 lastPeriodDayCounter = dc == standardDayCounter ? Actual360(true) : dc;
94 legData.lastPeriodDayCounter() = "A360 (Incl Last)";
95 } else {
96 lastPeriodDayCounter = dc;
97 }
98 }
99
100 // Build the coupon leg
101 auto legBuilder = engineFactory->legBuilder(legData.legType());
102 auto couponLeg =
103 legBuilder->buildLeg(legData, engineFactory, requiredFixings_, builder->configuration(MarketContext::pricing));
104 // for the accrual rebate calculation we may need historical coupons that are already paid
106
107 /* If we have an indexed leg we don't allow for an upfront fee, since we would need to index that
108 as well, btu the ql instrument / engine cdoes not support this currently */
109 QL_REQUIRE(legData.indexing().empty() || swap_.upfrontFee() == Null<Real>(),
110 "CreditDefaultSwap with indexed coupon leg does not allow for an upfront fee");
111
112 /* The rate is really only used to compute the fair spread in the add results and we support that only
113 for fixed coupons with a sinlge rate, otherwise we set this rate to zero */
114 Real fixedRate = 0.0;
115 if (auto fixedData = QuantLib::ext::dynamic_pointer_cast<FixedLegData>(legData.concreteLegData())) {
116 if (fixedData->rates().size() == 1)
117 fixedRate = fixedData->rates().front();
118 }
119
120 QuantLib::ext::shared_ptr<QuantLib::CreditDefaultSwap> cds;
121
122 if (swap_.upfrontFee() == Null<Real>()) {
123 cds = QuantLib::ext::make_shared<QuantLib::CreditDefaultSwap>(
124 prot, notional_, couponLeg, fixedRate, schedule, payConvention, dc, swap_.settlesAccrual(),
125 swap_.protectionPaymentTime(), swap_.protectionStart(), QuantLib::ext::shared_ptr<Claim>(), lastPeriodDayCounter,
127 } else {
128 cds = QuantLib::ext::make_shared<QuantLib::CreditDefaultSwap>(
129 prot, notional_, couponLeg, swap_.upfrontFee(), fixedRate, schedule, payConvention, dc,
131 QuantLib::ext::shared_ptr<Claim>(), lastPeriodDayCounter, swap_.rebatesAccrual(), swap_.tradeDate(),
133 }
134
135 maturity_ = cds->coupons().back()->date();
136
137 QuantLib::ext::shared_ptr<CreditDefaultSwapEngineBuilder> cdsBuilder =
138 QuantLib::ext::dynamic_pointer_cast<CreditDefaultSwapEngineBuilder>(builder);
139
140 QL_REQUIRE(cdsBuilder, "No Builder found for CreditDefaultSwap: " << id());
141 cds->setPricingEngine(cdsBuilder->engine(parseCurrency(npvCurrency_), swap_.creditCurveId(), swap_.recoveryRate()));
142 setSensitivityTemplate(*cdsBuilder);
143
144 instrument_.reset(new VanillaInstrument(cds));
145
146 legs_ = {cds->coupons()};
148 legPayers_ = {legData.isPayer()};
149
150 if (swap_.protectionStart() != Date())
152 else
153 additionalData_["startDate"] = to_string(schedule.dates().front());
154
156}
157
158const std::map<std::string, boost::any>& CreditDefaultSwap::additionalData() const {
160 additionalData_["legNPV[1]"] = instrument_->qlInstrument()->result<Real>("protectionLegNPV");
161 additionalData_["legNPV[2]"] = instrument_->qlInstrument()->result<Real>("premiumLegNPVDirty") +
162 instrument_->qlInstrument()->result<Real>("upfrontPremiumNPV") +
163 instrument_->qlInstrument()->result<Real>("accrualRebateNPV");
164 additionalData_["isPayer[1]"] = !swap_.leg().isPayer();
165 additionalData_["isPayer[2]"] = swap_.leg().isPayer();
166 additionalData_["legType[2]"] = swap_.leg().legType();
167 additionalData_["legType[1]"] = std::string("Protection");
168 additionalData_["currentNotional[1]"] = additionalData_["currentNotional[2]"];
169 additionalData_["originalNotional[1]"] = additionalData_["originalNotional[2]"];
170 additionalData_["notionalCurrency[1]"] = notionalCurrency_;
171 additionalData_["notionalCurrency[2]"] = notionalCurrency_;
172 return additionalData_;
173}
174
175QuantLib::Real CreditDefaultSwap::notional() const {
176 Date asof = Settings::instance().evaluationDate();
177 // get the current notional from CDS premium leg
178 if (!legs_.empty()) {
179 for (Size i = 0; i < legs_[0].size(); ++i) {
180 QuantLib::ext::shared_ptr<Coupon> coupon = boost::dynamic_pointer_cast<Coupon>(legs_[0][i]);
181 if (coupon->date() > asof)
182 return coupon->nominal();
183 }
184 }
185 // if no coupons are given, return the initial notional by default
186 return notional_;
187}
188
190 Trade::fromXML(node);
191 XMLNode* cdsNode = XMLUtils::getChildNode(node, "CreditDefaultSwapData");
192 QL_REQUIRE(cdsNode, "No CreditDefaultSwapData Node");
193 swap_.fromXML(cdsNode);
194}
195
197 XMLNode* node = Trade::toXML(doc);
198 XMLUtils::appendNode(node, swap_.toXML(doc));
199 return node;
200}
201} // namespace data
202} // namespace ore
Builder that returns an engine to price a credit default swap.
const boost::optional< CdsReferenceInformation > & referenceInformation() const
QuantLib::Natural cashSettlementDays() const
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
const QuantLib::Date & tradeDate() const
QuantLib::Real notional() const override
Return the current notional in npvCurrency. See individual sub-classes for the precise definition.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
const std::map< std::string, boost::any > & additionalData() const override
returns all additional data returned by the trade once built
bool isPayer() const
Definition: legdata.hpp:872
const string & legType() const
Definition: legdata.hpp:890
const vector< double > & notionals() const
Definition: legdata.hpp:875
string npvCurrency_
Definition: trade.hpp:201
std::vector< bool > legPayers_
Definition: trade.hpp:200
std::vector< string > legCurrencies_
Definition: trade.hpp:199
string issuer_
Definition: trade.hpp:205
std::vector< QuantLib::Leg > legs_
Definition: trade.hpp:198
QuantLib::Real notional_
Definition: trade.hpp:202
void setSensitivityTemplate(const EngineBuilder &builder)
Definition: trade.cpp:295
RequiredFixings requiredFixings_
Definition: trade.hpp:223
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
Definition: trade.hpp:197
string notionalCurrency_
Definition: trade.hpp:203
void setLegBasedAdditionalData(const Size legNo, Size resultLegId=Null< Size >()) const
Definition: trade.cpp:153
std::map< std::string, boost::any > additionalData_
Definition: trade.hpp:224
Vanilla Instrument Wrapper.
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
Ibor cap, floor or collar trade data model and serialization.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
Definition: parsers.cpp:173
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Definition: parsers.cpp:209
leg data model and serialization
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define ALOG(text)
Logging Macro (Level = Alert)
Definition: log.hpp:544
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
Schedule makeSchedule(const ScheduleDates &data)
Definition: schedule.cpp:263
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
Reference data model and serialization.
string conversion utilities