29#ifndef quantlib_sabr_swaption_volatility_cube_hpp
30#define quantlib_sabr_swaption_volatility_cube_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) {
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) {
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) {
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();
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) {
1014 "Cube::setPoints: incompatible number of layers ");
1016 "Cube::setPoints: incompatible size 1");
1018 "Cube::setPoints: incompatible size 2");
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) {
1076 if (expandOptionTimes) {
1080 if (expandSwapLengths) {
1088 for (
Size k=0; k<nLayers_; ++k) {
1090 Size indexOfRow = u;
1091 if (u>=i && expandOptionTimes) indexOfRow = u+1;
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) {
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)
backflat interpolation in first component, linear in second component
bilinear interpolation between discrete points
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_
const std::vector< Real > & points_
#define QL_ENSURE(condition, message)
throw an error if the given post-condition is not verified
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
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
linear interpolation between discrete points
matrix used in linear algebra.
XabrSwaptionVolatilityCube< SwaptionVolCubeSabrModel > SabrSwaptionVolatilityCube
SABR volatility cube for swaptions.
Matrix transpose(const Matrix &m)
ext::shared_ptr< BlackVolTermStructure > v
purely virtual base class for market observables
SABR interpolation interpolation between discrete points.
#define SWAPTIONVOLCUBE_TOL
#define SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL
Swaption Volatility Cube SABR.
SABRInterpolation Interpolation
SabrSmileSection SmileSection
Swaption volatility cube.