1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4 
5 Copyright (C) 2007 Mark Joshi
6 
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9 
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license.  You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE.  See the license for more details.
19 */
20 
21 #include <ql/models/marketmodels/models/capletcoterminalperiodic.hpp>
22 #include <ql/models/marketmodels/models/capletcoterminalmaxhomogeneity.hpp>
23 #include <ql/models/marketmodels/models/piecewiseconstantvariance.hpp>
24 #include <ql/models/marketmodels/models/volatilityinterpolationspecifier.hpp>
25 #include <ql/math/matrix.hpp>
26 #include <ql/models/marketmodels/curvestate.hpp>
27 #include <ql/models/marketmodels/evolutiondescription.hpp>
28 #include <ql/models/marketmodels/piecewiseconstantcorrelation.hpp>
29 #include <ql/models/marketmodels/models/pseudorootfacade.hpp>
30 #include <ql/models/marketmodels/models/cotswaptofwdadapter.hpp>
31 #include <ql/models/marketmodels/models/fwdperiodadapter.hpp>
32 #include <ql/models/marketmodels/models/fwdtocotswapadapter.hpp>
33 #include <ql/shared_ptr.hpp>
34 #include <vector>
35 
36 namespace QuantLib
37 {
38 
39     // for the displaced swap
40 
capletSwaptionPeriodicCalibration(const EvolutionDescription & evolution,const ext::shared_ptr<PiecewiseConstantCorrelation> & corr,VolatilityInterpolationSpecifier & displacedSwapVariances,const std::vector<Volatility> & capletVols,const ext::shared_ptr<CurveState> & cs,const Spread displacement,Real caplet0Swaption1Priority,Size numberOfFactors,Size period,Size max1dIterations,Real tolerance1d,Size maxUnperiodicIterations,Real toleranceUnperiodic,Size maxPeriodIterations,Real periodTolerance,Real &,Real & totalSwaptionError,std::vector<Matrix> & swapCovariancePseudoRoots,std::vector<Real> & finalScales,Size & iterationsDone,Real & errorImprovement,Matrix & modelSwaptionVolsMatrix)41     Integer capletSwaptionPeriodicCalibration(
42         const EvolutionDescription& evolution,
43         const ext::shared_ptr<PiecewiseConstantCorrelation>& corr,
44         VolatilityInterpolationSpecifier&
45         displacedSwapVariances,
46         const std::vector<Volatility>& capletVols,
47         const ext::shared_ptr<CurveState>& cs,
48         const Spread displacement,
49         Real caplet0Swaption1Priority,
50         Size numberOfFactors,
51         Size period,
52         Size max1dIterations,
53         Real tolerance1d,
54         Size maxUnperiodicIterations,
55         Real toleranceUnperiodic,
56         Size maxPeriodIterations,
57         Real periodTolerance,
58         Real& , // deformationSize used to return information, not set yet
59         Real& totalSwaptionError, // ?
60         std::vector<Matrix>& swapCovariancePseudoRoots,  // the thing we really want the pseudo root for each time step
61         std::vector<Real> & finalScales,  //scalings used for matching
62         Size& iterationsDone, // number of  period iteratations done
63         Real& errorImprovement, // improvement in error for last iteration
64         Matrix& modelSwaptionVolsMatrix // the swaption vols calibrated to at each step of the iteration
65         )
66     {
67 
68         Size numberSmallRates = evolution.numberOfRates();
69         Size numberSmallSteps = evolution.numberOfSteps();
70 
71         QL_REQUIRE( numberSmallSteps == numberSmallRates,
72             "periodic calibration class requires evolution to the reset of each rate");
73 
74         Size numberBigRates = numberSmallRates/period;
75         Size offset = numberSmallRates % period;
76 
77         std::vector<Spread> newDisplacements(numberBigRates,displacement);
78 
79         QL_REQUIRE(displacedSwapVariances.getNoBigRates() == numberBigRates,
80             "mismatch between number of swap variances given and number of rates and period");
81 
82         Integer failures=0;
83 
84 
85         std::vector<Real> scalingFactors(numberBigRates);
86         for (Size i=0; i < numberBigRates; ++i)
87             scalingFactors[i] =1.0;
88 
89         displacedSwapVariances.setLastCapletVol(*capletVols.rbegin());
90 
91 
92         std::vector<Real> marketSwaptionVols(numberBigRates);
93         for (Size i=0; i < numberBigRates; ++i) {
94             marketSwaptionVols[i] =
95                 displacedSwapVariances.originalVariances()[i]->totalVolatility(i);
96         }
97 
98         std::vector<Real> modelSwaptionVols(numberBigRates);
99 
100         Real periodSwaptionRmsError;
101 
102         iterationsDone = 0;
103 
104         Real previousError = 1.0e+10; // very large number
105 
106 
107         modelSwaptionVolsMatrix =Matrix(maxPeriodIterations,numberBigRates,0.0);
108 
109 
110         do
111         {
112             displacedSwapVariances.setScalingFactors(scalingFactors);
113 
114 
115             CTSMMCapletMaxHomogeneityCalibration unperiodicCalibrator(
116                 evolution,
117                 corr,
118                 displacedSwapVariances.interpolatedVariances(),
119                 capletVols,
120                 cs,
121                 displacement,
122                 caplet0Swaption1Priority);
123 
124 
125             failures = static_cast<QuantLib::Integer>(
126                 unperiodicCalibrator.calibrate(numberOfFactors, maxUnperiodicIterations,
127                                                toleranceUnperiodic, max1dIterations, tolerance1d));
128 
129             swapCovariancePseudoRoots = unperiodicCalibrator.swapPseudoRoots();
130 
131             ext::shared_ptr<MarketModel> smm(new
132                 PseudoRootFacade(swapCovariancePseudoRoots,
133                 evolution.rateTimes(),
134                 cs->coterminalSwapRates(),
135                 std::vector<Spread>(evolution.numberOfRates(), displacement)));
136 
137             ext::shared_ptr<MarketModel> flmm(new CotSwapToFwdAdapter(smm));
138 
139             Matrix capletTotCovariance = flmm->totalCovariance(numberSmallRates-1);
140 
141             ext::shared_ptr<MarketModel> periodflmm( new FwdPeriodAdapter(flmm, period,
142                 offset,
143                 newDisplacements));
144 
145             ext::shared_ptr<MarketModel> periodsmm(new FwdToCotSwapAdapter(periodflmm));
146 
147 
148             Matrix swaptionTotCovariance(periodsmm->totalCovariance(periodsmm->numberOfSteps()-1));
149 
150 
151 
152             totalSwaptionError=0.0;
153 
154             for (Size i=0; i < numberBigRates; ++i)
155             {
156                 modelSwaptionVols[i] = std::sqrt(swaptionTotCovariance[i][i]/periodsmm->evolution().rateTimes()[i]);
157                 Real scale = marketSwaptionVols[i]/modelSwaptionVols[i];
158                 scalingFactors[i] *= scale; // since applied to vol
159 
160                 totalSwaptionError +=  (marketSwaptionVols[i]-modelSwaptionVols[i])* (marketSwaptionVols[i]-modelSwaptionVols[i]);
161 
162             }
163 
164             for (Size i=0; i < numberBigRates; ++i)
165                 modelSwaptionVolsMatrix[iterationsDone][i] = modelSwaptionVols[i];
166 
167             periodSwaptionRmsError = std::sqrt(totalSwaptionError/numberBigRates);
168             errorImprovement = previousError -periodSwaptionRmsError;
169             previousError = periodSwaptionRmsError;
170         }
171         while (errorImprovement> periodTolerance/10.0 && periodSwaptionRmsError >periodTolerance && ++iterationsDone < maxPeriodIterations);
172 
173         finalScales = scalingFactors;
174 
175         return failures;
176 
177     }
178 
179 
180 }
181