Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Static Public Member Functions | Static Private Member Functions | List of all members
BondSpreadImply Class Reference

#include <ored/marketdata/bondspreadimply.hpp>

+ Collaboration diagram for BondSpreadImply:

Static Public Member Functions

static std::map< std::string, QuantLib::ext::shared_ptr< Security > > requiredSecurities (const Date &asof, const QuantLib::ext::shared_ptr< TodaysMarketParameters > &params, const QuantLib::ext::shared_ptr< CurveConfigurations > &curveConfigs, const Loader &loader, const bool continueOnError=false, const std::string &excludeRegex=std::string())
 
static QuantLib::ext::shared_ptr< LoaderimplyBondSpreads (const std::map< std::string, QuantLib::ext::shared_ptr< Security > > &securities, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager, const QuantLib::ext::shared_ptr< Market > &market, const QuantLib::ext::shared_ptr< EngineData > &engineData, const std::string &configuration, const IborFallbackConfig &iborFallbackConfig)
 

Static Private Member Functions

static Real implySpread (const std::string &securityId, const Real cleanPrice, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::ext::shared_ptr< SimpleQuote > &spreadQuote, const std::string &configuration)
 helper function that computes a single implied spread for a bond More...
 

Detailed Description

Definition at line 35 of file bondspreadimply.hpp.

Member Function Documentation

◆ requiredSecurities()

std::map< std::string, QuantLib::ext::shared_ptr< Security > > requiredSecurities ( const Date &  asof,
const QuantLib::ext::shared_ptr< TodaysMarketParameters > &  params,
const QuantLib::ext::shared_ptr< CurveConfigurations > &  curveConfigs,
const Loader loader,
const bool  continueOnError = false,
const std::string &  excludeRegex = std::string() 
)
static

Determine the securities that require a spread imply and return a map securityID => security containing them. If excludeRegex is non-empty security ids that match excludeRegex are excluded from the returned list.

Definition at line 39 of file bondspreadimply.cpp.

41 {
42 std::regex excludePattern;
43 if (!excludeRegex.empty())
44 excludePattern = std::regex(excludeRegex);
45
46 std::map<std::string, QuantLib::ext::shared_ptr<Security>> securities;
47 for (const auto& configuration : params->configurations()) {
48 LOG("identify securities that require a spread imply for configuration " << configuration.first);
49
50 /* Loop over the security curve specs, do the spread imply where we have a price, but no spread
51 and and store the calculated spread in the MarketImpl container */
52 for (const auto& it : params->curveSpecs(configuration.first)) {
53 auto securityspec = QuantLib::ext::dynamic_pointer_cast<SecuritySpec>(parseCurveSpec(it));
54 if (securityspec) {
55 std::string securityId = securityspec->securityID();
56 if (std::regex_match(securityId, excludePattern)) {
57 DLOG("skip " << securityId << " because it matches the exclude regex (" << excludeRegex << ")");
58 continue;
59 }
60 if (curveConfigs->hasSecurityConfig(securityId)) {
61 if (curveConfigs->securityConfig(securityId)->spreadQuote().empty()) {
62 DLOG("no spread quote configuraed, skip security " << securityId);
63 continue;
64 }
65 QuantLib::ext::shared_ptr<Security> security;
66 try {
67 security = QuantLib::ext::make_shared<Security>(asof, *securityspec, loader, *curveConfigs);
68 } catch (const std::exception& e) {
69 if (continueOnError) {
70 StructuredCurveErrorMessage(securityId, "Bond spread imply failed",
71 "Will continue the calculations with a zero security spread: " +
72 std::string(e.what()))
73 .log();
74 continue;
75 } else {
76 QL_FAIL("Cannot process security " << securityId << " " << e.what());
77 }
78 }
79 if (security->spread().empty()) {
80 if (!security->price().empty()) {
81 LOG("empty spread, non-empty price: will imply spread for security " << securityId);
82 securities[securityId] = security;
83 } else {
84 DLOG("empty spread, empty price: spread will be left empty for security " << securityId);
85 StructuredCurveErrorMessage("Security/" + securityId, "Missing security spread",
86 "No security spread or bond price to imply the spread is "
87 "given. Will proceed assuming a zero spread.")
88 .log();
89 }
90 } else {
91 if (!security->price().empty()) {
92 WLOG("non-empty spread, non-empty price, will not overwrite existing spread for security "
93 << securityId);
94 } else {
95 DLOG("non-empty spread, empty price, do nothing for security " << securityId);
96 }
97 }
98 } else {
99 WLOG("do not have security curve config for '" << securityId
100 << "' - skip this security in spread imply");
101 }
102 }
103 }
104 }
105 LOG("got " << securities.size() << " securities");
106 return securities;
107}
QuantLib::ext::shared_ptr< CurveSpec > parseCurveSpec(const string &s)
function to convert a string into a curve spec
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
vector< string > curveConfigs
+ Here is the call graph for this function:

◆ implyBondSpreads()

QuantLib::ext::shared_ptr< Loader > implyBondSpreads ( const std::map< std::string, QuantLib::ext::shared_ptr< Security > > &  securities,
const QuantLib::ext::shared_ptr< ReferenceDataManager > &  referenceDataManager,
const QuantLib::ext::shared_ptr< Market > &  market,
const QuantLib::ext::shared_ptr< EngineData > &  engineData,
const std::string &  configuration,
const IborFallbackConfig iborFallbackConfig 
)
static

