Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
creditdefaultswapdata.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
19#include <boost/lexical_cast.hpp>
25
26using namespace QuantLib;
27using namespace QuantExt;
28using std::ostream;
29
30namespace ore {
31namespace data {
32
33CdsTier parseCdsTier(const string& s) {
34 if (s == "SNRFOR") {
35 return CdsTier::SNRFOR;
36 } else if (s == "SUBLT2") {
37 return CdsTier::SUBLT2;
38 } else if (s == "SNRLAC") {
39 return CdsTier::SNRLAC;
40 } else if (s == "SECDOM") {
41 return CdsTier::SECDOM;
42 } else if (s == "JRSUBUT2") {
43 return CdsTier::JRSUBUT2;
44 } else if (s == "PREFT1") {
45 return CdsTier::PREFT1;
46 } else if (s == "LIEN1") {
47 return CdsTier::LIEN1;
48 } else if (s == "LIEN2") {
49 return CdsTier::LIEN2;
50 } else if (s == "LIEN3") {
51 return CdsTier::LIEN3;
52 }
53 QL_FAIL("Could not parse \"" << s << "\" to CdsTier");
54}
55
56ostream& operator<<(ostream& out, const CdsTier& cdsTier) {
57 switch (cdsTier) {
58 case CdsTier::SNRFOR:
59 return out << "SNRFOR";
60 case CdsTier::SUBLT2:
61 return out << "SUBLT2";
62 case CdsTier::SNRLAC:
63 return out << "SNRLAC";
64 case CdsTier::SECDOM:
65 return out << "SECDOM";
67 return out << "JRSUBUT2";
68 case CdsTier::PREFT1:
69 return out << "PREFT1";
70 case CdsTier::LIEN1:
71 return out << "LIEN1";
72 case CdsTier::LIEN2:
73 return out << "LIEN2";
74 case CdsTier::LIEN3:
75 return out << "LIEN3";
76 default:
77 QL_FAIL("Do not recognise CdsTier " << static_cast<int>(cdsTier));
78 }
79}
80
82 if (s == "CR") {
83 return CdsDocClause::CR;
84 } else if (s == "MM") {
85 return CdsDocClause::MM;
86 } else if (s == "MR") {
87 return CdsDocClause::MR;
88 } else if (s == "XR") {
89 return CdsDocClause::XR;
90 } else if (s == "CR14") {
91 return CdsDocClause::CR14;
92 } else if (s == "MM14") {
93 return CdsDocClause::MM14;
94 } else if (s == "MR14") {
95 return CdsDocClause::MR14;
96 } else if (s == "XR14") {
97 return CdsDocClause::XR14;
98 } else {
99 QL_FAIL("Could not parse \"" << s << "\" to CdsDocClause");
100 }
101}
102
103ostream& operator<<(ostream& out, const CdsDocClause& cdsDocClause) {
104 switch (cdsDocClause) {
105 case CdsDocClause::CR:
106 return out << "CR";
107 case CdsDocClause::MM:
108 return out << "MM";
109 case CdsDocClause::MR:
110 return out << "MR";
111 case CdsDocClause::XR:
112 return out << "XR";
114 return out << "CR14";
116 return out << "MM14";
118 return out << "MR14";
120 return out << "XR14";
121 default:
122 QL_FAIL("Do not recognise CdsDocClause " << static_cast<int>(cdsDocClause));
123 }
124}
125
126// TODO refactor to creditevents.cpp
128 if (s == "2003") {
130 } else if (s == "2014") {
132 } else {
133 QL_FAIL("Could not parse \"" << s << "\" to isdaRulesDefinitions");
134 }
135}
136
137ostream& operator<<(ostream& out, const IsdaRulesDefinitions& isdaRulesDefinitions) {
138 switch (isdaRulesDefinitions) {
140 return out << "2003";
142 return out << "2014";
143 default:
144 QL_FAIL("Do not recognise IsdaRulesDefinitions " << static_cast<int>(isdaRulesDefinitions));
145 }
146}
147
149 switch (cdsDocClause) {
150 case CdsDocClause::CR:
151 case CdsDocClause::MR:
152 case CdsDocClause::XR:
153 case CdsDocClause::MM:
159 default:
161 }
162}
163
165 if (s == "BANKRUPTCY") {
167 } else if (s == "FAILURE TO PAY") {
169 } else if (s == "RESTRUCTURING") {
171 } else if (s == "OBLIGATION ACCELERATION") {
173 } else if (s == "OBLIGATION DEFAULT") {
175 } else if (s == "REPUDIATION/MORATORIUM") {
177 } else if (s == "GOVERNMENTAL INTERVENTION") {
179 } else {
180 QL_FAIL("Could not parse \"" << s << "\" to a credit event.");
181 }
182}
183
184ostream& operator<<(ostream& out, const CreditEventType& creditEventType) {
185 switch (creditEventType) {
187 return out << "BANKRUPTCY";
189 return out << "FAILURE TO PAY";
191 return out << "RESTRUCTURING";
193 return out << "OBLIGATION ACCELERATION";
195 return out << "OBLIGATION DEFAULT";
197 return out << "REPUDIATION/MORATORIUM";
199 return out << "GOVERNMENTAL INTERVENTION";
200 default:
201 QL_FAIL("Do not recognise CreditEventType " << static_cast<int>(creditEventType));
202 }
203}
204
205bool isTriggeredDocClause(CdsDocClause contractDocClause, CreditEventType creditEventType) {
206 switch (creditEventType) {
210 // all of the above include a failure to pay
211 switch (contractDocClause) {
220 return true;
221 default:
222 break;
223 }
224 break;
226 // typically includes a conversion to shares with a write down
228 // it depends on the type of restructure!
229 switch (contractDocClause) {
236 return true;
239 return false;
240 default:
241 break;
242 }
245 // not necessarily a default itself, no examples in record.
246 return false;
247 break;
248 default:
249 break;
250 }
251 QL_FAIL("Could not recognize CreditEventType "
252 << static_cast<int>(creditEventType) << " or CdsDocClause " << static_cast<int>(contractDocClause)
253 << " when identifying whether a doc clause is triggrered for a given credit event type.");
254 return false;
255}
256
258 if (s == "SNR") {
260 } else if (s == "SUB") {
262 } else if (s == "SNRLAC") {
264 } else if (s == "SNR/SUB") {
266 } else if (s == "SNR/SNRLAC") {
268 } else if (s == "SUB/SNRLAC") {
270 } else if (s == "SNR/SUB/SNRLAC") {
272 } else {
273 QL_FAIL("Could not parse \"" << s << "\" to a credit event tiers set.");
274 }
275}
276
277ostream& operator<<(ostream& out, const CreditEventTiers& creditEventTiers) {
278 switch (creditEventTiers) {
280 return out << "SNR";
282 return out << "SUB";
284 return out << "SNRLAC";
286 return out << "SNR/SUB";
288 return out << "SNR/SNRLAC";
290 return out << "SUB/SNRLAC";
292 return out << "SNR/SUB/SNRLAC";
293 default:
294 QL_FAIL("Do not recognise CreditEventTiers " << static_cast<int>(creditEventTiers));
295 }
296}
297
298bool isAuctionedSeniority(CdsTier contractTier, CreditEventTiers creditEventTiers) {
299 switch (creditEventTiers) {
301 switch (contractTier) {
305 return true;
309 return false;
310 default:
311 break;
312 }
313 break;
315 switch (contractTier) {
318 return true;
323 return false;
324 default:
325 break;
326 }
327 break;
329 switch (contractTier) {
331 return true;
337 return false;
338 default:
339 break;
340 }
341 break;
343 switch (contractTier) {
349 return true;
351 return false;
352 default:
353 break;
354 }
355 break;
357 switch (contractTier) {
362 return true;
365 return false;
366 default:
367 break;
368 }
369 break;
371 switch (contractTier) {
375 return true;
379 return false;
380 default:
381 break;
382 }
383 break;
385 switch (contractTier) {
392 return true;
393 default:
394 break;
395 }
396 break;
397 default:
398 break;
399 }
400 QL_FAIL("Could not recognize CreditEventTiers "
401 << static_cast<int>(creditEventTiers) << " or CdsTier " << static_cast<int>(contractTier)
402 << " when identifying the applicability if an event for a given contract tier.");
403 return false;
404}
405// end TODO refactor to creditevents.cpp
406
408
409CdsReferenceInformation::CdsReferenceInformation(const string& referenceEntityId, CdsTier tier,
410 const Currency& currency, boost::optional<CdsDocClause> docClause)
411 : referenceEntityId_(referenceEntityId), tier_(tier), currency_(currency), docClause_(docClause) {
412 populateId();
413}
414
416 XMLUtils::checkNode(node, "ReferenceInformation");
417 referenceEntityId_ = XMLUtils::getChildValue(node, "ReferenceEntityId", true);
418 tier_ = parseCdsTier(XMLUtils::getChildValue(node, "Tier", true));
419 currency_ = parseCurrency(XMLUtils::getChildValue(node, "Currency", true));
420 if (auto s = XMLUtils::getChildValue(node, "DocClause", false); !s.empty()) {
422 }
423 populateId();
424}
425
427 XMLNode* node = doc.allocNode("ReferenceInformation");
428 XMLUtils::addChild(doc, node, "ReferenceEntityId", referenceEntityId_);
429 XMLUtils::addChild(doc, node, "Tier", to_string(tier_));
430 XMLUtils::addChild(doc, node, "Currency", currency_.code());
431 if(docClause_)
432 XMLUtils::addChild(doc, node, "DocClause", to_string(*docClause_));
433 return node;
434}
435
437 id_ = referenceEntityId_ + "|" + to_string(tier_) + "|" + currency_.code();
438 if (docClause_)
439 id_ += "|" + to_string(*docClause_);
440}
441
443 QL_REQUIRE(docClause_, "CdsReferenceInforamtion::docClause(): docClause not set.");
444 return *docClause_;
445}
446
447bool CdsReferenceInformation::hasDocClause() const { return docClause_ != boost::none; }
448
449bool tryParseCdsInformation(string strInfo, CdsReferenceInformation& cdsInfo) {
450
451 DLOG("tryParseCdsInformation: attempting to parse " << strInfo);
452
453 // As in documentation comment, expect strInfo of form ID|TIER|CCY(|DOCCLAUSE)
454 vector<string> tokens;
455 boost::split(tokens, strInfo, boost::is_any_of("|"));
456
457 if (tokens.size() != 4 && tokens.size() != 3) {
458 TLOG("String " << strInfo << " not of form ID|TIER|CCY(|DOCCLAUSE) so parsing failed");
459 return false;
460 }
461
462 CdsTier cdsTier;
463 if (!tryParse<CdsTier>(tokens[1], cdsTier, &parseCdsTier)) {
464 return false;
465 }
466
467 Currency ccy;
468 if (!tryParseCurrency(tokens[2], ccy)) {
469 return false;
470 }
471
472 boost::optional<CdsDocClause> cdsDocClause;
473 if (tokens.size() == 4) {
474 CdsDocClause tmp;
475 if (!tryParse<CdsDocClause>(tokens[3], tmp, &parseCdsDocClause)) {
476 return false;
477 }
478 cdsDocClause = tmp;
479 }
480
481 cdsInfo = CdsReferenceInformation(tokens[0], cdsTier, ccy, cdsDocClause);
482
483 return true;
484}
485
487 : settlesAccrual_(true), protectionPaymentTime_(QuantExt::CreditDefaultSwap::ProtectionPaymentTime::atDefault),
488 upfrontFee_(Null<Real>()), rebatesAccrual_(true), recoveryRate_(Null<Real>()), cashSettlementDays_(3) {}
489
490CreditDefaultSwapData::CreditDefaultSwapData(const string& issuerId, const string& creditCurveId, const LegData& leg,
491 const bool settlesAccrual, const PPT protectionPaymentTime,
492 const Date& protectionStart, const Date& upfrontDate, const Real upfrontFee, Real recoveryRate,
493 const string& referenceObligation, const Date& tradeDate, const string& cashSettlementDays,
494 const bool rebatesAccrual)
495 : issuerId_(issuerId), creditCurveId_(creditCurveId), leg_(leg), settlesAccrual_(settlesAccrual),
496 protectionPaymentTime_(protectionPaymentTime), protectionStart_(protectionStart), upfrontDate_(upfrontDate),
497 upfrontFee_(upfrontFee), rebatesAccrual_(rebatesAccrual), recoveryRate_(recoveryRate),
498 referenceObligation_(referenceObligation),
499 tradeDate_(tradeDate), strCashSettlementDays_(cashSettlementDays),
500 cashSettlementDays_(strCashSettlementDays_.empty() ? 3 : parseInteger(strCashSettlementDays_)) {}
501
503 const string& issuerId, const CdsReferenceInformation& referenceInformation, const LegData& leg,
504 bool settlesAccrual, const PPT protectionPaymentTime,
505 const Date& protectionStart, const Date& upfrontDate, Real upfrontFee, Real recoveryRate,
506 const std::string& referenceObligation, const Date& tradeDate, const string& cashSettlementDays,
507 const bool rebatesAccrual)
508 : issuerId_(issuerId), leg_(leg), settlesAccrual_(settlesAccrual), protectionPaymentTime_(protectionPaymentTime),
509 protectionStart_(protectionStart), upfrontDate_(upfrontDate), upfrontFee_(upfrontFee), rebatesAccrual_(rebatesAccrual),
510 recoveryRate_(recoveryRate), referenceObligation_(referenceObligation),
511 tradeDate_(tradeDate), strCashSettlementDays_(cashSettlementDays),
512 cashSettlementDays_(strCashSettlementDays_.empty() ? 3 : parseInteger(strCashSettlementDays_)),
513 referenceInformation_(referenceInformation) {}
514
516
517 check(node);
518
519 issuerId_ = XMLUtils::getChildValue(node, "IssuerId", false);
520
521 // May get an explicit CreditCurveId node. If so, we use it. Otherwise, we must have ReferenceInformation node.
522 // XMLNode* tmp = XMLUtils::getChildNode(node, "CreditCurveId");
523 if (auto tmp = XMLUtils::getChildNode(node, "CreditCurveId")) {
528 } else {
529 tmp = XMLUtils::getChildNode(node, "ReferenceInformation");
530 QL_REQUIRE(tmp, "Need either a CreditCurveId or ReferenceInformation node in CreditDefaultSwapData");
532 ref.fromXML(tmp);
534 creditCurveId_ = ref.id();
535 }
536
537 settlesAccrual_ = XMLUtils::getChildValueAsBool(node, "SettlesAccrual", false);
538 rebatesAccrual_ = XMLUtils::getChildValueAsBool(node, "RebatesAccrual", false);
539
540 protectionPaymentTime_ = PPT::atDefault;
541
542 // for backwards compatibility only
543 if (auto c = XMLUtils::getChildNode(node, "PaysAtDefaultTime"))
545 protectionPaymentTime_ = PPT::atPeriodEnd;
546
547 // new node overrides deprecated one, if both should be given
548 if (auto c = XMLUtils::getChildNode(node, "ProtectionPaymentTime")) {
549 if (XMLUtils::getNodeValue(c) == "atDefault")
550 protectionPaymentTime_ = PPT::atDefault;
551 else if (XMLUtils::getNodeValue(c) == "atPeriodEnd")
552 protectionPaymentTime_ = PPT::atPeriodEnd;
553 else if (XMLUtils::getNodeValue(c) == "atMaturity")
554 protectionPaymentTime_ = PPT::atMaturity;
555 else {
556 QL_FAIL("protection payment time '" << XMLUtils::getNodeValue(c) <<
557 "' not known, expected atDefault, atPeriodEnd, atMaturity");
558 }
559 }
560
561 protectionStart_ = Date();
562 if (auto tmp = XMLUtils::getChildNode(node, "ProtectionStart"))
564
565 upfrontDate_ = Date();
566 if (auto tmp = XMLUtils::getChildNode(node, "UpfrontDate"))
568
569 // zero if empty or missing
570 upfrontFee_ = Null<Real>();
571 string strUpfrontFee = XMLUtils::getChildValue(node, "UpfrontFee", false);
572 if (!strUpfrontFee.empty()) {
573 upfrontFee_ = parseReal(strUpfrontFee);
574 }
575
576 if (upfrontDate_ == Date()) {
577 QL_REQUIRE(close_enough(upfrontFee_, 0.0) || upfrontFee_ == Null<Real>(),
578 "fromXML(): UpfronFee (" << upfrontFee_ << ") must be empty or zero if no upfront date is given");
579 upfrontFee_ = Null<Real>();
580 }
581
582 // Recovery rate is Null<Real>() on a standard CDS i.e. if "FixedRecoveryRate" field is not populated.
583 recoveryRate_ = Null<Real>();
584 string strRecoveryRate = XMLUtils::getChildValue(node, "FixedRecoveryRate", false);
585 if (!strRecoveryRate.empty()) {
586 recoveryRate_ = parseReal(strRecoveryRate);
587 }
588
589 tradeDate_ = Date();
590 if (auto n = XMLUtils::getChildNode(node, "TradeDate"))
592
593 strCashSettlementDays_ = XMLUtils::getChildValue(node, "CashSettlementDays", false);
595
596 leg_.fromXML(XMLUtils::getChildNode(node, "LegData"));
597}
598
600
601 XMLNode* node = alloc(doc);
602
603 XMLUtils::addChild(doc, node, "IssuerId", issuerId_);
604
605 // We either have reference information or an explicit credit curve ID
608 } else {
609 XMLUtils::addChild(doc, node, "CreditCurveId", creditCurveId_);
610 }
611
612 XMLUtils::addChild(doc, node, "SettlesAccrual", settlesAccrual_);
613 if (!rebatesAccrual_)
614 XMLUtils::addChild(doc, node, "RebatesAccrual", rebatesAccrual_);
615 if (protectionPaymentTime_ == PPT::atDefault) {
616 XMLUtils::addChild(doc, node, "ProtectionPaymentTime", "atDefault");
617 } else if (protectionPaymentTime_ == PPT::atPeriodEnd) {
618 XMLUtils::addChild(doc, node, "ProtectionPaymentTime", "atPeriodEnd");
619 } else if (protectionPaymentTime_ == PPT::atMaturity) {
620 XMLUtils::addChild(doc, node, "ProtectionPaymentTime", "atMaturity");
621 } else {
622 QL_FAIL("toXML(): unexpected ProtectionPaymentTime");
623 }
624
625 if (protectionStart_ != Date()) {
626 XMLUtils::addChild(doc, node, "ProtectionStart", to_string(protectionStart_));
627 }
628
629 if (upfrontDate_ != Date()) {
630 XMLUtils::addChild(doc, node, "UpfrontDate", to_string(upfrontDate_));
631 }
632
633 if (upfrontFee_ != Null<Real>())
634 XMLUtils::addChild(doc, node, "UpfrontFee", upfrontFee_);
635
636 if (recoveryRate_ != Null<Real>())
637 XMLUtils::addChild(doc, node, "FixedRecoveryRate", recoveryRate_);
638
639 if (tradeDate_ != Date()) {
640 XMLUtils::addChild(doc, node, "TradeDate", to_string(tradeDate_));
641 }
642
643 if (!strCashSettlementDays_.empty()) {
644 XMLUtils::addChild(doc, node, "CashSettlementDays", strCashSettlementDays_);
645 }
646
647 XMLUtils::appendNode(node, leg_.toXML(doc));
648
649 return node;
650}
651
654 return referenceInformation_->id();
655 } else {
656 return creditCurveId_;
657 }
658}
659
661 XMLUtils::checkNode(node, "CreditDefaultSwapData");
662}
663
665 return doc.allocNode("CreditDefaultSwapData");
666}
667
668} // namespace data
669} // namespace ore
boost::optional< CdsDocClause > docClause_
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
void populateId()
Populate the id_ member.
virtual XMLNode * alloc(XMLDocument &doc) const
boost::optional< CdsReferenceInformation > referenceInformation_
QuantLib::Real recoveryRate_
Populated if the CDS is a fixed recovery rate CDS, otherwise Null<Real>()
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
virtual void check(XMLNode *node) const
Serializable object holding leg data.
Definition: legdata.hpp:844
virtual void fromXML(XMLNode *node) override
Definition: legdata.cpp:759
virtual XMLNode * toXML(XMLDocument &doc) const override
Definition: legdata.cpp:856
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 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 string getNodeValue(XMLNode *node)
Get a node's value.
Definition: xmlutils.cpp:489
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
A class to hold credit default swap data.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
bool tryParseCdsInformation(string strInfo, CdsReferenceInformation &cdsInfo)
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
Definition: parsers.cpp:136
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 TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
CreditEventTiers parseCreditEventTiers(const string &s)
CdsDocClause
CDS documentation clause enumeration.
CreditEventType parseCreditEventType(const string &s)
bool isTriggeredDocClause(CdsDocClause contractDocClause, CreditEventType creditEventType)
CreditEventTiers
ISDA credit event seniority sets enumeration.
IsdaRulesDefinitions isdaRulesDefinitionsFromDocClause(const CdsDocClause &cdsDocClause)
CdsTier
CDS debt tier enumeration.
CdsDocClause parseCdsDocClause(const string &s)
bool tryParseCurrency(const std::string &str, Currency &obj)
Definition: parsers.hpp:438
CdsTier parseCdsTier(const string &s)
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
CreditEventType
ISDA credit event types enumeration.
IsdaRulesDefinitions
ISDA CDS documentation rules set enumeration.
IsdaRulesDefinitions parseIsdaRulesDefinitions(const string &s)
bool isAuctionedSeniority(CdsTier contractTier, CreditEventTiers creditEventTiers)
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
string conversion utilities