33 bool singleRateClosestPointFinder(
35 const std::vector<Volatility>& homogeneousSolution,
36 const std::vector<Volatility>& previousRateSolution,
38 const std::vector<Real>& correlations,
41 Real capletSwaptionPriority,
44 std::vector<Volatility>& solution,
51 Real previousSwapVariance = previousRateSolution[0] *previousRateSolution[0];
52 Real thisSwapVariance = homogeneousSolution[0] *homogeneousSolution[0]
53 + homogeneousSolution[1] *homogeneousSolution[1];
54 Real crossTerm = 2*w0*w1*correlations[0]*previousRateSolution[0];
55 Real constantTerm = w0*w0* previousSwapVariance - capletVariance;
58 quadratic
q(
theta,crossTerm, constantTerm);
59 Real volminus, volplus;
60 bool capSuccess =
q.roots(volminus,volplus);
61 Real residual = thisSwapVariance - volminus*volminus;
62 bool swapSuccess = residual >=0;
63 bool success = capSuccess && swapSuccess;
67 solution[0] = volminus;
68 solution[1] = std::sqrt(residual);
74 bool prioritizeCaplet = capletSwaptionPriority <0.5;
76 if (capSuccess && prioritizeCaplet)
78 solution[0] = volminus;
80 swaptionError = std::sqrt(thisSwapVariance)-volminus;
85 if (capSuccess && !prioritizeCaplet)
87 solution[0] = std::sqrt(thisSwapVariance);
90 capletError= std::sqrt(
q(solution[0])+capletVariance) - std::sqrt(capletVariance);
98 solution[0] = volminus;
99 solution[1] = std::sqrt(residual);
101 capletError= std::sqrt(
q(solution[0])+capletVariance) - std::sqrt(capletVariance);
107 if (prioritizeCaplet)
109 solution[0] = volminus;
111 swaptionError = std::sqrt(thisSwapVariance)-volminus;
117 solution[0] = std::sqrt(thisSwapVariance);
120 capletError= std::sqrt(
q(solution[0])+capletVariance) - std::sqrt(capletVariance);
130 Real previousSwapVariance=0.0;
131 Real thisSwapVariance =0.0;
134 for (; i<capletNumber+1; ++i) {
135 previousSwapVariance += previousRateSolution[i] *
136 previousRateSolution[i];
137 thisSwapVariance += homogeneousSolution[i] *
138 homogeneousSolution[i];
140 thisSwapVariance+= homogeneousSolution[i]*homogeneousSolution[i];
144 std::vector<Real>
b(capletNumber+1);
145 Array cylinderCentre(capletNumber+1);
146 Array targetArray(capletNumber+2);
147 Array targetArrayRestricted(capletNumber+1);
151 for (
Size i=0; i<capletNumber+1; ++i) {
152 b[i] = 2*w0*w1*correlations[i]*previousRateSolution[i]/
theta;
153 cylinderCentre[i] = -0.5*
b[i];
154 targetArray[i] = homogeneousSolution[i];
155 targetArrayRestricted[i] = targetArray[i];
158 targetArray[capletNumber+1] = homogeneousSolution[capletNumber+1];
160 Real A = previousSwapVariance*w0*w0/
theta;
161 Real constQuadraticTerm = A - 0.25*bsq;
162 Real S2 = capletVariance/
theta - constQuadraticTerm;
165 Real S = S2 > 0 ?
Real(std::sqrt(S2)) : 0;
167 Real R = std::sqrt(thisSwapVariance);
169 BasisIncompleteOrdered basis(capletNumber+1);
170 basis.addVector(cylinderCentre);
171 basis.addVector(targetArrayRestricted);
172 for (
Size i=0; i<capletNumber+1; ++i) {
173 Array ei(capletNumber+1,0.0);
178 Matrix orthTransformationRestricted(basis.getBasisAsRowsInMatrix());
179 Matrix orthTransformation(capletNumber+2, capletNumber+2, 0.0);
181 orthTransformation[capletNumber+1][capletNumber+1]=1.0;
182 for (
Size k=0; k<capletNumber+1; ++k)
183 for (
Size l=0; l<capletNumber+1; ++l)
184 orthTransformation[k][l]=orthTransformationRestricted[k][l];
186 Array movedCentre = orthTransformationRestricted*cylinderCentre;
188 Array movedTarget = orthTransformation*targetArray;
190 Real Z1=0.0, Z2=0.0, Z3=0.0;
192 SphereCylinderOptimizer optimizer(R,
S,
alpha, movedTarget[0], movedTarget[1],movedTarget[movedTarget.size()-1],finalWeight);
194 bool success =
false;
196 if (!optimizer.isIntersectionNonEmpty())
198 Z1 = R*capletSwaptionPriority+(1-capletSwaptionPriority)*(
alpha-
S);
202 capletError = (
alpha-
S)-Z1;
210 if (maxIterations > 0.0)
212 optimizer.findClosest(maxIterations,
219 optimizer.findByProjection(
225 Array rotatedSolution(capletNumber+2,0.0);
226 rotatedSolution[0] = Z1;
227 rotatedSolution[1] = Z2;
228 rotatedSolution[capletNumber+1] = Z3;
230 Array arraySolution(
transpose(orthTransformation) *
234 for (; i < arraySolution.size(); ++i)
235 solution[i]=arraySolution[i];
236 for (; i < solution.size(); ++i)
248 const ext::shared_ptr<PiecewiseConstantCorrelation>& corr,
249 const std::vector<ext::shared_ptr<
251 displacedSwapVariances,
252 const std::vector<Volatility>& mktCapletVols,
253 const ext::shared_ptr<CurveState>& cs,
255 Real caplet0Swaption1Priority)
257 mktCapletVols, cs, displacement),
258 caplet0Swaption1Priority_(caplet0Swaption1Priority) {
261 caplet0Swaption1Priority<=1.0,
262 "caplet0Swaption1Priority (" << caplet0Swaption1Priority <<
263 ") must be in [0.0, 1.0]");
270 const std::vector<ext::shared_ptr<
272 const std::vector<Volatility>& capletVols,
274 const Spread displacement,
275 Real caplet0Swaption1Priority,
276 const Size numberOfFactors,
279 Real& deformationSize,
280 Real& totalSwaptionError,
281 std::vector<Matrix>& swapCovariancePseudoRoots)
285 displacedSwapVariances, capletVols, cs);
289 const std::vector<Time>& rateTimes = evolution.
rateTimes();
292 "number of factors (" << numberOfFactors <<
293 ") cannot be greater than numberOfRates (" <<
294 numberOfRates <<
")");
296 "number of factors (" << numberOfFactors <<
297 ") must be greater than zero");
302 totalSwaptionError = 0.0;
306 std::vector<Matrix> corrPseudo(corr.
times().size());
307 for (
Size i=0; i<corrPseudo.size(); ++i)
309 numberOfFactors, 1.0,
318 std::vector<std::vector<Volatility> > newVols;
319 std::vector<Volatility> theseNewVols(numberOfRates);
320 std::vector<Volatility> firstRateVols(numberOfRates);
321 firstRateVols[0] = std::sqrt(displacedSwapVariances[0]->variances()[0]);
322 std::vector<Volatility> secondRateVols(numberOfRates);
323 std::vector<Real> correlations(numberOfRates);
324 newVols.push_back(firstRateVols);
327 for (
Size i=0; i<numberOfRates-1; ++i)
330 Real thisFinalWeight = i > 1 ? (i-1)/2.0 : 1.0;
333 const std::vector<Real>& var =
334 displacedSwapVariances[i+1]->variances();
336 for (
Size j =0; j < i+2; ++j)
337 secondRateVols[j] = std::sqrt(var[j]);
339 for (
Size k=0; k < i+1; k++) {
340 Real correlation=0.0;
341 for (
Size l=0; l < numberOfFactors; ++l) {
342 Real term1 = corrPseudo[k][i][l];
343 Real term2 = corrPseudo[k][i+1][l];
344 correlation += term1*term2;
346 correlations[k] = correlation;
349 Real w0 = invertedZedMatrix[i][i];
350 Real w1 = invertedZedMatrix[i][i+1];
352 for (
Size k = i+2; k <invertedZedMatrix.
columns(); ++k)
353 w0+= invertedZedMatrix[i][k];
355 Real targetCapletVariance= capletVols[i]*capletVols[i]*rateTimes[i];
357 Real thisCapletError;
358 Real thisSwaptionError;
360 bool success = singleRateClosestPointFinder(
361 i, secondRateVols, firstRateVols, targetCapletVariance, correlations,
362 w0, w1, caplet0Swaption1Priority,maxIterations, tolerance,
363 theseNewVols, thisFinalWeight ,thisSwaptionError, thisCapletError);
365 totalSwaptionError+= thisSwaptionError*thisSwaptionError;
370 for (
Size j=0; j < i+2; ++j)
371 deformationSize += (theseNewVols[i]-secondRateVols[i])*(theseNewVols[i]-secondRateVols[i]);
373 newVols.push_back(theseNewVols);
374 firstRateVols = theseNewVols;
377 swapCovariancePseudoRoots.resize(numberOfSteps);
378 for (
Size k=0; k<numberOfSteps; ++k) {
379 swapCovariancePseudoRoots[k] = corrPseudo[k];
380 for (
Size j=0; j<numberOfRates; ++j) {
381 Real coeff =newVols[j][k];
382 for (
Size i=0; i<numberOfFactors; ++i)
383 swapCovariancePseudoRoots[k][j][i]*=coeff;
385 QL_ENSURE(swapCovariancePseudoRoots[k].rows()==numberOfRates,
386 "step " << k <<
" abcd vol wrong number of rows: " <<
387 swapCovariancePseudoRoots[k].rows() <<
388 " instead of " << numberOfRates);
389 QL_ENSURE(swapCovariancePseudoRoots[k].columns()==numberOfFactors,
390 "step " << k <<
" abcd vol wrong number of columns: " <<
391 swapCovariancePseudoRoots[k].columns() <<
392 " instead of " << numberOfFactors);
ext::shared_ptr< PiecewiseConstantCorrelation > corr_
Real deformationSize() const
ext::shared_ptr< CurveState > cs_
static void performChecks(const EvolutionDescription &evolution, const PiecewiseConstantCorrelation &corr, const std::vector< ext::shared_ptr< PiecewiseConstantVariance > > &displacedSwapVariances, const std::vector< Volatility > &mktCapletVols, const CurveState &cs)
std::vector< ext::shared_ptr< PiecewiseConstantVariance > > displacedSwapVariances_
std::vector< Volatility > usedCapletVols_
EvolutionDescription evolution_
std::vector< Matrix > swapCovariancePseudoRoots_
Real caplet0Swaption1Priority_
CTSMMCapletMaxHomogeneityCalibration(const EvolutionDescription &evolution, const ext::shared_ptr< PiecewiseConstantCorrelation > &corr, const std::vector< ext::shared_ptr< PiecewiseConstantVariance > > &displacedSwapVariances, const std::vector< Volatility > &capletVols, const ext::shared_ptr< CurveState > &cs, Spread displacement, Real caplet0Swaption1Priority=1.0)
static Natural capletMaxHomogeneityCalibration(const EvolutionDescription &evolution, const PiecewiseConstantCorrelation &corr, const std::vector< ext::shared_ptr< PiecewiseConstantVariance > > &displacedSwapVariances, const std::vector< Volatility > &capletVols, const CurveState &cs, Spread displacement, Real caplet0Swaption1Priority, Size numberOfFactors, Size maxIterations, Real tolerance, Real &deformationSize, Real &totalSwaptionError, std::vector< Matrix > &swapCovariancePseudoRoots)
Natural calibrationImpl_(Natural numberOfFactors, Natural maxIterations, Real tolerance) override
Curve state for market-model simulations
Market-model evolution description.
Size numberOfRates() const
const std::vector< Time > & rateTimes() const
Size numberOfSteps() const
Matrix used in linear algebra.
virtual const Matrix & correlation(Size i) const
virtual const std::vector< Time > & times() const =0
static Matrix coterminalSwapZedMatrix(const CurveState &cs, Spread displacement)
#define QL_ENSURE(condition, message)
throw an error if the given post-condition is not verified
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
ext::function< Real(Real)> b
unsigned QL_INTEGER Natural
positive integer
Real Spread
spreads on interest rates
std::size_t Size
size of a container
Matrix rankReducedSqrt(const Matrix &matrix, Size maxRank, Real componentRetainedPercentage, SalvagingAlgorithm::Type sa)
Matrix transpose(const Matrix &m)
Matrix inverse(const Matrix &m)
ext::shared_ptr< YieldTermStructure > q
pseudo square root of a real symmetric matrix
Find closest point of the intersection of a sphere and cylinder to a given point.
Utility functions for mapping between swap rate and forward rate.