29#include <ql/cashflows/cashflows.hpp>
30#include <ql/cashflows/coupon.hpp>
31#include <ql/cashflows/simplecashflow.hpp>
33#include <boost/make_shared.hpp>
41void BondRepo::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
42 DLOG(
"BondRepo::build() called for trade " <<
id());
46 auto builder = QuantLib::ext::dynamic_pointer_cast<BondRepoEngineBuilderBase>(engineFactory->builder(
"BondRepo"));
47 QL_REQUIRE(builder,
"BondRepo::build(): engine builder is null");
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");
60 auto configuration = builder->configuration(MarketContext::pricing);
61 auto legBuilder = engineFactory->legBuilder(cashLegData_.legType());
62 cashLeg_ = legBuilder->buildLeg(cashLegData_, engineFactory, requiredFixings_, configuration);
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()));
73 requiredFixings_.addData(securityLeg_->requiredFixings());
77 npvCurrency_ = cashLegData_.currency();
78 notionalCurrency_ = cashLegData_.currency();
79 maturity_ = CashFlows::maturityDate(
cashLeg_);
84 legCurrencies_ = {cashLegData_.currency()};
85 legPayers_ = {cashLegData_.isPayer()};
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());
94 QL_REQUIRE(cashLegData_.currency() == securityLeg_->bondData().currency(),
95 "BondRepo: cash leg currency (" << cashLegData_.currency() <<
") must match security leg currency ("
96 << securityLeg_->bondData().currency() <<
")");
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()));
103 qlInstr->setPricingEngine(builder->engine(securityLegData_.incomeCurveId()));
104 instrument_ = QuantLib::ext::make_shared<VanillaInstrument>(qlInstr);
105 setSensitivityTemplate(*builder);
108 additionalData_[
"underlyingSecurityId"] = securityLegData_.securityId();
109 additionalData_[
"legType[1]"] = string(
"Cash");
110 additionalData_[
"currentNotional[1]"] = notional_;
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();
120 Trade::fromXML(node);
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_;
129 XMLNode* repoNode = XMLUtils::getChildNode(dataNode,
"RepoData");
130 QL_REQUIRE(repoNode,
"RepoData node not found");
132 XMLNode* legNode = XMLUtils::getChildNode(repoNode,
"LegData");
133 QL_REQUIRE(legNode,
"LegData node not found");
134 cashLegData_.fromXML(legNode);
138 XMLNode* node = Trade::toXML(doc);
140 XMLUtils::appendNode(node, dataNode);
142 XMLUtils::appendNode(dataNode, originalSecurityLegData_.toXML(doc));
145 XMLUtils::appendNode(dataNode, repoNode);
146 XMLUtils::appendNode(repoNode, cashLegData_.toXML(doc));
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()};
Bond Repo trade data model and serialization.
builder that returns an engine to price a bond instrument
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Serializable object holding generic trade data, reporting dimensions.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Logic for calculating required fixing dates on legs.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
Real currentNotional(const Leg &leg)
Real originalNotional(const Leg &leg)
Serializable Credit Default Swap.