29#ifndef quantlib_sabr_swaption_volatility_cube_hpp
30#define quantlib_sabr_swaption_volatility_cube_hpp
32#include <ql/math/interpolations/backwardflatlinearinterpolation.hpp>
33#include <ql/math/interpolations/bilinearinterpolation.hpp>
34#include <ql/math/interpolations/flatextrapolation2d.hpp>
35#include <ql/math/interpolations/linearinterpolation.hpp>
36#include <ql/math/interpolations/sabrinterpolation.hpp>
37#include <ql/math/matrix.hpp>
38#include <ql/quote.hpp>
39#include <ql/termstructures/volatility/sabrsmilesection.hpp>
40#include <ql/termstructures/volatility/swaption/swaptionvolcube.hpp>
44#ifndef SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL
45 #define SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL 15.0e-4
47#ifndef SWAPTIONVOLCUBE_TOL
48 #define SWAPTIONVOLCUBE_TOL 100.0e-4
53 class Interpolation2D;
55 class OptimizationMethod;
72 bool extrapolation =
true,
73 bool backwardFlat =
false);
81 void setPoints(
const std::vector<Matrix>& x);
86 const std::vector<Real>& point);
90 bool expandOptionTimes,
92 bool expandSwapLengths);
101 const std::vector<Matrix>&
points()
const;
127 std::vector<bool> isParameterFixed,
128 bool isAtmCalibrated,
129 ext::shared_ptr<EndCriteria> endCriteria = ext::shared_ptr<EndCriteria>(),
131 ext::shared_ptr<OptimizationMethod> optMethod = ext::shared_ptr<OptimizationMethod>(),
133 bool useMaxError =
false,
134 Size maxGuesses = 50,
135 bool backwardFlat =
false,
136 Real cutoffStrike = 0.0001);
157 Cube& parametersCube,
158 const Period& swapTenor)
const;
164 const std::vector<Real> &beta,
173 const Cube& sabrParametersCube)
const;
178 const Period& atmSwapTenor)
const;
185 mutable std::vector< std::vector<ext::shared_ptr<SmileSection> > >
206 v_->setParameterGuess();
222 template <
class Model>
225 const std::vector<Period>& optionTenors,
226 const std::vector<Period>& swapTenors,
227 const std::vector<Spread>& strikeSpreads,
229 const ext::shared_ptr<SwapIndex>& swapIndexBase,
230 const ext::shared_ptr<SwapIndex>& shortSwapIndexBase,
231 bool vegaWeightedSmileFit,
233 std::vector<bool> isParameterFixed,
234 bool isAtmCalibrated,
235 ext::shared_ptr<EndCriteria> endCriteria,
236 Real maxErrorTolerance,
237 ext::shared_ptr<OptimizationMethod> optMethod,
238 const Real errorAccept,
239 const bool useMaxError,
240 const Size maxGuesses,
241 const bool backwardFlat,
242 const Real cutoffStrike)
250 vegaWeightedSmileFit),
251 parametersGuessQuotes_(
std::move(parametersGuess)),
252 isParameterFixed_(
std::move(isParameterFixed)), isAtmCalibrated_(isAtmCalibrated),
253 endCriteria_(
std::move(endCriteria)), optMethod_(
std::move(optMethod)),
254 useMaxError_(useMaxError), maxGuesses_(maxGuesses), backwardFlat_(backwardFlat),
255 cutoffStrike_(cutoffStrike), volatilityType_(atmVolStructure->volatilityType()) {
276 for (
Size i=0; i<4; i++)
277 for (
Size j=0; j<nOptionTenors_; j++)
278 for (
Size k=0; k<nSwapTenors_; k++)
279 privateObserver_->registerWith(parametersGuessQuotes_[j+k*nOptionTenors_][i]);
285 parametersGuess_ =
Cube(optionDates_, swapTenors_,
286 optionTimes_, swapLengths_, 4,
287 true, backwardFlat_);
290 for (
Size j=0; j<nOptionTenors_ ; j++)
291 for (
Size k=0; k<nSwapTenors_; k++) {
292 parametersGuess_.setElement(i, j, k,
293 parametersGuessQuotes_[j+k*nOptionTenors_][i]->value());
295 parametersGuess_.updateInterpolators();
304 marketVolCube_ =
Cube(optionDates_, swapTenors_,
305 optionTimes_, swapLengths_, nStrikes_);
308 for (
Size j=0; j<nOptionTenors_; ++j) {
309 for (
Size k=0; k<nSwapTenors_; ++k) {
310 atmForward = atmStrike(optionDates_[j], swapTenors_[k]);
311 atmVol = atmVol_->volatility(optionDates_[j], swapTenors_[k],
313 for (
Size i=0; i<nStrikes_; ++i) {
314 vol = atmVol + volSpreads_[j*nSwapTenors_+k][i]->value();
315 marketVolCube_.setElement(i, j, k, vol);
319 marketVolCube_.updateInterpolators();
321 sparseParameters_ = sabrCalibration(marketVolCube_);
323 sparseParameters_.updateInterpolators();
325 volCubeAtmCalibrated_= marketVolCube_;
327 if(isAtmCalibrated_){
328 fillVolatilityCube();
329 denseParameters_ = sabrCalibration(volCubeAtmCalibrated_);
330 denseParameters_.updateInterpolators();
335 volCubeAtmCalibrated_ = marketVolCube_;
336 if(isAtmCalibrated_){
337 fillVolatilityCube();
338 denseParameters_ = sabrCalibration(volCubeAtmCalibrated_);
339 denseParameters_.updateInterpolators();
344 template <
class Model>
348 const std::vector<Time>& optionTimes = marketVolCube.
optionTimes();
349 const std::vector<Time>& swapLengths = marketVolCube.
swapLengths();
350 const std::vector<Date>& optionDates = marketVolCube.
optionDates();
351 const std::vector<Period>& swapTenors = marketVolCube.
swapTenors();
352 Matrix alphas(optionTimes.size(), swapLengths.size(),0.);
359 Matrix endCriteria(alphas);
361 const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.
points();
363 std::vector<Real> strikes(strikeSpreads_.size());
364 std::vector<Real> volatilities(strikeSpreads_.size());
366 for (
Size j=0; j<optionTimes.size(); j++) {
367 for (
Size k=0; k<swapLengths.size(); k++) {
368 Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
369 Real shiftTmp = atmVol_->shift(optionTimes[j], swapLengths[k]);
371 volatilities.clear();
372 for (
Size i=0; i<nStrikes_; i++){
373 Real strike = atmForward+strikeSpreads_[i];
374 if(strike + shiftTmp >=cutoffStrike_) {
375 strikes.push_back(strike);
376 volatilities.push_back(tmpMarketVolCube[i][j][k]);
380 const std::vector<Real>& guess =
381 parametersGuess_(optionTimes[j], swapLengths[k]);
383 const ext::shared_ptr<typename Model::Interpolation> sabrInterpolation =
384 ext::shared_ptr<typename Model::Interpolation>(
new
385 (
typename Model::Interpolation)(strikes.begin(), strikes.end(),
386 volatilities.begin(),
387 optionTimes[j], atmForward,
390 isParameterFixed_[0],
391 isParameterFixed_[1],
392 isParameterFixed_[2],
393 isParameterFixed_[3],
394 vegaWeightedSmileFit_,
402 sabrInterpolation->update();
404 Real rmsError = sabrInterpolation->rmsError();
405 Real maxError = sabrInterpolation->maxError();
406 alphas [j][k] = sabrInterpolation->alpha();
407 betas [j][k] = sabrInterpolation->beta();
408 nus [j][k] = sabrInterpolation->nu();
409 rhos [j][k] = sabrInterpolation->rho();
410 forwards [j][k] = atmForward;
411 errors [j][k] = rmsError;
412 maxErrors [j][k] = maxError;
413 endCriteria[j][k] = sabrInterpolation->endCriteria();
416 "global swaptions calibration failed: "
417 "MaxIterations reached: " <<
"\n" <<
418 "option maturity = " << optionDates[j] <<
", \n" <<
419 "swap tenor = " << swapTenors[k] <<
", \n" <<
420 "rms error = " <<
io::rate(errors[j][k]) <<
", \n" <<
421 "max error = " <<
io::rate(maxErrors[j][k]) <<
", \n" <<
422 " alpha = " << alphas[j][k] <<
"n" <<
423 " beta = " << betas[j][k] <<
"\n" <<
424 " nu = " << nus[j][k] <<
"\n" <<
425 " rho = " << rhos[j][k] <<
"\n"
428 QL_ENSURE((useMaxError_ ? maxError : rmsError) < maxErrorTolerance_,
429 "global swaptions calibration failed: "
430 "error tolerance exceeded: "
432 <<
"using " << (useMaxError_ ?
"maxError" :
"rmsError")
433 <<
" tolerance " << maxErrorTolerance_ <<
", \n"
434 <<
"option maturity = " << optionDates[j] <<
", \n"
435 <<
"swap tenor = " << swapTenors[k] <<
", \n"
436 <<
"rms error = " <<
io::rate(errors[j][k]) <<
", \n"
437 <<
"max error = " <<
io::rate(maxErrors[j][k]) <<
", \n"
438 <<
" alpha = " << alphas[j][k] <<
"n"
439 <<
" beta = " << betas[j][k] <<
"\n"
440 <<
" nu = " << nus[j][k] <<
"\n"
441 <<
" rho = " << rhos[j][k] <<
"\n");
444 Cube sabrParametersCube(optionDates, swapTenors,
445 optionTimes, swapLengths, 8,
446 true, backwardFlat_);
447 sabrParametersCube.
setLayer(0, alphas);
448 sabrParametersCube.
setLayer(1, betas);
449 sabrParametersCube.
setLayer(2, nus);
450 sabrParametersCube.
setLayer(3, rhos);
451 sabrParametersCube.
setLayer(4, forwards);
452 sabrParametersCube.
setLayer(5, errors);
453 sabrParametersCube.
setLayer(6, maxErrors);
454 sabrParametersCube.
setLayer(7, endCriteria);
456 return sabrParametersCube;
461 const Cube& marketVolCube,
462 Cube& parametersCube,
463 const Period& swapTenor)
const {
465 const std::vector<Time>& optionTimes = marketVolCube.
optionTimes();
466 const std::vector<Time>& swapLengths = marketVolCube.
swapLengths();
467 const std::vector<Date>& optionDates = marketVolCube.
optionDates();
468 const std::vector<Period>& swapTenors = marketVolCube.
swapTenors();
470 Size k = std::find(swapTenors.begin(), swapTenors.end(),
471 swapTenor) - swapTenors.begin();
472 QL_REQUIRE(k != swapTenors.size(),
"swap tenor not found");
474 std::vector<Real> calibrationResult(8,0.);
475 const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.
points();
477 std::vector<Real> strikes(strikeSpreads_.size());
478 std::vector<Real> volatilities(strikeSpreads_.size());
480 for (
Size j=0; j<optionTimes.size(); j++) {
481 Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
482 Real shiftTmp = atmVol_->shift(optionTimes[j], swapLengths[k]);
484 volatilities.clear();
485 for (
Size i=0; i<nStrikes_; i++){
486 Real strike = atmForward+strikeSpreads_[i];
487 if(strike+shiftTmp>=cutoffStrike_) {
488 strikes.push_back(strike);
489 volatilities.push_back(tmpMarketVolCube[i][j][k]);
493 const std::vector<Real>& guess =
494 parametersGuess_(optionTimes[j], swapLengths[k]);
496 const ext::shared_ptr<typename Model::Interpolation> sabrInterpolation =
497 ext::shared_ptr<typename Model::Interpolation>(
new
498 (
typename Model::Interpolation)(strikes.begin(), strikes.end(),
499 volatilities.begin(),
500 optionTimes[j], atmForward,
503 isParameterFixed_[0],
504 isParameterFixed_[1],
505 isParameterFixed_[2],
506 isParameterFixed_[3],
507 vegaWeightedSmileFit_,
515 sabrInterpolation->update();
516 Real interpolationError = sabrInterpolation->rmsError();
517 calibrationResult[0]=sabrInterpolation->alpha();
518 calibrationResult[1]=sabrInterpolation->beta();
519 calibrationResult[2]=sabrInterpolation->nu();
520 calibrationResult[3]=sabrInterpolation->rho();
521 calibrationResult[4]=atmForward;
522 calibrationResult[5]=interpolationError;
523 calibrationResult[6]=sabrInterpolation->maxError();
524 calibrationResult[7]=sabrInterpolation->endCriteria();
527 "section calibration failed: "
528 "option tenor " << optionDates[j] <<
529 ", swap tenor " << swapTenors[k] <<
530 ": max iteration (" <<
531 endCriteria_->maxIterations() <<
")" <<
532 ", alpha " << calibrationResult[0]<<
533 ", beta " << calibrationResult[1] <<
534 ", nu " << calibrationResult[2] <<
535 ", rho " << calibrationResult[3] <<
536 ", max error " << calibrationResult[6] <<
537 ", error " << calibrationResult[5]
540 QL_ENSURE((useMaxError_ ? calibrationResult[6] : calibrationResult[5]) < maxErrorTolerance_,
541 "section calibration failed: "
542 "option tenor " << optionDates[j] <<
543 ", swap tenor " << swapTenors[k] <<
544 (useMaxError_ ?
": max error " :
": error ") <<
545 (useMaxError_ ? calibrationResult[6] : calibrationResult[5]) <<
546 ", alpha " << calibrationResult[0] <<
547 ", beta " << calibrationResult[1] <<
548 ", nu " << calibrationResult[2] <<
549 ", rho " << calibrationResult[3] <<
550 (useMaxError_ ?
": error" :
": max error ") <<
551 (useMaxError_ ? calibrationResult[5] : calibrationResult[6])
554 parametersCube.
setPoint(optionDates[j], swapTenors[k],
555 optionTimes[j], swapLengths[k],
564 const ext::shared_ptr<SwaptionVolatilityDiscrete> atmVolStructure =
565 ext::dynamic_pointer_cast<SwaptionVolatilityDiscrete>(*atmVol_);
567 std::vector<Time> atmOptionTimes(atmVolStructure->optionTimes());
568 std::vector<Time> optionTimes(volCubeAtmCalibrated_.optionTimes());
569 atmOptionTimes.insert(atmOptionTimes.end(),
570 optionTimes.begin(), optionTimes.end());
571 std::sort(atmOptionTimes.begin(),atmOptionTimes.end());
572 auto new_end = std::unique(atmOptionTimes.begin(), atmOptionTimes.end());
573 atmOptionTimes.erase(new_end, atmOptionTimes.end());
575 std::vector<Time> atmSwapLengths(atmVolStructure->swapLengths());
576 std::vector<Time> swapLengths(volCubeAtmCalibrated_.swapLengths());
577 atmSwapLengths.insert(atmSwapLengths.end(),
578 swapLengths.begin(), swapLengths.end());
579 std::sort(atmSwapLengths.begin(),atmSwapLengths.end());
580 new_end = std::unique(atmSwapLengths.begin(), atmSwapLengths.end());
581 atmSwapLengths.erase(new_end, atmSwapLengths.end());
583 std::vector<Date> atmOptionDates = atmVolStructure->optionDates();
584 std::vector<Date> optionDates(volCubeAtmCalibrated_.optionDates());
585 atmOptionDates.insert(atmOptionDates.end(),
586 optionDates.begin(), optionDates.end());
587 std::sort(atmOptionDates.begin(),atmOptionDates.end());
588 auto new_end_1 = std::unique(atmOptionDates.begin(), atmOptionDates.end());
589 atmOptionDates.erase(new_end_1, atmOptionDates.end());
591 std::vector<Period> atmSwapTenors = atmVolStructure->swapTenors();
592 std::vector<Period> swapTenors(volCubeAtmCalibrated_.swapTenors());
593 atmSwapTenors.insert(atmSwapTenors.end(),
594 swapTenors.begin(), swapTenors.end());
595 std::sort(atmSwapTenors.begin(),atmSwapTenors.end());
596 auto new_end_2 = std::unique(atmSwapTenors.begin(), atmSwapTenors.end());
597 atmSwapTenors.erase(new_end_2, atmSwapTenors.end());
599 createSparseSmiles();
601 for (
Size j=0; j<atmOptionTimes.size(); j++) {
603 for (
Size k=0; k<atmSwapLengths.size(); k++) {
604 bool expandOptionTimes =
605 !(std::binary_search(optionTimes.begin(),
608 bool expandSwapLengths =
609 !(std::binary_search(swapLengths.begin(),
612 if(expandOptionTimes || expandSwapLengths){
613 Rate atmForward = atmStrike(atmOptionDates[j],
616 atmOptionDates[j], atmSwapTenors[k], atmForward);
617 std::vector<Real> spreadVols =
618 spreadVolInterpolation(atmOptionDates[j],
620 std::vector<Real> volAtmCalibrated;
621 volAtmCalibrated.reserve(nStrikes_);
622 for (
Size i=0; i<nStrikes_; i++)
623 volAtmCalibrated.push_back(atmVol + spreadVols[i]);
624 volCubeAtmCalibrated_.setPoint(
625 atmOptionDates[j], atmSwapTenors[k],
626 atmOptionTimes[j], atmSwapLengths[k],
631 volCubeAtmCalibrated_.updateInterpolators();
637 std::vector<Time> optionTimes(sparseParameters_.optionTimes());
638 std::vector<Time> swapLengths(sparseParameters_.swapLengths());
639 sparseSmiles_.clear();
641 for (
Real& optionTime : optionTimes) {
642 std::vector<ext::shared_ptr<SmileSection> > tmp;
643 Size n = swapLengths.size();
645 for (
Size k=0; k<n; ++k) {
646 tmp.push_back(smileSection(optionTime, swapLengths[k], sparseParameters_));
648 sparseSmiles_.push_back(tmp);
654 const Date& atmOptionDate,
const Period& atmSwapTenor)
const {
656 Time atmOptionTime = timeFromReference(atmOptionDate);
657 Time atmTimeLength = swapLength(atmSwapTenor);
659 std::vector<Real> result;
660 const std::vector<Time>& optionTimes(sparseParameters_.optionTimes());
661 const std::vector<Time>& swapLengths(sparseParameters_.swapLengths());
662 const std::vector<Date>& optionDates =
663 sparseParameters_.optionDates();
664 const std::vector<Period>& swapTenors = sparseParameters_.swapTenors();
666 std::vector<Real>::const_iterator optionTimesPreviousNode,
667 swapLengthsPreviousNode;
669 optionTimesPreviousNode = std::lower_bound(optionTimes.begin(),
672 Size optionTimesPreviousIndex =
673 optionTimesPreviousNode - optionTimes.begin();
674 if (optionTimesPreviousIndex >0)
675 optionTimesPreviousIndex --;
677 swapLengthsPreviousNode = std::lower_bound(swapLengths.begin(),
680 Size swapLengthsPreviousIndex = swapLengthsPreviousNode - swapLengths.begin();
681 if (swapLengthsPreviousIndex >0)
682 swapLengthsPreviousIndex --;
684 std::vector< std::vector<ext::shared_ptr<SmileSection> > > smiles;
685 std::vector<ext::shared_ptr<SmileSection> > smilesOnPreviousExpiry;
686 std::vector<ext::shared_ptr<SmileSection> > smilesOnNextExpiry;
688 QL_REQUIRE(optionTimesPreviousIndex+1 < sparseSmiles_.size(),
689 "optionTimesPreviousIndex+1 >= sparseSmiles_.size()");
690 QL_REQUIRE(swapLengthsPreviousIndex+1 < sparseSmiles_[0].size(),
691 "swapLengthsPreviousIndex+1 >= sparseSmiles_[0].size()");
692 smilesOnPreviousExpiry.push_back(
693 sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex]);
694 smilesOnPreviousExpiry.push_back(
695 sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex+1]);
696 smilesOnNextExpiry.push_back(
697 sparseSmiles_[optionTimesPreviousIndex+1][swapLengthsPreviousIndex]);
698 smilesOnNextExpiry.push_back(
699 sparseSmiles_[optionTimesPreviousIndex+1][swapLengthsPreviousIndex+1]);
701 smiles.push_back(smilesOnPreviousExpiry);
702 smiles.push_back(smilesOnNextExpiry);
704 std::vector<Real> optionsNodes(2);
705 optionsNodes[0] = optionTimes[optionTimesPreviousIndex];
706 optionsNodes[1] = optionTimes[optionTimesPreviousIndex+1];
708 std::vector<Date> optionsDateNodes(2);
709 optionsDateNodes[0] = optionDates[optionTimesPreviousIndex];
710 optionsDateNodes[1] = optionDates[optionTimesPreviousIndex+1];
712 std::vector<Real> swapLengthsNodes(2);
713 swapLengthsNodes[0] = swapLengths[swapLengthsPreviousIndex];
714 swapLengthsNodes[1] = swapLengths[swapLengthsPreviousIndex+1];
716 std::vector<Period> swapTenorNodes(2);
717 swapTenorNodes[0] = swapTenors[swapLengthsPreviousIndex];
718 swapTenorNodes[1] = swapTenors[swapLengthsPreviousIndex+1];
720 Rate atmForward = atmStrike(atmOptionDate, atmSwapTenor);
721 Real shift = atmVol_->shift(atmOptionTime, atmTimeLength);
723 Matrix atmForwards(2, 2, 0.0);
724 Matrix atmShifts(2,2,0.0);
725 Matrix atmVols(2, 2, 0.0);
726 for (
Size i=0; i<2; i++) {
727 for (
Size j=0; j<2; j++) {
728 atmForwards[i][j] = atmStrike(optionsDateNodes[i],
730 atmShifts[i][j] = atmVol_->shift(optionsNodes[i], swapLengthsNodes[j]);
732 atmVols[i][j] = atmVol_->volatility(
733 optionsDateNodes[i], swapTenorNodes[j], atmForwards[i][j]);
753 for (
Size k=0; k<nStrikes_; k++){
754 const Real strike = std::max(atmForward + strikeSpreads_[k],cutoffStrike_-shift);
755 const Real moneyness = (atmForward+shift)/(strike+shift);
758 Matrix spreadVols(2,2,0.);
759 for (
Size i=0; i<2; i++){
760 for (
Size j=0; j<2; j++){
761 strikes[i][j] = (atmForwards[i][j]+atmShifts[i][j])/moneyness - atmShifts[i][j];
763 smiles[i][j]->volatility(strikes[i][j]) - atmVols[i][j];
766 Cube localInterpolator(optionsDateNodes, swapTenorNodes,
767 optionsNodes, swapLengthsNodes, 1);
768 localInterpolator.
setLayer(0, spreadVols);
771 result.push_back(localInterpolator(atmOptionTime, atmTimeLength)[0]);
776 template<
class Model> ext::shared_ptr<SmileSection>
778 const Cube& sabrParametersCube)
const {
781 const std::vector<Real> sabrParameters =
782 sabrParametersCube(optionTime, swapLength);
783 Real shiftTmp = atmVol_->shift(optionTime,swapLength);
784 return ext::shared_ptr<SmileSection>(
new (
typename Model::SmileSection)(
785 optionTime, sabrParameters[4], sabrParameters,shiftTmp, volatilityType_));
788 template<
class Model> ext::shared_ptr<SmileSection>
790 Time swapLength)
const {
791 if (isAtmCalibrated_)
792 return smileSection(optionTime, swapLength, denseParameters_);
794 return smileSection(optionTime, swapLength, sparseParameters_);
799 return sparseParameters_.browse();
804 return denseParameters_.browse();
809 return marketVolCube_.browse();
814 return volCubeAtmCalibrated_.browse();
818 const Period& swapTenor) {
820 std::vector<Real> betaVector(nOptionTenors_, beta);
821 recalibration(betaVector,swapTenor);
826 const Period& swapTenor) {
828 QL_REQUIRE(beta.size() == nOptionTenors_,
831 <<
") must be equal to number of option tenors ("
832 << nOptionTenors_ <<
")");
834 const std::vector<Period> &swapTenors = marketVolCube_.swapTenors();
835 Size k = std::find(swapTenors.begin(), swapTenors.end(), swapTenor) -
838 QL_REQUIRE(k != swapTenors.size(),
"swap tenor (" << swapTenor
841 for (
Size i = 0; i < nOptionTenors_; ++i) {
842 parametersGuess_.setElement(1, i, k, beta[i]);
845 parametersGuess_.updateInterpolators();
846 sabrCalibrationSection(marketVolCube_, sparseParameters_, swapTenor);
848 volCubeAtmCalibrated_ = marketVolCube_;
849 if (isAtmCalibrated_) {
850 fillVolatilityCube();
851 sabrCalibrationSection(volCubeAtmCalibrated_, denseParameters_,
859 const std::vector<Real> &beta,
860 const Period &swapTenor) {
862 QL_REQUIRE(beta.size() == swapLengths.size(),
865 <<
") must be equal to number of swap lengths ("
866 << swapLengths.size() <<
")");
868 std::vector<Time> betaTimes;
869 for (
Size i = 0; i < beta.size(); i++)
871 timeFromReference(optionDateFromTenor(swapLengths[i])));
874 betaTimes.end(), beta.begin());
876 std::vector<Real> cubeBeta;
877 for (
Size i = 0; i < optionTimes().size(); i++) {
878 Real t = optionTimes()[i];
880 if (t < betaTimes.front())
881 t = betaTimes.front();
882 if (t > betaTimes.back())
883 t = betaTimes.back();
884 cubeBeta.push_back(betaInterpolation(t));
887 recalibration(cubeBeta, swapTenor);
897 const std::vector<Period>& swapTenors,
898 const std::vector<Time>& optionTimes,
899 const std::vector<Time>& swapLengths,
903 : optionTimes_(optionTimes), swapLengths_(swapLengths),
904 optionDates_(optionDates), swapTenors_(swapTenors),
905 nLayers_(nLayers), extrapolation_(extrapolation),
906 backwardFlat_(backwardFlat) {
908 QL_REQUIRE(
optionTimes.size()>1,
"Cube::Cube(...): optionTimes.size()<2");
909 QL_REQUIRE(
swapLengths.size()>1,
"Cube::Cube(...): swapLengths.size()<2");
912 "Cube::Cube(...): optionTimes/optionDates mismatch");
914 "Cube::Cube(...): swapTenors/swapLengths mismatch");
919 ext::shared_ptr<Interpolation2D> interpolation;
923 ext::make_shared<BackwardflatLinearInterpolation>(
929 ext::make_shared<BilinearInterpolation>(
943 nLayers_(o.nLayers_), transposedPoints_(o.transposedPoints_),
946 ext::shared_ptr<Interpolation2D> interpolation;
949 ext::make_shared<BackwardflatLinearInterpolation>(
955 ext::make_shared<BilinearInterpolation>(
976 for(
Size k=0;k<nLayers_;k++){
977 ext::shared_ptr<Interpolation2D> interpolation;
980 ext::make_shared<BackwardflatLinearInterpolation>(
983 transposedPoints_[k]);
986 ext::make_shared<BilinearInterpolation>(
989 transposedPoints_[k]);
990 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
992 interpolators_[k]->enableExtrapolation();
1002 QL_REQUIRE(IndexOfLayer<nLayers_,
1003 "Cube::setElement: incompatible IndexOfLayer ");
1005 "Cube::setElement: incompatible IndexOfRow");
1007 "Cube::setElement: incompatible IndexOfColumn");
1008 points_[IndexOfLayer][IndexOfRow][IndexOfColumn] = x;
1012 const std::vector<Matrix>& x) {
1013 QL_REQUIRE(x.size()==nLayers_,
1014 "Cube::setPoints: incompatible number of layers ");
1016 "Cube::setPoints: incompatible size 1");
1018 "Cube::setPoints: incompatible size 2");
1025 QL_REQUIRE(i<nLayers_,
1026 "Cube::setLayer: incompatible number of layer ");
1028 "Cube::setLayer: incompatible size 1");
1030 "Cube::setLayer: incompatible size 2");
1035 template <
class Model>
1040 const std::vector<Real>& point)
1042 const bool expandOptionTimes =
1044 const bool expandSwapLengths =
1047 std::vector<Real>::const_iterator optionTimesPreviousNode,
1048 swapLengthsPreviousNode;
1050 optionTimesPreviousNode =
1054 swapLengthsPreviousNode =
1058 if (expandOptionTimes || expandSwapLengths)
1059 expandLayers(optionTimesIndex, expandOptionTimes,
1060 swapLengthsIndex, expandSwapLengths);
1062 for (
Size k=0; k<nLayers_; ++k)
1063 points_[k][optionTimesIndex][swapLengthsIndex] = point[k];
1072 Size j,
bool expandSwapLengths) {
1073 QL_REQUIRE(i<=
optionTimes_.size(),
"Cube::expandLayers: incompatible size 1");
1074 QL_REQUIRE(j<=
swapLengths_.size(),
"Cube::expandLayers: incompatible size 2");
1076 if (expandOptionTimes) {
1080 if (expandSwapLengths) {
1088 for (
Size k=0; k<nLayers_; ++k) {
1089 for (
Size u=0; u<points_[k].rows(); ++u) {
1090 Size indexOfRow = u;
1091 if (u>=i && expandOptionTimes) indexOfRow = u+1;
1092 for (
Size v=0; v<points_[k].columns(); ++v) {
1093 Size indexOfCol = v;
1094 if (v>=j && expandSwapLengths) indexOfCol = v+1;
1095 newPoints[k][indexOfRow][indexOfCol]=points_[k][u][v];
1099 setPoints(newPoints);
1102 template<
class Model>
const std::vector<Matrix>&
1109 std::vector<Real> result;
1110 for (
Size k=0; k<nLayers_; ++k)
1111 result.push_back((*interpolators_[k])(optionTime,
swapLength));
1115 template<
class Model>
const std::vector<Time>&
1120 template<
class Model>
const std::vector<Time>&
1126 for (
Size k = 0; k < nLayers_; ++k) {
1127 transposedPoints_[k] =
transpose(points_[k]);
1128 ext::shared_ptr<Interpolation2D> interpolation;
1131 ext::make_shared<BackwardflatLinearInterpolation>(
1134 transposedPoints_[k]);
1137 ext::make_shared<BilinearInterpolation>(
1140 transposedPoints_[k]);
1141 interpolators_[k] = ext::shared_ptr<Interpolation2D>(
1143 interpolators_[k]->enableExtrapolation();
1153 for (
Size k=0; k<nLayers_; ++k)
1154 result[i*
optionTimes_.size()+j][2+k] = points_[k][j][i];
1163 template <
class Model>
1187 [[deprecated(
"renamed to SabrSwaptionVolatilityCube")]]
Shared handle to an observable.
Linear interpolation between discrete points
Matrix used in linear algebra.
template class providing a null value for a given type.
Object that gets notified when a given observable changes.
SABR smile interpolation between discrete volatility points.
void performCalculations() const override
const std::vector< std::vector< Handle< Quote > > > & volSpreads() const
bool vegaWeightedSmileFit_
ext::shared_ptr< SwapIndex > shortSwapIndexBase() const
bool vegaWeightedSmileFit() const
ext::shared_ptr< SwapIndex > swapIndexBase() const
const std::vector< Spread > & strikeSpreads() const
std::vector< Date > optionDates_
const std::vector< Time > & swapLengths() const
std::vector< Period > swapTenors_
std::vector< Time > swapLengths_
const std::vector< Period > & swapTenors() const
const std::vector< Period > & optionTenors() const
std::vector< Time > optionTimes_
Time swapLength(const Period &swapTenor) const
implements the conversion between swap tenor and swap (time) length
std::vector< Date > optionDates_
std::vector< Matrix > transposedPoints_
void expandLayers(Size i, bool expandOptionTimes, Size j, bool expandSwapLengths)
std::vector< Matrix > points_
const std::vector< Time > & swapLengths() const
std::vector< Period > swapTenors_
void setPoint(const Date &optionDate, const Period &swapTenor, Time optionTime, Time swapLength, const std::vector< Real > &point)
std::vector< Time > swapLengths_
std::vector< Real > operator()(Time optionTime, Time swapLengths) const
void setPoints(const std::vector< Matrix > &x)
const std::vector< Period > & swapTenors() const
const std::vector< Matrix > & points() const
void setLayer(Size i, const Matrix &x)
void setElement(Size IndexOfLayer, Size IndexOfRow, Size IndexOfColumn, Real x)
const std::vector< Time > & optionTimes() const
std::vector< Time > optionTimes_
std::vector< ext::shared_ptr< Interpolation2D > > interpolators_
const std::vector< Date > & optionDates() const
void updateInterpolators() const
Cube & operator=(const Cube &o)
XabrSwaptionVolatilityCube< Model > * v_
PrivateObserver(XabrSwaptionVolatilityCube< Model > *v)
XABR Swaption Volatility Cube.
void createSparseSmiles() const
void performCalculations() const override
std::vector< Real > spreadVolInterpolation(const Date &atmOptionDate, const Period &atmSwapTenor) const
void updateAfterRecalibration()
std::vector< std::vector< Handle< Quote > > > parametersGuessQuotes_
XabrSwaptionVolatilityCube(const Handle< SwaptionVolatilityStructure > &atmVolStructure, const std::vector< Period > &optionTenors, const std::vector< Period > &swapTenors, const std::vector< Spread > &strikeSpreads, const std::vector< std::vector< Handle< Quote > > > &volSpreads, const ext::shared_ptr< SwapIndex > &swapIndexBase, const ext::shared_ptr< SwapIndex > &shortSwapIndexBase, bool vegaWeightedSmileFit, std::vector< std::vector< Handle< Quote > > > parametersGuess, std::vector< bool > isParameterFixed, bool isAtmCalibrated, ext::shared_ptr< EndCriteria > endCriteria=ext::shared_ptr< EndCriteria >(), Real maxErrorTolerance=Null< Real >(), ext::shared_ptr< OptimizationMethod > optMethod=ext::shared_ptr< OptimizationMethod >(), Real errorAccept=Null< Real >(), bool useMaxError=false, Size maxGuesses=50, bool backwardFlat=false, Real cutoffStrike=0.0001)
const ext::shared_ptr< OptimizationMethod > optMethod_
Matrix denseSabrParameters() const
ext::shared_ptr< SmileSection > smileSectionImpl(Time optionTime, Time swapLength) const override
const ext::shared_ptr< EndCriteria > endCriteria_
Cube volCubeAtmCalibrated_
void registerWithParametersGuess()
std::vector< bool > isParameterFixed_
std::vector< std::vector< ext::shared_ptr< SmileSection > > > sparseSmiles_
Matrix marketVolCube() const
ext::shared_ptr< SmileSection > smileSection(Time optionTime, Time swapLength, const Cube &sabrParametersCube) const
ext::shared_ptr< PrivateObserver > privateObserver_
void fillVolatilityCube() const
void sabrCalibrationSection(const Cube &marketVolCube, Cube ¶metersCube, const Period &swapTenor) const
void setParameterGuess() const
const Matrix & marketVolCube(Size i) const
Size requiredNumberOfStrikes() const override
Matrix volCubeAtmCalibrated() const
void recalibration(Real beta, const Period &swapTenor)
Matrix sparseSabrParameters() const
Cube sabrCalibration(const Cube &marketVolCube) const
VolatilityType volatilityType_
detail::percent_holder rate(Rate)
output rates and spreads as percentages
Real Time
continuous quantity with 1-year units
Real Volatility
volatility
QL_INTEGER Integer
integer number
std::size_t Size
size of a container
XabrSwaptionVolatilityCube< SwaptionVolCubeSabrModel > SwaptionVolCube1
XabrSwaptionVolatilityCube< SwaptionVolCubeSabrModel > SabrSwaptionVolatilityCube
SABR volatility cube for swaptions.
Matrix transpose(const Matrix &m)
Swaption Volatility Cube SABR.
SABRInterpolation Interpolation
SabrSmileSection SmileSection