Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
optionletcurve.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file qle/termstructures/optionletcurve.hpp
20 \brief Interpolated one-dimensional curve of optionlet volatilities
21*/
22
23#ifndef quantext_optionlet_curve_hpp
24#define quantext_optionlet_curve_hpp
25
26#include <ql/math/comparison.hpp>
27#include <ql/math/interpolations/linearinterpolation.hpp>
28#include <ql/termstructures/interpolatedcurve.hpp>
29#include <ql/termstructures/volatility/flatsmilesection.hpp>
30#include <ql/termstructures/volatility/optionlet/optionletvolatilitystructure.hpp>
31#include <ql/utilities/dataformatters.hpp>
32
33namespace QuantExt {
34
35/*! OptionletVolatilityStructure based on interpolation of one-dimensional vector of optionlet volatilities
36
37 The intended use case for this class is to represent the optionlet volatilities along a strike column of a cap
38 floor volatility surface.
39
40 \ingroup termstructures
41*/
42template <class Interpolator>
43class InterpolatedOptionletCurve : public QuantLib::OptionletVolatilityStructure,
44 protected QuantLib::InterpolatedCurve<Interpolator> {
45
46public:
47 /*! Constructor
48 \param dates The fixing dates of the underlying interest rate index
49 \param volatilities The optionlet volatility at each of the \p dates
50 \param bdc Business day convention used when getting an optionlet expiry date from an optionlet
51 expiry tenor
52 \param dayCounter The day counter used to convert dates to times
53 \param calendar The calendar used when getting an optionlet expiry date from an optionlet expiry tenor
54 and. Also used to advance from today to reference date if necessary.
55 \param volatilityType The volatility type of the provided \p volatilities
56 \param displacement The applicable shift size if the \p volatilityType is \c ShiftedLognormal
57 \param flatFirstPeriod If the volatility between the first date and second date in \p dates is assumed constant
58 and equal to the second element of \p volatilities. This means that the first element of
59 \p volatilities is ignored.
60 \param interpolator The interpolation object used to interpolate between the provided \p dates
61 */
62 InterpolatedOptionletCurve(const std::vector<QuantLib::Date>& dates,
63 const std::vector<QuantLib::Real>& volatilities, QuantLib::BusinessDayConvention bdc,
64 const QuantLib::DayCounter& dayCounter,
65 const QuantLib::Calendar& calendar = QuantLib::Calendar(),
66 QuantLib::VolatilityType volatilityType = QuantLib::Normal,
67 QuantLib::Real displacement = 0.0, bool flatFirstPeriod = true,
68 const Interpolator& interpolator = Interpolator());
69
70 //! \name TermStructure interface
71 //@{
72 QuantLib::Date maxDate() const override;
73 //@}
74
75 //! \name VolatilityTermStructure interface
76 //@{
77 QuantLib::Rate minStrike() const override;
78 QuantLib::Rate maxStrike() const override;
79 //@}
80
81 //! \name OptionletVolatilityStructure interface
82 //@{
83 QuantLib::VolatilityType volatilityType() const override;
84 QuantLib::Real displacement() const override;
85 //@}
86
87 //! \name Other inspectors
88 //@{
89 const std::vector<QuantLib::Time>& times() const;
90 const std::vector<QuantLib::Date>& dates() const;
91 const std::vector<QuantLib::Real>& volatilities() const;
92 const std::vector<QuantLib::Real>& data() const;
93 std::vector<std::pair<QuantLib::Date, QuantLib::Real> > nodes() const;
94 //@}
95
96protected:
97 InterpolatedOptionletCurve(QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter& dayCounter,
98 QuantLib::VolatilityType volatilityType = QuantLib::Normal,
99 QuantLib::Real displacement = 0.0, bool flatFirstPeriod = true,
100 const Interpolator& interpolator = Interpolator());
101
102 InterpolatedOptionletCurve(const QuantLib::Date& referenceDate, const QuantLib::Calendar& calendar,
103 QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter& dayCounter,
104 QuantLib::VolatilityType volatilityType = QuantLib::Normal,
105 QuantLib::Real displacement = 0.0, bool flatFirstPeriod = true,
106 const Interpolator& interpolator = Interpolator());
107
108 InterpolatedOptionletCurve(QuantLib::Natural settlementDays, const QuantLib::Calendar& calendar,
109 QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter& dayCounter,
110 QuantLib::VolatilityType volatilityType = QuantLib::Normal,
111 QuantLib::Real displacement = 0.0, bool flatFirstPeriod = true,
112 const Interpolator& interpolator = Interpolator());
113
114 //! \name OptionletVolatilityStructure interface
115 //@{
116 /*! Gives a flat SmileSection at the requested \p optionTime. The flat value is obtained by interpolating the
117 input volatilities at the given \p optionTime.
118 */
119 QuantLib::ext::shared_ptr<QuantLib::SmileSection> smileSectionImpl(QuantLib::Time optionTime) const override;
120
121 /*! Gives the interpolated optionlet volatility at the requested \p optionTime. The \p strike is ignored.
122 */
123 QuantLib::Real volatilityImpl(QuantLib::Time optionTime, QuantLib::Rate strike) const override;
124 //@}
125
126 //! The fixing dates of the index underlying the optionlets
127 mutable std::vector<QuantLib::Date> dates_;
128
129private:
130 //! The optionlet volatility type
131 QuantLib::VolatilityType volatilityType_;
132
133 //! If the volatility type is ShiftedLognormal, this holds the shift value
134 QuantLib::Real displacement_;
135
136 //! True if the volatility from the initial date to the first date is assumed flat
138
139 //! Initialise the dates and the interpolation object.
140 void initialise();
141};
142
143/*! Term structure based on linear interpolation of optionlet volatilities
144 \ingroup termstructures
145*/
147
148template <class Interpolator>
150 const std::vector<QuantLib::Date>& dates, const std::vector<QuantLib::Real>& volatilities,
151 QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter& dayCounter, const QuantLib::Calendar& calendar,
152 QuantLib::VolatilityType volatilityType, QuantLib::Real displacement, bool flatFirstPeriod,
153 const Interpolator& interpolator)
154 : QuantLib::OptionletVolatilityStructure(dates.at(0), calendar, bdc, dayCounter),
155 QuantLib::InterpolatedCurve<Interpolator>(std::vector<QuantLib::Time>(), volatilities, interpolator),
156 dates_(dates), volatilityType_(volatilityType), displacement_(displacement), flatFirstPeriod_(flatFirstPeriod) {
157 initialise();
158}
159
160template <class Interpolator>
162 const QuantLib::DayCounter& dayCounter,
163 QuantLib::VolatilityType volatilityType,
164 QuantLib::Real displacement, bool flatFirstPeriod,
165 const Interpolator& interpolator)
166 : QuantLib::OptionletVolatilityStructure(bdc, dayCounter), QuantLib::InterpolatedCurve<Interpolator>(interpolator),
167 volatilityType_(volatilityType), displacement_(displacement), flatFirstPeriod_(flatFirstPeriod) {}
168
169template <class Interpolator>
171 const QuantLib::Date& referenceDate, const QuantLib::Calendar& calendar, QuantLib::BusinessDayConvention bdc,
172 const QuantLib::DayCounter& dayCounter, QuantLib::VolatilityType volatilityType, QuantLib::Real displacement,
173 bool flatFirstPeriod, const Interpolator& interpolator)
174 : QuantLib::OptionletVolatilityStructure(referenceDate, calendar, bdc, dayCounter),
175 QuantLib::InterpolatedCurve<Interpolator>(interpolator), volatilityType_(volatilityType),
176 displacement_(displacement), flatFirstPeriod_(flatFirstPeriod) {}
177
178template <class Interpolator>
180 QuantLib::Natural settlementDays, const QuantLib::Calendar& calendar, QuantLib::BusinessDayConvention bdc,
181 const QuantLib::DayCounter& dayCounter, QuantLib::VolatilityType volatilityType, QuantLib::Real displacement,
182 bool flatFirstPeriod, const Interpolator& interpolator)
183 : QuantLib::OptionletVolatilityStructure(settlementDays, calendar, bdc, dayCounter),
184 QuantLib::InterpolatedCurve<Interpolator>(interpolator), volatilityType_(volatilityType),
185 displacement_(displacement), flatFirstPeriod_(flatFirstPeriod) {}
186
187template <class T> inline QuantLib::Date InterpolatedOptionletCurve<T>::maxDate() const {
188 if (this->maxDate_ != Date())
189 return this->maxDate_;
190 return dates_.back();
191}
192
193template <class T> inline QuantLib::Rate InterpolatedOptionletCurve<T>::minStrike() const {
194 if (volatilityType() == QuantLib::ShiftedLognormal) {
195 return displacement_ > 0.0 ? -displacement_ : 0.0;
196 } else {
197 return QL_MIN_REAL;
198 }
199}
200
201template <class T> inline QuantLib::Rate InterpolatedOptionletCurve<T>::maxStrike() const { return QL_MAX_REAL; }
202
203template <class T> inline QuantLib::VolatilityType InterpolatedOptionletCurve<T>::volatilityType() const {
204 return volatilityType_;
205}
206
207template <class T> inline QuantLib::Real InterpolatedOptionletCurve<T>::displacement() const { return displacement_; }
208
209template <class T> inline const std::vector<QuantLib::Time>& InterpolatedOptionletCurve<T>::times() const {
210 return this->times_;
211}
212
213template <class T> inline const std::vector<QuantLib::Date>& InterpolatedOptionletCurve<T>::dates() const {
214 return dates_;
215}
216
217template <class T> inline const std::vector<QuantLib::Real>& InterpolatedOptionletCurve<T>::volatilities() const {
218 if (flatFirstPeriod_)
219 this->data_[0] = this->data_[1];
220 return this->data_;
221}
222
223template <class T> inline const std::vector<QuantLib::Real>& InterpolatedOptionletCurve<T>::data() const {
224 if (flatFirstPeriod_)
225 this->data_[0] = this->data_[1];
226 return this->data_;
227}
228
229template <class T>
230inline std::vector<std::pair<QuantLib::Date, QuantLib::Real> > InterpolatedOptionletCurve<T>::nodes() const {
231 std::vector<std::pair<QuantLib::Date, QuantLib::Real> > results(dates_.size());
232 for (QuantLib::Size i = 0; i < dates_.size(); ++i)
233 results[i] = std::make_pair(dates_[i], this->data_[i]);
234 if (flatFirstPeriod_)
235 results[0].second = this->data_[1];
236 return results;
237}
238
239template <class T>
240QuantLib::ext::shared_ptr<QuantLib::SmileSection>
241InterpolatedOptionletCurve<T>::smileSectionImpl(QuantLib::Time optionTime) const {
242 QuantLib::Volatility vol = volatility(optionTime, 0.0, true);
243 return QuantLib::ext::make_shared<QuantLib::FlatSmileSection>(
244 optionTime, vol, dayCounter(), QuantLib::Null<QuantLib::Rate>(), volatilityType_, displacement_);
245}
246
247template <class T>
248QuantLib::Real InterpolatedOptionletCurve<T>::volatilityImpl(QuantLib::Time optionTime, QuantLib::Rate strike) const {
249 if (flatFirstPeriod_ && optionTime < this->times_[1])
250 return this->data_[1];
251 else
252 return this->interpolation_(optionTime, true);
253}
254
256
257 QL_REQUIRE(dates_.size() >= T::requiredPoints, "Not enough input dates given for interpolation method");
258 QL_REQUIRE(this->data_.size() == dates_.size(), "Number of dates does not equal the number of volatilities");
259
260 this->times_.resize(dates_.size());
261 this->times_[0] = 0.0;
262 for (QuantLib::Size i = 1; i < dates_.size(); ++i) {
263 QL_REQUIRE(dates_[i] > dates_[i - 1], "Dates must be increasing but "
264 << QuantLib::io::ordinal(i) << " date " << dates_[i]
265 << " is not after " << QuantLib::io::ordinal(i - 1) << " date "
266 << dates_[i - 1]);
267 this->times_[i] = dayCounter().yearFraction(dates_[0], dates_[i]);
268 QL_REQUIRE(!QuantLib::close(this->times_[i], this->times_[i - 1]),
269 "The " << QuantLib::io::ordinal(i) << " date " << dates_[i] << " and "
270 << QuantLib::io::ordinal(i - 1) << " date " << dates_[i - 1]
271 << " correspond to the same time, " << this->times_[i]
272 << ", under this curve's day count convention, " << dayCounter());
273 QL_REQUIRE(this->data_[i] > 0.0,
274 "The " << QuantLib::io::ordinal(i) << " volatility, " << this->data_[i] << ", is not positive");
275 }
276
277 if (flatFirstPeriod_)
278 this->data_[0] = this->data_[1];
279
280 this->setupInterpolation();
281}
282
283} // namespace QuantExt
284
285#endif
QuantLib::Real volatilityImpl(QuantLib::Time optionTime, QuantLib::Rate strike) const override
void initialise()
Initialise the dates and the interpolation object.
QuantLib::Real displacement() const override
std::vector< QuantLib::Date > dates_
The fixing dates of the index underlying the optionlets.
const std::vector< QuantLib::Time > & times() const
const std::vector< QuantLib::Real > & data() const
QuantLib::VolatilityType volatilityType() const override
QuantLib::VolatilityType volatilityType_
The optionlet volatility type.
QuantLib::ext::shared_ptr< QuantLib::SmileSection > smileSectionImpl(QuantLib::Time optionTime) const override
QuantLib::Date maxDate() const override
const std::vector< QuantLib::Real > & volatilities() const
InterpolatedOptionletCurve(const std::vector< QuantLib::Date > &dates, const std::vector< QuantLib::Real > &volatilities, QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter &dayCounter, const QuantLib::Calendar &calendar=QuantLib::Calendar(), QuantLib::VolatilityType volatilityType=QuantLib::Normal, QuantLib::Real displacement=0.0, bool flatFirstPeriod=true, const Interpolator &interpolator=Interpolator())
QuantLib::Rate minStrike() const override
const std::vector< QuantLib::Date > & dates() const
QuantLib::Rate maxStrike() const override
std::vector< std::pair< QuantLib::Date, QuantLib::Real > > nodes() const
QuantLib::Real displacement_
If the volatility type is ShiftedLognormal, this holds the shift value.
bool flatFirstPeriod_
True if the volatility from the initial date to the first date is assumed flat.
InterpolatedOptionletCurve< QuantLib::Linear > OptionletCurve