Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
bond.hpp
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/*! \file portfolio/builders/bond.hpp
20\brief builder that returns an engine to price a bond instrument
21\ingroup builders
22*/
23
24#pragma once
25
30
33
34#include <ql/termstructures/yield/zerospreadedtermstructure.hpp>
35
36#include <boost/make_shared.hpp>
37
38#include <regex>
39
40namespace ore {
41namespace data {
42
43//! Engine Builder base class for Bonds
44/*! Pricing engines are cached by security id
45\ingroup builders
46*/
47
48class BondEngineBuilder : public CachingPricingEngineBuilder<string, const Currency&, const string&, const bool,
49 const string&, const string&> {
50protected:
51 BondEngineBuilder(const std::string& model, const std::string& engine)
52 : CachingEngineBuilder(model, engine, {"Bond"}) {}
53
54 virtual string keyImpl(const Currency& ccy, const string& creditCurveId, const bool hasCreditRisk,
55 const string& securityId, const string& referenceCurveId) override {
56 return ccy.code() + "_" + creditCurveId + "_" + securityId + "_" + referenceCurveId;
57 }
58};
59
60//! Discounting Engine Builder class for Bonds
61/*! This class creates a DiscountingRiskyBondEngine
62\ingroup builders
63*/
64
66public:
67 BondDiscountingEngineBuilder() : BondEngineBuilder("DiscountedCashflows", "DiscountingRiskyBondEngine") {}
68
69protected:
70 virtual QuantLib::ext::shared_ptr<PricingEngine> engineImpl(const Currency& ccy, const string& creditCurveId,
71 const bool hasCreditRisk, const string& securityId,
72 const string& referenceCurveId) override {
73
74 string tsperiodStr = engineParameter("TimestepPeriod");
75 Period tsperiod = parsePeriod(tsperiodStr);
76 Handle<YieldTermStructure> yts = market_->yieldCurve(referenceCurveId, configuration(MarketContext::pricing));
77 Handle<DefaultProbabilityTermStructure> dpts;
78 // credit curve may not always be used. If credit curve ID is empty proceed without it
79 if (!creditCurveId.empty())
80 dpts =
82 ->curve();
83 Handle<Quote> recovery;
84 try {
85 // try security recovery first
86 recovery = market_->recoveryRate(securityId, configuration(MarketContext::pricing));
87 } catch (...) {
88 // otherwise fall back on curve recovery
89 WLOG("security specific recovery rate not found for security ID "
90 << securityId << ", falling back on the recovery rate for credit curve Id " << creditCurveId);
91 if (!creditCurveId.empty())
92 recovery = market_->recoveryRate(creditCurveId, configuration(MarketContext::pricing));
93 }
94 Handle<Quote> spread;
95 try {
96 // spread is optional, pass empty handle to engine if not given (will be treated as 0 spread there)
97 spread = market_->securitySpread(securityId, configuration(MarketContext::pricing));
98 } catch (...) {
99 }
100
101 if (!hasCreditRisk) {
102 dpts = Handle<DefaultProbabilityTermStructure>();
103 }
104
105 return QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngine>(yts, dpts, recovery, spread, tsperiod);
106 }
107};
108
109//! Multi State Engine Builder class for Bonds
110/*! This creates a DiscountingRiskyBondEngineMultiState
111 \ingroup portfolio
112*/
113
115public:
117 : BondEngineBuilder("DiscountedCashflows", "DiscountingRiskyBondEngineMultiState") {}
118
119protected:
120 virtual QuantLib::ext::shared_ptr<PricingEngine> engineImpl(const Currency& ccy, const string& creditCurveId,
121 const bool hasCreditRisk, const string& securityId,
122 const string& referenceCurveId) override {
123 string tsperiodStr = engineParameter("TimestepPeriod");
124 Period tsperiod = parsePeriod(tsperiodStr);
125 Handle<YieldTermStructure> yts = market_->yieldCurve(referenceCurveId, configuration(MarketContext::pricing));
126 Handle<Quote> spread;
127 try {
128 spread = market_->securitySpread(securityId, configuration(MarketContext::pricing));
129 } catch (...) {
130 }
131 // build state curves and recovery rates
132 std::vector<Handle<DefaultProbabilityTermStructure>> dpts;
133 std::vector<Handle<Quote>> recovery;
134 Size mainResultState = Null<Size>();
135 Size i = 0;
136 for (; true; ++i) {
137 std::ostringstream rule_s;
138 rule_s << "Rule_" << i;
139 if (engineParameters_.count(rule_s.str()) == 0)
140 break;
141 std::vector<std::string> tokens;
142 std::string rule = engineParameters_[rule_s.str()];
143 std::string stateCreditCurveId;
144 // if rule is empty, we use the initial curve for this state
145 // TODO computation should be optimised in this case, so that only different
146 // curves are recomputed in the engine
147 if (rule.empty()) {
148 stateCreditCurveId = creditCurveId;
149 DLOG("Rule " << rule_s.str() << " is empty, use initial curve " << stateCreditCurveId
150 << " for this state.");
151 } else {
152 boost::split(tokens, rule, boost::is_any_of(","));
153 QL_REQUIRE(tokens.size() == 2, "invalid rule: " << rule);
154 stateCreditCurveId = regex_replace(creditCurveId, std::regex(tokens[0]), tokens[1]);
155 DLOG("Apply " << rule_s.str() << " => " << tokens[0] << " in " << creditCurveId << " yields state #"
156 << i << " creditCurve id " << stateCreditCurveId);
157 }
158 if (stateCreditCurveId == creditCurveId) {
159 mainResultState = i;
160 DLOG("State #" << i << " is the main result state (overwriting previous choice)");
161 }
162 Handle<DefaultProbabilityTermStructure> this_dpts;
163 Handle<Quote> this_recovery;
164 if (!stateCreditCurveId.empty() && hasCreditRisk) {
165 this_dpts = market_->defaultCurve(stateCreditCurveId, configuration(MarketContext::pricing))->curve();
166 this_recovery = market_->recoveryRate(stateCreditCurveId, configuration(MarketContext::pricing));
167 }
168 dpts.push_back(this_dpts);
169 recovery.push_back(this_recovery);
170 }
171 // If there were no rules at all we take the original creditCurveId as the only state
172 if (i == 0) {
173 Handle<DefaultProbabilityTermStructure> this_dpts;
174 Handle<Quote> this_recovery;
175 if (!creditCurveId.empty() && hasCreditRisk) {
176 this_dpts = market_->defaultCurve(creditCurveId, configuration(MarketContext::pricing))->curve();
177 this_recovery = market_->recoveryRate(creditCurveId, configuration(MarketContext::pricing));
178 }
179 dpts.push_back(this_dpts);
180 recovery.push_back(this_recovery);
181 mainResultState = 0;
182 DLOG("No rules given, only states are " << creditCurveId << " and default");
183 }
184 // check we have a main result state
185 QL_REQUIRE(mainResultState != Null<Size>(),
186 "BondMultiStateEngineBuilder: No main state found for " << securityId << " / " << creditCurveId);
187 // return engine
188 return QuantLib::ext::make_shared<QuantExt::DiscountingRiskyBondEngineMultiState>(yts, dpts, recovery, mainResultState,
189 spread, tsperiod);
190 }
191};
192
193} // namespace data
194} // namespace ore
Abstract template engine builder class.
Discounting Engine Builder class for Bonds.
Definition: bond.hpp:65
virtual QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const Currency &ccy, const string &creditCurveId, const bool hasCreditRisk, const string &securityId, const string &referenceCurveId) override
Definition: bond.hpp:70
Engine Builder base class for Bonds.
Definition: bond.hpp:49
BondEngineBuilder(const std::string &model, const std::string &engine)
Definition: bond.hpp:51
virtual string keyImpl(const Currency &ccy, const string &creditCurveId, const bool hasCreditRisk, const string &securityId, const string &referenceCurveId) override
Definition: bond.hpp:54
Multi State Engine Builder class for Bonds.
Definition: bond.hpp:114
virtual QuantLib::ext::shared_ptr< PricingEngine > engineImpl(const Currency &ccy, const string &creditCurveId, const bool hasCreditRisk, const string &securityId, const string &referenceCurveId) override
Definition: bond.hpp:120
Abstract template EngineBuilder class that can cache engines and coupon pricers.
QuantLib::ext::shared_ptr< Market > market_
const string & engine() const
Return the engine name.
map< string, string > engineParameters_
const string & model() const
Return the model name.
std::string engineParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
const string & configuration(const MarketContext &key)
Return a configuration (or the default one if key not found)
Pricing Engine Factory.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
market data related utilties
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