swaptionvolcube1.cpp
来自「有很多的函数库」· C++ 代码 · 共 783 行 · 第 1/3 页
CPP
783 行
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2006 Giorgio Facchinetti
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
#include <ql/termstructures/volatilities/swaptionvolcube1.hpp>
#include <ql/math/interpolations/sabrinterpolation.hpp>
#include <ql/termstructures/volatilities/swaptionvolmatrix.hpp>
#include <ql/math/interpolations/flatextrapolation2d.hpp>
#ifndef SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL
#define SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL 15.0e-4
#endif
#ifndef SWAPTIONVOLCUBE_TOL
#define SWAPTIONVOLCUBE_TOL 100.0e-4
#endif
namespace QuantLib {
//=======================================================================//
// SwaptionVolCube1 //
//=======================================================================//
SwaptionVolCube1::SwaptionVolCube1(
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 boost::shared_ptr<SwapIndex>& swapIndexBase,
bool vegaWeightedSmileFit,
const std::vector<std::vector<Handle<Quote> > >& parametersGuess,
const std::vector<bool>& isParameterFixed,
bool isAtmCalibrated,
const boost::shared_ptr<EndCriteria>& endCriteria,
Real maxErrorTolerance)
: SwaptionVolatilityCube(atmVolStructure, optionTenors, swapTenors,
strikeSpreads, volSpreads, swapIndexBase,
vegaWeightedSmileFit),
parametersGuessQuotes_(parametersGuess),
isParameterFixed_(isParameterFixed), isAtmCalibrated_(isAtmCalibrated),
endCriteria_(endCriteria)
{
if(maxErrorTolerance != Null<Rate>()){
maxErrorTolerance_ = maxErrorTolerance;
} else{
maxErrorTolerance_ = SWAPTIONVOLCUBE_VEGAWEIGHTED_TOL;
if (vegaWeightedSmileFit_) maxErrorTolerance_ = SWAPTIONVOLCUBE_TOL;
}
registerWithParametersGuess();
}
void SwaptionVolCube1::registerWithParametersGuess()
{
for (Size i=0; i<4; i++)
for (Size j=0; j<nOptionTenors_; j++)
for (Size k=0; k<nSwapTenors_; k++)
registerWith(parametersGuessQuotes_[j+k*nOptionTenors_][i]);
}
void SwaptionVolCube1::performCalculations() const{
//! set parametersGuess_ by parametersGuessQuotes_
parametersGuess_ = Cube(optionDates_, swapTenors_,
optionTimes_, swapLengths_, 4);
Size i;
for (i=0; i<4; i++)
for (Size j=0; j<nOptionTenors_ ; j++)
for (Size k=0; k<nSwapTenors_; k++) {
parametersGuess_.setElement(i, j, k,
parametersGuessQuotes_[j+k*nOptionTenors_][i]->value());
}
parametersGuess_.updateInterpolators();
//! set marketVolCube_ by volSpreads_ quotes
marketVolCube_ = Cube(optionDates_, swapTenors_,
optionTimes_, swapLengths_, nStrikes_);
Rate atmForward;
Volatility vol;
for (Size i=0; i<nStrikes_; i++)
for (Size j=0; j<nOptionTenors_; j++)
for (Size k=0; k<nSwapTenors_; k++) {
atmForward = atmStrike(optionDates_[j], swapTenors_[k]);
vol = volSpreads_[j*nSwapTenors_+k][i]->value() +
atmVol_->volatility(optionDates_[j], swapTenors_[k],
atmForward);
marketVolCube_.setElement(i, j, k, vol);
}
marketVolCube_.updateInterpolators();
sparseParameters_ = sabrCalibration(marketVolCube_);
//parametersGuess_ = sparseParameters_;
sparseParameters_.updateInterpolators();
//parametersGuess_.updateInterpolators();
volCubeAtmCalibrated_= marketVolCube_;
if(isAtmCalibrated_){
fillVolatilityCube();
denseParameters_ = sabrCalibration(volCubeAtmCalibrated_);
denseParameters_.updateInterpolators();
}
}
SwaptionVolCube1::Cube
SwaptionVolCube1::sabrCalibration(const Cube& marketVolCube) const {
const std::vector<Time>& optionTimes = marketVolCube.optionTimes();
const std::vector<Time>& swapLengths = marketVolCube.swapLengths();
const std::vector<Date>& optionDates = marketVolCube.optionDates();
const std::vector<Period>& swapTenors = marketVolCube.swapTenors();
Matrix alphas(optionTimes.size(), swapLengths.size(),0.);
Matrix betas(alphas);
Matrix nus(alphas);
Matrix rhos(alphas);
Matrix forwards(alphas);
Matrix errors(alphas);
Matrix maxErrors(alphas);
Matrix endCriteria(alphas);
const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();
std::vector<Real> strikes(strikeSpreads_.size());
std::vector<Real> volatilities(strikeSpreads_.size());
for (Size j=0; j<optionTimes.size(); j++) {
for (Size k=0; k<swapLengths.size(); k++) {
Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
for (Size i=0; i<nStrikes_; i++){
strikes[i] = atmForward+strikeSpreads_[i];
volatilities[i] = tmpMarketVolCube[i][j][k];
}
const std::vector<Real>& guess = parametersGuess_.operator()(
optionTimes[j], swapLengths[k]);
const boost::shared_ptr<SABRInterpolation> sabrInterpolation =
boost::shared_ptr<SABRInterpolation>(new
SABRInterpolation(strikes.begin(), strikes.end(),
volatilities.begin(),
optionTimes[j], atmForward,
guess[0], guess[1],
guess[2], guess[3],
isParameterFixed_[0],
isParameterFixed_[1],
isParameterFixed_[2],
isParameterFixed_[3],
vegaWeightedSmileFit_,
endCriteria_,
boost::shared_ptr<OptimizationMethod>()));
sabrInterpolation->update();
Real interpolationError =
sabrInterpolation->interpolationError();
alphas [j][k]=sabrInterpolation->alpha();
betas [j][k]=sabrInterpolation->beta();
nus [j][k]=sabrInterpolation->nu();
rhos [j][k]=sabrInterpolation->rho();
forwards [j][k]=atmForward;
errors [j][k]=interpolationError;
maxErrors [j][k]=sabrInterpolation->interpolationMaxError();
endCriteria[j][k]=sabrInterpolation->endCriteria();
QL_ENSURE(endCriteria[j][k]!=EndCriteria::MaxIterations,
"global swaptions calibration failed: "
"MaxIterations reached: " << "\n" <<
"option maturity = " << optionDates[j] << ", \n" <<
"swap tenor = " << swapTenors[k] << ", \n" <<
"alpha = " << alphas[j][k]<< ", \n" <<
"beta = " << betas[j][k] << ", \n" <<
"nu = " << nus[j][k] << ", \n" <<
"rho = " << rhos[j][k] << ", \n" <<
"error = " << io::rate(errors[j][k])
);
QL_ENSURE(maxErrors[j][k]<maxErrorTolerance_,
"global swaptions calibration failed: "
"maxErrorTolerance not reached: " << "\n" <<
"option maturity = " << optionDates[j] << ", \n" <<
"swap tenor = " << swapTenors[k] << "\n" <<
"max error = " << io::rate(maxErrors[j][k]) << "\n" <<
"error = " << io::rate(errors[j][k]) << "\n" <<
"alpha = " << alphas[j][k]<< "\n" <<
"beta = " << betas[j][k] << "\n" <<
"nu = " << nus[j][k] << "\n" <<
"rho = " << rhos[j][k]
);
}
}
Cube sabrParametersCube(optionDates, swapTenors,
optionTimes, swapLengths, 8);
sabrParametersCube.setLayer(0, alphas);
sabrParametersCube.setLayer(1, betas);
sabrParametersCube.setLayer(2, nus);
sabrParametersCube.setLayer(3, rhos);
sabrParametersCube.setLayer(4, forwards);
sabrParametersCube.setLayer(5, errors);
sabrParametersCube.setLayer(6, maxErrors);
sabrParametersCube.setLayer(7, endCriteria);
return sabrParametersCube;
}
void SwaptionVolCube1::sabrCalibrationSection(
const Cube& marketVolCube,
Cube& parametersCube,
const Period& swapTenor) const {
const std::vector<Time>& optionTimes = marketVolCube.optionTimes();
const std::vector<Time>& swapLengths = marketVolCube.swapLengths();
const std::vector<Date>& optionDates = marketVolCube.optionDates();
const std::vector<Period>& swapTenors = marketVolCube.swapTenors();
Size k = std::find(swapTenors.begin(), swapTenors.end(),
swapTenor) - swapTenors.begin();
QL_REQUIRE(k != swapTenors.size(), "swap tenor not found");
std::vector<Real> calibrationResult(8,0.);
const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();
std::vector<Real> strikes(strikeSpreads_.size());
std::vector<Real> volatilities(strikeSpreads_.size());
for (Size j=0; j<optionTimes.size(); j++) {
Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
for (Size i=0; i<nStrikes_; i++){
strikes[i] = atmForward+strikeSpreads_[i];
volatilities[i] = tmpMarketVolCube[i][j][k];
}
const std::vector<Real>& guess = parametersGuess_.operator()(
optionTimes[j], swapLengths[k]);
const boost::shared_ptr<SABRInterpolation> sabrInterpolation =
boost::shared_ptr<SABRInterpolation>(new
SABRInterpolation(strikes.begin(), strikes.end(),
volatilities.begin(),
optionTimes[j], atmForward,
guess[0], guess[1],
guess[2], guess[3],
isParameterFixed_[0],
isParameterFixed_[1],
isParameterFixed_[2],
isParameterFixed_[3],
vegaWeightedSmileFit_,
endCriteria_,
boost::shared_ptr<OptimizationMethod>()));
sabrInterpolation->update();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?