QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
sabrswaptionvolatilitycube.hpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006, 2007 Giorgio Facchinetti
5 Copyright (C) 2014, 2015 Peter Caspers
6 Copyright (C) 2023 Ignacio Anguita
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22/*! \file sabrswaptionvolatilitycube.hpp
23 \brief Swaption volatility cube, fit-early-interpolate-later approach
24 The provided types are
25 SabrSwaptionVolatilityCube using the classic Hagan 2002 Sabr formula
26 NoArbSabrSwaptionVolatilityCube using the No Arbitrage Sabr model (Doust)
27*/
28
29#ifndef quantlib_sabr_swaption_volatility_cube_hpp
30#define quantlib_sabr_swaption_volatility_cube_hpp
31
37#include <ql/math/matrix.hpp>
38#include <ql/quote.hpp>
41#include <utility>
42
43
44#ifndef SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL
45 #define SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL 15.0e-4
46#endif
47#ifndef SWAPTIONVOLCUBE_TOL
48 #define SWAPTIONVOLCUBE_TOL 100.0e-4
49#endif
50
51namespace QuantLib {
52
53 class Interpolation2D;
54 class EndCriteria;
55 class OptimizationMethod;
56
57 //! XABR Swaption Volatility Cube
58 /*! This class implements the XABR Swaption Volatility Cube
59 which is a generic for different SABR, ZABR and
60 different smile models that can be used to instantiate concrete cubes.
61 */
62 template<class Model>
64 class Cube { // NOLINT(cppcoreguidelines-special-member-functions)
65 public:
66 Cube() = default;
67 Cube(const std::vector<Date>& optionDates,
68 const std::vector<Period>& swapTenors,
69 const std::vector<Time>& optionTimes,
70 const std::vector<Time>& swapLengths,
71 Size nLayers,
72 bool extrapolation = true,
73 bool backwardFlat = false);
74 Cube& operator=(const Cube& o);
75 Cube(const Cube&);
76 virtual ~Cube() = default;
77 void setElement(Size IndexOfLayer,
78 Size IndexOfRow,
79 Size IndexOfColumn,
80 Real x);
81 void setPoints(const std::vector<Matrix>& x);
82 void setPoint(const Date& optionDate,
83 const Period& swapTenor,
84 Time optionTime,
86 const std::vector<Real>& point);
87 void setLayer(Size i,
88 const Matrix& x);
89 void expandLayers(Size i,
90 bool expandOptionTimes,
91 Size j,
92 bool expandSwapLengths);
93 const std::vector<Date>& optionDates() const {
94 return optionDates_;
95 }
96 const std::vector<Period>& swapTenors() const {
97 return swapTenors_;
98 }
99 const std::vector<Time>& optionTimes() const;
100 const std::vector<Time>& swapLengths() const;
101 const std::vector<Matrix>& points() const;
102 std::vector<Real> operator()(Time optionTime, Time swapLengths) const;
103 void updateInterpolators()const;
104 Matrix browse() const;
105 private:
106 std::vector<Time> optionTimes_, swapLengths_;
107 std::vector<Date> optionDates_;
108 std::vector<Period> swapTenors_;
110 std::vector<Matrix> points_;
111 mutable std::vector<Matrix> transposedPoints_;
114 mutable std::vector< ext::shared_ptr<Interpolation2D> > interpolators_;
115 };
116 public:
118 const Handle<SwaptionVolatilityStructure>& atmVolStructure,
119 const std::vector<Period>& optionTenors,
120 const std::vector<Period>& swapTenors,
121 const std::vector<Spread>& strikeSpreads,
122 const std::vector<std::vector<Handle<Quote> > >& volSpreads,
123 const ext::shared_ptr<SwapIndex>& swapIndexBase,
124 const ext::shared_ptr<SwapIndex>& shortSwapIndexBase,
126 std::vector<std::vector<Handle<Quote> > > parametersGuess,
127 std::vector<bool> isParameterFixed,
128 bool isAtmCalibrated,
129 ext::shared_ptr<EndCriteria> endCriteria = ext::shared_ptr<EndCriteria>(),
130 Real maxErrorTolerance = Null<Real>(),
131 ext::shared_ptr<OptimizationMethod> optMethod = ext::shared_ptr<OptimizationMethod>(),
132 Real errorAccept = Null<Real>(),
133 bool useMaxError = false,
134 Size maxGuesses = 50,
135 bool backwardFlat = false,
136 Real cutoffStrike = 0.0001);
137 //! \name LazyObject interface
138 //@{
139 void performCalculations() const override;
140 //@}
141 //! \name SwaptionVolatilityCube interface
142 //@{
143 ext::shared_ptr<SmileSection> smileSectionImpl(Time optionTime,
144 Time swapLength) const override;
145 //@}
146 //! \name Other inspectors
147 //@{
148 const Matrix& marketVolCube(Size i) const {
149 return marketVolCube_.points()[i];
150 }
153 Matrix marketVolCube() const;
155 //@}
156 void sabrCalibrationSection(const Cube& marketVolCube,
157 Cube& parametersCube,
158 const Period& swapTenor) const;
160 const Period& swapTenor);
161 void recalibration(const std::vector<Real> &beta,
162 const Period& swapTenor);
163 void recalibration(const std::vector<Period> &swapLengths,
164 const std::vector<Real> &beta,
165 const Period& swapTenor);
167 protected:
169 void setParameterGuess() const;
170 ext::shared_ptr<SmileSection> smileSection(
171 Time optionTime,
173 const Cube& sabrParametersCube) const;
174 Cube sabrCalibration(const Cube &marketVolCube) const;
175 void fillVolatilityCube() const;
176 void createSparseSmiles() const;
177 std::vector<Real> spreadVolInterpolation(const Date& atmOptionDate,
178 const Period& atmSwapTenor) const;
179 private:
180 Size requiredNumberOfStrikes() const override { return 1; }
185 mutable std::vector< std::vector<ext::shared_ptr<SmileSection> > >
187 std::vector<std::vector<Handle<Quote> > > parametersGuessQuotes_;
189 std::vector<bool> isParameterFixed_;
191 const ext::shared_ptr<EndCriteria> endCriteria_;
193 const ext::shared_ptr<OptimizationMethod> optMethod_;
195 const bool useMaxError_;
197 const bool backwardFlat_;
200
201 class PrivateObserver : public Observer {
202 public:
204 : v_(v) {}
205 void update() override {
206 v_->setParameterGuess();
207 v_->update();
208 }
209
210 private:
212 };
213
214 ext::shared_ptr<PrivateObserver> privateObserver_;
215
216 };
217
218 //=======================================================================//
219 // XabrSwaptionVolatilityCube //
220 //=======================================================================//
221
222 template <class Model>
224 const Handle<SwaptionVolatilityStructure>& atmVolStructure,
225 const std::vector<Period>& optionTenors,
226 const std::vector<Period>& swapTenors,
227 const std::vector<Spread>& strikeSpreads,
228 const std::vector<std::vector<Handle<Quote> > >& volSpreads,
229 const ext::shared_ptr<SwapIndex>& swapIndexBase,
230 const ext::shared_ptr<SwapIndex>& shortSwapIndexBase,
231 bool vegaWeightedSmileFit,
232 std::vector<std::vector<Handle<Quote> > > parametersGuess,
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)
243 : SwaptionVolatilityCube(atmVolStructure,
244 optionTenors,
245 swapTenors,
246 strikeSpreads,
247 volSpreads,
248 swapIndexBase,
249 shortSwapIndexBase,
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()) {
256
257 if (maxErrorTolerance != Null<Rate>()) {
258 maxErrorTolerance_ = maxErrorTolerance;
259 } else{
262 }
263 if (errorAccept != Null<Rate>()) {
264 errorAccept_ = errorAccept;
265 } else{
267 }
268
269 privateObserver_ = ext::make_shared<PrivateObserver>(this);
272 }
273
275 {
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]);
280 }
281
282 template<class Model> void XabrSwaptionVolatilityCube<Model>::setParameterGuess() const {
283
284 //! set parametersGuess_ by parametersGuessQuotes_
285 parametersGuess_ = Cube(optionDates_, swapTenors_,
286 optionTimes_, swapLengths_, 4,
287 true, backwardFlat_);
288 Size i;
289 for (i=0; i<4; i++)
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());
294 }
295 parametersGuess_.updateInterpolators();
296
297 }
298
300
302
303 //! set marketVolCube_ by volSpreads_ quotes
304 marketVolCube_ = Cube(optionDates_, swapTenors_,
305 optionTimes_, swapLengths_, nStrikes_);
306 Rate atmForward;
307 Volatility atmVol, vol;
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],
312 atmForward);
313 for (Size i=0; i<nStrikes_; ++i) {
314 vol = atmVol + volSpreads_[j*nSwapTenors_+k][i]->value();
315 marketVolCube_.setElement(i, j, k, vol);
316 }
317 }
318 }
319 marketVolCube_.updateInterpolators();
320
321 sparseParameters_ = sabrCalibration(marketVolCube_);
322 //parametersGuess_ = sparseParameters_;
323 sparseParameters_.updateInterpolators();
324 //parametersGuess_.updateInterpolators();
325 volCubeAtmCalibrated_= marketVolCube_;
326
327 if(isAtmCalibrated_){
328 fillVolatilityCube();
329 denseParameters_ = sabrCalibration(volCubeAtmCalibrated_);
330 denseParameters_.updateInterpolators();
331 }
332 }
333
335 volCubeAtmCalibrated_ = marketVolCube_;
336 if(isAtmCalibrated_){
337 fillVolatilityCube();
338 denseParameters_ = sabrCalibration(volCubeAtmCalibrated_);
339 denseParameters_.updateInterpolators();
340 }
341 notifyObservers();
342 }
343
344 template <class Model>
347
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.);
353 Matrix betas(alphas);
354 Matrix nus(alphas);
355 Matrix rhos(alphas);
356 Matrix forwards(alphas);
357 Matrix errors(alphas);
358 Matrix maxErrors(alphas);
359 Matrix endCriteria(alphas);
360
361 const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();
362
363 std::vector<Real> strikes(strikeSpreads_.size());
364 std::vector<Real> volatilities(strikeSpreads_.size());
365
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]);
370 strikes.clear();
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]);
377 }
378 }
379
380 const std::vector<Real>& guess =
381 parametersGuess_(optionTimes[j], swapLengths[k]);
382
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,
388 guess[0], guess[1],
389 guess[2], guess[3],
390 isParameterFixed_[0],
391 isParameterFixed_[1],
392 isParameterFixed_[2],
393 isParameterFixed_[3],
394 vegaWeightedSmileFit_,
395 endCriteria_,
396 optMethod_,
397 errorAccept_,
398 useMaxError_,
399 maxGuesses_,
400 shiftTmp,
401 volatilityType_));
402 sabrInterpolation->update();
403
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();
414
415 QL_ENSURE(endCriteria[j][k] != Integer(EndCriteria::MaxIterations),
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"
426 );
427
428 QL_ENSURE((useMaxError_ ? maxError : rmsError) < maxErrorTolerance_,
429 "global swaptions calibration failed: "
430 "error tolerance exceeded: "
431 << "\n"
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");
442 }
443 }
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);
455
456 return sabrParametersCube;
457
458 }
459
461 const Cube& marketVolCube,
462 Cube& parametersCube,
463 const Period& swapTenor) const {
464
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();
469
470 Size k = std::find(swapTenors.begin(), swapTenors.end(),
471 swapTenor) - swapTenors.begin();
472 QL_REQUIRE(k != swapTenors.size(), "swap tenor not found");
473
474 std::vector<Real> calibrationResult(8,0.);
475 const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();
476
477 std::vector<Real> strikes(strikeSpreads_.size());
478 std::vector<Real> volatilities(strikeSpreads_.size());
479
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]);
483 strikes.clear();
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]);
490 }
491 }
492
493 const std::vector<Real>& guess =
494 parametersGuess_(optionTimes[j], swapLengths[k]);
495
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,
501 guess[0], guess[1],
502 guess[2], guess[3],
503 isParameterFixed_[0],
504 isParameterFixed_[1],
505 isParameterFixed_[2],
506 isParameterFixed_[3],
507 vegaWeightedSmileFit_,
508 endCriteria_,
509 optMethod_,
510 errorAccept_,
511 useMaxError_,
512 maxGuesses_,
513 shiftTmp));
514
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();
525
526 QL_ENSURE(calibrationResult[7] != Integer(EndCriteria::MaxIterations),
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]
538 );
539
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])
552 );
553
554 parametersCube.setPoint(optionDates[j], swapTenors[k],
555 optionTimes[j], swapLengths[k],
556 calibrationResult);
557 parametersCube.updateInterpolators();
558 }
559
560 }
561
562 template<class Model> void XabrSwaptionVolatilityCube<Model>::fillVolatilityCube() const {
563
564 const ext::shared_ptr<SwaptionVolatilityDiscrete> atmVolStructure =
565 ext::dynamic_pointer_cast<SwaptionVolatilityDiscrete>(*atmVol_);
566
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());
574
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());
582
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());
590
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());
598
599 createSparseSmiles();
600
601 for (Size j=0; j<atmOptionTimes.size(); j++) {
602
603 for (Size k=0; k<atmSwapLengths.size(); k++) {
604 bool expandOptionTimes =
605 !(std::binary_search(optionTimes.begin(),
606 optionTimes.end(),
607 atmOptionTimes[j]));
608 bool expandSwapLengths =
609 !(std::binary_search(swapLengths.begin(),
610 swapLengths.end(),
611 atmSwapLengths[k]));
612 if(expandOptionTimes || expandSwapLengths){
613 Rate atmForward = atmStrike(atmOptionDates[j],
614 atmSwapTenors[k]);
615 Volatility atmVol = atmVol_->volatility(
616 atmOptionDates[j], atmSwapTenors[k], atmForward);
617 std::vector<Real> spreadVols =
618 spreadVolInterpolation(atmOptionDates[j],
619 atmSwapTenors[k]);
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],
627 volAtmCalibrated);
628 }
629 }
630 }
631 volCubeAtmCalibrated_.updateInterpolators();
632 }
633
634
635 template<class Model> void XabrSwaptionVolatilityCube<Model>::createSparseSmiles() const {
636
637 std::vector<Time> optionTimes(sparseParameters_.optionTimes());
638 std::vector<Time> swapLengths(sparseParameters_.swapLengths());
639 sparseSmiles_.clear();
640
641 for (Real& optionTime : optionTimes) {
642 std::vector<ext::shared_ptr<SmileSection> > tmp;
643 Size n = swapLengths.size();
644 tmp.reserve(n);
645 for (Size k=0; k<n; ++k) {
646 tmp.push_back(smileSection(optionTime, swapLengths[k], sparseParameters_));
647 }
648 sparseSmiles_.push_back(tmp);
649 }
650 }
651
652
653 template<class Model> std::vector<Real> XabrSwaptionVolatilityCube<Model>::spreadVolInterpolation(
654 const Date& atmOptionDate, const Period& atmSwapTenor) const {
655
656 Time atmOptionTime = timeFromReference(atmOptionDate);
657 Time atmTimeLength = swapLength(atmSwapTenor);
658
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();
665
666 std::vector<Real>::const_iterator optionTimesPreviousNode,
667 swapLengthsPreviousNode;
668
669 optionTimesPreviousNode = std::lower_bound(optionTimes.begin(),
670 optionTimes.end(),
671 atmOptionTime);
672 Size optionTimesPreviousIndex =
673 optionTimesPreviousNode - optionTimes.begin();
674 if (optionTimesPreviousIndex >0)
675 optionTimesPreviousIndex --;
676
677 swapLengthsPreviousNode = std::lower_bound(swapLengths.begin(),
678 swapLengths.end(),
679 atmTimeLength);
680 Size swapLengthsPreviousIndex = swapLengthsPreviousNode - swapLengths.begin();
681 if (swapLengthsPreviousIndex >0)
682 swapLengthsPreviousIndex --;
683
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;
687
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]);
700
701 smiles.push_back(smilesOnPreviousExpiry);
702 smiles.push_back(smilesOnNextExpiry);
703
704 std::vector<Real> optionsNodes(2);
705 optionsNodes[0] = optionTimes[optionTimesPreviousIndex];
706 optionsNodes[1] = optionTimes[optionTimesPreviousIndex+1];
707
708 std::vector<Date> optionsDateNodes(2);
709 optionsDateNodes[0] = optionDates[optionTimesPreviousIndex];
710 optionsDateNodes[1] = optionDates[optionTimesPreviousIndex+1];
711
712 std::vector<Real> swapLengthsNodes(2);
713 swapLengthsNodes[0] = swapLengths[swapLengthsPreviousIndex];
714 swapLengthsNodes[1] = swapLengths[swapLengthsPreviousIndex+1];
715
716 std::vector<Period> swapTenorNodes(2);
717 swapTenorNodes[0] = swapTenors[swapLengthsPreviousIndex];
718 swapTenorNodes[1] = swapTenors[swapLengthsPreviousIndex+1];
719
720 Rate atmForward = atmStrike(atmOptionDate, atmSwapTenor);
721 Real shift = atmVol_->shift(atmOptionTime, atmTimeLength);
722
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],
729 swapTenorNodes[j]);
730 atmShifts[i][j] = atmVol_->shift(optionsNodes[i], swapLengthsNodes[j]);
731 // atmVols[i][j] = smiles[i][j]->volatility(atmForwards[i][j]);
732 atmVols[i][j] = atmVol_->volatility(
733 optionsDateNodes[i], swapTenorNodes[j], atmForwards[i][j]);
734 /* With the old implementation the interpolated spreads on ATM
735 volatilities were null even if the spreads on ATM volatilities to be
736 interpolated were non-zero. The new implementation removes
737 this behaviour, but introduces a small ERROR in the cube:
738 even if no spreads are applied on any cube ATM volatility corresponding
739 to quoted smile sections (that is ATM volatilities in sparse cube), the
740 cube ATM volatilities corresponding to not quoted smile sections (that
741 is ATM volatilities in dense cube) are no more exactly the quoted values,
742 but that ones PLUS the linear interpolation of the fit errors on the ATM
743 volatilities in sparse cube whose spreads are used in the calculation.
744 A similar imprecision is introduced to the volatilities in dense cube
745 whith moneyness near to 1.
746 (See below how spreadVols are calculated).
747 The extent of this error depends on the quality of the fit: in case of
748 good fits it is negligibile.
749 */
750 }
751 }
752
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);
756
757 Matrix strikes(2,2,0.);
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];
762 spreadVols[i][j] =
763 smiles[i][j]->volatility(strikes[i][j]) - atmVols[i][j];
764 }
765 }
766 Cube localInterpolator(optionsDateNodes, swapTenorNodes,
767 optionsNodes, swapLengthsNodes, 1);
768 localInterpolator.setLayer(0, spreadVols);
769 localInterpolator.updateInterpolators();
770
771 result.push_back(localInterpolator(atmOptionTime, atmTimeLength)[0]);
772 }
773 return result;
774 }
775
776 template<class Model> ext::shared_ptr<SmileSection>
778 const Cube& sabrParametersCube) const {
779
780 calculate();
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_));
786 }
787
788 template<class Model> ext::shared_ptr<SmileSection>
790 Time swapLength) const {
791 if (isAtmCalibrated_)
792 return smileSection(optionTime, swapLength, denseParameters_);
793 else
794 return smileSection(optionTime, swapLength, sparseParameters_);
795 }
796
798 calculate();
799 return sparseParameters_.browse();
800 }
801
803 calculate();
804 return denseParameters_.browse();
805 }
806
808 calculate();
809 return marketVolCube_.browse();
810 }
811
813 calculate();
814 return volCubeAtmCalibrated_.browse();
815 }
816
818 const Period& swapTenor) {
819
820 std::vector<Real> betaVector(nOptionTenors_, beta);
821 recalibration(betaVector,swapTenor);
822
823 }
824
825 template<class Model> void XabrSwaptionVolatilityCube<Model>::recalibration(const std::vector<Real> &beta,
826 const Period& swapTenor) {
827
828 QL_REQUIRE(beta.size() == nOptionTenors_,
829 "beta size ("
830 << beta.size()
831 << ") must be equal to number of option tenors ("
832 << nOptionTenors_ << ")");
833
834 const std::vector<Period> &swapTenors = marketVolCube_.swapTenors();
835 Size k = std::find(swapTenors.begin(), swapTenors.end(), swapTenor) -
836 swapTenors.begin();
837
838 QL_REQUIRE(k != swapTenors.size(), "swap tenor (" << swapTenor
839 << ") not found");
840
841 for (Size i = 0; i < nOptionTenors_; ++i) {
842 parametersGuess_.setElement(1, i, k, beta[i]);
843 }
844
845 parametersGuess_.updateInterpolators();
846 sabrCalibrationSection(marketVolCube_, sparseParameters_, swapTenor);
847
848 volCubeAtmCalibrated_ = marketVolCube_;
849 if (isAtmCalibrated_) {
850 fillVolatilityCube();
851 sabrCalibrationSection(volCubeAtmCalibrated_, denseParameters_,
852 swapTenor);
853 }
854 notifyObservers();
855
856 }
857
858 template<class Model> void XabrSwaptionVolatilityCube<Model>::recalibration(const std::vector<Period> &swapLengths,
859 const std::vector<Real> &beta,
860 const Period &swapTenor) {
861
862 QL_REQUIRE(beta.size() == swapLengths.size(),
863 "beta size ("
864 << beta.size()
865 << ") must be equal to number of swap lengths ("
866 << swapLengths.size() << ")");
867
868 std::vector<Time> betaTimes;
869 for (Size i = 0; i < beta.size(); i++)
870 betaTimes.push_back(
871 timeFromReference(optionDateFromTenor(swapLengths[i])));
872
873 LinearInterpolation betaInterpolation(betaTimes.begin(),
874 betaTimes.end(), beta.begin());
875
876 std::vector<Real> cubeBeta;
877 for (Size i = 0; i < optionTimes().size(); i++) {
878 Real t = optionTimes()[i];
879 // flat extrapolation ensures admissable values
880 if (t < betaTimes.front())
881 t = betaTimes.front();
882 if (t > betaTimes.back())
883 t = betaTimes.back();
884 cubeBeta.push_back(betaInterpolation(t));
885 }
886
887 recalibration(cubeBeta, swapTenor);
888
889 }
890
891 //======================================================================//
892 // XabrSwaptionVolatilityCube::Cube //
893 //======================================================================//
894
895
896 template<class Model> XabrSwaptionVolatilityCube<Model>::Cube::Cube(const std::vector<Date>& optionDates,
897 const std::vector<Period>& swapTenors,
898 const std::vector<Time>& optionTimes,
899 const std::vector<Time>& swapLengths,
900 Size nLayers,
901 bool extrapolation,
902 bool backwardFlat)
903 : optionTimes_(optionTimes), swapLengths_(swapLengths),
904 optionDates_(optionDates), swapTenors_(swapTenors),
905 nLayers_(nLayers), extrapolation_(extrapolation),
906 backwardFlat_(backwardFlat) {
907
908 QL_REQUIRE(optionTimes.size()>1,"Cube::Cube(...): optionTimes.size()<2");
909 QL_REQUIRE(swapLengths.size()>1,"Cube::Cube(...): swapLengths.size()<2");
910
911 QL_REQUIRE(optionTimes.size()==optionDates.size(),
912 "Cube::Cube(...): optionTimes/optionDates mismatch");
913 QL_REQUIRE(swapTenors.size()==swapLengths.size(),
914 "Cube::Cube(...): swapTenors/swapLengths mismatch");
915
916 std::vector<Matrix> points(nLayers_, Matrix(optionTimes_.size(),
917 swapLengths_.size(), 0.0));
918 for (Size k=0;k<nLayers_;k++) {
919 ext::shared_ptr<Interpolation2D> interpolation;
920 transposedPoints_.push_back(transpose(points[k]));
921 if (k <= 4 && backwardFlat_)
922 interpolation =
923 ext::make_shared<BackwardflatLinearInterpolation>(
924 optionTimes_.begin(), optionTimes_.end(),
925 swapLengths_.begin(), swapLengths_.end(),
927 else
928 interpolation =
929 ext::make_shared<BilinearInterpolation>(
930 optionTimes_.begin(), optionTimes_.end(),
931 swapLengths_.begin(), swapLengths_.end(),
933 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
934 new FlatExtrapolator2D(interpolation)));
935 interpolators_[k]->enableExtrapolation();
936 }
938 }
939
943 nLayers_(o.nLayers_), transposedPoints_(o.transposedPoints_),
944 extrapolation_(o.extrapolation_), backwardFlat_(o.backwardFlat_) {
945 for (Size k=0; k<nLayers_; ++k) {
946 ext::shared_ptr<Interpolation2D> interpolation;
947 if (k <= 4 && backwardFlat_)
948 interpolation =
949 ext::make_shared<BackwardflatLinearInterpolation>(
950 optionTimes_.begin(), optionTimes_.end(),
951 swapLengths_.begin(), swapLengths_.end(),
953 else
954 interpolation =
955 ext::make_shared<BilinearInterpolation>(
956 optionTimes_.begin(), optionTimes_.end(),
957 swapLengths_.begin(), swapLengths_.end(),
959 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
960 new FlatExtrapolator2D(interpolation)));
961 interpolators_[k]->enableExtrapolation();
962 }
964 }
965
966 template<class Model> typename XabrSwaptionVolatilityCube<Model>::Cube&
972 nLayers_ = o.nLayers_;
973 extrapolation_ = o.extrapolation_;
975 transposedPoints_ = o.transposedPoints_;
976 for(Size k=0;k<nLayers_;k++){
977 ext::shared_ptr<Interpolation2D> interpolation;
978 if (k <= 4 && backwardFlat_)
979 interpolation =
980 ext::make_shared<BackwardflatLinearInterpolation>(
981 optionTimes_.begin(), optionTimes_.end(),
982 swapLengths_.begin(), swapLengths_.end(),
983 transposedPoints_[k]);
984 else
985 interpolation =
986 ext::make_shared<BilinearInterpolation>(
987 optionTimes_.begin(), optionTimes_.end(),
988 swapLengths_.begin(), swapLengths_.end(),
989 transposedPoints_[k]);
990 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
991 new FlatExtrapolator2D(interpolation)));
992 interpolators_[k]->enableExtrapolation();
993 }
994 setPoints(o.points_);
995 return *this;
996 }
997
998 template<class Model> void XabrSwaptionVolatilityCube<Model>::Cube::setElement(Size IndexOfLayer,
999 Size IndexOfRow,
1000 Size IndexOfColumn,
1001 Real x) {
1002 QL_REQUIRE(IndexOfLayer<nLayers_,
1003 "Cube::setElement: incompatible IndexOfLayer ");
1004 QL_REQUIRE(IndexOfRow<optionTimes_.size(),
1005 "Cube::setElement: incompatible IndexOfRow");
1006 QL_REQUIRE(IndexOfColumn<swapLengths_.size(),
1007 "Cube::setElement: incompatible IndexOfColumn");
1008 points_[IndexOfLayer][IndexOfRow][IndexOfColumn] = x;
1009 }
1010
1012 const std::vector<Matrix>& x) {
1013 QL_REQUIRE(x.size()==nLayers_,
1014 "Cube::setPoints: incompatible number of layers ");
1015 QL_REQUIRE(x[0].rows()==optionTimes_.size(),
1016 "Cube::setPoints: incompatible size 1");
1017 QL_REQUIRE(x[0].columns()==swapLengths_.size(),
1018 "Cube::setPoints: incompatible size 2");
1019
1020 points_ = x;
1021 }
1022
1024 const Matrix& x) {
1025 QL_REQUIRE(i<nLayers_,
1026 "Cube::setLayer: incompatible number of layer ");
1027 QL_REQUIRE(x.rows()==optionTimes_.size(),
1028 "Cube::setLayer: incompatible size 1");
1029 QL_REQUIRE(x.columns()==swapLengths_.size(),
1030 "Cube::setLayer: incompatible size 2");
1031
1032 points_[i] = x;
1033 }
1034
1035 template <class Model>
1037 const Period& swapTenor,
1038 Time optionTime,
1040 const std::vector<Real>& point)
1041 {
1042 const bool expandOptionTimes =
1043 !(std::binary_search(optionTimes_.begin(),optionTimes_.end(),optionTime));
1044 const bool expandSwapLengths =
1045 !(std::binary_search(swapLengths_.begin(),swapLengths_.end(),swapLength));
1046
1047 std::vector<Real>::const_iterator optionTimesPreviousNode,
1048 swapLengthsPreviousNode;
1049
1050 optionTimesPreviousNode =
1051 std::lower_bound(optionTimes_.begin(),optionTimes_.end(),optionTime);
1052 Size optionTimesIndex = optionTimesPreviousNode - optionTimes_.begin();
1053
1054 swapLengthsPreviousNode =
1055 std::lower_bound(swapLengths_.begin(),swapLengths_.end(),swapLength);
1056 Size swapLengthsIndex = swapLengthsPreviousNode - swapLengths_.begin();
1057
1058 if (expandOptionTimes || expandSwapLengths)
1059 expandLayers(optionTimesIndex, expandOptionTimes,
1060 swapLengthsIndex, expandSwapLengths);
1061
1062 for (Size k=0; k<nLayers_; ++k)
1063 points_[k][optionTimesIndex][swapLengthsIndex] = point[k];
1064
1065 optionTimes_[optionTimesIndex] = optionTime;
1066 swapLengths_[swapLengthsIndex] = swapLength;
1067 optionDates_[optionTimesIndex] = optionDate;
1068 swapTenors_[swapLengthsIndex] = swapTenor;
1069 }
1070
1071 template<class Model> void XabrSwaptionVolatilityCube<Model>::Cube::expandLayers(Size i, bool expandOptionTimes,
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");
1075
1076 if (expandOptionTimes) {
1077 optionTimes_.insert(optionTimes_.begin()+i,0.);
1078 optionDates_.insert(optionDates_.begin()+i, Date());
1079 }
1080 if (expandSwapLengths) {
1081 swapLengths_.insert(swapLengths_.begin()+j,0.);
1082 swapTenors_.insert(swapTenors_.begin()+j, Period());
1083 }
1084
1085 std::vector<Matrix> newPoints(nLayers_,Matrix(optionTimes_.size(),
1086 swapLengths_.size(), 0.));
1087
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];
1096 }
1097 }
1098 }
1099 setPoints(newPoints);
1100 }
1101
1102 template<class Model> const std::vector<Matrix>&
1104 return points_;
1105 }
1106
1107 template<class Model> std::vector<Real> XabrSwaptionVolatilityCube<Model>::Cube::operator()(
1108 const Time optionTime, const Time swapLength) const {
1109 std::vector<Real> result;
1110 for (Size k=0; k<nLayers_; ++k)
1111 result.push_back((*interpolators_[k])(optionTime, swapLength));
1112 return result;
1113 }
1114
1115 template<class Model> const std::vector<Time>&
1117 return optionTimes_;
1118 }
1119
1120 template<class Model> const std::vector<Time>&
1122 return swapLengths_;
1123 }
1124
1126 for (Size k = 0; k < nLayers_; ++k) {
1127 transposedPoints_[k] = transpose(points_[k]);
1128 ext::shared_ptr<Interpolation2D> interpolation;
1129 if (k <= 4 && backwardFlat_)
1130 interpolation =
1131 ext::make_shared<BackwardflatLinearInterpolation>(
1132 optionTimes_.begin(), optionTimes_.end(),
1133 swapLengths_.begin(), swapLengths_.end(),
1134 transposedPoints_[k]);
1135 else
1136 interpolation =
1137 ext::make_shared<BilinearInterpolation>(
1138 optionTimes_.begin(), optionTimes_.end(),
1139 swapLengths_.begin(), swapLengths_.end(),
1140 transposedPoints_[k]);
1141 interpolators_[k] = ext::shared_ptr<Interpolation2D>(
1142 new FlatExtrapolator2D(interpolation));
1143 interpolators_[k]->enableExtrapolation();
1144 }
1145 }
1146
1148 Matrix result(swapLengths_.size()*optionTimes_.size(), nLayers_+2, 0.0);
1149 for (Size i=0; i<swapLengths_.size(); ++i) {
1150 for (Size j=0; j<optionTimes_.size(); ++j) {
1151 result[i*optionTimes_.size()+j][0] = swapLengths_[i];
1152 result[i*optionTimes_.size()+j][1] = optionTimes_[j];
1153 for (Size k=0; k<nLayers_; ++k)
1154 result[i*optionTimes_.size()+j][2+k] = points_[k][j][i];
1155 }
1156 }
1157 return result;
1158 }
1159
1160 //======================================================================//
1161 // SabrSwaptionVolatilityCube //
1162 //======================================================================//
1163
1164 //! Swaption Volatility Cube SABR
1165 /*! This struct defines the types used by SABR Volatility cubes
1166 for interpolation (SABRInterpolation) and for modeling the
1167 smile (SabrSmileSection).
1168 */
1172 };
1173
1174
1175 //! SABR volatility cube for swaptions
1177
1178}
1179
1180#endif
backflat interpolation in first component, linear in second component
bilinear interpolation between discrete points
Concrete date class.
Definition: date.hpp:125
Shared handle to an observable.
Definition: handle.hpp:41
Linear interpolation between discrete points
Matrix used in linear algebra.
Definition: matrix.hpp:41
Size rows() const
Definition: matrix.hpp:504
Size columns() const
Definition: matrix.hpp:508
template class providing a null value for a given type.
Definition: null.hpp:76
Object that gets notified when a given observable changes.
Definition: observable.hpp:116
SABR smile interpolation between discrete volatility points.
swaption-volatility cube
void performCalculations() const override
const std::vector< std::vector< Handle< Quote > > > & volSpreads() const
ext::shared_ptr< SwapIndex > shortSwapIndexBase() const
ext::shared_ptr< SwapIndex > swapIndexBase() const
const std::vector< Spread > & strikeSpreads() const
const std::vector< Time > & swapLengths() const
const std::vector< Period > & swapTenors() const
const std::vector< Period > & optionTenors() const
Time swapLength(const Period &swapTenor) const
implements the conversion between swap tenor and swap (time) length
void expandLayers(Size i, bool expandOptionTimes, Size j, bool expandSwapLengths)
void setPoint(const Date &optionDate, const Period &swapTenor, Time optionTime, Time swapLength, const std::vector< Real > &point)
std::vector< Real > operator()(Time optionTime, Time swapLengths) const
const std::vector< Period > & swapTenors() const
void setElement(Size IndexOfLayer, Size IndexOfRow, Size IndexOfColumn, Real x)
std::vector< ext::shared_ptr< Interpolation2D > > interpolators_
const std::vector< Date > & optionDates() const
std::vector< Real > spreadVolInterpolation(const Date &atmOptionDate, const Period &atmSwapTenor) const
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_
ext::shared_ptr< SmileSection > smileSectionImpl(Time optionTime, Time swapLength) const override
const ext::shared_ptr< EndCriteria > endCriteria_
std::vector< std::vector< ext::shared_ptr< SmileSection > > > sparseSmiles_
ext::shared_ptr< SmileSection > smileSection(Time optionTime, Time swapLength, const Cube &sabrParametersCube) const
ext::shared_ptr< PrivateObserver > privateObserver_
void sabrCalibrationSection(const Cube &marketVolCube, Cube &parametersCube, const Period &swapTenor) const
void recalibration(Real beta, const Period &swapTenor)
Cube sabrCalibration(const Cube &marketVolCube) const
const std::vector< Real > & points_
const DefaultType & t
#define QL_ENSURE(condition, message)
throw an error if the given post-condition is not verified
Definition: errors.hpp:130
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
abstract base classes for 2-D flat extrapolations
detail::percent_holder rate(Rate)
output rates and spreads as percentages
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real Volatility
volatility
Definition: types.hpp:78
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
linear interpolation between discrete points
matrix used in linear algebra.
Definition: any.hpp:35
XabrSwaptionVolatilityCube< SwaptionVolCubeSabrModel > SabrSwaptionVolatilityCube
SABR volatility cube for swaptions.
Matrix transpose(const Matrix &m)
Definition: matrix.hpp:700
STL namespace.
ext::shared_ptr< BlackVolTermStructure > v
purely virtual base class for market observables
Real beta
Definition: sabr.cpp:200
SABR interpolation interpolation between discrete points.
sabr smile section class
#define SWAPTIONVOLCUBE_TOL
#define SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL
Swaption volatility cube.