Imply bond spreads and add them to the loader.

Definition at line 110 of file bondspreadimply.cpp.

114 {
115
116 LOG("run bond spread imply");
117
118 Settings::instance().evaluationDate() = market->asofDate();
119
120 // build engine factory against which we build the bonds
121 map<MarketContext, string> configurations;
122 configurations[MarketContext::pricing] = configuration;
123 auto spreadImplyMarket = QuantLib::ext::make_shared<BondSpreadImplyMarket>(market);
124 auto edCopy = QuantLib::ext::make_shared<EngineData>(*engineData);
125 edCopy->globalParameters()["RunType"] = "BondSpreadImply";
126 auto engineFactory = QuantLib::ext::make_shared<EngineFactory>(edCopy, spreadImplyMarket, configurations,
127 referenceDataManager, iborFallbackConfig);
128
129 // imply spreads and store the generate market data
130
131 std::map<std::string, QuantLib::ext::shared_ptr<MarketDatum>> generatedSpreads;
132 for (auto const& sec : securities) {
133 auto storedSpread = generatedSpreads.find(sec.first);
134 if (storedSpread == generatedSpreads.end()) {
135 try {
136 auto impliedSpread = QuantLib::ext::make_shared<SecuritySpreadQuote>(
137 implySpread(sec.first, sec.second->price()->value(), referenceDataManager, engineFactory,
138 spreadImplyMarket->spreadQuote(sec.first), configuration),
139 market->asofDate(), "BOND/YIELD_SPREAD/" + sec.first, sec.first);
140 generatedSpreads[sec.first] = impliedSpread;
141 LOG("spread imply succeded for security " << sec.first << ", got " << std::setprecision(10)
142 << impliedSpread->quote()->value());
143 } catch (const std::exception& e) {
144 StructuredCurveErrorMessage(
145 sec.first,
146 "bond spread imply failed (target price = " + std::to_string(sec.second->price()->value()) +
147 "). Will continue the calculations with a zero security spread.",
148 e.what()).log();
149 }
150 }
151 }
152
153 // add generated market data to loader and return the loader
154
155 auto loader = QuantLib::ext::make_shared<InMemoryLoader>();
156
157 for (auto const& s : generatedSpreads) {
158 DLOG("adding market datum " << s.second->name() << " (" << s.second->quote()->value() << ") for asof "
159 << market->asofDate() << " to loader");
160 loader->add(market->asofDate(), s.second->name(), s.second->quote()->value());
161 }
162
163 LOG("bond spread imply finished.");
164 return loader;
165}
static Real implySpread(const std::string &securityId, const Real cleanPrice, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::ext::shared_ptr< SimpleQuote > &spreadQuote, const std::string &configuration)
helper function that computes a single implied spread for a bond
+ Here is the call graph for this function:

◆ implySpread()

Real implySpread ( const std::string &  securityId,
const Real  cleanPrice,
const QuantLib::ext::shared_ptr< ReferenceDataManager > &  referenceDataManager,
const QuantLib::ext::shared_ptr< EngineFactory > &  engineFactory,
const QuantLib::ext::shared_ptr< SimpleQuote > &  spreadQuote,
const std::string &  configuration 
)
staticprivate

helper function that computes a single implied spread for a bond

Definition at line 167 of file bondspreadimply.cpp.

170 {
171
172 // checks, build bond from reference data
173
174 QL_REQUIRE(referenceDataManager, "no reference data manager given");
175
176 auto b = BondFactory::instance().build(engineFactory, referenceDataManager, securityId);
177 Real adj = b.priceQuoteMethod == QuantExt::BondIndex::PriceQuoteMethod::CurrencyPerUnit
178 ? 1.0 / b.priceQuoteBaseValue
179 : 1.0;
180
181 Real inflationFactor = b.inflationFactor();
182
183 DLOG("implySpread for securityId " << securityId << ":");
184 DLOG("settlement date = " << QuantLib::io::iso_date(b.bond->settlementDate()));
185 DLOG("market quote = " << cleanPrice);
186 DLOG("accrueds = " << b.bond->accruedAmount());
187 DLOG("inflation factor = " << inflationFactor);
188 DLOG("price quote method adj = " << adj);
189 DLOG("effective market price = " << cleanPrice * inflationFactor * adj);
190
191 auto targetFunction = [&b, spreadQuote, cleanPrice, adj, inflationFactor](const Real& s) {
192 spreadQuote->setValue(s);
193 if (b.modelBuilder != nullptr)
194 b.modelBuilder->recalibrate();
195 Real c = b.bond->cleanPrice() / 100.0;
196 TLOG("--> spread imply: trying s = " << s << " yields clean price " << c);
197 return c - cleanPrice * inflationFactor * adj;
198 };
199
200 // edge case: bond has a zero settlement value -> skip spread imply
201
202 if (QuantLib::close_enough(b.bond->cleanPrice(), 0.0)) {
203 DLOG("bond has a theoretical clean price of zero (no outstanding flows as of settlement date) -> skip spread "
204 "imply and continue with zero security spread.");
205 return 0.0;
206 }
207
208 // solve for spread and return result
209
210 Brent brent;
211 Real s = brent.solve(targetFunction, 1E-8, 0.0, 0.001);
212
213 DLOG("theoretical pricing = " << b.bond->cleanPrice() / 100.0);
214 return s;
215}
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
+ Here is the caller graph for this function: