34 : smileAndCms_(smileAndCms), volCube_(smileAndCms->volCube_),
35 cmsMarket_(smileAndCms->cmsMarket_),
36 weights_(smileAndCms->weights_),
37 calibrationType_(smileAndCms->calibrationType_) {};
43 Real switchErrorFunctionOnCalibrationType()
const;
44 Array switchErrorsFunctionOnCalibrationType()
const;
48 ext::shared_ptr<CmsMarket> cmsMarket_;
53 virtual void updateVolatilityCubeAndCmsMarket(
const Array &x)
const;
56 class ObjectiveFunction2 :
public ObjectiveFunction {
59 Real fixedMeanReversion)
60 : ObjectiveFunction(smileAndCms),
61 fixedMeanReversion_(fixedMeanReversion) {};
64 void updateVolatilityCubeAndCmsMarket(
const Array& x)
const override;
65 Real fixedMeanReversion_;
68 class ObjectiveFunction3 :
public ObjectiveFunction {
71 : ObjectiveFunction(smileAndCms) {};
74 void updateVolatilityCubeAndCmsMarket(
const Array& x)
const override;
77 class ObjectiveFunction4 :
public ObjectiveFunction {
80 Real fixedMeanReversion)
81 : ObjectiveFunction(smileAndCms),
82 fixedMeanReversion_(fixedMeanReversion) {};
85 void updateVolatilityCubeAndCmsMarket(
const Array& x)
const override;
86 Real fixedMeanReversion_;
89 class ObjectiveFunction5 :
public ObjectiveFunction {
92 Real fixedMeanReversion)
93 : ObjectiveFunction(smileAndCms),
94 fixedMeanReversion_(fixedMeanReversion) {};
97 void updateVolatilityCubeAndCmsMarket(
const Array& x)
const override;
98 Real fixedMeanReversion_;
101 class ObjectiveFunction6 :
public ObjectiveFunction {
104 : ObjectiveFunction(smileAndCms) {};
107 void updateVolatilityCubeAndCmsMarket(
const Array& x)
const override;
114 Real ObjectiveFunction::value(
const Array &x)
const {
115 updateVolatilityCubeAndCmsMarket(x);
116 return switchErrorFunctionOnCalibrationType();
119 Array ObjectiveFunction::values(
const Array &x)
const {
120 updateVolatilityCubeAndCmsMarket(x);
121 return switchErrorsFunctionOnCalibrationType();
125 ObjectiveFunction::updateVolatilityCubeAndCmsMarket(
const Array &x)
const {
126 const std::vector<Period> &swapTenors = cmsMarket_->swapTenors();
127 Size nSwapTenors = swapTenors.size();
129 "bad calibration guess nSwapTenors+1 != x.size()");
130 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
131 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*volCube_);
132 for (
Size i = 0; i < nSwapTenors; ++i)
137 cmsMarket_->reprice(volCube_, meanReversion);
140 Real ObjectiveFunction::switchErrorFunctionOnCalibrationType()
const {
141 switch (calibrationType_) {
143 return cmsMarket_->weightedSpreadError(weights_);
145 return cmsMarket_->weightedSpotNpvError(weights_);
147 return cmsMarket_->weightedFwdNpvError(weights_);
149 QL_FAIL(
"unknown/illegal calibration type");
153 Array ObjectiveFunction::switchErrorsFunctionOnCalibrationType()
const {
154 switch (calibrationType_) {
156 return cmsMarket_->weightedSpreadErrors(weights_);
158 return cmsMarket_->weightedSpotNpvErrors(weights_);
160 return cmsMarket_->weightedFwdNpvErrors(weights_);
162 QL_FAIL(
"unknown/illegal calibration type");
171 ObjectiveFunction2::updateVolatilityCubeAndCmsMarket(
const Array &x)
const {
172 const std::vector<Period> &swapTenors = cmsMarket_->swapTenors();
173 Size nSwapTenors = swapTenors.size();
175 "bad calibration guess nSwapTenors != x.size()");
176 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
177 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*volCube_);
178 for (
Size i = 0; i < nSwapTenors; ++i)
181 cmsMarket_->reprice(volCube_, fixedMeanReversion_ ==
Null<Real>() ?
184 fixedMeanReversion_));
192 ObjectiveFunction3::updateVolatilityCubeAndCmsMarket(
const Array &x)
const {
193 const std::vector<Period> &swapTenors = cmsMarket_->swapTenors();
194 const std::vector<Period> &swapLengths = cmsMarket_->swapLengths();
195 Size nSwapTenors = swapTenors.size();
196 Size nSwapLengths = swapLengths.size();
198 (nSwapLengths * nSwapTenors) + 1 == x.
size(),
199 "bad calibration guess (nSwapLengths*nSwapTenors)+1 != x.size()");
200 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
201 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*volCube_);
202 for (
Size i = 0; i < nSwapTenors; ++i) {
203 std::vector<Real>
beta(x.
begin() + (i * nSwapLengths),
204 x.
begin() + ((i + 1) * nSwapLengths));
207 volCubeBySabr->recalibration(swapLengths,
beta, swapTenors[i]);
211 cmsMarket_->reprice(volCube_, meanReversion);
219 ObjectiveFunction4::updateVolatilityCubeAndCmsMarket(
const Array &x)
const {
220 const std::vector<Period> &swapTenors = cmsMarket_->swapTenors();
221 const std::vector<Period> &swapLengths = cmsMarket_->swapLengths();
222 Size nSwapTenors = swapTenors.size();
223 Size nSwapLengths = swapLengths.size();
225 (nSwapLengths * nSwapTenors) == x.
size(),
226 "bad calibration guess (nSwapLengths*nSwapTenors) != x.size()");
227 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
228 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*volCube_);
229 for (
Size i = 0; i < nSwapTenors; ++i) {
230 std::vector<Real>
beta(x.
begin() + (i * nSwapLengths),
231 x.
begin() + ((i + 1) * nSwapLengths));
234 volCubeBySabr->recalibration(swapLengths,
beta, swapTenors[i]);
236 cmsMarket_->reprice(volCube_, fixedMeanReversion_ ==
Null<Real>() ?
239 fixedMeanReversion_));
247 ObjectiveFunction5::updateVolatilityCubeAndCmsMarket(
const Array &x)
const {
248 const std::vector<Period> &swapTenors = cmsMarket_->swapTenors();
249 const std::vector<Period> &swapLengths = cmsMarket_->swapLengths();
250 Size nSwapTenors = swapTenors.size();
251 Size nSwapLengths = swapLengths.size();
253 "bad calibration guess (3*nSwapTenors) != x.size()");
254 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
255 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*volCube_);
256 for (
Size i = 0; i < nSwapTenors; ++i) {
259 Real decay = x[2 + 3 * i] * x[2 + 3 * i];
260 std::vector<Real>
beta(nSwapLengths);
261 for (
Size j = 0; j <
beta.size(); ++j) {
262 Real t = smileAndCms_->volCube_->timeFromReference(
263 smileAndCms_->volCube_->optionDateFromTenor(swapLengths[j]));
264 beta[j] = betaInf + (beta0 - betaInf) * std::exp(-decay *
t);
266 volCubeBySabr->recalibration(swapLengths,
beta, swapTenors[i]);
268 cmsMarket_->reprice(volCube_, fixedMeanReversion_ ==
Null<Real>() ?
271 fixedMeanReversion_));
279 ObjectiveFunction6::updateVolatilityCubeAndCmsMarket(
const Array &x)
const {
280 const std::vector<Period> &swapTenors = cmsMarket_->swapTenors();
281 const std::vector<Period> &swapLengths = cmsMarket_->swapLengths();
282 Size nSwapTenors = swapTenors.size();
283 Size nSwapLengths = swapLengths.size();
285 "bad calibration guess (3*nSwapTenors) != x.size()");
286 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
287 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*volCube_);
288 for (
Size i = 0; i < nSwapTenors; ++i) {
291 Real decay = x[2 + 3 * i] * x[2 + 3 * i];
292 std::vector<Real>
beta(nSwapLengths);
293 for (
Size j = 0; j <
beta.size(); ++j) {
294 Real t = smileAndCms_->volCube_->timeFromReference(
295 smileAndCms_->volCube_->optionDateFromTenor(swapLengths[j]));
296 beta[j] = betaInf + (beta0 - betaInf) * std::exp(-decay *
t);
298 volCubeBySabr->recalibration(swapLengths,
beta, swapTenors[i]);
302 cmsMarket_->reprice(volCube_, meanReversion);
314 ext::shared_ptr<CmsMarket> &cmsMarket,
const Matrix &weights,
316 : volCube_(volCube), cmsMarket_(cmsMarket), weights_(weights),
317 calibrationType_(calibrationType) {
320 "weights number of rows ("
322 <<
") must be equal to number of swap lengths ("
325 "weights number of columns ("
327 <<
") must be equal to number of swap indexes ("
332 const ext::shared_ptr<EndCriteria> &endCriteria,
333 const ext::shared_ptr<OptimizationMethod> &method,
const Array &guess,
334 bool isMeanReversionFixed) {
336 QL_REQUIRE(isMeanReversionFixed || guess.
size() == nSwapTenors + 1,
337 "if mean reversion is not fixed, a guess must be provided");
339 nSwapTenors == guess.
size() - 1,
340 "guess size (" << guess.
size()
341 <<
") must be equal to swap tenors size ("
343 <<
") or greater by one if mean reversion is "
344 "given as last element");
345 bool isMeanReversionGiven = (nSwapTenors == guess.
size() - 1);
346 Size nBeta = guess.
size() - (isMeanReversionGiven ? 1 : 0);
348 if (isMeanReversionFixed) {
350 Real fixedMeanReversion =
351 isMeanReversionGiven ? guess[nBeta] :
Null<Real>();
352 Array betasGuess(nBeta);
353 for (
Size i = 0; i < nBeta; ++i)
354 betasGuess[i] = guess[i];
355 ObjectiveFunction2 costFunction(
359 Problem problem(costFunction, constraint, betasGuess);
362 error_ = costFunction.value(tmp);
363 result =
Array(nBeta + (isMeanReversionGiven ? 1 : 0));
364 for (
Size i = 0; i < nBeta; ++i)
366 if (isMeanReversionGiven)
367 result[nBeta] = fixedMeanReversion;
370 ObjectiveFunction costFunction(
this);
371 Array betaReversionGuess(nBeta + 1);
372 for (
Size i = 0; i < nBeta; ++i)
375 Problem problem(costFunction, constraint, betaReversionGuess);
378 error_ = costFunction.value(result);
379 for (
Size i = 0; i < nBeta; ++i)
383 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
384 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*
volCube_);
385 volCubeBySabr->updateAfterRecalibration();
394 const ext::shared_ptr<EndCriteria> &endCriteria,
395 const ext::shared_ptr<OptimizationMethod> &method,
396 const Matrix &guess,
bool isMeanReversionFixed,
397 const Real meanReversionGuess) {
401 "if mean reversion is not fixed, a guess must be provided");
403 "number of swap tenors ("
405 <<
") must be equal to number of guess columns ("
408 "number of swap lengths ("
410 <<
") must be equal to number of guess rows ("
411 << guess.
rows() <<
")");
413 Size nBeta = nSwapTenors * nSwapLengths;
414 if (isMeanReversionFixed) {
416 Array betasGuess(nBeta);
417 for (
Size i = 0; i < nSwapTenors; ++i) {
418 for (
Size j = 0; j < nSwapLengths; ++j) {
419 betasGuess[i * nSwapLengths + j] =
423 ObjectiveFunction4 costFunction(
427 Problem problem(costFunction, constraint, betasGuess);
430 error_ = costFunction.value(tmp);
431 result =
Matrix(nSwapLengths,
433 (meanReversionGuess !=
Null<Real>() ? 1 : 0));
434 for (
Size i = 0; i < nSwapTenors; ++i) {
435 for (
Size j = 0; j < nSwapLengths; ++j) {
441 for (
Size j = 0; j < nSwapLengths; ++j) {
442 result[j][nSwapTenors] = meanReversionGuess;
447 Array betasReversionGuess(nBeta + 1);
448 for (
Size i = 0; i < nSwapTenors; ++i) {
449 for (
Size j = 0; j < nSwapLengths; ++j) {
450 betasReversionGuess[i * nSwapLengths + j] =
454 betasReversionGuess[nBeta] =
456 ObjectiveFunction3 costFunction(
this);
457 Problem problem(costFunction, constraint, betasReversionGuess);
460 error_ = costFunction.value(tmp);
461 result =
Matrix(nSwapLengths, nSwapTenors + 1);
462 for (
Size i = 0; i < nSwapTenors; ++i) {
463 for (
Size j = 0; j < nSwapLengths; ++j) {
468 for (
Size j = 0; j < nSwapLengths; ++j) {
472 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
473 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*
volCube_);
474 volCubeBySabr->updateAfterRecalibration();
483 const ext::shared_ptr<EndCriteria> &endCriteria,
484 const ext::shared_ptr<OptimizationMethod> &method,
485 const Matrix &guess,
bool isMeanReversionFixed,
486 const Real meanReversionGuess) {
491 "if mean reversion is not fixed, a guess must be provided");
493 "number of swap tenors ("
495 <<
") must be equal to number of guess columns ("
498 "number of parameters ("
499 << 3 <<
") must be equal to number of guess rows ("
500 << guess.
rows() <<
")");
503 Size nParams = nSwapTenors * 3;
504 if (isMeanReversionFixed) {
506 Array betasGuess(nParams);
507 for (
Size i = 0; i < nSwapTenors; ++i) {
508 for (
Size j = 0; j < nParams; ++j) {
509 betasGuess[i * 3 + j] =
511 : std::sqrt(guess[j][i]);
514 ObjectiveFunction5 costFunction(
518 Problem problem(costFunction, constraint, betasGuess);
521 error_ = costFunction.value(tmp);
523 3, nSwapTenors + (meanReversionGuess !=
Null<Real>() ? 1 : 0));
524 for (
Size i = 0; i < nSwapTenors; ++i) {
525 for (
Size j = 0; j < 3; ++j) {
526 result[j][i] = (j == 0 || j == 1)
528 : tmp[i * 3 + j] * tmp[i * 3 + j];
532 for (
Size j = 0; j < nSwapLengths; ++j) {
533 result[j][nSwapTenors] = meanReversionGuess;
538 Array betasReversionGuess(nParams + 1);
539 for (
Size i = 0; i < nSwapTenors; ++i) {
540 for (
Size j = 0; j < nParams; ++j) {
541 betasReversionGuess[i * nSwapLengths + j] =
543 : std::sqrt(guess[j][i]);
546 betasReversionGuess[nParams] =
548 ObjectiveFunction6 costFunction(
this);
549 Problem problem(costFunction, constraint, betasReversionGuess);
552 error_ = costFunction.value(tmp);
553 result =
Matrix(3, nSwapTenors + 1);
554 for (
Size i = 0; i < nSwapTenors; ++i) {
555 for (
Size j = 0; j < 3; ++j) {
559 : tmp[i * 3 + j] * tmp[i * 3 + j];
562 for (
Size j = 0; j < nSwapLengths; ++j) {
567 const ext::shared_ptr<SabrSwaptionVolatilityCube> volCubeBySabr =
568 ext::dynamic_pointer_cast<SabrSwaptionVolatilityCube>(*
volCube_);
569 volCubeBySabr->updateAfterRecalibration();
1-D array used in linear algebra.
Size size() const
dimension of the array
const_iterator begin() const
static Real reversionTransformDirect(Real y)
Matrix sparseSabrParameters_
static Real betaTransformInverse(Real beta)
Matrix denseSabrParameters_
Matrix computeParametric(const ext::shared_ptr< EndCriteria > &endCriteria, const ext::shared_ptr< OptimizationMethod > &method, const Matrix &guess, bool isMeanReversionFixed, Real meanReversionGuess=Null< Real >())
EndCriteria::Type endCriteria()
Array compute(const ext::shared_ptr< EndCriteria > &endCriteria, const ext::shared_ptr< OptimizationMethod > &method, const Array &guess, bool isMeanReversionFixed)
static Real reversionTransformInverse(Real reversion)
EndCriteria::Type endCriteria_
CmsMarketCalibration(Handle< SwaptionVolatilityStructure > &volCube, ext::shared_ptr< CmsMarket > &cmsMarket, const Matrix &weights, CalibrationType calibrationType)
ext::shared_ptr< CmsMarket > cmsMarket_
static Real betaTransformDirect(Real y)
Handle< SwaptionVolatilityStructure > volCube_
Cost function abstract class for optimization problem.
virtual Array values(const Array &x) const =0
method to overload to compute the cost function values in x
virtual Real value(const Array &x) const
method to overload to compute the cost function value in x
Shared handle to an observable.
Matrix used in linear algebra.
template class providing a null value for a given type.
Constrained optimization problem.
const Array & currentValue() const
current value of the local minimum
Abstract constraint class.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
std::size_t Size
size of a container
Abstract optimization problem class.
Swaption volatility cube, fit-early-interpolate-later approach The provided types are SabrSwaptionVol...