1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2006, 2008 Ferdinando Ametrano
5  Copyright (C) 2006 François du Vignaud
6  Copyright (C) 2006 Katiuscia Manzoni
7  Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
8  Copyright (C) 2015 Peter Caspers
9 
10  This file is part of QuantLib, a free-software/open-source library
11  for financial quantitative analysts and developers - http://quantlib.org/
12 
13  QuantLib is free software: you can redistribute it and/or modify it
14  under the terms of the QuantLib license.  You should have received a
15  copy of the license along with this program; if not, please email
16  <quantlib-dev@lists.sf.net>. The license is also available online at
17  <http://quantlib.org/license.shtml>.
18 
19  This program is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21  FOR A PARTICULAR PURPOSE.  See the license for more details.
22 */
23 
24 #include <ql/termstructures/volatility/swaption/swaptionvolmatrix.hpp>
25 #include <ql/termstructures/volatility/flatsmilesection.hpp>
26 #include <ql/time/calendars/nullcalendar.hpp>
27 #include <ql/utilities/dataformatters.hpp>
28 #include <ql/quotes/simplequote.hpp>
29 #include <ql/math/interpolations/bilinearinterpolation.hpp>
30 #include <ql/math/interpolations/flatextrapolation2d.hpp>
31 
32 
33 namespace QuantLib {
34 
35     // floating reference date, floating market data
SwaptionVolatilityMatrix(const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const std::vector<std::vector<Handle<Quote>>> & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const std::vector<std::vector<Real>> & shifts)36     SwaptionVolatilityMatrix::SwaptionVolatilityMatrix(
37                     const Calendar& cal,
38                     BusinessDayConvention bdc,
39                     const std::vector<Period>& optionT,
40                     const std::vector<Period>& swapT,
41                     const std::vector<std::vector<Handle<Quote> > >& vols,
42                     const DayCounter& dc,
43                     const bool flatExtrapolation,
44                     const VolatilityType type,
45                     const std::vector<std::vector<Real> >& shifts)
46     : SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc),
47       volHandles_(vols), shiftValues_(shifts),
48       volatilities_(vols.size(), vols.front().size()),
49       shifts_(vols.size(), vols.front().size(), 0.0), volatilityType_(type) {
50         checkInputs(volatilities_.rows(), volatilities_.columns(), shifts.size(),
51                     shifts.empty() ? 0 : shifts.front().size());
52         registerWithMarketData();
53         if (flatExtrapolation) {
54             interpolation_ =
55                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
56                     swapLengths_.begin(), swapLengths_.end(),
57                     optionTimes_.begin(), optionTimes_.end(), volatilities_));
58             interpolationShifts_ =
59                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
60                     swapLengths_.begin(), swapLengths_.end(),
61                     optionTimes_.begin(), optionTimes_.end(), shifts_));
62         } else {
63             interpolation_ = BilinearInterpolation(
64                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
65                 optionTimes_.end(), volatilities_);
66             interpolationShifts_ = BilinearInterpolation(
67                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
68                 optionTimes_.end(), shifts_);
69         }
70    }
71 
72     // fixed reference date, floating market data
SwaptionVolatilityMatrix(const Date & refDate,const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const std::vector<std::vector<Handle<Quote>>> & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const std::vector<std::vector<Real>> & shifts)73     SwaptionVolatilityMatrix::SwaptionVolatilityMatrix(
74                     const Date& refDate,
75                     const Calendar& cal,
76                     BusinessDayConvention bdc,
77                     const std::vector<Period>& optionT,
78                     const std::vector<Period>& swapT,
79                     const std::vector<std::vector<Handle<Quote> > >& vols,
80                     const DayCounter& dc,
81                     const bool flatExtrapolation,
82                     const VolatilityType type,
83                     const std::vector<std::vector<Real> >& shifts)
84     : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc),
85       volHandles_(vols), shiftValues_(shifts),
86       volatilities_(vols.size(), vols.front().size()),
87       shifts_(vols.size(), vols.front().size(), 0.0), volatilityType_(type) {
88         checkInputs(volatilities_.rows(), volatilities_.columns(), shifts.size(),
89                     shifts.empty() ? 0 : shifts.front().size());
90         registerWithMarketData();
91         if (flatExtrapolation) {
92             interpolation_ =
93                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
94                     swapLengths_.begin(), swapLengths_.end(),
95                     optionTimes_.begin(), optionTimes_.end(), volatilities_));
96             interpolationShifts_ =
97                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
98                     swapLengths_.begin(), swapLengths_.end(),
99                     optionTimes_.begin(), optionTimes_.end(), shifts_));
100         } else {
101             interpolation_ = BilinearInterpolation(
102                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
103                 optionTimes_.end(), volatilities_);
104             interpolationShifts_ = BilinearInterpolation(
105                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
106                 optionTimes_.end(), shifts_);
107         }
108     }
109 
110     // floating reference date, fixed market data
SwaptionVolatilityMatrix(const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const Matrix & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const Matrix & shifts)111     SwaptionVolatilityMatrix::SwaptionVolatilityMatrix(
112                         const Calendar& cal,
113                         BusinessDayConvention bdc,
114                         const std::vector<Period>& optionT,
115                         const std::vector<Period>& swapT,
116                         const Matrix& vols,
117                         const DayCounter& dc,
118                         const bool flatExtrapolation,
119                         const VolatilityType type,
120                         const Matrix& shifts)
121     : SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc),
122       volHandles_(vols.rows()), shiftValues_(vols.rows()),
123       volatilities_(vols.rows(), vols.columns()),
124       shifts_(vols.rows(), vols.columns(), 0.0), volatilityType_(type) {
125 
126         checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns());
127 
128         // fill dummy handles to allow generic handle-based
129         // computations later on
130         for (Size i=0; i<vols.rows(); ++i) {
131             volHandles_[i].resize(vols.columns());
132             shiftValues_[i].resize(vols.columns());
133             for (Size j=0; j<vols.columns(); ++j) {
134                 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new
135                     SimpleQuote(vols[i][j])));
136                 shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0;
137             }
138         }
139         if (flatExtrapolation) {
140             interpolation_ =
141                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
142                     swapLengths_.begin(), swapLengths_.end(),
143                     optionTimes_.begin(), optionTimes_.end(), volatilities_));
144             interpolationShifts_ =
145                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
146                     swapLengths_.begin(), swapLengths_.end(),
147                     optionTimes_.begin(), optionTimes_.end(), shifts_));
148         } else {
149             interpolation_ = BilinearInterpolation(
150                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
151                 optionTimes_.end(), volatilities_);
152             interpolationShifts_ = BilinearInterpolation(
153                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
154                 optionTimes_.end(), shifts_);
155         }
156     }
157 
158     // fixed reference date, fixed market data
SwaptionVolatilityMatrix(const Date & refDate,const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const Matrix & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const Matrix & shifts)159     SwaptionVolatilityMatrix::SwaptionVolatilityMatrix(
160                         const Date& refDate,
161                         const Calendar& cal,
162                         BusinessDayConvention bdc,
163                         const std::vector<Period>& optionT,
164                         const std::vector<Period>& swapT,
165                         const Matrix& vols,
166                         const DayCounter& dc,
167                         const bool flatExtrapolation,
168                         const VolatilityType type,
169                         const Matrix& shifts)
170     : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc),
171       volHandles_(vols.rows()), shiftValues_(vols.rows()),
172       volatilities_(vols.rows(), vols.columns()),
173       shifts_(shifts.rows(), shifts.columns(), 0.0), volatilityType_(type) {
174 
175         checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns());
176 
177         // fill dummy handles to allow generic handle-based
178         // computations later on
179         for (Size i=0; i<vols.rows(); ++i) {
180             volHandles_[i].resize(vols.columns());
181             shiftValues_[i].resize(vols.columns());
182             for (Size j=0; j<vols.columns(); ++j) {
183                 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new
184                     SimpleQuote(vols[i][j])));
185                 shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0;
186             }
187         }
188         if (flatExtrapolation) {
189             interpolation_ =
190                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
191                     swapLengths_.begin(), swapLengths_.end(),
192                     optionTimes_.begin(), optionTimes_.end(), volatilities_));
193             interpolationShifts_ =
194                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
195                     swapLengths_.begin(), swapLengths_.end(),
196                     optionTimes_.begin(), optionTimes_.end(), shifts_));
197         } else {
198             interpolation_ = BilinearInterpolation(
199                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
200                 optionTimes_.end(), volatilities_);
201             interpolationShifts_ = BilinearInterpolation(
202                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
203                 optionTimes_.end(), shifts_);
204         }
205     }
206 
207     // fixed reference date and fixed market data, option dates
SwaptionVolatilityMatrix(const Date & today,const Calendar & calendar,BusinessDayConvention bdc,const std::vector<Date> & optionDates,const std::vector<Period> & swapT,const Matrix & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const Matrix & shifts)208     SwaptionVolatilityMatrix::SwaptionVolatilityMatrix(
209                     const Date& today,
210                     const Calendar& calendar,
211                     BusinessDayConvention bdc,
212                     const std::vector<Date>& optionDates,
213                     const std::vector<Period>& swapT,
214                     const Matrix& vols,
215                     const DayCounter& dc,
216                     const bool flatExtrapolation,
217                     const VolatilityType type,
218                     const Matrix& shifts)
219     : SwaptionVolatilityDiscrete(optionDates, swapT, today, calendar, bdc, dc),
220       volHandles_(vols.rows()), shiftValues_(vols.rows()),
221       volatilities_(vols.rows(), vols.columns()),
222       shifts_(shifts.rows(),shifts.columns(),0.0), volatilityType_(type) {
223 
224         checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns());
225 
226         // fill dummy handles to allow generic handle-based
227         // computations later on
228         for (Size i=0; i<vols.rows(); ++i) {
229             volHandles_[i].resize(vols.columns());
230             shiftValues_[i].resize(vols.columns());
231             for (Size j=0; j<vols.columns(); ++j) {
232                 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new
233                     SimpleQuote(vols[i][j])));
234                 shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0;
235             }
236         }
237         if (flatExtrapolation) {
238             interpolation_ =
239                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
240                     swapLengths_.begin(), swapLengths_.end(),
241                     optionTimes_.begin(), optionTimes_.end(), volatilities_));
242             interpolationShifts_ =
243                 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>(
244                     swapLengths_.begin(), swapLengths_.end(),
245                     optionTimes_.begin(), optionTimes_.end(), shifts_));
246         } else {
247             interpolation_ = BilinearInterpolation(
248                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
249                 optionTimes_.end(), volatilities_);
250             interpolationShifts_ = BilinearInterpolation(
251                 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(),
252                 optionTimes_.end(), shifts_);
253         }
254     }
255 
256 
checkInputs(Size volRows,Size volsColumns,Size shiftRows,Size shiftsColumns) const257     void SwaptionVolatilityMatrix::checkInputs(Size volRows,
258                                                Size volsColumns,
259                                                Size shiftRows,
260                                                Size shiftsColumns) const {
261         QL_REQUIRE(nOptionTenors_==volRows,
262                    "mismatch between number of option dates (" <<
263                    nOptionTenors_ << ") and number of rows (" << volRows <<
264                    ") in the vol matrix");
265         QL_REQUIRE(nSwapTenors_==volsColumns,
266                    "mismatch between number of swap tenors (" <<
267                    nSwapTenors_ << ") and number of columns (" << volsColumns <<
268                    ") in the vol matrix");
269 
270         if(shiftRows==0 && shiftsColumns==0) {
271             shifts_ = Matrix(volRows, volsColumns, 0.0);
272             shiftRows = volRows;
273             shiftsColumns = volsColumns;
274         }
275 
276         QL_REQUIRE(nOptionTenors_==shiftRows,
277                    "mismatch between number of option dates (" <<
278                    nOptionTenors_ << ") and number of rows (" << shiftRows <<
279                    ") in the shift matrix");
280         QL_REQUIRE(nSwapTenors_==shiftsColumns,
281                    "mismatch between number of swap tenors (" <<
282                    nSwapTenors_ << ") and number of columns (" << shiftsColumns <<
283                    ") in the shift matrix");
284 
285     }
286 
registerWithMarketData()287     void SwaptionVolatilityMatrix::registerWithMarketData()
288     {
289         for (Size i=0; i<volHandles_.size(); ++i)
290             for (Size j=0; j<volHandles_.front().size(); ++j)
291                 registerWith(volHandles_[i][j]);
292     }
293 
performCalculations() const294     void SwaptionVolatilityMatrix::performCalculations() const {
295 
296         SwaptionVolatilityDiscrete::performCalculations();
297 
298         // we might use iterators here...
299         for (Size i=0; i<volatilities_.rows(); ++i) {
300             for (Size j=0; j<volatilities_.columns(); ++j) {
301                 volatilities_[i][j] = volHandles_[i][j]->value();
302                 if (!shiftValues_.empty())
303                     shifts_[i][j] = shiftValues_[i][j];
304             }
305         }
306     }
307 
308     //ext::shared_ptr<SmileSection>
309     //SwaptionVolatilityMatrix::smileSectionImpl(const Date& d,
310     //                                           const Period& swapTenor) const {
311     //    Time optionTime = timeFromReference(d);
312     //    Time swapLength = convertSwapTenor(swapTenor);
313     //    // dummy strike
314     //    Volatility atmVol = volatilityImpl(optionTime, swapLength, 0.05);
315     //    return ext::shared_ptr<SmileSection>(new
316     //        FlatSmileSection(d, atmVol, dayCounter(), referenceDate()));
317     //}
318 
319     ext::shared_ptr<SmileSection>
smileSectionImpl(Time optionTime,Time swapLength) const320     SwaptionVolatilityMatrix::smileSectionImpl(Time optionTime,
321                                                Time swapLength) const {
322         // dummy strike
323         Volatility atmVol = volatilityImpl(optionTime, swapLength, 0.05);
324         return ext::shared_ptr<SmileSection>(new FlatSmileSection(
325             optionTime, atmVol, dayCounter(), Null<Real>(), volatilityType(),
326             shift(optionTime, swapLength, true)));
327     }
328 
329 }
330