// calculating swaption volatility matrix using // Rebonatos approx. formula. Be aware that this // matrix is valid only for regular fixings and // assumes that the fix and floating leg have the // same frequency ext::shared_ptr<SwaptionVolatilityMatrix> LiborForwardModel::getSwaptionVolatilityMatrix() const { if (swaptionVola) { return swaptionVola; } const ext::shared_ptr<IborIndex> index = process_->index(); const Date today = process_->fixingDates()[0]; const Size size=process_->size()/2; Matrix volatilities(size, size); std::vector<Date> exercises(process_->fixingDates().begin() + 1, process_->fixingDates().begin() + size+1); std::vector<Period> lengths(size); for (Size i=0; i < size; ++i) { lengths[i] = (i+1)*index->tenor(); } const Array f = process_->initialValues(); for (Size k=0; k < size; ++k) { const Size alpha =k; const Time t_alpha=process_->fixingTimes()[alpha+1]; Matrix var(size, size); for (Size i=alpha+1; i <= k+size; ++i) { for (Size j=i; j <= k+size; ++j) { var[i-alpha-1][j-alpha-1] = var[j-alpha-1][i-alpha-1] = covarProxy_->integratedCovariance(i, j, t_alpha); } } for (Size l=1; l <= size; ++l) { const Size beta =l + k; const Array w = w_0(alpha, beta); Real sum=0.0; for (Size i=alpha+1; i <= beta; ++i) { for (Size j=alpha+1; j <= beta; ++j) { sum+=w[i]*w[j]*f[i]*f[j]*var[i-alpha-1][j-alpha-1]; } } volatilities[k][l-1] = std::sqrt(sum/t_alpha)/S_0(alpha, beta); } } return swaptionVola = ext::make_shared<SwaptionVolatilityMatrix>( today, exercises, lengths, volatilities, index->dayCounter()); }
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]); strikes.clear(); volatilities.clear(); for (Size i=0; i<nStrikes_; i++){ Real strike = atmForward+strikeSpreads_[i]; if(strike>=MINSTRIKE) { strikes.push_back(strike); volatilities.push_back(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_, optMethod_, errorAccept_, useMaxError_, maxGuesses_)); sabrInterpolation->update(); Real rmsError = sabrInterpolation->rmsError(); Real maxError = sabrInterpolation->maxError(); 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] = rmsError; maxErrors [j][k] = maxError; 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" << "error = " << io::rate(errors[j][k]) << ", \n" << "max error = " << io::rate(maxErrors[j][k]) << ", \n" << " alpha = " << alphas[j][k] << "n" << " beta = " << betas[j][k] << "\n" << " nu = " << nus[j][k] << "\n" << " rho = " << rhos[j][k] << "\n" ); QL_ENSURE(useMaxError_ ? maxError : rmsError < maxErrorTolerance_, "global swaptions calibration failed: " "option tenor " << optionDates[j] << ", swap tenor " << swapTenors[k] << (useMaxError_ ? ": max error " : ": error") << (useMaxError_ ? maxError : rmsError) << " alpha = " << alphas[j][k] << "n" << " beta = " << betas[j][k] << "\n" << " nu = " << nus[j][k] << "\n" << " rho = " << rhos[j][k] << "\n" << (useMaxError_ ? ": error" : ": max error ") << (useMaxError_ ? rmsError :maxError) ); } } 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]); strikes.clear(); volatilities.clear(); for (Size i=0; i<nStrikes_; i++){ Real strike = atmForward+strikeSpreads_[i]; if(strike>=MINSTRIKE) { strikes.push_back(strike); volatilities.push_back(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_, optMethod_, errorAccept_, useMaxError_, maxGuesses_)); sabrInterpolation->update(); Real interpolationError = sabrInterpolation->rmsError(); calibrationResult[0]=sabrInterpolation->alpha(); calibrationResult[1]=sabrInterpolation->beta(); calibrationResult[2]=sabrInterpolation->nu(); calibrationResult[3]=sabrInterpolation->rho(); calibrationResult[4]=atmForward; calibrationResult[5]=interpolationError; calibrationResult[6]=sabrInterpolation->maxError(); calibrationResult[7]=sabrInterpolation->endCriteria(); QL_ENSURE(calibrationResult[7]!=EndCriteria::MaxIterations, "section calibration failed: " "option tenor " << optionDates[j] << ", swap tenor " << swapTenors[k] << ": max iteration (" << endCriteria_->maxIterations() << ")" << ", alpha " << calibrationResult[0]<< ", beta " << calibrationResult[1] << ", nu " << calibrationResult[2] << ", rho " << calibrationResult[3] << ", max error " << calibrationResult[6] << ", error " << calibrationResult[5] ); QL_ENSURE(useMaxError_ ? calibrationResult[6] : calibrationResult[5] < maxErrorTolerance_, "section calibration failed: " "option tenor " << optionDates[j] << ", swap tenor " << swapTenors[k] << (useMaxError_ ? ": max error " : ": error ") << (useMaxError_ ? calibrationResult[6] : calibrationResult[5]) << ", alpha " << calibrationResult[0] << ", beta " << calibrationResult[1] << ", nu " << calibrationResult[2] << ", rho " << calibrationResult[3] << (useMaxError_ ? ": error" : ": max error ") << (useMaxError_ ? calibrationResult[5] : calibrationResult[6]) ); parametersCube.setPoint(optionDates[j], swapTenors[k], optionTimes[j], swapLengths[k], calibrationResult); parametersCube.updateInterpolators(); } }
Volatility PiecewiseConstantVariance::volatility(Size i) const { QL_REQUIRE(i<volatilities().size(), "invalid step index"); return volatilities()[i]; }