Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
bondrepo.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 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
22
24
28
29#include <ql/cashflows/cashflows.hpp>
30#include <ql/cashflows/coupon.hpp>
31#include <ql/cashflows/simplecashflow.hpp>
32
33#include <boost/make_shared.hpp>
34
35using namespace QuantLib;
36using namespace QuantExt;
37
38namespace ore {
39namespace data {
40
41void BondRepo::build(const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
42 DLOG("BondRepo::build() called for trade " << id());
43
44 // get bond repo engine builder
45
46 auto builder = QuantLib::ext::dynamic_pointer_cast<BondRepoEngineBuilderBase>(engineFactory->builder("BondRepo"));
47 QL_REQUIRE(builder, "BondRepo::build(): engine builder is null");
48
49 // build security leg (as a bond)
50
51 securityLegData_ = originalSecurityLegData_;
52 securityLegData_.populateFromBondReferenceData(engineFactory->referenceData());
53 securityLeg_ = QuantLib::ext::make_shared<ore::data::Bond>(Envelope(), securityLegData_);
54 securityLeg_->id() = id() + "_SecurityLeg";
55 securityLeg_->build(engineFactory);
56 QL_REQUIRE(!securityLeg_->legs().empty(), "BondRepo::build(): security leg has no cashflows");
57
58 // build cash leg
59
60 auto configuration = builder->configuration(MarketContext::pricing);
61 auto legBuilder = engineFactory->legBuilder(cashLegData_.legType());
62 cashLeg_ = legBuilder->buildLeg(cashLegData_, engineFactory, requiredFixings_, configuration);
63
64 // add notional payment
65
66 QL_REQUIRE(!cashLeg_.empty(), "BondRepo::build(): cash leg empty");
67 auto lastCpn = QuantLib::ext::dynamic_pointer_cast<Coupon>(cashLeg_.back());
68 QL_REQUIRE(lastCpn, "BondRepo::build(): expected coupon on cash leg");
69 cashLeg_.push_back(QuantLib::ext::make_shared<QuantLib::SimpleCashFlow>(lastCpn->nominal(), lastCpn->date()));
70
71 // add required fixings from bond
72
73 requiredFixings_.addData(securityLeg_->requiredFixings());
74
75 // set trade members
76
77 npvCurrency_ = cashLegData_.currency();
78 notionalCurrency_ = cashLegData_.currency();
79 maturity_ = CashFlows::maturityDate(cashLeg_);
80 notional_ = currentNotional(cashLeg_);
81
82 // start with the cashleg's legs
83 legs_ = {cashLeg_};
84 legCurrencies_ = {cashLegData_.currency()};
85 legPayers_ = {cashLegData_.isPayer()};
86
87 // add security legs to trade legs (should be 1 leg only, but to be safe we copy all legs in the trade)
88 legs_.insert(legs_.end(), securityLeg_->legs().begin(), securityLeg_->legs().end());
89 legCurrencies_.insert(legCurrencies_.end(), securityLeg_->legCurrencies().begin(),
90 securityLeg_->legCurrencies().end());
91 std::vector<bool> securityLegPayers(securityLeg_->legs().size(), !cashLegData_.isPayer());
92 legPayers_.insert(legPayers_.end(), securityLegPayers.begin(), securityLegPayers.end());
93
94 QL_REQUIRE(cashLegData_.currency() == securityLeg_->bondData().currency(),
95 "BondRepo: cash leg currency (" << cashLegData_.currency() << ") must match security leg currency ("
96 << securityLeg_->bondData().currency() << ")");
97
98 auto qlBondInstr = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(securityLeg_->instrument()->qlInstrument());
99 QL_REQUIRE(qlBondInstr, "BondRepo: could not cast to QuantLib::Bond instrument, this is unexpected");
100 auto qlInstr = QuantLib::ext::make_shared<QuantExt::BondRepo>(cashLeg_, cashLegData_.isPayer(), qlBondInstr,
101 std::abs(securityLeg_->instrument()->multiplier()));
102
103 qlInstr->setPricingEngine(builder->engine(securityLegData_.incomeCurveId()));
104 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(qlInstr);
105 setSensitivityTemplate(*builder);
106
107 // set additionalData
108 additionalData_["underlyingSecurityId"] = securityLegData_.securityId();
109 additionalData_["legType[1]"] = string("Cash");
110 additionalData_["currentNotional[1]"] = notional_;
111 additionalData_["originalNotional[1]"] = originalNotional(cashLeg_);
112 additionalData_["notionalCurrency[1]"] = notionalCurrency_;
113 additionalData_["legType[2]"] = string("Security");
114 additionalData_["originalNotional[2]"] = securityLegData_.bondNotional();
115 additionalData_["currentNotional[2]"] = currentNotional(qlBondInstr->cashflows()) * securityLegData_.bondNotional();
116 additionalData_["notionalCurrency[2]"] = securityLegData_.currency();
117}
118
119void BondRepo::fromXML(XMLNode* node) {
120 Trade::fromXML(node);
121
122 XMLNode* dataNode = XMLUtils::getChildNode(node, "BondRepoData");
123 QL_REQUIRE(dataNode, "BondRepoData node not found");
124 XMLNode* bondNode = XMLUtils::getChildNode(dataNode, "BondData");
125 QL_REQUIRE(bondNode, "BondData node not found");
126 originalSecurityLegData_.fromXML(bondNode);
127 securityLegData_ = originalSecurityLegData_;
128
129 XMLNode* repoNode = XMLUtils::getChildNode(dataNode, "RepoData");
130 QL_REQUIRE(repoNode, "RepoData node not found");
131
132 XMLNode* legNode = XMLUtils::getChildNode(repoNode, "LegData");
133 QL_REQUIRE(legNode, "LegData node not found");
134 cashLegData_.fromXML(legNode);
135}
136
137XMLNode* BondRepo::toXML(XMLDocument& doc) const {
138 XMLNode* node = Trade::toXML(doc);
139 XMLNode* dataNode = doc.allocNode("BondRepoData");
140 XMLUtils::appendNode(node, dataNode);
141
142 XMLUtils::appendNode(dataNode, originalSecurityLegData_.toXML(doc));
143
144 XMLNode* repoNode = doc.allocNode("RepoData");
145 XMLUtils::appendNode(dataNode, repoNode);
146 XMLUtils::appendNode(repoNode, cashLegData_.toXML(doc));
147
148 return node;
149}
150
151std::map<AssetClass, std::set<std::string>>
152BondRepo::underlyingIndices(const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager) const {
153 std::map<AssetClass, std::set<std::string>> result;
154 result[AssetClass::BOND] = {securityLegData_.securityId()};
155 return result;
156}
157
158} // namespace data
159} // namespace ore
Bond Repo trade data model and serialization.
bond utilities
builder that returns an engine to price a bond instrument
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Definition: bondrepo.cpp:41
Serializable object holding generic trade data, reporting dimensions.
Definition: envelope.hpp:51
Small XML Document wrapper class.
Definition: xmlutils.hpp:65
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Definition: xmlutils.cpp:132
Logic for calculating required fixing dates on legs.
Classes and functions for log message handling.
@ 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
Real originalNotional(const Leg &leg)
Definition: legdata.cpp:2449
Serializable Credit Default Swap.
Definition: namespaces.docs:23