Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
piecewiseatmoptionletcurve.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/piecewiseatmoptionletcurve.hpp
20 \brief Create optionlet volatility structure from at-the-money cap floor term volatility curve
21*/
22
23#ifndef quantext_piecewiseatmoptionletcurve_hpp
24#define quantext_piecewiseatmoptionletcurve_hpp
25
29
30namespace QuantExt {
31
32/*! Helper class to strip caplet/floorlet volatilities from the cap floor term volatilities of a
33 CapFloorTermVolCurve.
34*/
35template <class Interpolator, template <class> class Bootstrap = QuantExt::IterativeBootstrap>
36class PiecewiseAtmOptionletCurve : public QuantLib::OptionletVolatilityStructure, public QuantLib::LazyObject {
37
38public:
40
41 PiecewiseAtmOptionletCurve(QuantLib::Natural settlementDays, const QuantLib::ext::shared_ptr<CapFloorTermVolCurve>& cftvc,
42 const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index,
43 const QuantLib::Handle<QuantLib::YieldTermStructure>& discount,
44 bool flatFirstPeriod = true,
45 const QuantLib::VolatilityType capFloorVolType = QuantLib::ShiftedLognormal,
46 const QuantLib::Real capFloorVolDisplacement = 0.0,
47 const boost::optional<QuantLib::VolatilityType> optionletVolType = boost::none,
48 const boost::optional<QuantLib::Real> optionletVolDisplacement = boost::none,
49 bool interpOnOptionlets = true, const Interpolator& i = Interpolator(),
50 const Bootstrap<optionlet_curve>& bootstrap = Bootstrap<optionlet_curve>());
51
52 PiecewiseAtmOptionletCurve(const QuantLib::Date& referenceDate,
53 const QuantLib::ext::shared_ptr<CapFloorTermVolCurve>& cftvc,
54 const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index,
55 const QuantLib::Handle<QuantLib::YieldTermStructure>& discount,
56 bool flatFirstPeriod = true,
57 const QuantLib::VolatilityType capFloorVolType = QuantLib::ShiftedLognormal,
58 const QuantLib::Real capFloorVolDisplacement = 0.0,
59 const boost::optional<QuantLib::VolatilityType> optionletVolType = boost::none,
60 const boost::optional<QuantLib::Real> optionletVolDisplacement = boost::none,
61 bool interpOnOptionlets = true, const Interpolator& i = Interpolator(),
62 const Bootstrap<optionlet_curve>& bootstrap = Bootstrap<optionlet_curve>());
63
64 //! \name Inspectors
65 //@{
66 //! Volatility type for the underlying ATM cap floor curve
67 QuantLib::VolatilityType capFloorVolType() const { return capFloorVolType_; }
68
69 //! The applicable shift if the underlying ATM cap floor curve has shifted lognormal volatility
70 QuantLib::Real capFloorVolDisplacement() const { return capFloorVolDisplacement_; }
71
72 //! \name Observer interface
73 //@{
74 void update() override;
75 //@}
76
77 //! \name LazyObject interface
78 //@{
79 void performCalculations() const override;
80 //@}
81
82 //! \name TermStructure interface
83 //@{
84 QuantLib::Date maxDate() const override;
85 //@}
86
87 //! \name VolatilityTermStructure interface
88 //@{
89 QuantLib::Rate minStrike() const override;
90 QuantLib::Rate maxStrike() const override;
91 //@}
92
93 //! \name OptionletVolatilityStructure interface
94 //@{
95 QuantLib::VolatilityType volatilityType() const override;
96 QuantLib::Real displacement() const override;
97 //@}
98
99 //! The underlying optionlet curve
100 QuantLib::ext::shared_ptr<optionlet_curve> curve() const;
101
102protected:
103 //! \name OptionletVolatilityStructure interface
104 //@{
105 QuantLib::ext::shared_ptr<QuantLib::SmileSection> smileSectionImpl(QuantLib::Time optionTime) const override;
106 QuantLib::Volatility volatilityImpl(QuantLib::Time optionTime, QuantLib::Rate strike) const override;
107 //@}
108
109private:
110 //! The underlying ATM cap floor term volatility curve
111 QuantLib::ext::shared_ptr<CapFloorTermVolCurve> cftvc_;
112
113 //! Flat optionlet volatility before first optionlet fixing date
115
116 //! Volatility type for the underlying ATM cap floor volatility curve
117 QuantLib::VolatilityType capFloorVolType_;
118
119 //! The applicable shift if the underlying ATM cap floor volatility curve has shifted lognormal volatility
121
122 //! This optionlet structure's volatility type
123 QuantLib::VolatilityType volatilityType_;
124
125 //! This optionlet structure's shift if its volatility type is shifted lognormal
126 QuantLib::Real displacement_;
127
128 //! True to interpolate on optionlet volatilities, false to interpolate on cap floor term volatilities
130
131 //! The interpolator
132 Interpolator interpolator_;
133
134 //! The bootstrapper
135 Bootstrap<optionlet_curve> bootstrap_;
136
137 //! The stripped optionlet curve
138 QuantLib::ext::shared_ptr<optionlet_curve> curve_;
139
140 //! Store the helper tenors
141 std::vector<QuantLib::Period> tenors_;
142
143 //! Store the vector of ATM cap floor helpers that are used in the bootstrap
144 typedef QuantLib::BootstrapHelper<QuantLib::OptionletVolatilityStructure> helper;
145 std::vector<QuantLib::ext::shared_ptr<helper> > helpers_;
146
147 //! Store the ATM cap floor curve quotes
148 std::vector<QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> > quotes_;
149
150 //! Shared initialisation
151 void initialise(const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index,
152 const QuantLib::Handle<QuantLib::YieldTermStructure>& discount);
153};
154
155template <class Interpolator, template <class> class Bootstrap>
157 QuantLib::Natural settlementDays, const QuantLib::ext::shared_ptr<CapFloorTermVolCurve>& cftvc,
158 const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index, const QuantLib::Handle<QuantLib::YieldTermStructure>& discount,
159 bool flatFirstPeriod, const QuantLib::VolatilityType capFloorVolType, const QuantLib::Real capFloorVolDisplacement,
160 const boost::optional<QuantLib::VolatilityType> optionletVolType,
161 const boost::optional<QuantLib::Real> optionletVolDisplacement, bool interpOnOptionlets, const Interpolator& i,
162 const Bootstrap<optionlet_curve>& bootstrap)
163 : QuantLib::OptionletVolatilityStructure(settlementDays, cftvc->calendar(), cftvc->businessDayConvention(),
164 cftvc->dayCounter()),
165 cftvc_(cftvc), flatFirstPeriod_(flatFirstPeriod), capFloorVolType_(capFloorVolType),
166 capFloorVolDisplacement_(capFloorVolDisplacement),
167 volatilityType_(optionletVolType ? *optionletVolType : capFloorVolType),
168 displacement_(optionletVolDisplacement ? *optionletVolDisplacement : 0.0),
169 interpOnOptionlets_(interpOnOptionlets), interpolator_(i), bootstrap_(bootstrap), tenors_(cftvc_->optionTenors()),
170 helpers_(tenors_.size()), quotes_(tenors_.size()) {
171
172 initialise(index, discount);
173
174 curve_ = QuantLib::ext::make_shared<optionlet_curve>(settlementDays, helpers_, cftvc_->calendar(),
175 cftvc_->businessDayConvention(), cftvc_->dayCounter(), volatilityType_,
177}
178
179template <class Interpolator, template <class> class Bootstrap>
181 const QuantLib::Date& referenceDate, const QuantLib::ext::shared_ptr<CapFloorTermVolCurve>& cftvc,
182 const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index, const QuantLib::Handle<QuantLib::YieldTermStructure>& discount,
183 bool flatFirstPeriod, const QuantLib::VolatilityType capFloorVolType, const QuantLib::Real capFloorVolDisplacement,
184 const boost::optional<QuantLib::VolatilityType> optionletVolType,
185 const boost::optional<QuantLib::Real> optionletVolDisplacement, bool interpOnOptionlets, const Interpolator& i,
186 const Bootstrap<optionlet_curve>& bootstrap)
187 : QuantLib::OptionletVolatilityStructure(referenceDate, cftvc->calendar(), cftvc->businessDayConvention(),
188 cftvc->dayCounter()),
189 cftvc_(cftvc), flatFirstPeriod_(flatFirstPeriod), capFloorVolType_(capFloorVolType),
190 capFloorVolDisplacement_(capFloorVolDisplacement),
191 volatilityType_(optionletVolType ? *optionletVolType : capFloorVolType),
192 displacement_(optionletVolDisplacement ? *optionletVolDisplacement : 0.0),
193 interpOnOptionlets_(interpOnOptionlets), interpolator_(i), bootstrap_(bootstrap), tenors_(cftvc_->optionTenors()),
194 helpers_(tenors_.size()), quotes_(tenors_.size()) {
195
196 initialise(index, discount);
197
198 curve_ = QuantLib::ext::make_shared<optionlet_curve>(referenceDate, helpers_, cftvc_->calendar(),
199 cftvc_->businessDayConvention(), cftvc_->dayCounter(), volatilityType_,
201}
202
203template <class Interpolator, template <class> class Bootstrap>
205
206 LazyObject::update();
207
208 if (this->moving_)
209 this->updated_ = false;
210}
211
212template <class Interpolator, template <class> class Bootstrap>
214
215 // Update the quotes from the cap floor term volatility surface
216 for (QuantLib::Size i = 0; i < tenors_.size(); i++) {
217 quotes_[i]->setValue(cftvc_->volatility(tenors_[i], 0.01));
218 }
219}
220
221template <class Interpolator, template <class> class Bootstrap>
223 calculate();
224 return curve_->maxDate();
225}
226
227template <class Interpolator, template <class> class Bootstrap>
229 calculate();
230 return curve_->minStrike();
231}
232
233template <class Interpolator, template <class> class Bootstrap>
235 calculate();
236 return curve_->maxStrike();
237}
238
239template <class Interpolator, template <class> class Bootstrap>
241 return volatilityType_;
242}
243
244template <class Interpolator, template <class> class Bootstrap>
246 return displacement_;
247}
248
249template <class Interpolator, template <class> class Bootstrap>
250QuantLib::ext::shared_ptr<typename PiecewiseAtmOptionletCurve<Interpolator, Bootstrap>::optionlet_curve>
252 calculate();
253 return curve_;
254}
255
256template <class Interpolator, template <class> class Bootstrap>
257QuantLib::ext::shared_ptr<QuantLib::SmileSection>
259 calculate();
260 return curve_->smileSection(optionTime, true);
261}
262
263template <class Interpolator, template <class> class Bootstrap>
264QuantLib::Volatility PiecewiseAtmOptionletCurve<Interpolator, Bootstrap>::volatilityImpl(QuantLib::Time optionTime,
265 QuantLib::Rate strike) const {
266 calculate();
267 return curve_->volatility(optionTime, 0.01, true);
268}
269
270template <class Interpolator, template <class> class Bootstrap>
272 const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& index,
273 const QuantLib::Handle<QuantLib::YieldTermStructure>& discount) {
274
275 // Readability
276 using QuantLib::Handle;
277 using QuantLib::Null;
278 using QuantLib::Period;
279 using QuantLib::Quote;
280 using QuantLib::Rate;
281 using QuantLib::Real;
282 using QuantLib::SimpleQuote;
283 using QuantLib::Size;
284 using std::vector;
285
286 // Observe the underlying cap floor term volatility curve
287 registerWith(cftvc_);
288
289 // If the term structure is not moving, ensure that the cap floor helpers are not moving and are set up with the
290 // correct effective date relative to the reference date. Mimic logic in MakeCapFloor here.
291 Date effectiveDate;
292 if (!this->moving_) {
293 Calendar cal = index->fixingCalendar();
294 Date ref = referenceDate();
295 ref = cal.adjust(ref);
296 effectiveDate = cal.advance(ref, index->fixingDays() * Days);
297 }
298
299 // Number of tenors, helpers and quotes depends on whether we are interpolating on optionlet volatilities or
300 // cap floor term volatilities
301 if (!interpOnOptionlets_) {
302
303 // We are interpolating on the cap floor term volatilities
304 Period indexTenor = index->tenor();
305 Period maxCapFloorTenor = tenors_.back();
306
307 // Add tenor of first cap floor - 2 x index tenor since first optionlet is excluded
308 tenors_.clear();
309 tenors_.push_back(indexTenor + indexTenor);
310 QL_REQUIRE(maxCapFloorTenor >= tenors_.back(),
311 "First cap floor tenor, " << tenors_.back()
312 << ", is greater than cap floor term vol surface's max tenor, "
313 << maxCapFloorTenor);
314
315 // Add all term cap floor instruments up to max tenor of term vol surface
316 Period nextTenor = tenors_.back() + indexTenor;
317 while (nextTenor <= maxCapFloorTenor) {
318 tenors_.push_back(nextTenor);
319 nextTenor += indexTenor;
320 }
321
322 // Resize the helpers and quotes vectors
323 quotes_.resize(tenors_.size());
324 helpers_.resize(tenors_.size());
325 }
326
327 // Initialise the quotes and helpers
328 for (Size i = 0; i < tenors_.size(); i++) {
329 quotes_[i] = QuantLib::ext::make_shared<SimpleQuote>(cftvc_->volatility(tenors_[i], 0.01));
330 helpers_[i] = QuantLib::ext::make_shared<CapFloorHelper>(
331 CapFloorHelper::Cap, tenors_[i], Null<Real>(), Handle<Quote>(quotes_[i]), index, discount, this->moving_,
332 effectiveDate, CapFloorHelper::Volatility, capFloorVolType_, capFloorVolDisplacement_);
333 }
334}
335
336} // namespace QuantExt
337
338#endif
Cap floor at-the-money term volatility curve.
std::vector< QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > > quotes_
Store the ATM cap floor curve quotes.
QuantLib::Real displacement() const override
std::vector< QuantLib::ext::shared_ptr< helper > > helpers_
QuantLib::ext::shared_ptr< optionlet_curve > curve_
The stripped optionlet curve.
PiecewiseOptionletCurve< Interpolator, Bootstrap >::this_curve optionlet_curve
QuantLib::VolatilityType capFloorVolType() const
Volatility type for the underlying ATM cap floor curve.
QuantLib::Volatility volatilityImpl(QuantLib::Time optionTime, QuantLib::Rate strike) const override
std::vector< QuantLib::Period > tenors_
Store the helper tenors.
QuantLib::VolatilityType volatilityType() const override
QuantLib::VolatilityType capFloorVolType_
Volatility type for the underlying ATM cap floor volatility curve.
QuantLib::Real capFloorVolDisplacement_
The applicable shift if the underlying ATM cap floor volatility curve has shifted lognormal volatilit...
QuantLib::VolatilityType volatilityType_
This optionlet structure's volatility type.
QuantLib::ext::shared_ptr< optionlet_curve > curve() const
The underlying optionlet curve.
QuantLib::ext::shared_ptr< QuantLib::SmileSection > smileSectionImpl(QuantLib::Time optionTime) const override
Bootstrap< optionlet_curve > bootstrap_
The bootstrapper.
QuantLib::ext::shared_ptr< CapFloorTermVolCurve > cftvc_
The underlying ATM cap floor term volatility curve.
PiecewiseAtmOptionletCurve(QuantLib::Natural settlementDays, const QuantLib::ext::shared_ptr< CapFloorTermVolCurve > &cftvc, const QuantLib::ext::shared_ptr< QuantLib::IborIndex > &index, const QuantLib::Handle< QuantLib::YieldTermStructure > &discount, bool flatFirstPeriod=true, const QuantLib::VolatilityType capFloorVolType=QuantLib::ShiftedLognormal, const QuantLib::Real capFloorVolDisplacement=0.0, const boost::optional< QuantLib::VolatilityType > optionletVolType=boost::none, const boost::optional< QuantLib::Real > optionletVolDisplacement=boost::none, bool interpOnOptionlets=true, const Interpolator &i=Interpolator(), const Bootstrap< optionlet_curve > &bootstrap=Bootstrap< optionlet_curve >())
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
Store the vector of ATM cap floor helpers that are used in the bootstrap.
bool interpOnOptionlets_
True to interpolate on optionlet volatilities, false to interpolate on cap floor term volatilities.
QuantLib::Real displacement_
This optionlet structure's shift if its volatility type is shifted lognormal.
QuantLib::Real capFloorVolDisplacement() const
The applicable shift if the underlying ATM cap floor curve has shifted lognormal volatility.
void initialise(const QuantLib::ext::shared_ptr< QuantLib::IborIndex > &index, const QuantLib::Handle< QuantLib::YieldTermStructure > &discount)
Shared initialisation.
bool flatFirstPeriod_
Flat optionlet volatility before first optionlet fixing date.
Straight copy of ql/termstructures/iterativebootstrap.hpp with minor changes.
One-dimensional curve of bootstrapped optionlet volatilities.