QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
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*nSwapTenors_+k][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*nSwapTenors_+k][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 betaTimes.reserve(beta.size());
870 for (Size i = 0; i < beta.size(); i++)
871 betaTimes.push_back(
872 timeFromReference(optionDateFromTenor(swapLengths[i])));
873
874 LinearInterpolation betaInterpolation(betaTimes.begin(),
875 betaTimes.end(), beta.begin());
876
877 std::vector<Real> cubeBeta;
878 for (Size i = 0; i < optionTimes().size(); i++) {
879 Real t = optionTimes()[i];
880 // flat extrapolation ensures admissable values
881 if (t < betaTimes.front())
882 t = betaTimes.front();
883 if (t > betaTimes.back())
884 t = betaTimes.back();
885 cubeBeta.push_back(betaInterpolation(t));
886 }
887
888 recalibration(cubeBeta, swapTenor);
889
890 }
891
892 //======================================================================//
893 // XabrSwaptionVolatilityCube::Cube //
894 //======================================================================//
895
896
897 template<class Model> XabrSwaptionVolatilityCube<Model>::Cube::Cube(const std::vector<Date>& optionDates,
898 const std::vector<Period>& swapTenors,
899 const std::vector<Time>& optionTimes,
900 const std::vector<Time>& swapLengths,
901 Size nLayers,
902 bool extrapolation,
903 bool backwardFlat)
904 : optionTimes_(optionTimes), swapLengths_(swapLengths),
905 optionDates_(optionDates), swapTenors_(swapTenors),
906 nLayers_(nLayers), extrapolation_(extrapolation),
907 backwardFlat_(backwardFlat) {
908
909 QL_REQUIRE(optionTimes.size()>1,"Cube::Cube(...): optionTimes.size()<2");
910 QL_REQUIRE(swapLengths.size()>1,"Cube::Cube(...): swapLengths.size()<2");
911
912 QL_REQUIRE(optionTimes.size()==optionDates.size(),
913 "Cube::Cube(...): optionTimes/optionDates mismatch");
914 QL_REQUIRE(swapTenors.size()==swapLengths.size(),
915 "Cube::Cube(...): swapTenors/swapLengths mismatch");
916
917 std::vector<Matrix> points(nLayers_, Matrix(optionTimes_.size(),
918 swapLengths_.size(), 0.0));
919 for (Size k=0;k<nLayers_;k++) {
920 ext::shared_ptr<Interpolation2D> interpolation;
921 transposedPoints_.push_back(transpose(points[k]));
922 if (k <= 4 && backwardFlat_)
923 interpolation =
924 ext::make_shared<BackwardflatLinearInterpolation>(
925 optionTimes_.begin(), optionTimes_.end(),
926 swapLengths_.begin(), swapLengths_.end(),
928 else
929 interpolation =
930 ext::make_shared<BilinearInterpolation>(
931 optionTimes_.begin(), optionTimes_.end(),
932 swapLengths_.begin(), swapLengths_.end(),
934 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
935 new FlatExtrapolator2D(interpolation)));
936 interpolators_[k]->enableExtrapolation();
937 }
939 }
940
944 nLayers_(o.nLayers_), transposedPoints_(o.transposedPoints_),
945 extrapolation_(o.extrapolation_), backwardFlat_(o.backwardFlat_) {
946 for (Size k=0; k<nLayers_; ++k) {
947 ext::shared_ptr<Interpolation2D> interpolation;
948 if (k <= 4 && backwardFlat_)
949 interpolation =
950 ext::make_shared<BackwardflatLinearInterpolation>(
951 optionTimes_.begin(), optionTimes_.end(),
952 swapLengths_.begin(), swapLengths_.end(),
954 else
955 interpolation =
956 ext::make_shared<BilinearInterpolation>(
957 optionTimes_.begin(), optionTimes_.end(),
958 swapLengths_.begin(), swapLengths_.end(),
960 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
961 new FlatExtrapolator2D(interpolation)));
962 interpolators_[k]->enableExtrapolation();
963 }
965 }
966
967 template<class Model> typename XabrSwaptionVolatilityCube<Model>::Cube&
973 nLayers_ = o.nLayers_;
974 extrapolation_ = o.extrapolation_;
976 transposedPoints_ = o.transposedPoints_;
977 for(Size k=0;k<nLayers_;k++){
978 ext::shared_ptr<Interpolation2D> interpolation;
979 if (k <= 4 && backwardFlat_)
980 interpolation =
981 ext::make_shared<BackwardflatLinearInterpolation>(
982 optionTimes_.begin(), optionTimes_.end(),
983 swapLengths_.begin(), swapLengths_.end(),
984 transposedPoints_[k]);
985 else
986 interpolation =
987 ext::make_shared<BilinearInterpolation>(
988 optionTimes_.begin(), optionTimes_.end(),
989 swapLengths_.begin(), swapLengths_.end(),
990 transposedPoints_[k]);
991 interpolators_.push_back(ext::shared_ptr<Interpolation2D>(
992 new FlatExtrapolator2D(interpolation)));
993 interpolators_[k]->enableExtrapolation();
994 }
995 setPoints(o.points_);
996 return *this;
997 }
998
999 template<class Model> void XabrSwaptionVolatilityCube<Model>::Cube::setElement(Size IndexOfLayer,
1000 Size IndexOfRow,
1001 Size IndexOfColumn,
1002 Real x) {
1003 QL_REQUIRE(IndexOfLayer<nLayers_,
1004 "Cube::setElement: incompatible IndexOfLayer ");
1005 QL_REQUIRE(IndexOfRow<optionTimes_.size(),
1006 "Cube::setElement: incompatible IndexOfRow");
1007 QL_REQUIRE(IndexOfColumn<swapLengths_.size(),
1008 "Cube::setElement: incompatible IndexOfColumn");
1009 points_[IndexOfLayer][IndexOfRow][IndexOfColumn] = x;
1010 }
1011
1013 const std::vector<Matrix>& x) {
1014 QL_REQUIRE(x.size()==nLayers_,
1015 "Cube::setPoints: incompatible number of layers ");
1016 QL_REQUIRE(x[0].rows()==optionTimes_.size(),
1017 "Cube::setPoints: incompatible size 1");
1018 QL_REQUIRE(x[0].columns()==swapLengths_.size(),
1019 "Cube::setPoints: incompatible size 2");
1020
1021 points_ = x;
1022 }
1023
1025 const Matrix& x) {
1026 QL_REQUIRE(i<nLayers_,
1027 "Cube::setLayer: incompatible number of layer ");
1028 QL_REQUIRE(x.rows()==optionTimes_.size(),
1029 "Cube::setLayer: incompatible size 1");
1030 QL_REQUIRE(x.columns()==swapLengths_.size(),
1031 "Cube::setLayer: incompatible size 2");
1032
1033 points_[i] = x;
1034 }
1035
1036 template <class Model>
1038 const Period& swapTenor,
1039 Time optionTime,
1041 const std::vector<Real>& point)
1042 {
1043 const bool expandOptionTimes =
1044 !(std::binary_search(optionTimes_.begin(),optionTimes_.end(),optionTime));
1045 const bool expandSwapLengths =
1046 !(std::binary_search(swapLengths_.begin(),swapLengths_.end(),swapLength));
1047
1048 std::vector<Real>::const_iterator optionTimesPreviousNode,
1049 swapLengthsPreviousNode;
1050
1051 optionTimesPreviousNode =
1052 std::lower_bound(optionTimes_.begin(),optionTimes_.end(),optionTime);
1053 Size optionTimesIndex = optionTimesPreviousNode - optionTimes_.begin();
1054
1055 swapLengthsPreviousNode =
1056 std::lower_bound(swapLengths_.begin(),swapLengths_.end(),swapLength);
1057 Size swapLengthsIndex = swapLengthsPreviousNode - swapLengths_.begin();
1058
1059 if (expandOptionTimes || expandSwapLengths)
1060 expandLayers(optionTimesIndex, expandOptionTimes,
1061 swapLengthsIndex, expandSwapLengths);
1062
1063 for (Size k=0; k<nLayers_; ++k)
1064 points_[k][optionTimesIndex][swapLengthsIndex] = point[k];
1065
1066 optionTimes_[optionTimesIndex] = optionTime;
1067 swapLengths_[swapLengthsIndex] = swapLength;
1068 optionDates_[optionTimesIndex] = optionDate;
1069 swapTenors_[swapLengthsIndex] = swapTenor;
1070 }
1071
1072 template<class Model> void XabrSwaptionVolatilityCube<Model>::Cube::expandLayers(Size i, bool expandOptionTimes,
1073 Size j, bool expandSwapLengths) {
1074 QL_REQUIRE(i<=optionTimes_.size(),"Cube::expandLayers: incompatible size 1");
1075 QL_REQUIRE(j<=swapLengths_.size(),"Cube::expandLayers: incompatible size 2");
1076
1077 if (expandOptionTimes) {
1078 optionTimes_.insert(optionTimes_.begin()+i,0.);
1079 optionDates_.insert(optionDates_.begin()+i, Date());
1080 }
1081 if (expandSwapLengths) {
1082 swapLengths_.insert(swapLengths_.begin()+j,0.);
1083 swapTenors_.insert(swapTenors_.begin()+j, Period());
1084 }
1085
1086 std::vector<Matrix> newPoints(nLayers_,Matrix(optionTimes_.size(),
1087 swapLengths_.size(), 0.));
1088
1089 for (Size k=0; k<nLayers_; ++k) {
1090 for (Size u=0; u<points_[k].rows(); ++u) {
1091 Size indexOfRow = u;
1092 if (u>=i && expandOptionTimes) indexOfRow = u+1;
1093 for (Size v=0; v<points_[k].columns(); ++v) {
1094 Size indexOfCol = v;
1095 if (v>=j && expandSwapLengths) indexOfCol = v+1;
1096 newPoints[k][indexOfRow][indexOfCol]=points_[k][u][v];
1097 }
1098 }
1099 }
1100 setPoints(newPoints);
1101 }
1102
1103 template<class Model> const std::vector<Matrix>&
1105 return points_;
1106 }
1107
1108 template<class Model> std::vector<Real> XabrSwaptionVolatilityCube<Model>::Cube::operator()(
1109 const Time optionTime, const Time swapLength) const {
1110 std::vector<Real> result;
1111 result.reserve(nLayers_);
1112 for (Size k=0; k<nLayers_; ++k)
1113 result.push_back((*interpolators_[k])(optionTime, swapLength));
1114 return result;
1115 }
1116
1117 template<class Model> const std::vector<Time>&
1119 return optionTimes_;
1120 }
1121
1122 template<class Model> const std::vector<Time>&
1124 return swapLengths_;
1125 }
1126
1128 for (Size k = 0; k < nLayers_; ++k) {
1129 transposedPoints_[k] = transpose(points_[k]);
1130 ext::shared_ptr<Interpolation2D> interpolation;
1131 if (k <= 4 && backwardFlat_)
1132 interpolation =
1133 ext::make_shared<BackwardflatLinearInterpolation>(
1134 optionTimes_.begin(), optionTimes_.end(),
1135 swapLengths_.begin(), swapLengths_.end(),
1136 transposedPoints_[k]);
1137 else
1138 interpolation =
1139 ext::make_shared<BilinearInterpolation>(
1140 optionTimes_.begin(), optionTimes_.end(),
1141 swapLengths_.begin(), swapLengths_.end(),
1142 transposedPoints_[k]);
1143 interpolators_[k] = ext::shared_ptr<Interpolation2D>(
1144 new FlatExtrapolator2D(interpolation));
1145 interpolators_[k]->enableExtrapolation();
1146 }
1147 }
1148
1150 Matrix result(swapLengths_.size()*optionTimes_.size(), nLayers_+2, 0.0);
1151 for (Size i=0; i<swapLengths_.size(); ++i) {
1152 for (Size j=0; j<optionTimes_.size(); ++j) {
1153 result[i*optionTimes_.size()+j][0] = swapLengths_[i];
1154 result[i*optionTimes_.size()+j][1] = optionTimes_[j];
1155 for (Size k=0; k<nLayers_; ++k)
1156 result[i*optionTimes_.size()+j][2+k] = points_[k][j][i];
1157 }
1158 }
1159 return result;
1160 }
1161
1162 //======================================================================//
1163 // SabrSwaptionVolatilityCube //
1164 //======================================================================//
1165
1166 //! Swaption Volatility Cube SABR
1167 /*! This struct defines the types used by SABR Volatility cubes
1168 for interpolation (SABRInterpolation) and for modeling the
1169 smile (SabrSmileSection).
1170 */
1174 };
1175
1176
1177 //! SABR volatility cube for swaptions
1179
1180}
1181
1182#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:59
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:37
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.