📄 capletcoterminalswaptioncalibration.cpp
字号:
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2007 Ferdinando Ametrano
Copyright (C) 2007 Mark Joshi
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/models/marketmodels/models/capletcoterminalswaptioncalibration.hpp>
#include <ql/models/marketmodels/models/piecewiseconstantvariance.hpp>
#include <ql/models/marketmodels/models/pseudorootfacade.hpp>
#include <ql/models/marketmodels/models/cotswaptofwdadapter.hpp>
#include <ql/models/marketmodels/swapforwardmappings.hpp>
#include <ql/models/marketmodels/marketmodel.hpp>
#include <ql/math/matrixutilities/pseudosqrt.hpp>
namespace QuantLib {
CapletCoterminalSwaptionCalibration::CapletCoterminalSwaptionCalibration(
const EvolutionDescription& evolution,
const boost::shared_ptr<PiecewiseConstantCorrelation>& corr,
const std::vector<boost::shared_ptr<
PiecewiseConstantVariance> >&
displacedSwapVariances,
const std::vector<Volatility>& mktCapletVols,
const boost::shared_ptr<CurveState>& cs,
Spread displacement)
: evolution_(evolution), corr_(corr),
displacedSwapVariances_(displacedSwapVariances),
mktCapletVols_(mktCapletVols),
cs_(cs), displacement_(displacement), calibrated_(false) {}
bool CapletCoterminalSwaptionCalibration::calibrationFunction(
const EvolutionDescription& evolution,
const PiecewiseConstantCorrelation& corr,
const std::vector<boost::shared_ptr<
PiecewiseConstantVariance> >&
displacedSwapVariances,
const std::vector<Volatility>& capletVols,
const CurveState& cs,
const Spread displacement,
const Size numberOfFactors,
const std::vector<Real>& alpha,
const bool lowestRoot,
const bool useFullAprox,
std::vector<Matrix>& swapCovariancePseudoRoots,
Size& negativeDiscriminants) {
negativeDiscriminants = 0;
QL_REQUIRE(evolution.evolutionTimes()==corr.times(),
"evolutionTimes not equal to correlation times");
Size numberOfRates = evolution.numberOfRates();
QL_REQUIRE(numberOfFactors<=numberOfRates,
"number of factors (" << numberOfFactors <<
") cannot be greater than numberOfRates (" <<
numberOfRates << ")");
QL_REQUIRE(numberOfFactors>0,
"number of factors (" << numberOfFactors <<
") must be greater than zero");
QL_REQUIRE(numberOfRates==displacedSwapVariances.size(),
"mismatch between number of rates (" << numberOfRates <<
") and displacedSwapVariances");
QL_REQUIRE(numberOfRates==capletVols.size(),
"mismatch between number of rates (" << numberOfRates <<
") and capletVols (" << capletVols.size() <<
")");
const std::vector<Time>& rateTimes = evolution.rateTimes();
QL_REQUIRE(rateTimes==cs.rateTimes(),
"mismatch between EvolutionDescriptionand CurveState rate times ");
QL_REQUIRE(numberOfRates==cs.numberOfRates(),
"mismatch between number of rates (" << numberOfRates <<
") and CurveState");
QL_REQUIRE(numberOfRates==alpha.size(),
"mismatch between number of rates (" << numberOfRates <<
") and alphas (" << alpha.size() << ")");
const std::vector<Time>& evolutionTimes = evolution.evolutionTimes();
QL_REQUIRE(std::vector<Time>(rateTimes.begin(), rateTimes.end()-1)==evolutionTimes,
"mismatch between evolutionTimes and rateTimes");
Real extraMultiplier =useFullAprox ? 1.0 : 0.0;
Size numberOfSteps = evolution.numberOfSteps();
// factor reduction
std::vector<Matrix> corrPseudo(corr.times().size());
for (Size i=0; i<corrPseudo.size(); ++i)
corrPseudo[i] = rankReducedSqrt(corr.correlation(i),
numberOfFactors, 1.0,
SalvagingAlgorithm::None);
// do alpha part
// first modify variances to take account of alpha
// then rescale so total variance is unchanged
Matrix swapTimeInhomogeneousVariances(numberOfSteps, numberOfRates, 0.0);
std::vector<Real> originalVariances(numberOfRates, 0.0);
std::vector<Real> modifiedVariances(numberOfRates, 0.0);
for (Size i=0; i<numberOfSteps; ++i) {
Real s = (i==0 ? 0.0 : evolutionTimes[i-1]);
for (Size j=i; j<numberOfRates; ++j) {
const std::vector<Real>& var = displacedSwapVariances[j]->variances();
originalVariances[j]+=var[i];
swapTimeInhomogeneousVariances[i][j] = var[i]/
((1.0+alpha[j]*s)*(1.0+alpha[j]*s));
modifiedVariances[j]+=swapTimeInhomogeneousVariances[i][j];
}
}
for (Size i=0; i<numberOfSteps; ++i)
for (Size j=i; j<numberOfRates; ++j)
swapTimeInhomogeneousVariances[i][j] *= originalVariances[j]/
modifiedVariances[j];
Matrix zedMatrix =
SwapForwardMappings::coterminalSwapZedMatrix(cs, displacement);
Matrix invertedZedMatrix = inverse(zedMatrix);
// compute swap covariances for caplet approximation formula
// without taking into account A and B
std::vector<Matrix> CovarianceSwapPseudos(numberOfSteps);
std::vector<Matrix> CovarianceSwapCovs(numberOfSteps); // this is total cov
std::vector<Matrix> CovarianceSwapMarginalCovs(numberOfSteps); // this is cov for one step
for (Size i=0; i<numberOfSteps; ++i) {
CovarianceSwapPseudos[i] = corrPseudo[i];
for (Size j=0; j<numberOfRates; ++j)
for (Size k=0; k < CovarianceSwapPseudos[i].columns(); ++k)
CovarianceSwapPseudos[i][j][k] *=
sqrt(swapTimeInhomogeneousVariances[i][j]);
CovarianceSwapMarginalCovs[i] = CovarianceSwapPseudos[i] *
transpose(CovarianceSwapPseudos[i]);
CovarianceSwapCovs[i] = CovarianceSwapMarginalCovs[i];
if (i>0)
CovarianceSwapCovs[i]+= CovarianceSwapCovs[i-1];
}
// compute partial variances and covariances which will take A and B coefficients
//const std::vector<Time>& taus = evolution.rateTaus();
std::vector<Real> totVariance(numberOfRates, 0.0);
std::vector<Real> almostTotVariance(numberOfRates, 0.0);
std::vector<Real> almostTotCovariance(numberOfRates, 0.0);
std::vector<Real> leftCovariance(numberOfRates, 0.0);
for (Size i=0; i<numberOfRates; ++i) {
for (Size j=0; j<=i; ++j)
totVariance[i] += displacedSwapVariances[i]->variances()[j];
for (Integer j=0; j<=static_cast<Integer>(i)-1; ++j)
almostTotVariance[i] += swapTimeInhomogeneousVariances[j][i];
Integer j=0;
for (; j<=static_cast<Integer>(i)-2; ++j) {
const Matrix& thisPseudo = corrPseudo[j];
Real correlation = 0.0;
for (Size k=0; k<numberOfFactors; ++k)
correlation += thisPseudo[i-1][k]*thisPseudo[i][k];
almostTotCovariance[i] += correlation *
sqrt(swapTimeInhomogeneousVariances[j][i] *
swapTimeInhomogeneousVariances[j][i-1]);
}
if (i>0) {
const Matrix& thisPseudo = corrPseudo[j];
Real correlation = 0.0;
for (Size k=0; k<numberOfFactors; ++k)
correlation += thisPseudo[i-1][k]*thisPseudo[i][k];
leftCovariance[i] = correlation *
sqrt(swapTimeInhomogeneousVariances[j][i] *
swapTimeInhomogeneousVariances[j][i-1]);
}
}
// multiplier up to rate reset previous time
// the first element is not used
std::vector<Real> a(numberOfSteps, 1.0);
// multiplier afterward
std::vector<Real> b(numberOfSteps);
b[0]=displacedSwapVariances[0]->variances()[0]/swapTimeInhomogeneousVariances[0][0];
// main loop where work is done
for (Size i=1; i<numberOfSteps; ++i) {
Integer j=0;
// up date variances to take account of last a and b computed
for (; j <= static_cast<Integer>(i)-2; j++)
swapTimeInhomogeneousVariances[j][i-1]*= a[i-1]*a[i-1];
swapTimeInhomogeneousVariances[j][i-1]*= b[i-1]*b[i-1];
Real w0 = invertedZedMatrix[i-1][i-1];
Real w1 = -invertedZedMatrix[i-1][i];
Real v1t1 = capletVols[i-1]*capletVols[i-1]*rateTimes[i-1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -