40#include <qle/termstructures/sabrstrippedoptionletadapter.hpp>
44#include <ql/math/comparison.hpp>
45#include <ql/math/matrix.hpp>
46#include <ql/termstructures/volatility/capfloor/capfloortermvolcurve.hpp>
47#include <ql/termstructures/volatility/optionlet/strippedoptionletadapter.hpp>
65 "Expected InterpolateOn to be one of TermVolatilities or OptionletVolatilities");
72 Handle<YieldTermStructure> discountCurve,
const QuantLib::ext::shared_ptr<IborIndex> sourceIndex,
73 const QuantLib::ext::shared_ptr<IborIndex> targetIndex,
74 const std::map<std::string,
75 std::pair<QuantLib::ext::shared_ptr<ore::data::CapFloorVolCurve>, std::pair<std::string, QuantLib::Period>>>&
76 requiredCapFloorVolCurves,
77 const bool buildCalibrationInfo)
82 const QuantLib::ext::shared_ptr<CapFloorVolatilityCurveConfig>& config =
83 curveConfigs.capFloorVolCurveConfig(spec_.curveConfigID());
85 if (!config->proxySourceCurveId().empty()) {
87 buildProxyCurve(*config, sourceIndex, targetIndex, requiredCapFloorVolCurves);
89 QL_REQUIRE(QuantLib::ext::dynamic_pointer_cast<BMAIndexWrapper>(iborIndex) ==
nullptr,
90 "CapFloorVolCurve: BMA/SIFMA index in '"
91 << spec_.curveConfigID()
92 <<
" not allowed - vol surfaces for SIFMA can only be proxied from Ibor / OIS");
96 if (config->volatilityType() == CfgVolType::ShiftedLognormal) {
97 shift = shiftQuote(asof, *config, loader);
101 if (config->type() == CfgType::TermAtm) {
102 termAtmOptCurve(asof, *config, loader, iborIndex, discountCurve, shift);
103 }
else if (config->type() == CfgType::TermSurface || config->type() == CfgType::TermSurfaceWithAtm) {
104 termOptSurface(asof, *config, loader, iborIndex, discountCurve, shift);
105 }
else if (config->type() == CfgType::OptionletSurface ||
106 config->type() == CfgType::OptionletSurfaceWithAtm) {
107 optOptSurface(asof, *config, loader, iborIndex, discountCurve, shift);
108 }
else if (config->type() == CfgType::OptionletAtm) {
109 optAtmOptCurve(asof, *config, loader, iborIndex, discountCurve, shift);
111 QL_FAIL(
"Unexpected type (" <<
static_cast<int>(config->type()) <<
") for cap floor config "
112 << config->curveID());
115 capletVol_->enableExtrapolation(config->extrapolate());
119 if (buildCalibrationInfo) {
120 this->buildCalibrationInfo(asof,
curveConfigs, config, iborIndex);
123 }
catch (exception& e) {
124 QL_FAIL(
"cap/floor vol curve building failed :" << e.what());
126 QL_FAIL(
"cap/floor vol curve building failed: unknown error");
130 capletVol_->volatility(QL_EPSILON, capletVol_->minStrike());
135 const QuantLib::ext::shared_ptr<IborIndex>& targetIndex,
136 const std::map<std::string,
137 std::pair<QuantLib::ext::shared_ptr<ore::data::CapFloorVolCurve>, std::pair<std::string, QuantLib::Period>>>&
138 requiredCapFloorVolCurves) {
141 QL_REQUIRE(sourceVol != requiredCapFloorVolCurves.end(),
142 "CapFloorVolCurve::buildProxyCurve(): required source cap vol curve '" << config.
proxySourceCurveId()
145 capletVol_ = QuantLib::ext::make_shared<ProxyOptionletVolatility>(
146 Handle<OptionletVolatilityStructure>(sourceVol->second.first->capletVolStructure()), sourceIndex, targetIndex,
151 QuantLib::ext::shared_ptr<IborIndex> index, Handle<YieldTermStructure> discountCurve,
155 QuantLib::ext::shared_ptr<QuantExt::CapFloorTermVolCurve> cftvc =
atmCurve(asof, config, loader);
158 bool flatFirstPeriod =
true;
159 VolatilityType optVolType = Normal;
160 Real optDisplacement = 0.0;
177 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<Linear>> tmp =
178 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<Linear>>(
179 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
183 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
184 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Linear>>(
185 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
186 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
187 tmp->volatilityType(), tmp->displacement()));
189 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<LinearFlat>> tmp =
190 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<LinearFlat>>(
191 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
195 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
196 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Linear>>(
197 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
198 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
199 tmp->volatilityType(), tmp->displacement()));
201 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<BackwardFlat>> tmp =
202 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<BackwardFlat>>(
203 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
207 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
208 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, Linear>>(
209 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
210 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
211 tmp->volatilityType(), tmp->displacement()));
213 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<Cubic>> tmp =
214 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<Cubic>>(
215 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
219 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
220 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Linear>>(
221 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
222 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
223 tmp->volatilityType(), tmp->displacement()));
225 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<CubicFlat>> tmp =
226 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<CubicFlat>>(
227 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
231 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
232 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Linear>>(
233 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
234 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
235 tmp->volatilityType(), tmp->displacement()));
237 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected time interpolation "
245 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<CubicFlat>> tmp =
246 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<CubicFlat>>(
247 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
251 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
252 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Linear>>(
253 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
254 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
255 tmp->volatilityType(), tmp->displacement()));
257 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<Cubic>> tmp =
258 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<Cubic>>(
259 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
263 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
264 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Linear>>(
265 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
266 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
267 tmp->volatilityType(), tmp->displacement()));
271 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<LinearFlat>> tmp =
272 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<LinearFlat>>(
273 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
278 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
279 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Linear>>(
280 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
281 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
282 tmp->volatilityType(), tmp->displacement()));
284 QuantLib::ext::shared_ptr<PiecewiseAtmOptionletCurve<Linear>> tmp =
285 QuantLib::ext::make_shared<PiecewiseAtmOptionletCurve<Linear>>(
286 config.
settleDays(), cftvc, index, discountCurve, flatFirstPeriod,
290 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps));
291 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Linear>>(
292 asof,
transform(asof, tmp->curve()->dates(), tmp->curve()->volatilities(), tmp->settlementDays(),
293 tmp->calendar(), tmp->businessDayConvention(), index, tmp->dayCounter(),
294 tmp->volatilityType(), tmp->displacement()));
297 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected interpolation method "
304 QuantLib::ext::shared_ptr<IborIndex> index, Handle<YieldTermStructure> discountCurve,
308 QuantLib::ext::shared_ptr<QuantExt::CapFloorTermVolSurface> cftvs =
capSurface(asof, config, loader);
312 Handle<QuantExt::CapFloorTermVolCurve> cftvc;
314 cftvc = Handle<QuantExt::CapFloorTermVolCurve>(
atmCurve(asof, config, loader));
318 bool flatFirstPeriod =
true;
319 VolatilityType optVolType = Normal;
320 Real optDisplacement = 0.0;
332 std::vector<std::vector<std::pair<Real, bool>>> initialModelParameters;
333 Size maxCalibrationAttempts = 10;
334 Real exitEarlyErrorThreshold = 0.005;
335 Real maxAcceptableError = 0.05;
341 QL_REQUIRE(alpha.initialValue.size() == beta.initialValue.size() &&
342 alpha.initialValue.size() == nu.initialValue.size() &&
343 alpha.initialValue.size() == rho.initialValue.size(),
344 "CapFloorVolCurve: parametric smile config: alpha size ("
345 << alpha.initialValue.size() <<
") beta size (" << beta.initialValue.size() <<
") nu size ("
346 << nu.initialValue.size() <<
") rho size (" << rho.initialValue.size() <<
") must match");
347 for (Size i = 0; i < alpha.initialValue.size(); ++i) {
348 initialModelParameters.push_back(std::vector<std::pair<Real, bool>>());
349 initialModelParameters.back().push_back(std::make_pair(alpha.initialValue[i], alpha.isFixed));
350 initialModelParameters.back().push_back(std::make_pair(beta.initialValue[i], beta.isFixed));
351 initialModelParameters.back().push_back(std::make_pair(nu.initialValue[i], nu.isFixed));
352 initialModelParameters.back().push_back(std::make_pair(rho.initialValue[i], rho.isFixed));
360 QuantLib::ext::shared_ptr<QuantExt::OptionletStripper> optionletStripper;
363 SabrParametricVolatility::ModelVariant sabrModelVariant;
367 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<Linear>>(
368 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
372 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
376 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Linear, Linear>>(
377 optionletStripper, cftvc, discountCurve, volType, shift);
379 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Linear>>(
383 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Linear, LinearFlat>>(
384 optionletStripper, cftvc, discountCurve, volType, shift);
386 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, LinearFlat>>(
390 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Linear, Cubic>>(
391 optionletStripper, cftvc, discountCurve, volType, shift);
393 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Cubic>>(
397 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Linear, CubicFlat>>(
398 optionletStripper, cftvc, discountCurve, volType, shift);
400 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, CubicFlat>>(
404 std::function<QuantExt::SabrParametricVolatility::ModelVariant(
const std::string&)>(
405 [](
const std::string& s) { return parseSabrParametricVolatilityModelVariant(s); }))) {
407 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Linear, Linear>>(
408 optionletStripper, cftvc, discountCurve, volType, shift);
410 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<Linear>>(
411 asof,
transform(*optionletStripper), sabrModelVariant, Linear(), boost::none,
412 initialModelParameters, maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
414 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected strike interpolation "
418 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<LinearFlat>>(
419 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
423 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
427 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<LinearFlat, Linear>>(
428 optionletStripper, cftvc, discountCurve, volType, shift);
430 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Linear>>(
434 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<LinearFlat, LinearFlat>>(
435 optionletStripper, cftvc, discountCurve, volType, shift);
437 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, LinearFlat>>(
441 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<LinearFlat, Cubic>>(
442 optionletStripper, cftvc, discountCurve, volType, shift);
444 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Cubic>>(
448 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<LinearFlat, CubicFlat>>(
449 optionletStripper, cftvc, discountCurve, volType, shift);
451 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, CubicFlat>>(
455 std::function<QuantExt::SabrParametricVolatility::ModelVariant(
const std::string&)>(
456 [](
const std::string& s) { return parseSabrParametricVolatilityModelVariant(s); }))) {
458 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<LinearFlat, Linear>>(
459 optionletStripper, cftvc, discountCurve, volType, shift);
461 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<LinearFlat>>(
463 initialModelParameters, maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
465 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected strike interpolation "
469 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<BackwardFlat>>(
470 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
474 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
478 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<BackwardFlat, Linear>>(
479 optionletStripper, cftvc, discountCurve, volType, shift);
481 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, Linear>>(
485 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<BackwardFlat, LinearFlat>>(
486 optionletStripper, cftvc, discountCurve, volType, shift);
488 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, LinearFlat>>(
492 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<BackwardFlat, Cubic>>(
493 optionletStripper, cftvc, discountCurve, volType, shift);
495 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, Cubic>>(
499 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<BackwardFlat, CubicFlat>>(
500 optionletStripper, cftvc, discountCurve, volType, shift);
502 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, CubicFlat>>(
506 std::function<QuantExt::SabrParametricVolatility::ModelVariant(
const std::string&)>(
507 [](
const std::string& s) { return parseSabrParametricVolatilityModelVariant(s); }))) {
509 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<BackwardFlat, Linear>>(
510 optionletStripper, cftvc, discountCurve, volType, shift);
512 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<Linear>>(
513 asof,
transform(*optionletStripper), sabrModelVariant, Linear(), boost::none,
514 initialModelParameters, maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
516 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected strike interpolation "
520 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<Cubic>>(
521 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
525 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
529 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Cubic, Linear>>(
530 optionletStripper, cftvc, discountCurve, volType, shift);
532 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Linear>>(
536 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Cubic, LinearFlat>>(
537 optionletStripper, cftvc, discountCurve, volType, shift);
539 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, LinearFlat>>(
543 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Cubic, Cubic>>(
544 optionletStripper, cftvc, discountCurve, volType, shift);
546 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Cubic>>(
550 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Cubic, CubicFlat>>(
551 optionletStripper, cftvc, discountCurve, volType, shift);
553 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, CubicFlat>>(
557 std::function<QuantExt::SabrParametricVolatility::ModelVariant(
const std::string&)>(
558 [](
const std::string& s) { return parseSabrParametricVolatilityModelVariant(s); }))) {
560 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Cubic, Linear>>(
561 optionletStripper, cftvc, discountCurve, volType, shift);
563 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<Cubic>>(
564 asof,
transform(*optionletStripper), sabrModelVariant, Cubic(), boost::none, initialModelParameters,
565 maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
568 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected strike interpolation "
572 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<CubicFlat>>(
573 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
577 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
581 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<CubicFlat, Linear>>(
582 optionletStripper, cftvc, discountCurve, volType, shift);
584 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Linear>>(
588 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<CubicFlat, LinearFlat>>(
589 optionletStripper, cftvc, discountCurve, volType, shift);
591 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, LinearFlat>>(
595 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<CubicFlat, Cubic>>(
596 optionletStripper, cftvc, discountCurve, volType, shift);
598 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Cubic>>(
602 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<CubicFlat, CubicFlat>>(
603 optionletStripper, cftvc, discountCurve, volType, shift);
605 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, CubicFlat>>(
609 std::function<QuantExt::SabrParametricVolatility::ModelVariant(
const std::string&)>(
610 [](
const std::string& s) { return parseSabrParametricVolatilityModelVariant(s); }))) {
612 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<CubicFlat, Linear>>(
613 optionletStripper, cftvc, discountCurve, volType, shift);
615 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<CubicFlat>>(
617 initialModelParameters, maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
619 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected strike interpolation "
623 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected time interpolation "
631 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<CubicFlat>>(
632 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
636 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
639 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<CubicFlat, CubicFlat>>(
640 optionletStripper, cftvc, discountCurve, volType, shift);
642 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, CubicFlat>>(
645 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<Cubic>>(
646 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
650 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
653 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Cubic, Cubic>>(
654 optionletStripper, cftvc, discountCurve, volType, shift);
656 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Cubic>>(
661 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<LinearFlat>>(
662 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
666 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
669 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<LinearFlat, LinearFlat>>(
670 optionletStripper, cftvc, discountCurve, volType, shift);
672 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, LinearFlat>>(
675 optionletStripper = QuantLib::ext::make_shared<PiecewiseOptionletStripper<Linear>>(
676 cftvs, index, discountCurve, flatFirstPeriod, volType, shift, optVolType, optDisplacement, onOpt,
680 accuracy, globalAccuracy, dontThrow, maxAttempts, maxFactor, minFactor, dontThrowSteps),
683 optionletStripper = QuantLib::ext::make_shared<OptionletStripperWithAtm<Linear, Linear>>(
684 optionletStripper, cftvc, discountCurve, volType, shift);
686 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Linear>>(
690 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected interpolation method "
697 QuantLib::ext::shared_ptr<IborIndex> index, Handle<YieldTermStructure> discountCurve,
699 QL_REQUIRE(config.
optionalQuotes() ==
false,
"Optional quotes for optionlet volatilities are not supported.");
701 bool tenorRelevant =
false;
702 bool wildcardTenor =
false;
705 string currency = config.
currency();
706 vector<Period> configTenors;
707 std::map<Period, Real> capfloorVols;
709 wildcardTenor =
true;
713 std::ostringstream ss;
716 ss << config.
index() <<
"/";
719 for (
const auto& md : loader.
get(w, asof)) {
720 QL_REQUIRE(md->asofDate() == asof,
"MarketDatum asofDate '" << md->asofDate() <<
"' <> asof '" << asof <<
"'");
721 QuantLib::ext::shared_ptr<CapFloorQuote> cfq = QuantLib::ext::dynamic_pointer_cast<CapFloorQuote>(md);
722 QL_REQUIRE(cfq,
"Internal error: could not downcast MarketDatum '" << md->name() <<
"' to CapFloorQuote");
723 QL_REQUIRE(cfq->ccy() == currency,
724 "CapFloorQuote ccy '" << cfq->ccy() <<
"' <> config ccy '" << currency <<
"'");
725 if (cfq->underlying() == tenor && cfq->atm()) {
726 auto findTenor = std::find(configTenors.begin(), configTenors.end(), cfq->term());
728 tenorRelevant =
true;
730 tenorRelevant = findTenor != configTenors.end();
734 auto k = capfloorVols.find(cfq->term());
735 if (k != capfloorVols.end()) {
737 QL_FAIL(
"Duplicate optionlet atm vol quote in config "
738 << config.
curveID() <<
", with underlying tenor " << tenor <<
" ,currency "
739 << currency <<
" and index " << config.
index() <<
", for tenor " << cfq->term());
741 QL_FAIL(
"Duplicate optionlet atm vol quote in config "
742 << config.
curveID() <<
", with underlying tenor " << tenor <<
" and currency "
743 << currency <<
", for tenor " << cfq->term());
746 capfloorVols[cfq->term()]= cfq->quote()->value();
750 vector<Real> vols_tenor;
751 auto tenor_itr = configTenors.begin();
752 for (
auto const& vols_outer : capfloorVols) {
755 configTenors.push_back(vols_outer.first);
757 QL_REQUIRE(*tenor_itr == vols_outer.first,
"Quote with tenor " << *tenor_itr
758 <<
" not loaded for optionlet vol config "
762 vols_tenor.push_back(vols_outer.second);
766 DLOG(
"Found " << capfloorVols.size() <<
" quotes for optionlet vol surface " << config.
curveID());
770 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Linear>>(
775 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Linear>>(
780 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, Linear>>(
785 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Linear>>(
790 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Linear>>(
795 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected time interpolation "
801 const Loader& loader, QuantLib::ext::shared_ptr<QuantLib::IborIndex> iborIndex,
802 QuantLib::Handle<QuantLib::YieldTermStructure> discountCurve,
803 QuantLib::Real shift) {
804 QL_REQUIRE(config.
optionalQuotes() ==
false,
"Optional quotes for optionlet volatilities are not supported.");
807 std::vector<std::vector<std::pair<Real,bool>>> initialModelParameters;
808 Size maxCalibrationAttempts = 10;
809 Real exitEarlyErrorThreshold = 0.005;
810 Real maxAcceptableError = 0.05;
816 QL_REQUIRE(alpha.initialValue.size() == beta.initialValue.size() &&
817 alpha.initialValue.size() == nu.initialValue.size() &&
818 alpha.initialValue.size() == rho.initialValue.size(),
819 "CapFloorVolCurve: parametric smile config: alpha size ("
820 << alpha.initialValue.size() <<
") beta size (" << beta.initialValue.size() <<
") nu size ("
821 << nu.initialValue.size() <<
") rho size (" << rho.initialValue.size() <<
") must match");
822 for (Size i = 0; i < alpha.initialValue.size(); ++i) {
823 initialModelParameters.push_back(std::vector<std::pair<Real, bool>>());
824 initialModelParameters.back().push_back(std::make_pair(alpha.initialValue[i], alpha.isFixed));
825 initialModelParameters.back().push_back(std::make_pair(beta.initialValue[i], beta.isFixed));
826 initialModelParameters.back().push_back(std::make_pair(nu.initialValue[i], nu.isFixed));
827 initialModelParameters.back().push_back(std::make_pair(rho.initialValue[i], rho.isFixed));
835 Size quoteCounter = 0;
836 bool quoteRelevant =
false;
837 bool tenorRelevant =
false;
838 bool strikeRelevant =
false;
839 bool wildcardTenor =
false;
840 bool atmTenorRelevant =
false;
841 bool atmWildcardTenor =
false;
845 string currency = config.
currency();
846 vector<Period> configTenors;
847 std::map<Period, std::map<Real, Real>> capfloorVols;
848 vector<Period> atmConfigTenors;
849 std::map<Period, Real> atmCapFloorVols;
851 bool isOis = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(iborIndex) !=
nullptr;
853 if (config.
tenors()[0] ==
"*") {
854 wildcardTenor =
true;
860 atmWildcardTenor =
true;
865 std::ostringstream ss;
868 ss << config.
index() <<
"/";
871 for (
const auto& md : loader.
get(w, asof)) {
872 QL_REQUIRE(md->asofDate() == asof,
"MarketDatum asofDate '" << md->asofDate() <<
"' <> asof '" << asof <<
"'");
873 QuantLib::ext::shared_ptr<CapFloorQuote> cfq = QuantLib::ext::dynamic_pointer_cast<CapFloorQuote>(md);
874 QL_REQUIRE(cfq,
"Internal error: could not downcast MarketDatum '" << md->name() <<
"' to CapFloorQuote");
875 QL_REQUIRE(cfq->ccy() == currency,
876 "CapFloorQuote ccy '" << cfq->ccy() <<
"' <> config ccy '" << currency <<
"'");
877 if (cfq->underlying() == tenor) {
880 auto findTenor = std::find(configTenors.begin(), configTenors.end(), cfq->term());
882 tenorRelevant =
true;
884 tenorRelevant = findTenor != configTenors.end();
887 Real strike = cfq->strike();
888 auto i = std::find_if(config.
strikes().begin(), config.
strikes().end(),
889 [&strike](
const std::string& x) { return close_enough(parseReal(x), strike); });
890 strikeRelevant = i != config.
strikes().end();
892 quoteRelevant = strikeRelevant && tenorRelevant;
897 auto k = capfloorVols.find(cfq->term());
898 if (k != capfloorVols.end()) {
899 if (k->second.find(cfq->strike()) != k->second.end()) {
901 QL_FAIL(
"Duplicate optionlet vol quote in config "
902 << config.
curveID() <<
", with underlying tenor " << tenor <<
" ,currency "
903 << currency <<
" and index " << config.
index() <<
", for tenor " << cfq->term()
904 <<
" and strike " << cfq->strike());
906 QL_FAIL(
"Duplicate optionlet vol quote in config "
907 << config.
curveID() <<
", with underlying tenor " << tenor <<
" and currency "
908 << currency <<
", for tenor " << cfq->term() <<
" and strike "
913 capfloorVols[cfq->term()][cfq->strike()] = cfq->quote()->value();
915 }
else if (includeAtm) {
917 auto findTenor = std::find(atmConfigTenors.begin(), atmConfigTenors.end(), cfq->term());
918 if (atmWildcardTenor) {
919 atmTenorRelevant =
true;
921 atmTenorRelevant = findTenor != atmConfigTenors.end();
923 if (atmTenorRelevant) {
926 auto k = atmCapFloorVols.find(cfq->term());
927 if (k != atmCapFloorVols.end()) {
929 QL_FAIL(
"Duplicate optionlet atm vol quote in config "
930 << config.
curveID() <<
", with underlying tenor " << tenor <<
" ,currency "
931 << currency <<
" and index " << config.
index() <<
", for tenor " << cfq->term());
933 QL_FAIL(
"Duplicate optionlet atm vol quote in config "
934 << config.
curveID() <<
", with underlying tenor " << tenor <<
" and currency "
935 << currency <<
", for tenor " << cfq->term());
938 atmCapFloorVols[cfq->term()] = cfq->quote()->value();
944 auto tenor_itr = configTenors.begin();
945 for (
auto const& vols_outer: capfloorVols) {
947 if (!wildcardTenor) {
948 QL_REQUIRE(*tenor_itr == vols_outer.first,
"Quote with tenor " << *tenor_itr
949 <<
" not loaded for optionlet vol config "
954 for (Size j = 0; j <
strikes.size(); j++) {
955 auto it = vols_outer.second.find(
strikes[j]);
956 QL_REQUIRE(it != vols_outer.second.end(),
957 "Quote with tenor " << vols_outer.first <<
" and strike " <<
strikes[j]
958 <<
" not loaded for optionlet vol config "
962 std::map<Date, Date> tenorMap;
965 if (!atmWildcardTenor) {
966 auto tenor_itr = atmConfigTenors.begin();
967 for (
auto const& vols_outer : atmCapFloorVols) {
968 QL_REQUIRE(*tenor_itr == vols_outer.first,
"Quote with tenor "
969 << *tenor_itr <<
" not loaded for optionlet vol config "
975 for (
auto const& vols_outer : atmCapFloorVols) {
976 capfloorVols[vols_outer.first];
980 vector<Period> tenors;
981 for (
auto const& vols_outer : capfloorVols) {
982 tenors.push_back(vols_outer.first);
990 for (
auto const& vols_outer : atmCapFloorVols) {
991 auto it = find(tenors.begin(), tenors.end(), vols_outer.first);
992 Size ind = it - tenors.begin();
994 atmStrike =
getOisAtmLevel(QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(iborIndex), fixingDates[ind],
997 atmStrike = iborIndex->forecastFixing(fixingDates[ind]);
999 if (capfloorVols[vols_outer.first].find(atmStrike) == capfloorVols[vols_outer.first].end()) {
1000 capfloorVols[vols_outer.first][atmStrike] = vols_outer.second;
1004 vector<vector<Rate>> strikes_vec;
1005 vector<Rate> strikes_tenor;
1006 vector<vector<Handle<Quote>>> vols_vec;
1007 vector<Handle<Quote>> vols_tenor;
1008 for (
auto const& vols_outer : capfloorVols) {
1009 for (
auto const& vols_inner : vols_outer.second) {
1010 vols_tenor.push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(vols_inner.second)));
1011 strikes_tenor.push_back(vols_inner.first);
1013 tenors.push_back(vols_outer.first);
1014 strikes_vec.push_back(strikes_tenor);
1015 strikes_tenor.clear();
1016 vols_vec.push_back(vols_tenor);
1019 DLOG(
"Found " << quoteCounter <<
" quotes for optionlet vol surface " << config.
curveID());
1020 QuantLib::ext::shared_ptr<StrippedOptionlet> optionletSurface;
1023 optionletSurface = QuantLib::ext::make_shared<StrippedOptionlet>(
1025 vols_vec, config.
dayCounter(), volType, shift);
1027 SabrParametricVolatility::ModelVariant sabrModelVariant;
1032 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Linear>>(asof, optionletSurface);
1035 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, LinearFlat>>(asof, optionletSurface);
1037 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, Cubic>>(asof, optionletSurface);
1040 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Linear, CubicFlat>>(asof, optionletSurface);
1042 std::function<QuantExt::SabrParametricVolatility::ModelVariant(const std::string&)>(
1044 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<Linear>>(
1045 asof, optionletSurface, sabrModelVariant, Linear(), boost::none, initialModelParameters,
1046 maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
1048 QL_FAIL(
"Optionlet vol config " << config.
curveID() <<
" has unexpected strike interpolation "
1054 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Linear>>(asof, optionletSurface);
1057 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, LinearFlat>>(asof, optionletSurface);
1060 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, Cubic>>(asof, optionletSurface);
1063 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, CubicFlat>>(asof, optionletSurface);
1065 std::function<QuantExt::SabrParametricVolatility::ModelVariant(const std::string&)>(
1067 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<LinearFlat>>(
1068 asof, optionletSurface, sabrModelVariant,
LinearFlat(), boost::none, initialModelParameters,
1069 maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
1071 QL_FAIL(
"Optionlet vol config " << config.
curveID() <<
" has unexpected strike interpolation "
1077 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, Linear>>(asof, optionletSurface);
1079 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, LinearFlat>>(
1080 asof, optionletSurface);
1083 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, Cubic>>(asof, optionletSurface);
1086 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<BackwardFlat, CubicFlat>>(asof, optionletSurface);
1088 std::function<QuantExt::SabrParametricVolatility::ModelVariant(const std::string&)>(
1090 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<BackwardFlat>>(
1091 asof, optionletSurface, sabrModelVariant, BackwardFlat(), boost::none, initialModelParameters,
1092 maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
1094 QL_FAIL(
"Optionlet vol config " << config.
curveID() <<
" has unexpected strike interpolation "
1099 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Linear>>(asof, optionletSurface);
1102 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, LinearFlat>>(asof, optionletSurface);
1104 capletVol_ = QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, Cubic>>(asof, optionletSurface);
1107 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<Cubic, CubicFlat>>(asof, optionletSurface);
1109 std::function<QuantExt::SabrParametricVolatility::ModelVariant(const std::string&)>(
1111 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<Cubic>>(
1112 asof, optionletSurface, sabrModelVariant, Cubic(), boost::none, initialModelParameters,
1113 maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
1115 QL_FAIL(
"Optionlet vol config " << config.
curveID() <<
" has unexpected strike interpolation "
1121 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Linear>>(asof, optionletSurface);
1124 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, LinearFlat>>(asof, optionletSurface);
1127 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, Cubic>>(asof, optionletSurface);
1130 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<CubicFlat, CubicFlat>>(asof, optionletSurface);
1132 std::function<QuantExt::SabrParametricVolatility::ModelVariant(const std::string&)>(
1134 capletVol_ = QuantLib::ext::make_shared<QuantExt::SabrStrippedOptionletAdapter<CubicFlat>>(
1135 asof, optionletSurface, sabrModelVariant,
CubicFlat(), boost::none, initialModelParameters,
1136 maxCalibrationAttempts, exitEarlyErrorThreshold, maxAcceptableError);
1138 QL_FAIL(
"Optionlet vol config " << config.
curveID() <<
" has unexpected strike interpolation "
1142 QL_FAIL(
"Optionlet vol config " << config.
curveID() <<
" has unexpected time interpolation "
1147QuantLib::ext::shared_ptr<QuantExt::CapFloorTermVolSurface>
1152 auto comp = [](
const pair<Period, Rate>& a,
const pair<Period, Rate>& b) {
1153 return (a.first < b.first) || (!(b.first < a.first) && (a.second < b.second && !close(a.second, b.second)));
1155 map<pair<Period, Rate>, Real,
decltype(comp)> volQuotes(comp);
1158 Size quoteCounter = 0;
1159 bool quoteRelevant =
false;
1160 bool tenorRelevant =
false;
1161 bool strikeRelevant =
false;
1163 vector<Real> qtStrikes;
1164 vector<Real> qtData;
1165 vector<Period> qtTenors;
1167 string currency = config.
currency();
1168 vector<Period> configTenors = parseVectorOfValues<Period>(config.
tenors(), &
parsePeriod);
1170 std::ostringstream ss;
1173 ss << config.
index() <<
"/";
1176 for (
const auto& md : loader.
get(w, asof)) {
1177 QL_REQUIRE(md->asofDate() == asof,
"MarketDatum asofDate '" << md->asofDate() <<
"' <> asof '" << asof <<
"'");
1178 QuantLib::ext::shared_ptr<CapFloorQuote> cfq = QuantLib::ext::dynamic_pointer_cast<CapFloorQuote>(md);
1179 QL_REQUIRE(cfq,
"Internal error: could not downcast MarketDatum '" << md->name() <<
"' to CapFloorQuote");
1180 QL_REQUIRE(cfq->ccy() == currency,
"CapFloorQuote ccy '" << cfq->ccy() <<
"' <> config ccy '" << currency <<
"'");
1181 if (cfq->underlying() == tenor && !cfq->atm()) {
1182 auto j = std::find(configTenors.begin(), configTenors.end(), cfq->term());
1183 tenorRelevant = j != configTenors.end();
1185 Real strike = cfq->strike();
1186 auto i = std::find_if(config.
strikes().begin(), config.
strikes().end(),
1187 [&strike](
const std::string& x) {
1188 return close_enough(parseReal(x), strike);
1190 strikeRelevant = i != config.
strikes().end();
1192 quoteRelevant = strikeRelevant && tenorRelevant;
1194 if (quoteRelevant) {
1198 if (optionalQuotes) {
1199 qtStrikes.push_back(cfq->strike());
1200 qtTenors.push_back(cfq->term());
1201 qtData.push_back(cfq->quote()->value());
1203 auto key = make_pair(cfq->term(), cfq->strike());
1204 auto r = volQuotes.insert(make_pair(key, cfq->quote()->value()));
1206 QL_REQUIRE(r.second,
"Duplicate cap floor quote in config " << config.
curveID() <<
", with underlying tenor " << tenor <<
1207 " ,currency " << currency <<
" and index " << config.
index() <<
", for tenor " << key.first <<
" and strike " << key.second);
1209 QL_REQUIRE(r.second,
"Duplicate cap floor quote in config " << config.
curveID() <<
", with underlying tenor " << tenor <<
1210 " and currency " << currency <<
", for tenor " << key.first <<
" and strike " << key.second);
1215 Size totalQuotes = config.
tenors().size() * config.
strikes().size();
1216 if (quoteCounter < totalQuotes) {
1217 WLOG(
"Found only " << quoteCounter <<
" out of " << totalQuotes <<
" quotes for CapFloor surface " << config.
curveID());
1220 vector<Period> tenors = parseVectorOfValues<Period>(config.
tenors(), &
parsePeriod);
1222 Matrix vols(tenors.size(),
strikes.size());
1223 for (Size i = 0; i < tenors.size(); i++) {
1224 for (Size j = 0; j <
strikes.size(); j++) {
1225 auto key = make_pair(tenors[i],
strikes[j]);
1226 auto it = volQuotes.find(key);
1227 if (!optionalQuotes) {
1228 QL_REQUIRE(it != volQuotes.end(),
"Quote with tenor " << key.first <<
" and strike " << key.second
1229 <<
" not loaded for cap floor config "
1232 vols[i][j] = it->second;
1234 if (it == volQuotes.end()) {
1235 DLOG(
"Could not find quote with tenor " << key.first <<
" and strike " << key.second <<
1236 " for cap floor config " << config.
curveID());
1242 DLOG(
"Found " << quoteCounter <<
" quotes for capfloor surface " << config.
curveID());
1243 if (optionalQuotes) {
1244 QL_REQUIRE(quoteCounter > 0,
"No Quotes provided for CapFloor surface " << config.
curveID());
1246 return QuantLib::ext::make_shared<QuantExt::CapFloorTermVolSurfaceSparse<Linear, Linear>>(
1248 qtStrikes, qtData,
true,
true);
1250 return QuantLib::ext::make_shared<QuantExt::CapFloorTermVolSurfaceSparse<Cubic, Cubic>>(
1252 qtStrikes, qtData,
true,
true);
1254 QL_FAIL(
"Invalid Interpolation method for capfloor surface " << config.
curveID() <<
", must be either "
1259 return QuantLib::ext::make_shared<QuantExt::CapFloorTermVolSurfaceExact>(config.
settleDays(), config.
calendar(),
1265QuantLib::ext::shared_ptr<QuantExt::CapFloorTermVolCurve>
1269 map<Period, Handle<Quote>> volQuotes;
1273 string currency = config.
currency();
1275 std::ostringstream ss;
1278 for (
const auto& md : loader.
get(w, asof)) {
1279 QL_REQUIRE(md->asofDate() == asof,
"MarketDatum asofDate '" << md->asofDate() <<
"' <> asof '" << asof <<
"'");
1280 QuantLib::ext::shared_ptr<CapFloorQuote> cfq = QuantLib::ext::dynamic_pointer_cast<CapFloorQuote>(md);
1281 QL_REQUIRE(cfq,
"Internal error: could not downcast MarketDatum '" << md->name() <<
"' to CapFloorQuote");
1282 QL_REQUIRE(cfq->ccy() == currency,
"CapFloorQuote ccy '" << cfq->ccy() <<
"' <> config ccy '" << currency <<
"'");
1283 if (cfq->underlying() == tenor && cfq->atm()) {
1286 auto r = volQuotes.insert(make_pair(cfq->term(), cfq->quote()));
1287 QL_REQUIRE(r.second,
"Duplicate ATM cap floor quote in config " << config.
curveID() <<
" for tenor "
1295 vector<Handle<Quote>> vols;
1296 vector<Period> quoteTenors;
1297 if (!optionalQuotes) {
1298 vols.resize(tenors.size());
1299 quoteTenors = tenors;
1301 for (Size i = 0; i < tenors.size(); i++) {
1302 auto it = volQuotes.find(tenors[i]);
1303 if (!optionalQuotes) {
1304 QL_REQUIRE(it != volQuotes.end(),
1305 "ATM cap floor quote in config " << config.
curveID() <<
" for tenor " << tenors[i] <<
" not found ");
1306 vols[i] = it->second;
1308 if (it == volQuotes.end()) {
1309 DLOG(
"Could not find ATM cap floor quote with tenor " << tenors[i] <<
" for cap floor config " << config.
curveID());
1311 vols.push_back(it->second);
1312 quoteTenors.push_back(it->first);
1317 if (optionalQuotes) {
1318 QL_REQUIRE(vols.size() > 0,
"No ATM cap floor quotes found for cap floor config " << config.
curveID());
1319 if (vols.size() == 1)
1320 WLOG(
"Only one ATM cap floor quote found for cap floor config " << config.
curveID() <<
", using constant volatility");
1328 return QuantLib::ext::make_shared<InterpolatedCapFloorTermVolCurve<CubicFlat>>(
1332 return QuantLib::ext::make_shared<InterpolatedCapFloorTermVolCurve<Cubic>>(config.
settleDays(), config.
calendar(),
1338 return QuantLib::ext::make_shared<InterpolatedCapFloorTermVolCurve<LinearFlat>>(
1342 return QuantLib::ext::make_shared<InterpolatedCapFloorTermVolCurve<Linear>>(config.
settleDays(), config.
calendar(),
1347 QL_FAIL(
"Cap floor config " << config.
curveID() <<
" has unexpected interpolation method "
1353 const Loader& loader)
const {
1355 QL_REQUIRE(config.
volatilityType() == CfgVolType::ShiftedLognormal,
1356 "Method shiftQuote should not be called with a config who's volatility type is not ShiftedLognormal");
1359 for (
const string& quoteId : config.
quotes()) {
1361 QuantLib::ext::shared_ptr<MarketDatum> md = loader.
get(quoteId, asof);
1364 if (QuantLib::ext::shared_ptr<CapFloorShiftQuote> sq = QuantLib::ext::dynamic_pointer_cast<CapFloorShiftQuote>(md)) {
1365 return sq->quote()->value();
1369 QL_FAIL(
"Could not find a shift quote for cap floor config " << config.
curveID());
1380 vols[i].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(os.
optionletVolatilities(i)[j])));
1384 vector<vector<Real>> optionletStrikes;
1389 QuantLib::ext::shared_ptr<StrippedOptionlet> res = QuantLib::ext::make_shared<StrippedOptionlet>(
1393 res->unregisterWithAll();
1398QuantLib::ext::shared_ptr<StrippedOptionlet>
1400 Natural settleDays,
const Calendar& cal, BusinessDayConvention bdc,
1401 QuantLib::ext::shared_ptr<IborIndex> index,
const DayCounter& dc, VolatilityType type,
1402 Real displacement)
const {
1404 vector<vector<Handle<Quote>>> vols(dates.size());
1405 for (Size i = 0; i < dates.size(); i++) {
1406 vols[i].push_back(Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(volatilities[i])));
1411 if (dates[0] == asof) {
1416 QuantLib::ext::shared_ptr<StrippedOptionlet> res = QuantLib::ext::make_shared<StrippedOptionlet>(
1417 settleDays, cal, bdc, index, dates, strikes, vols, dc, type, displacement);
1419 res->unregisterWithAll();
1425 QuantLib::ext::shared_ptr<QuantLib::IborIndex> iborIndex,
const vector<Period>& configTenors) {
1427 vector<Date> fixingDates;
1428 bool isOis = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(iborIndex) !=
nullptr;
1429 QuantLib::ext::shared_ptr<BlackCapFloorEngine> dummyEngine =
1430 QuantLib::ext::make_shared<BlackCapFloorEngine>(iborIndex->forwardingTermStructure(), 0.20, config.
dayCounter());
1431 for (Size i = 0; i < configTenors.size(); i++) {
1434 MakeOISCapFloor(CapFloor::Cap, configTenors[i], QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(iborIndex),
1438 auto lastCoupon = QuantLib::ext::dynamic_pointer_cast<CappedFlooredOvernightIndexedCoupon>(dummyCap.back());
1439 QL_REQUIRE(lastCoupon,
"OptionletStripper::populateDates(): expected CappedFlooredOvernightIndexedCoupon");
1440 fixingDates.push_back(std::max(asof + 1, lastCoupon->underlying()->fixingDates().front()));
1443 MakeCapFloor(CapFloor::Cap, configTenors[i], iborIndex, 0.04, 0 * Days).withPricingEngine(dummyEngine);
1444 QuantLib::ext::shared_ptr<FloatingRateCoupon> lastCoupon = dummyCap.lastFloatingRateCoupon();
1445 fixingDates.push_back(std::max(asof + 1, lastCoupon->fixingDate()));
1451 const QuantLib::ext::shared_ptr<CapFloorVolatilityCurveConfig> config,
1452 const QuantLib::ext::shared_ptr<IborIndex>& index) {
1453 DLOG(
"Building calibration info for cap floor vols");
1460 std::vector<Period> expiries = *rc.
expiries();
1461 std::vector<Period> underlyingTenorsReport(1, index->tenor());
1465 calibrationInfo_->dayCounter = config->dayCounter().empty() ?
"na" : config->dayCounter().name();
1466 calibrationInfo_->calendar = config->calendar().empty() ?
"na" : config->calendar().name();
1470 bool isOis = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(index) !=
nullptr;
1472 Size onSettlementDays = 0;
1474 onSettlementDays = config->onCapSettlementDays();
1477 std::vector<Real> times;
1478 std::vector<std::vector<Real>> forwards;
1479 for (
auto const& p : expiries) {
1483 Leg dummyCap =
MakeOISCapFloor(CapFloor::Cap, p, QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(index),
1484 config->rateComputationPeriod(), 0.04)
1487 if (dummyCap.empty())
1489 auto lastCoupon = QuantLib::ext::dynamic_pointer_cast<CappedFlooredOvernightIndexedCoupon>(dummyCap.back());
1490 QL_REQUIRE(lastCoupon,
"OptionletStripper::populateDates(): expected CappedFlooredOvernightIndexedCoupon");
1491 fixingDate = std::max(asof + 1, lastCoupon->underlying()->fixingDates().front());
1492 forward = lastCoupon->underlying()->rate();
1494 CapFloor dummyCap = MakeCapFloor(CapFloor::Cap, p, index, 0.04, 0 * Days);
1495 if (dummyCap.floatingLeg().empty())
1497 QuantLib::ext::shared_ptr<FloatingRateCoupon> lastCoupon = dummyCap.lastFloatingRateCoupon();
1502 times.push_back(
capletVol_->dayCounter().empty() ? Actual365Fixed().yearFraction(asof,
fixingDate)
1504 forwards.push_back(std::vector<Real>(1, forward));
1510 std::vector<std::vector<std::vector<Real>>> callPricesStrike(
1512 std::vector<std::vector<Real>>(underlyingTenorsReport.size(), std::vector<Real>(
strikes.size(), 0.0)));
1513 std::vector<std::vector<std::vector<Real>>> callPricesStrikeSpread(
1515 std::vector<std::vector<Real>>(underlyingTenorsReport.size(), std::vector<Real>(strikeSpreads.size(), 0.0)));
1519 if (reportOnStrikeGrid) {
1521 calibrationInfo_->strikeGridStrikes = std::vector<std::vector<std::vector<Real>>>(
1523 std::vector<std::vector<Real>>(underlyingTenorsReport.size(), std::vector<Real>(
strikes.size(), 0.0)));
1524 calibrationInfo_->strikeGridProb = std::vector<std::vector<std::vector<Real>>>(
1526 std::vector<std::vector<Real>>(underlyingTenorsReport.size(), std::vector<Real>(
strikes.size(), 0.0)));
1527 calibrationInfo_->strikeGridImpliedVolatility = std::vector<std::vector<std::vector<Real>>>(
1529 std::vector<std::vector<Real>>(underlyingTenorsReport.size(), std::vector<Real>(
strikes.size(), 0.0)));
1530 calibrationInfo_->strikeGridCallSpreadArbitrage = std::vector<std::vector<std::vector<bool>>>(
1532 std::vector<std::vector<bool>>(underlyingTenorsReport.size(), std::vector<bool>(
strikes.size(),
true)));
1533 calibrationInfo_->strikeGridButterflyArbitrage = std::vector<std::vector<std::vector<bool>>>(
1535 std::vector<std::vector<bool>>(underlyingTenorsReport.size(), std::vector<bool>(
strikes.size(),
true)));
1536 TLOG(
"Strike surface arbitrage analysis result:");
1537 for (Size u = 0; u < underlyingTenorsReport.size(); ++u) {
1538 TLOG(
"Underlying tenor " << underlyingTenorsReport[u]);
1539 for (Size i = 0; i < times.size(); ++i) {
1542 bool validSlice =
true;
1543 for (Size j = 0; j <
strikes.size(); ++j) {
1546 if (
capletVol_->volatilityType() == ShiftedLognormal) {
1548 (forwards[i][u] > -shift ||
close_enough(forwards[i][u], -shift))) {
1551 callPricesStrike[i][u][j] =
1552 blackFormula(Option::Type::Call,
strikes[j], forwards[i][u], stddev);
1556 callPricesStrike[i][u][j] =
1557 bachelierBlackFormula(Option::Type::Call,
strikes[j], forwards[i][u], stddev);
1560 calibrationInfo_->strikeGridImpliedVolatility[i][u][j] = stddev / std::sqrt(t);
1561 }
catch (
const std::exception& e) {
1563 TLOG(
"error for time " << t <<
" strike " <<
strikes[j] <<
": " << e.what());
1569 forwards[i][u], callPricesStrike[i][u],
1577 }
catch (
const std::exception& e) {
1578 TLOG(
"error for time " << t <<
": " << e.what());
1587 TLOG(
"Strike cube arbitrage analysis completed.");
1590 if (reportOnStrikeSpreadGrid) {
1592 calibrationInfo_->strikeSpreadGridStrikes = std::vector<std::vector<std::vector<Real>>>(
1593 times.size(), std::vector<std::vector<Real>>(underlyingTenorsReport.size(),
1594 std::vector<Real>(strikeSpreads.size(), 0.0)));
1595 calibrationInfo_->strikeSpreadGridProb = std::vector<std::vector<std::vector<Real>>>(
1596 times.size(), std::vector<std::vector<Real>>(underlyingTenorsReport.size(),
1597 std::vector<Real>(strikeSpreads.size(), 0.0)));
1598 calibrationInfo_->strikeSpreadGridImpliedVolatility = std::vector<std::vector<std::vector<Real>>>(
1599 times.size(), std::vector<std::vector<Real>>(underlyingTenorsReport.size(),
1600 std::vector<Real>(strikeSpreads.size(), 0.0)));
1601 calibrationInfo_->strikeSpreadGridCallSpreadArbitrage = std::vector<std::vector<std::vector<bool>>>(
1602 times.size(), std::vector<std::vector<bool>>(underlyingTenorsReport.size(),
1603 std::vector<bool>(strikeSpreads.size(),
true)));
1604 calibrationInfo_->strikeSpreadGridButterflyArbitrage = std::vector<std::vector<std::vector<bool>>>(
1605 times.size(), std::vector<std::vector<bool>>(underlyingTenorsReport.size(),
1606 std::vector<bool>(strikeSpreads.size(),
true)));
1607 TLOG(
"Strike Spread surface arbitrage analysis result:");
1608 for (Size u = 0; u < underlyingTenorsReport.size(); ++u) {
1609 TLOG(
"Underlying tenor " << underlyingTenorsReport[u]);
1610 for (Size i = 0; i < times.size(); ++i) {
1613 bool validSlice =
true;
1614 for (Size j = 0; j < strikeSpreads.size(); ++j) {
1615 Real strike = forwards[i][u] + strikeSpreads[j];
1618 if (
capletVol_->volatilityType() == ShiftedLognormal) {
1619 if ((strike > -shift ||
close_enough(strike, -shift)) &&
1620 (forwards[i][u] > -shift ||
close_enough(forwards[i][u], -shift))) {
1621 stddev = std::sqrt(
capletVol_->blackVariance(t, strike));
1622 callPricesStrikeSpread[i][u][j] =
1623 blackFormula(Option::Type::Call, strike, forwards[i][u], stddev);
1626 stddev = std::sqrt(
capletVol_->blackVariance(t, strike));
1627 callPricesStrikeSpread[i][u][j] =
1628 bachelierBlackFormula(Option::Type::Call, strike, forwards[i][u], stddev);
1631 calibrationInfo_->strikeSpreadGridImpliedVolatility[i][u][j] = stddev / std::sqrt(t);
1632 }
catch (
const std::exception& e) {
1634 TLOG(
"error for time " << t <<
" strike spread " << strikeSpreads[j] <<
" strike " << strike
1635 <<
": " << e.what());
1642 callPricesStrikeSpread[i][u],
capletVol_->volatilityType(), shift);
1649 }
catch (
const std::exception& e) {
1650 TLOG(
"error for time " << t <<
": " << e.what());
1659 TLOG(
"Strike Spread cube arbitrage analysis completed.");
1664 QuantLib::ext::shared_ptr<QuantExt::SabrParametricVolatility> p;
1665 if (
auto s = QuantLib::ext::dynamic_pointer_cast<SabrStrippedOptionletAdapter<Linear>>(
capletVol_))
1666 p = QuantExt::ext::dynamic_pointer_cast<SabrParametricVolatility>(s->parametricVolatility());
1667 else if (
auto s = QuantLib::ext::dynamic_pointer_cast<SabrStrippedOptionletAdapter<LinearFlat>>(
capletVol_))
1668 p = QuantExt::ext::dynamic_pointer_cast<SabrParametricVolatility>(s->parametricVolatility());
1669 else if (
auto s = QuantLib::ext::dynamic_pointer_cast<SabrStrippedOptionletAdapter<Cubic>>(
capletVol_))
1670 p = QuantExt::ext::dynamic_pointer_cast<SabrParametricVolatility>(s->parametricVolatility());
1671 else if (
auto s = QuantLib::ext::dynamic_pointer_cast<SabrStrippedOptionletAdapter<CubicFlat>>(
capletVol_))
1672 p = QuantExt::ext::dynamic_pointer_cast<SabrParametricVolatility>(s->parametricVolatility());
1673 else if (
auto s = QuantLib::ext::dynamic_pointer_cast<SabrStrippedOptionletAdapter<BackwardFlat>>(
capletVol_))
1674 p = QuantExt::ext::dynamic_pointer_cast<SabrParametricVolatility>(s->parametricVolatility());
1677 DLOG(
"SABR parameters:");
1678 DLOG(
"alpha (pls ignore second row, this is present for technical reasons):");
1680 DLOG(
"beta (pls ignore second row, this is present for technical reasons):");
1682 DLOG(
"nu (pls ignore second row, this is present for technical reasons):");
1684 DLOG(
"rho (pls ignore second row, this is present for technical reasons):");
1686 DLOG(
"lognormal shift (pls ignore second row, this is present for technical reasons):");
1688 DLOG(
"calibration attempts:");
1690 DLOG(
"calibration error:");
1692 DLOG(
"isInterpolated (1 means calibration failed and point is interpolated):");
1696 DLOG(
"Building calibration info cap floor vols completed.");
ore::data::CapFloorVolatilityCurveConfig::VolatilityType CfgVolType
QuantExt::CapFloorTermVolSurfaceExact::InterpolationMethod CftvsInterp
ore::data::CapFloorVolatilityCurveConfig::Type CfgType
Build optionlet volatility structures from cap floor configurations.
const std::vector< bool > & butterflyArbitrage() const
bool arbitrageFree() const
const std::vector< bool > & callSpreadArbitrage() const
const std::vector< Real > & density() const
MakeOISCapFloor & withSettlementDays(Natural settlementDays)
MakeOISCapFloor & withTelescopicValueDates(bool telescopicValueDates)
Calendar calendar() const override
const std::vector< Date > & optionletFixingDates() const override
const std::vector< Rate > & optionletStrikes(Size i) const override
const std::vector< Volatility > & optionletVolatilities(Size i) const override
const std::vector< Rate > & atmOptionletRates() const override
VolatilityType volatilityType() const override
Natural settlementDays() const override
DayCounter dayCounter() const override
BusinessDayConvention businessDayConvention() const override
Real displacement() const override
ext::shared_ptr< IborIndex > index() const
QuantLib::Real maxFactor() const
QuantLib::Size dontThrowSteps() const
QuantLib::Real globalAccuracy() const
QuantLib::Real accuracy() const
QuantLib::Real minFactor() const
QuantLib::Size maxAttempts() const
Serializable cap, floor, collar.
Real shiftQuote(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader) const
Get a shift quote value from the configured quotes.
QuantLib::ext::shared_ptr< IrVolCalibrationInfo > calibrationInfo_
QuantLib::ext::shared_ptr< QuantLib::StrippedOptionlet > transform(const QuantExt::OptionletStripper &os) const
Transform QuantExt::OptionletStripper to QuantLib::StrippedOptionlet.
QuantLib::ext::shared_ptr< QuantExt::CapFloorTermVolSurface > capSurface(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader) const
Build a cap floor term volatility surface.
CapFloorVolCurve()
Default constructor.
void buildCalibrationInfo(const Date &asof, const CurveConfigurations &curveConfigs, const QuantLib::ext::shared_ptr< CapFloorVolatilityCurveConfig > config, const QuantLib::ext::shared_ptr< IborIndex > &iborIndex)
Build calibration info.
QuantLib::ext::shared_ptr< QuantExt::CapFloorTermVolCurve > atmCurve(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader) const
Build an ATM cap floor term volatility curve.
void termOptSurface(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader, QuantLib::ext::shared_ptr< QuantLib::IborIndex > iborIndex, QuantLib::Handle< QuantLib::YieldTermStructure > discountCurve, QuantLib::Real shift)
Build optionlet surface from term vol.
void optOptSurface(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader, QuantLib::ext::shared_ptr< QuantLib::IborIndex > iborIndex, QuantLib::Handle< QuantLib::YieldTermStructure > discountCurve, QuantLib::Real shift)
Build optionlet surface from optionlet vol.
void termAtmOptCurve(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader, QuantLib::ext::shared_ptr< QuantLib::IborIndex > iborIndex, QuantLib::Handle< QuantLib::YieldTermStructure > discountCurve, QuantLib::Real shift)
Build ATM optionlet curve from term vol.
void optAtmOptCurve(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, const Loader &loader, QuantLib::ext::shared_ptr< QuantLib::IborIndex > iborIndex, QuantLib::Handle< QuantLib::YieldTermStructure > discountCurve, QuantLib::Real shift)
Build ATM optionlet curve from optionlet vol.
QuantLib::ext::shared_ptr< QuantLib::OptionletVolatilityStructure > capletVol_
vector< Date > populateFixingDates(const QuantLib::Date &asof, CapFloorVolatilityCurveConfig &config, QuantLib::ext::shared_ptr< QuantLib::IborIndex > iborIndex, const vector< Period > &configTenors)
Generate fixing days from end date for optionlet vol.
void buildProxyCurve(const CapFloorVolatilityCurveConfig &config, const QuantLib::ext::shared_ptr< IborIndex > &sourceIndex, const QuantLib::ext::shared_ptr< IborIndex > &targetIndex, const std::map< std::string, std::pair< QuantLib::ext::shared_ptr< ore::data::CapFloorVolCurve >, std::pair< std::string, QuantLib::Period > > > &requiredCapFloorVolCurves)
Build proxy curve.
MarketDatum::QuoteType quoteType() const
const std::string & index() const
const string & currency() const
Type
The type of structure that has been configured.
const boost::optional< ParametricSmileConfiguration > parametricSmileConfiguration() const
const QuantLib::Natural & settleDays() const
bool quoteIncludesIndexName() const
bool optionalQuotes() const
const std::string & interpolateOn() const
const std::string & timeInterpolation() const
const std::string & proxySourceCurveId() const
const std::vector< std::string > & tenors() const
const QuantLib::Period & proxyTargetRateComputationPeriod() const
const QuantLib::BusinessDayConvention & businessDayConvention() const
const QuantLib::Calendar & calendar() const
bool flatExtrapolation() const
const QuantLib::DayCounter & dayCounter() const
QuantLib::Size onCapSettlementDays() const
VolatilityType
The type of volatility quotes that have been configured.
const std::vector< std::string > & atmTenors() const
const BootstrapConfig & bootstrapConfig() const
const QuantLib::Period & proxySourceRateComputationPeriod() const
string indexTenor() const
const VolatilityType & volatilityType() const
const QuantLib::Period & rateComputationPeriod() const
QuantExt::CapFloorTermVolSurfaceExact::InterpolationMethod interpolationMethod() const
const std::vector< std::string > & strikes() const
const std::string & strikeInterpolation() const
Cap/Floor Volatility curve description.
const string & curveID() const
virtual const vector< string > & quotes()
Return all the market quotes required for this config.
Container class for all Curve Configurations.
Market data loader base class.
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
const boost::optional< std::vector< Real > > & strikes() const
const boost::optional< bool > reportOnStrikeSpreadGrid() const
const boost::optional< bool > reportOnStrikeGrid() const
const boost::optional< std::vector< Period > > & expiries() const
const boost::optional< std::vector< Real > > & strikeSpreads() const
bool tryParse(const std::string &str, T &obj, std::function< T(const std::string &)> parser)
SabrParametricVolatility::ModelVariant parseSabrParametricVolatilityModelVariant(const std::string &s)
Parse SabrParametricVolatility::ModelVariant.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Real parseReal(const string &s)
Convert text to Real.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
#define TLOGGERSTREAM(text)
#define WLOG(text)
Logging Macro (Level = Warning)
#define TLOG(text)
Logging Macro (Level = Data)
#define DLOGGERSTREAM(text)
QuantLib::Date fixingDate(const QuantLib::Date &d, const QuantLib::Period obsLag, const QuantLib::Frequency freq, bool interpolated)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::string arbitrageAsString(const CarrMadanMarginalProbabilityClass &cm)
Real getOisAtmLevel(const boost::shared_ptr< OvernightIndex > &on, const Date &fixingDate, const Period &rateComputationPeriod)
ReportConfig effectiveReportConfig(const ReportConfig &globalConfig, const ReportConfig &localConfig)
VolatilityType volatilityType(CapFloorVolatilityCurveConfig::VolatilityType type)
Imply QuantLib::VolatilityType from CapFloorVolatilityCurveConfig::VolatilityType.
Size size(const ValueType &v)
bool interpOnOpt(CapFloorVolatilityCurveConfig &config)
std::string to_string(const LocationInfo &l)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
vector< string > curveConfigs
string conversion utilities