Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
bondindexbuilder.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2023 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
21
22namespace ore {
23namespace data {
24
25BondIndexBuilder::BondIndexBuilder(BondData securityData, const bool dirty, const bool relative,
26 const Calendar& fixingCalendar, const bool conditionalOnSurvival,
27 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, Real bidAskAdjustment,
28 const bool bondIssueDateFallback)
29 : dirty_(dirty) {
30
31 securityData.populateFromBondReferenceData(engineFactory->referenceData());
32 bond_ = Bond(Envelope(), securityData);
33 bond_.build(engineFactory);
34 buildIndex(relative, fixingCalendar, conditionalOnSurvival, engineFactory, bidAskAdjustment, bondIssueDateFallback);
35}
36
37BondIndexBuilder::BondIndexBuilder(const Bond& bond, const bool dirty, const bool relative,
38 const Calendar& fixingCalendar, const bool conditionalOnSurvival,
39 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, Real bidAskAdjustment,
40 const bool bondIssueDateFallback)
41 : bond_(bond), dirty_(dirty) {
42 buildIndex(relative, fixingCalendar, conditionalOnSurvival, engineFactory, bidAskAdjustment, bondIssueDateFallback);
43}
44
45BondIndexBuilder::BondIndexBuilder(const std::string& securityId, const bool dirty, const bool relative,
46 const Calendar& fixingCalendar, const bool conditionalOnSurvival,
47 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, Real bidAskAdjustment,
48 const bool bondIssueDateFallback)
49 : dirty_(dirty) {
50 BondData bondData(securityId, 100.0);
51 bondData.populateFromBondReferenceData(engineFactory->referenceData());
52 bond_ = Bond(Envelope(), bondData);
53 bond_.build(engineFactory);
54 buildIndex(relative, fixingCalendar, conditionalOnSurvival, engineFactory, bidAskAdjustment, bondIssueDateFallback);
55}
56
57void BondIndexBuilder::buildIndex(const bool relative, const Calendar& fixingCalendar, const bool conditionalOnSurvival,
58 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, Real bidAskAdjustment,
59 const bool bondIssueDateFallback) {
60
61 fixings_ = bond_.requiredFixings();
62
63 auto qlBond = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(bond_.instrument()->qlInstrument());
64 QL_REQUIRE(qlBond, "buildBondIndex(): could not cast to QuantLib::Bond, this is unexpected");
65
66 // get the curves
67 auto bondData = bond_.bondData();
68 string securityId = bondData.securityId();
69
70 Handle<YieldTermStructure> discountCurve = engineFactory->market()->yieldCurve(
71 bondData.referenceCurveId(), engineFactory->configuration(MarketContext::pricing));
72
73 Handle<DefaultProbabilityTermStructure> defaultCurve;
74 if (!bondData.creditCurveId().empty())
75 defaultCurve = securitySpecificCreditCurve(engineFactory->market(), securityId, bondData.creditCurveId(),
76 engineFactory->configuration(MarketContext::pricing))
77 ->curve();
78
79 Handle<YieldTermStructure> incomeCurve;
80 if (!bondData.incomeCurveId().empty())
81 incomeCurve = engineFactory->market()->yieldCurve(bondData.incomeCurveId(),
82 engineFactory->configuration(MarketContext::pricing));
83
84 Handle<Quote> recovery;
85 try {
86 recovery =
87 engineFactory->market()->recoveryRate(securityId, engineFactory->configuration(MarketContext::pricing));
88 } catch (...) {
89 WLOG("security specific recovery rate not found for security ID "
90 << securityId << ", falling back on the recovery rate for credit curve Id " << bondData.creditCurveId());
91 if (!bondData.creditCurveId().empty())
92 recovery = engineFactory->market()->recoveryRate(bondData.creditCurveId(),
93 engineFactory->configuration(MarketContext::pricing));
94 }
95
96 Handle<Quote> spread(QuantLib::ext::make_shared<SimpleQuote>(0.0));
97 try {
98 spread =
99 engineFactory->market()->securitySpread(securityId, engineFactory->configuration(MarketContext::pricing));
100 } catch (...) {
101 }
102
103 if (!bondData.hasCreditRisk())
104 defaultCurve = Handle<DefaultProbabilityTermStructure>();
105
106 // build and return the index
107 bondIndex_ = QuantLib::ext::make_shared<QuantExt::BondIndex>(securityId, dirty_, relative, fixingCalendar, qlBond,
108 discountCurve, defaultCurve, recovery, spread, incomeCurve, conditionalOnSurvival, parseDate(bondData.issueDate()), bondData.priceQuoteMethod(),
109 bondData.priceQuoteBaseValue(), bondData.isInflationLinked(), bidAskAdjustment, bondIssueDateFallback);
110}
111
112QuantLib::ext::shared_ptr<QuantExt::BondIndex> BondIndexBuilder::bondIndex() const { return bondIndex_; }
113
114void BondIndexBuilder::addRequiredFixings(RequiredFixings& requiredFixings, Leg leg) {
115 requiredFixings.addData(fixings_.filteredFixingDates());
116 if (dirty_) {
117 QL_REQUIRE(leg.size() > 0, "BondIndexBuild: Leg is required if dirty flag set to true");
118 RequiredFixings legFixings;
119 auto fixingGetter = QuantLib::ext::make_shared<FixingDateGetter>(legFixings);
120 fixingGetter->setRequireFixingStartDates(true);
121 addToRequiredFixings(leg, fixingGetter);
122
123 set<Date> fixingDates;
124
125 auto fixingMap = legFixings.fixingDatesIndices();
126 if (fixingMap.size() > 0) {
127 std::map<std::string, std::set<Date>> indexFixings;
128 for (const auto& [_, dates] : fixingMap) {
129 for (const auto& [d, mandatory] : dates) {
130 auto tmp = fixings_.filteredFixingDates(d);
131 requiredFixings.addData(tmp);
132 }
133 }
134 }
135 }
136}
137
138Real BondIndexBuilder::priceAdjustment(Real price) {
139 if (price == Null<Real>())
140 return price;
141
142 Real adj = bond_.bondData().priceQuoteMethod() == QuantExt::BondIndex::PriceQuoteMethod::CurrencyPerUnit
143 ? 1.0 / bond_.bondData().priceQuoteBaseValue()
144 : 1.0;
145 return price * adj;
146}
147
148} // namespace data
149} // namespace ore
Interface for building a bond index.
BondIndexBuilder(BondData bondData, const bool dirty, const bool relative, const Calendar &fixingCalendar, const bool conditionalOnSurvival, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, QuantLib::Real bidAskAdjustment=0.0, const bool bondIssueDateFallback=false)
void addData(const RequiredFixings &requiredFixings)
std::map< std::string, FixingDates > fixingDatesIndices(const QuantLib::Date &settlementDate=QuantLib::Date()) const
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Definition: parsers.cpp:51
const Bond & bond_
@ data
Definition: log.hpp:77
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
market data related utilties
void addToRequiredFixings(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< FixingDateGetter > &fixingDateGetter)
QuantLib::Handle< QuantExt::CreditCurve > securitySpecificCreditCurve(const QuantLib::ext::shared_ptr< Market > &market, const std::string &securityId, const std::string &creditCurveId, const std::string &configuration)
Definition: marketdata.cpp:98
Serializable Credit Default Swap.
Definition: namespaces.docs:23