Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cdsvolcurve.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 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#include <algorithm>
25#include <ql/math/interpolations/loginterpolation.hpp>
26#include <ql/termstructures/volatility/equityfx/blackconstantvol.hpp>
27#include <ql/termstructures/volatility/equityfx/blackvariancecurve.hpp>
28#include <ql/termstructures/yield/flatforward.hpp>
29#include <ql/time/calendars/weekendsonly.hpp>
30#include <ql/time/daycounters/actual365fixed.hpp>
32
33using namespace QuantExt;
34using namespace QuantLib;
35using namespace std;
36
37namespace ore {
38namespace data {
39
40CDSVolCurve::CDSVolCurve(Date asof, CDSVolatilityCurveSpec spec, const Loader& loader,
41 const CurveConfigurations& curveConfigs,
42 const std::map<std::string, QuantLib::ext::shared_ptr<CDSVolCurve>>& requiredCdsVolCurves,
43 const std::map<std::string, QuantLib::ext::shared_ptr<DefaultCurve>>& requiredCdsCurves) {
44
45 try {
46
47 LOG("CDSVolCurve: start building CDS volatility structure with ID " << spec.curveConfigID());
48
49 QL_REQUIRE(curveConfigs.hasCdsVolCurveConfig(spec.curveConfigID()), "No curve configuration found for CDS "
50 << "volatility curve spec with ID "
51 << spec.curveConfigID() << ".");
52 auto config = *curveConfigs.cdsVolCurveConfig(spec.curveConfigID());
53
54 calendar_ = parseCalendar(config.calendar());
55 dayCounter_ = parseDayCounter(config.dayCounter());
56
57 strikeType_ = config.strikeType() == "Price" ? CreditVolCurve::Type::Price : CreditVolCurve::Type::Spread;
58
59 // Do different things depending on the type of volatility configured
60 QuantLib::ext::shared_ptr<VolatilityConfig> vc = config.volatilityConfig();
61 if (auto cvc = QuantLib::ext::dynamic_pointer_cast<ConstantVolatilityConfig>(vc)) {
62 buildVolatility(asof, config, *cvc, loader);
63 } else if (auto vcc = QuantLib::ext::dynamic_pointer_cast<VolatilityCurveConfig>(vc)) {
64 buildVolatility(asof, config, *vcc, loader);
65 } else if (auto vssc = QuantLib::ext::dynamic_pointer_cast<VolatilityStrikeSurfaceConfig>(vc)) {
66 buildVolatility(asof, config, *vssc, loader, requiredCdsCurves);
67 } else if (auto vdsc = QuantLib::ext::dynamic_pointer_cast<VolatilityDeltaSurfaceConfig>(vc)) {
68 QL_FAIL("CDSVolCurve does not support a VolatilityDeltaSurfaceConfig yet.");
69 } else if (auto vmsc = QuantLib::ext::dynamic_pointer_cast<VolatilityMoneynessSurfaceConfig>(vc)) {
70 QL_FAIL("CDSVolCurve does not support a VolatilityMoneynessSurfaceConfig yet.");
71 } else if (auto vapo = QuantLib::ext::dynamic_pointer_cast<VolatilityApoFutureSurfaceConfig>(vc)) {
72 QL_FAIL("VolatilityApoFutureSurfaceConfig does not make sense for CDSVolCurve.");
73 } else if (auto vpc = QuantLib::ext::dynamic_pointer_cast<CDSProxyVolatilityConfig>(vc)) {
74 buildVolatility(asof, spec, config, *vpc, requiredCdsVolCurves, requiredCdsCurves);
75 } else {
76 QL_FAIL("Unexpected VolatilityConfig in CDSVolatilityConfig");
77 }
78
79 LOG("CDSVolCurve: finished building CDS volatility structure with ID " << spec.curveConfigID());
80
81 } catch (exception& e) {
82 QL_FAIL("CDS volatility curve building for ID " << spec.curveConfigID() << " failed : " << e.what());
83 } catch (...) {
84 QL_FAIL("CDS volatility curve building for ID " << spec.curveConfigID() << " failed: unknown error");
85 }
86}
87
88void CDSVolCurve::buildVolatility(const Date& asof, const CDSVolatilityCurveConfig& vc,
89 const ConstantVolatilityConfig& cvc, const Loader& loader) {
90
91 LOG("CDSVolCurve: start building constant volatility structure");
92
93 const QuantLib::ext::shared_ptr<MarketDatum>& md = loader.get(cvc.quote(), asof);
94 QL_REQUIRE(md->asofDate() == asof, "MarketDatum asofDate '" << md->asofDate() << "' <> asof '" << asof << "'");
95 QL_REQUIRE(md->instrumentType() == MarketDatum::InstrumentType::INDEX_CDS_OPTION,
96 "MarketDatum instrument type '" << md->instrumentType() << "' <> 'MarketDatum::InstrumentType::INDEX_CDS_OPTION'");
97 QuantLib::ext::shared_ptr<IndexCDSOptionQuote> q = QuantLib::ext::dynamic_pointer_cast<IndexCDSOptionQuote>(md);
98 QL_REQUIRE(q, "Internal error: could not downcast MarketDatum '" << md->name() << "' to IndexCDSOptionQuote");
99 QL_REQUIRE(q->name() == cvc.quote(),
100 "IndexCDSOptionQuote name '" << q->name() << "' <> ConstantVolatilityConfig quote '" << cvc.quote() << "'");
101 TLOG("Found the constant volatility quote " << q->name());
102 Handle<Quote> quote = q->quote();
103
104 DLOG("Creating CreditVolCurve structure");
105
106 std::map<std::tuple<QuantLib::Date, QuantLib::Period, QuantLib::Real>, QuantLib::Handle<QuantLib::Quote>> quotes;
107 quotes[std::make_tuple(asof + 1 * Years, 5 * Years, strikeType_ == CreditVolCurve::Type::Price ? 1.0 : 0.0)] =
108 quote;
109 vol_ = QuantLib::ext::make_shared<QuantExt::InterpolatingCreditVolCurve>(
110 asof, calendar_, Following, dayCounter_, std::vector<QuantLib::Period>{},
111 std::vector<Handle<QuantExt::CreditCurve>>{}, quotes, strikeType_);
112
113 LOG("CDSVolCurve: finished building constant volatility structure");
114}
115
116void CDSVolCurve::buildVolatility(const QuantLib::Date& asof, const CDSVolatilityCurveConfig& vc,
117 const VolatilityCurveConfig& vcc, const Loader& loader) {
118
119 LOG("CDSVolCurve: start building 1-D volatility curve");
120
121 // Must have at least one quote
122 QL_REQUIRE(vcc.quotes().size() > 0, "No quotes specified in config " << vc.curveID());
123
124 // Check if we are using a regular expression to select the quotes for the curve. If we are, the quotes should
125 // contain exactly one element.
126 auto wildcard = getUniqueWildcard(vcc.quotes());
127
128 // curveData will be populated with the expiry dates and volatility values.
129 std::map<std::tuple<QuantLib::Date, QuantLib::Period, QuantLib::Real>, QuantLib::Handle<QuantLib::Quote>> quotes;
130
131 // Different approaches depending on whether we are using a regex or searching for a list of explicit quotes.
132 if (wildcard) {
133
134 DLOG("Have single quote with pattern " << wildcard->pattern());
135
136 // Loop over quotes and process CDS option quotes matching pattern on asof
137 for (const auto& md : loader.get(*wildcard, asof)) {
138
139 QL_REQUIRE(md->asofDate() == asof, "MarketDatum asofDate '" << md->asofDate() << "' <> asof '" << asof << "'");
140
141 auto q = QuantLib::ext::dynamic_pointer_cast<IndexCDSOptionQuote>(md);
142 QL_REQUIRE(q, "Internal error: could not downcast MarketDatum '" << md->name() << "' to IndexCDSOptionQuote");
143
144 TLOG("The quote " << q->name() << " matched the pattern");
145
146 /* - We load quotes with empty term only if there is at most one term specified in the curve config.
147 - We load quotes with a term, if they match a term specified in the curve config or if no term is
148 specified in the curve config.
149 - Quotes with an empty term get the unique term of the curve config assigned, if the curve config
150 has no terms specified, 5 * Years. */
151 QuantLib::Period quoteTerm;
152 if (q->indexTerm().empty()) {
153 if (vc.terms().size() > 1)
154 continue;
155 quoteTerm = vc.terms().empty() ? 5 * Years : vc.terms().front();
156 } else {
157 quoteTerm = parsePeriod(q->indexTerm());
158 if (std::find(vc.terms().begin(), vc.terms().end(), quoteTerm) == vc.terms().end() &&
159 !vc.terms().empty())
160 continue;
161 }
162
163 Date expiryDate = getExpiry(asof, q->expiry());
164 if (expiryDate > asof) {
165 quotes[std::make_tuple(expiryDate, quoteTerm,
166 strikeType_ == CreditVolCurve::Type::Price ? 1.0 : 0.0)] = q->quote();
167 TLOG("Added quote " << q->name() << ": (" << io::iso_date(expiryDate) << "," << fixed
168 << setprecision(9) << q->quote()->value() << ")");
169 }
170 }
171
172 // Check that we have quotes in the end
173 QL_REQUIRE(quotes.size() > 0, "No quotes found matching regular expression " << vcc.quotes()[0]);
174
175 } else {
176
177 DLOG("Have " << vcc.quotes().size() << " explicit quotes");
178
179 // Loop over quotes and process CDS option quotes that are explicitly specified in the config
180 std::ostringstream ss;
182 Wildcard w(ss.str());
183 for (const auto& md : loader.get(w, asof)) {
184
185 QL_REQUIRE(md->asofDate() == asof, "MarketDatum asofDate '" << md->asofDate() << "' <> asof '" << asof << "'");
186
187 auto q = QuantLib::ext::dynamic_pointer_cast<IndexCDSOptionQuote>(md);
188 QL_REQUIRE(q, "Internal error: could not downcast MarketDatum '" << md->name() << "' to IndexCDSOptionQuote");
189
190 // Find quote name in configured quotes.
191 auto it = find(vcc.quotes().begin(), vcc.quotes().end(), q->name());
192 if (it != vcc.quotes().end()) {
193 TLOG("Found the configured quote " << q->name());
194
195 Date expiryDate = getExpiry(asof, q->expiry());
196 QL_REQUIRE(expiryDate > asof, "CDS volatility quote '" << q->name() << "' has expiry in the past ("
197 << io::iso_date(expiryDate) << ")");
198 // we load all quotes, just populate the term of empty quotes
199 QuantLib::Period quoteTerm;
200 if (q->indexTerm().empty()) {
201 quoteTerm = vc.terms().size() == 1 ? vc.terms().front() : 5 * Years;
202 } else {
203 quoteTerm = parsePeriod(q->indexTerm());
204 }
205 quotes[std::make_tuple(expiryDate, quoteTerm,
206 strikeType_ == CreditVolCurve::Type::Price ? 1.0 : 0.0)] = q->quote();
207 TLOG("Added quote " << q->name() << ": (" << io::iso_date(expiryDate) << "," << fixed
208 << setprecision(9) << q->quote()->value() << ")");
209 }
210 }
211
212 // Check that we have found all of the explicitly configured quotes
213 QL_REQUIRE(quotes.size() == vcc.quotes().size(), "Found " << quotes.size() << " quotes, but "
214 << vcc.quotes().size()
215 << " quotes were given in config.");
216 }
217
218 DLOG("Creating InterpolatingCreditVolCurve object.");
219 vol_ = QuantLib::ext::make_shared<QuantExt::InterpolatingCreditVolCurve>(
220 asof, calendar_, Following, dayCounter_, std::vector<QuantLib::Period>{},
221 std::vector<Handle<QuantExt::CreditCurve>>{}, quotes, strikeType_);
222
223 LOG("CDSVolCurve: finished building 1-D volatility curve");
224}
225
227 const VolatilityStrikeSurfaceConfig& vssc, const Loader& loader,
228 const std::map<std::string, QuantLib::ext::shared_ptr<DefaultCurve>>& requiredCdsCurves) {
229
230 LOG("CDSVolCurve: start building 2-D volatility absolute strike surface");
231
232 // We are building a cds volatility surface here of the form expiry vs strike where the strikes are absolute
233 // numbers. The list of expiries may be explicit or contain a single wildcard character '*'. Similarly, the list
234 // of strikes may be explicit or contain a single wildcard character '*'. So, we have four options here.
235 // 1. explicit strikes and explicit expiries
236 // 2. wildcard strikes and/or wildcard expiries (3 combinations)
237 // All variants are handled by CreditVolCurve.
238
239 bool expWc = false;
240 if (find(vssc.expiries().begin(), vssc.expiries().end(), "*") != vssc.expiries().end()) {
241 expWc = true;
242 QL_REQUIRE(vssc.expiries().size() == 1, "Wild card expiry specified but more expiries also specified.");
243 DLOG("Have expiry wildcard pattern " << vssc.expiries()[0]);
244 }
245
246 bool strkWc = false;
247 if (find(vssc.strikes().begin(), vssc.strikes().end(), "*") != vssc.strikes().end()) {
248 strkWc = true;
249 QL_REQUIRE(vssc.strikes().size() == 1, "Wild card strike specified but more strikes also specified.");
250 DLOG("Have strike wildcard pattern " << vssc.strikes()[0]);
251 }
252
253 // If we do not have a strike wild card, we expect a list of absolute strike values
254 vector<Real> configuredStrikes;
255 if (!strkWc) {
256 // Parse the list of absolute strikes
257 configuredStrikes = parseVectorOfValues<Real>(vssc.strikes(), &parseReal);
258 sort(configuredStrikes.begin(), configuredStrikes.end(), [](Real x, Real y) { return !close(x, y) && x < y; });
259 QL_REQUIRE(adjacent_find(configuredStrikes.begin(), configuredStrikes.end(),
260 [](Real x, Real y) { return close(x, y); }) == configuredStrikes.end(),
261 "The configured strikes contain duplicates");
262 DLOG("Parsed " << configuredStrikes.size() << " unique configured absolute strikes");
263 }
264
265 // If we do not have an expiry wild card, parse the configured expiries.
266 vector<QuantLib::ext::shared_ptr<Expiry>> configuredExpiries;
267 if (!expWc) {
268 // Parse the list of expiry strings.
269 for (const string& strExpiry : vssc.expiries()) {
270 configuredExpiries.push_back(parseExpiry(strExpiry));
271 }
272 DLOG("Parsed " << configuredExpiries.size() << " unique configured expiries");
273 }
274
275 // If there are no wildcard strikes or wildcard expiries, delegate to buildVolatilityExplicit.
276 if (!expWc && !strkWc) {
277 buildVolatilityExplicit(asof, vc, vssc, loader, configuredStrikes, requiredCdsCurves);
278 return;
279 }
280
281 DLOG("Expiries and or strikes have been configured via wildcards so building a "
282 << "wildcard based absolute strike surface");
283
284 // Store quotes by expiry, term, strike in a map
285 std::map<std::tuple<QuantLib::Date, QuantLib::Period, QuantLib::Real>, QuantLib::Handle<QuantLib::Quote>> quotes;
286 Size quotesAdded = 0;
287
288 // Loop over quotes and process any CDS option quote that matches a wildcard
289 std::ostringstream ss;
290 ss << MarketDatum::InstrumentType::INDEX_CDS_OPTION << "/RATE_LNVOL/*";
291 Wildcard w(ss.str());
292 for (const auto& md : loader.get(w, asof)) {
293
294 QL_REQUIRE(md->asofDate() == asof, "MarketDatum asofDate '" << md->asofDate() << "' <> asof '" << asof << "'");
295
296 // Go to next quote if not a CDS option quote.
297 auto q = QuantLib::ext::dynamic_pointer_cast<IndexCDSOptionQuote>(md);
298 QL_REQUIRE(q, "Internal error: could not downcast MarketDatum '" << md->name() << "' to IndexCDSOptionQuote");
299
300 // Go to next quote if index name in the quote does not match the cds vol configuration name.
301 if (vc.curveID() != q->indexName() && vc.quoteName() != q->indexName())
302 continue;
303
304 // This surface is for absolute strikes only.
305 auto strike = QuantLib::ext::dynamic_pointer_cast<AbsoluteStrike>(q->strike());
306 if (!strike)
307 continue;
308
309 QuantLib::Period quoteTerm;
310 if (q->indexTerm().empty()) {
311 if (vc.terms().size() > 1)
312 continue;
313 quoteTerm = vc.terms().empty() ? 5 * Years : vc.terms().front();
314 } else {
315 quoteTerm = parsePeriod(q->indexTerm());
316 if (std::find(vc.terms().begin(), vc.terms().end(), quoteTerm) == vc.terms().end() && !vc.terms().empty())
317 continue;
318 }
319
320 // If we have been given a list of explicit expiries, check that the quote matches one of them.
321 // Move to the next quote if it does not.
322 if (!expWc) {
323 auto expiryIt = find_if(configuredExpiries.begin(), configuredExpiries.end(),
324 [&q](QuantLib::ext::shared_ptr<Expiry> e) { return *e == *q->expiry(); });
325 if (expiryIt == configuredExpiries.end())
326 continue;
327 }
328
329 // If we have been given a list of explicit strikes, check that the quote matches one of them.
330 // Move to the next quote if it does not.
331 if (!strkWc) {
332 auto strikeIt = find_if(configuredStrikes.begin(), configuredStrikes.end(),
333 [&strike](Real s) { return close(s, strike->strike()); });
334 if (strikeIt == configuredStrikes.end())
335 continue;
336 }
337
338 // If we make it here, add the data to the map
339 quotes[std::make_tuple(getExpiry(asof, q->expiry()), quoteTerm, strike->strike() / vc.strikeFactor())] =
340 q->quote();
341 quotesAdded++;
342
343 TLOG("Added quote " << q->name() << ": (" << q->expiry() << "," << fixed << setprecision(9) << strike->strike()
344 << "," << q->quote()->value() << ")");
345 }
346
347 LOG("CDSVolCurve: added " << quotesAdded << " quotes in building wildcard based absolute strike surface.");
348 QL_REQUIRE(quotesAdded > 0, "No quotes loaded for " << vc.curveID());
349
350 DLOG("Creating the CreditVolCurve object");
351
352 std::vector<QuantLib::Period> effTerms;
353 std::vector<QuantLib::Handle<CreditCurve>> termCurves;
354 for (Size i = 0; i < vc.termCurves().size(); ++i) {
355 if (vc.termCurves()[i].empty())
356 continue;
357 auto t = requiredCdsCurves.find(vc.termCurves()[i]);
358 QL_REQUIRE(t != requiredCdsCurves.end(), "CDSVolCurve: required cds curve '"
359 << vc.termCurves()[i]
360 << "' was not found during vol curve building.");
361 termCurves.push_back(Handle<QuantExt::CreditCurve>(t->second->creditCurve()));
362 effTerms.push_back(vc.terms()[i]);
363 }
364
365 vol_ = QuantLib::ext::make_shared<QuantExt::InterpolatingCreditVolCurve>(asof, calendar_, Following, dayCounter_, effTerms,
366 termCurves, quotes, strikeType_);
367 vol_->enableExtrapolation();
368
369 LOG("CDSVolCurve: finished building 2-D volatility absolute strike surface");
370}
371
372void CDSVolCurve::buildVolatility(const Date& asof, const CDSVolatilityCurveSpec& spec,
374 const std::map<std::string, QuantLib::ext::shared_ptr<CDSVolCurve>>& requiredCdsVolCurves,
375 const std::map<std::string, QuantLib::ext::shared_ptr<DefaultCurve>>& requiredCdsCurves) {
376 LOG("CDSVolCurve: start building proxy volatility surface");
377 auto proxyVolCurve = requiredCdsVolCurves.find(CDSVolatilityCurveSpec(pvc.cdsVolatilityCurve()).name());
378 QL_REQUIRE(proxyVolCurve != requiredCdsVolCurves.end(), "CDSVolCurve: Failed to find cds vol curve '"
379 << pvc.cdsVolatilityCurve() << "' when building '"
380 << spec.name() << "'");
381 std::vector<QuantLib::Period> effTerms;
382 std::vector<QuantLib::Handle<CreditCurve>> termCurves;
383 for (Size i = 0; i < vc.termCurves().size(); ++i) {
384 if (vc.termCurves()[i].empty())
385 continue;
386 auto t = requiredCdsCurves.find(vc.termCurves()[i]);
387 QL_REQUIRE(t != requiredCdsCurves.end(), "CDSVolCurve: required cds curve '"
388 << vc.termCurves()[i]
389 << "' was not found during vol curve building.");
390 termCurves.push_back(Handle<QuantExt::CreditCurve>(t->second->creditCurve()));
391 effTerms.push_back(vc.terms()[i]);
392 }
393 LOG("Will use " << termCurves.size()
394 << " term curves in target surface to determine atm levels and moneyness-adjustments");
395 vol_ = QuantLib::ext::make_shared<QuantExt::ProxyCreditVolCurve>(
396 Handle<CreditVolCurve>(proxyVolCurve->second->volTermStructure()), effTerms, termCurves);
397 LOG("CDSVolCurve: finished building proxy volatility surface");
398}
399
401 const Date& asof, CDSVolatilityCurveConfig& vc, const VolatilityStrikeSurfaceConfig& vssc, const Loader& loader,
402 const vector<Real>& configuredStrikes,
403 const std::map<std::string, QuantLib::ext::shared_ptr<DefaultCurve>>& requiredCdsCurves) {
404
405 LOG("CDSVolCurve: start building 2-D volatility absolute strike surface with explicit strikes and expiries");
406
407 // Store quotes by expiry, term, strike in a map
408 std::map<std::tuple<QuantLib::Date, QuantLib::Period, QuantLib::Real>, QuantLib::Handle<QuantLib::Quote>> quotes;
409
410 // Count the number of quotes added. We check at the end that we have added all configured quotes.
411 Size quotesAdded = 0;
412
413 // Loop over quotes and process CDS option quotes that have been requested
414 std::ostringstream ss;
416 Wildcard w(ss.str());
417 for (const auto& md : loader.get(w, asof)) {
418
419 QL_REQUIRE(md->asofDate() == asof, "MarketDatum asofDate '" << md->asofDate() << "' <> asof '" << asof << "'");
420
421 // Go to next quote if not a CDS option quote.
422 auto q = QuantLib::ext::dynamic_pointer_cast<IndexCDSOptionQuote>(md);
423 QL_REQUIRE(q, "Internal error: could not downcast MarketDatum '" << md->name() << "' to IndexCDSOptionQuote");
424
425 // This surface is for absolute strikes only.
426 auto strike = QuantLib::ext::dynamic_pointer_cast<AbsoluteStrike>(q->strike());
427 if (!strike)
428 continue;
429
430 QuantLib::Period quoteTerm;
431 if (q->indexTerm().empty()) {
432 if (vc.terms().size() > 1)
433 continue;
434 quoteTerm = vc.terms().empty() ? 5 * Years : vc.terms().front();
435 } else {
436 quoteTerm = parsePeriod(q->indexTerm());
437 if (std::find(vc.terms().begin(), vc.terms().end(), quoteTerm) == vc.terms().end() && !vc.terms().empty())
438 continue;
439 }
440
441 // Add quote to surface
442 quotes[std::make_tuple(getExpiry(asof, q->expiry()), quoteTerm, strike->strike() / vc.strikeFactor())] =
443 q->quote();
444 quotesAdded++;
445
446 TLOG("Added quote " << q->name() << ": (" << q->expiry() << "," << fixed << setprecision(9) << strike->strike()
447 << "," << q->quote()->value() << ")")
448 }
449
450 LOG("CDSVolCurve: added " << quotesAdded << " quotes in building explicit absolute strike surface.");
451
452 QL_REQUIRE(vc.quotes().size() == quotesAdded,
453 "Found " << quotesAdded << " quotes, but " << vc.quotes().size() << " quotes required by config.");
454
455 DLOG("Creating the CreditVolCurve object");
456
457 std::vector<QuantLib::Period> effTerms;
458 std::vector<QuantLib::Handle<CreditCurve>> termCurves;
459 for (Size i = 0; i < vc.termCurves().size(); ++i) {
460 if (vc.termCurves()[i].empty())
461 continue;
462 auto t = requiredCdsCurves.find(vc.termCurves()[i]);
463 QL_REQUIRE(t != requiredCdsCurves.end(), "CDSVolCurve: required cds curve '"
464 << vc.termCurves()[i]
465 << "' was not found during vol curve building.");
466 termCurves.push_back(Handle<QuantExt::CreditCurve>(t->second->creditCurve()));
467 effTerms.push_back(vc.terms()[i]);
468 }
469
470 vol_ = QuantLib::ext::make_shared<QuantExt::InterpolatingCreditVolCurve>(asof, calendar_, Following, dayCounter_, effTerms,
471 termCurves, quotes, strikeType_);
472 vol_->enableExtrapolation();
473
474 LOG("CDSVolCurve: finished building 2-D volatility absolute strike "
475 << "surface with explicit strikes and expiries");
476}
477
478Date CDSVolCurve::getExpiry(const Date& asof, const QuantLib::ext::shared_ptr<Expiry>& expiry) const {
479
480 Date result;
481
482 if (auto expiryDate = QuantLib::ext::dynamic_pointer_cast<ExpiryDate>(expiry)) {
483 result = expiryDate->expiryDate();
484 } else if (auto expiryPeriod = QuantLib::ext::dynamic_pointer_cast<ExpiryPeriod>(expiry)) {
485 // We may need more conventions here eventually.
486 result = calendar_.adjust(asof + expiryPeriod->expiryPeriod());
487 } else if (auto fcExpiry = QuantLib::ext::dynamic_pointer_cast<FutureContinuationExpiry>(expiry)) {
488 QL_FAIL("CDSVolCurve::getExpiry: future continuation expiry not supported for CDS volatility quotes.");
489 } else {
490 QL_FAIL("CDSVolCurve::getExpiry: cannot determine expiry type.");
491 }
492
493 return result;
494}
495
496} // namespace data
497} // namespace ore
Class for building cds volatility structures.
const std::string & cdsVolatilityCurve() const
CDSVolCurve()
Default constructor.
Definition: cdsvolcurve.hpp:43
QuantLib::Date getExpiry(const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< Expiry > &expiry) const
Get an explicit expiry date from a CDS option quote's Expiry.
QuantExt::CreditVolCurve::Type strikeType_
Definition: cdsvolcurve.hpp:63
QuantLib::Calendar calendar_
Definition: cdsvolcurve.hpp:61
QuantLib::ext::shared_ptr< QuantExt::CreditVolCurve > vol_
Definition: cdsvolcurve.hpp:60
void buildVolatilityExplicit(const QuantLib::Date &asof, CDSVolatilityCurveConfig &vc, const VolatilityStrikeSurfaceConfig &vssc, const Loader &loader, const std::vector< QuantLib::Real > &configuredStrikes, const std::map< std::string, QuantLib::ext::shared_ptr< DefaultCurve > > &requiredCdsCurves)
const CDSVolatilityCurveSpec & spec() const
Definition: cdsvolcurve.hpp:54
QuantLib::DayCounter dayCounter_
Definition: cdsvolcurve.hpp:62
void buildVolatility(const QuantLib::Date &asof, const CDSVolatilityCurveConfig &vc, const ConstantVolatilityConfig &cvc, const Loader &loader)
Build a volatility structure from a single constant volatility quote.
const std::vector< QuantLib::Period > & terms() const
const std::string & quoteName() const
const std::vector< std::string > & termCurves() const
CDS Volatility curve description.
Definition: curvespec.hpp:156
const string & curveID() const
Definition: curveconfig.hpp:54
virtual const vector< string > & quotes()
Return all the market quotes required for this config.
Definition: curveconfig.hpp:69
const std::string & curveConfigID() const
Definition: curvespec.hpp:83
string name() const
returns the unique curve name
Definition: curvespec.hpp:78
Market data loader base class.
Definition: loader.hpp:47
virtual QuantLib::ext::shared_ptr< MarketDatum > get(const std::string &name, const QuantLib::Date &d) const
get quote by its unique name, throws if not existent, override in derived classes for performance
Definition: loader.cpp:24
const std::vector< std::string > & quotes() const
const std::vector< std::string > & expiries() const
const std::vector< std::string > & strikes() const
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Definition: parsers.cpp:157
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Definition: parsers.cpp:209
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
Size size(const ValueType &v)
Definition: value.cpp:145
QuantLib::ext::shared_ptr< Expiry > parseExpiry(const string &strExpiry)
Parse an Expiry from its string representation, strExpiry.
Definition: expiry.cpp:110
boost::optional< Wildcard > getUniqueWildcard(const C &c)
checks if at most one element in C has a wild card and returns it in this case
Definition: wildcard.hpp:65
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
Error for market data or curve.
vector< string > curveConfigs
utilities for wildcard handling