Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
dynamicblackvoltermstructure.cpp File Reference
#include "toplevelfixture.hpp"
#include "utilities.hpp"
#include <boost/test/unit_test.hpp>
#include <qle/termstructures/dynamicblackvoltermstructure.hpp>
#include <ql/math/matrix.hpp>
#include <ql/quotes/simplequote.hpp>
#include <ql/termstructures/volatility/equityfx/blackvariancesurface.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/calendars/target.hpp>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testConstantVarianceStickyStrike)
 
 BOOST_AUTO_TEST_CASE (testConstantVarianceStickyLogMoneyness)
 
 BOOST_AUTO_TEST_CASE (testForwardVarianceStickyStrike)
 
 BOOST_AUTO_TEST_CASE (testForwardVarianceStickyLogMoneyness)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/4]

BOOST_AUTO_TEST_CASE ( testConstantVarianceStickyStrike  )

Definition at line 91 of file dynamicblackvoltermstructure.cpp.

91 {
92
93 BOOST_TEST_MESSAGE("Testing constant variance, sticky strike dynamics of "
94 "DynamicBlackVolTermStructure...");
95
96 TestData d;
97
98 Handle<DynamicBlackVolTermStructure<tag::surface> > dyn(
99 QuantLib::ext::make_shared<DynamicBlackVolTermStructure<tag::surface> >(
100 d.refVol, 0, TARGET(), ConstantVariance, StickyStrike, d.riskfreeTs, d.dividendTs, d.spot_q));
101
102 dyn->enableExtrapolation();
103
104 Real tol = 1.0E-8;
105
106 // initially we should get the same volatilities
107
108 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.80), d.refVol->blackVol(0.5, 0.80), tol);
109 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.90), d.refVol->blackVol(0.5, 0.90), tol);
110 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.95), d.refVol->blackVol(0.5, 0.95), tol);
111 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 1.15), d.refVol->blackVol(0.5, 1.15), tol);
112
113 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackVol(1.5, 0.80), tol);
114 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackVol(1.5, 0.90), tol);
115 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackVol(1.5, 0.95), tol);
116 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackVol(1.5, 1.15), tol);
117
118 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.80), d.refVol->blackVol(5.0, 0.80), tol);
119 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.90), d.refVol->blackVol(5.0, 0.90), tol);
120 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.95), d.refVol->blackVol(5.0, 0.95), tol);
121 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 1.15), d.refVol->blackVol(5.0, 1.15), tol);
122
123 // check atm vol retrieval via null strike (atm is spot here)
124
125 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, Null<Real>()), d.refVol->blackVol(0.5, d.spot->value()), tol);
126 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, Null<Real>()), d.refVol->blackVol(1.5, d.spot->value()), tol);
127 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, Null<Real>()), d.refVol->blackVol(5.0, d.spot->value()), tol);
128
129 // move forward in time, we expect a constant surface in every respect
130 // even when atm is changing via spot or rates
131
132 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 6 * Months);
133 d.spot->setValue(0.9);
134 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, 0.80), d.refVol->blackVol(0.7, 0.80), tol);
135 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, 0.90), d.refVol->blackVol(0.7, 0.90), tol);
136 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, 0.95), d.refVol->blackVol(0.7, 0.95), tol);
137 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, 1.15), d.refVol->blackVol(0.7, 1.15), tol);
138
139 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 18 * Months);
140 d.rate->setValue(0.01);
141 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, 0.80), d.refVol->blackVol(1.7, 0.80), tol);
142 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, 0.90), d.refVol->blackVol(1.7, 0.90), tol);
143 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, 0.95), d.refVol->blackVol(1.7, 0.95), tol);
144 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, 1.15), d.refVol->blackVol(1.7, 1.15), tol);
145
146 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 3 * Years);
147 d.div->setValue(0.03);
148 BOOST_CHECK_CLOSE(dyn->blackVol(1.71, 0.80), d.refVol->blackVol(1.71, 0.80), tol);
149 BOOST_CHECK_CLOSE(dyn->blackVol(1.71, 0.90), d.refVol->blackVol(1.71, 0.90), tol);
150 BOOST_CHECK_CLOSE(dyn->blackVol(1.71, 0.95), d.refVol->blackVol(1.71, 0.95), tol);
151 BOOST_CHECK_CLOSE(dyn->blackVol(1.71, 1.15), d.refVol->blackVol(1.71, 1.15), tol);
152
153} // testConstantVarianceStickyStrike
Takes a BlackVolTermStructure with fixed reference date and turns it into a floating reference date t...
@ ConstantVariance

◆ BOOST_AUTO_TEST_CASE() [2/4]

BOOST_AUTO_TEST_CASE ( testConstantVarianceStickyLogMoneyness  )

Definition at line 155 of file dynamicblackvoltermstructure.cpp.

155 {
156
157 BOOST_TEST_MESSAGE("Testing constant variance, sticky log-moneyness "
158 "dynamics of DynamicBlackVolTermStructure...");
159
160 TestData d;
161
162 Handle<DynamicBlackVolTermStructure<tag::surface> > dyn(
163 QuantLib::ext::make_shared<DynamicBlackVolTermStructure<tag::surface> >(
164 d.refVol, 0, TARGET(), ConstantVariance, StickyLogMoneyness, d.riskfreeTs, d.dividendTs, d.spot_q));
165
166 dyn->enableExtrapolation();
167
168 Real tol = 1.0E-8;
169
170 // initially we should get the same volatilities
171
172 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.80), d.refVol->blackVol(0.5, 0.80), tol);
173 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.90), d.refVol->blackVol(0.5, 0.90), tol);
174 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.95), d.refVol->blackVol(0.5, 0.95), tol);
175 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 1.15), d.refVol->blackVol(0.5, 1.15), tol);
176
177 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackVol(1.5, 0.80), tol);
178 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackVol(1.5, 0.90), tol);
179 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackVol(1.5, 0.95), tol);
180 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackVol(1.5, 1.15), tol);
181
182 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.80), d.refVol->blackVol(5.0, 0.80), tol);
183 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.90), d.refVol->blackVol(5.0, 0.90), tol);
184 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.95), d.refVol->blackVol(5.0, 0.95), tol);
185 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 1.15), d.refVol->blackVol(5.0, 1.15), tol);
186
187 // move forward in time, in time direction we expect a constant
188 // surface, but the strike range is constant in log money now
189 // instead of absolute strike
190
191 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 6 * Months);
192
193 Real atm0 = d.spot->value(); // original atm value
194 d.spot->setValue(0.9);
195 Real atm = d.spot->value(); // new atm value
196
197 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, atm * std::exp(-0.25)), d.refVol->blackVol(0.7, atm0 * std::exp(-0.25)), tol);
198 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, atm * std::exp(0.00)), d.refVol->blackVol(0.7, atm0 * std::exp(0.00)), tol);
199 BOOST_CHECK_CLOSE(dyn->blackVol(0.7, atm * std::exp(0.25)), d.refVol->blackVol(0.7, atm0 * std::exp(0.25)), tol);
200
201 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, atm * std::exp(-0.25)), d.refVol->blackVol(1.7, atm0 * std::exp(-0.25)), tol);
202 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, atm * std::exp(0.00)), d.refVol->blackVol(1.7, atm0 * std::exp(0.00)), tol);
203 BOOST_CHECK_CLOSE(dyn->blackVol(1.7, atm * std::exp(0.25)), d.refVol->blackVol(1.7, atm0 * std::exp(0.25)), tol);
204
205 BOOST_CHECK_CLOSE(dyn->blackVol(3.0, atm * std::exp(-0.25)), d.refVol->blackVol(3.0, atm0 * std::exp(-0.25)), tol);
206 BOOST_CHECK_CLOSE(dyn->blackVol(3.0, atm * std::exp(0.00)), d.refVol->blackVol(3.0, atm0 * std::exp(0.00)), tol);
207 BOOST_CHECK_CLOSE(dyn->blackVol(3.0, atm * std::exp(0.25)), d.refVol->blackVol(3.0, atm0 * std::exp(0.25)), tol);
208
209 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 18 * Months);
210 d.rate->setValue(0.01);
211 // new atm for t=1.8
212 atm = d.spot->value() / d.riskfreeTs->discount(1.8) * d.dividendTs->discount(1.8);
213
214 BOOST_CHECK_CLOSE(dyn->blackVol(1.8, atm * std::exp(-0.25)), d.refVol->blackVol(1.8, atm0 * std::exp(-0.25)), tol);
215 BOOST_CHECK_CLOSE(dyn->blackVol(1.8, atm * std::exp(0.00)), d.refVol->blackVol(1.8, atm0 * std::exp(0.00)), tol);
216 BOOST_CHECK_CLOSE(dyn->blackVol(1.8, atm * std::exp(0.25)), d.refVol->blackVol(1.8, atm0 * std::exp(0.25)), tol);
217
218 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 3 * Years);
219 d.div->setValue(0.03);
220 // new atm for t=3.5
221 atm = d.spot->value() / d.riskfreeTs->discount(3.5) * d.dividendTs->discount(3.5);
222
223 BOOST_CHECK_CLOSE(dyn->blackVol(3.5, atm * std::exp(-0.25)), d.refVol->blackVol(3.5, atm0 * std::exp(-0.25)), tol);
224 BOOST_CHECK_CLOSE(dyn->blackVol(3.5, atm * std::exp(0.00)), d.refVol->blackVol(3.5, atm0 * std::exp(0.00)), tol);
225 BOOST_CHECK_CLOSE(dyn->blackVol(3.5, atm * std::exp(0.25)), d.refVol->blackVol(3.5, atm0 * std::exp(0.25)), tol);
226
227} // testConstantVarianceStickyLogMoneyness
@ StickyLogMoneyness

◆ BOOST_AUTO_TEST_CASE() [3/4]

BOOST_AUTO_TEST_CASE ( testForwardVarianceStickyStrike  )

Definition at line 229 of file dynamicblackvoltermstructure.cpp.

229 {
230
231 BOOST_TEST_MESSAGE("Testing forward-forward variance, sticky strike "
232 "dynamics of DynamicBlackVolTermStructure...");
233
234 TestData d;
235
236 Handle<DynamicBlackVolTermStructure<tag::surface> > dyn(
237 QuantLib::ext::make_shared<DynamicBlackVolTermStructure<tag::surface> >(
238 d.refVol, 0, TARGET(), ForwardForwardVariance, StickyStrike, d.riskfreeTs, d.dividendTs, d.spot_q));
239
240 dyn->enableExtrapolation();
241
242 Real tol = 1.0E-8;
243
244 // initially we should get the same volatilities
245
246 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.80), d.refVol->blackVol(0.5, 0.80), tol);
247 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.90), d.refVol->blackVol(0.5, 0.90), tol);
248 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.95), d.refVol->blackVol(0.5, 0.95), tol);
249 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 1.15), d.refVol->blackVol(0.5, 1.15), tol);
250
251 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackVol(1.5, 0.80), tol);
252 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackVol(1.5, 0.90), tol);
253 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackVol(1.5, 0.95), tol);
254 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackVol(1.5, 1.15), tol);
255
256 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.80), d.refVol->blackVol(5.0, 0.80), tol);
257 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.90), d.refVol->blackVol(5.0, 0.90), tol);
258 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.95), d.refVol->blackVol(5.0, 0.95), tol);
259 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 1.15), d.refVol->blackVol(5.0, 1.15), tol);
260
261 // move forward in time, in time direction we expect to roll
262 // down the curve (i.e. forward vols from the original vol ts
263 // are realized), with the strike range held constant
264
265 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 6 * Months);
266 Real t = d.refVol->timeFromReference(Settings::instance().evaluationDate());
267 d.spot->setValue(0.9);
268
269 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackForwardVol(t, t + 1.5, 0.80), tol);
270 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackForwardVol(t, t + 1.5, 0.90), tol);
271 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackForwardVol(t, t + 1.5, 0.95), tol);
272 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackForwardVol(t, t + 1.5, 1.15), tol);
273
274 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 18 * Months);
275 t = d.refVol->timeFromReference(Settings::instance().evaluationDate());
276 d.rate->setValue(0.01);
277
278 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackForwardVol(t, t + 1.5, 0.80), tol);
279 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackForwardVol(t, t + 1.5, 0.90), tol);
280 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackForwardVol(t, t + 1.5, 0.95), tol);
281 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackForwardVol(t, t + 1.5, 1.15), tol);
282
283 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 3 * Years);
284 t = d.refVol->timeFromReference(Settings::instance().evaluationDate());
285 d.div->setValue(0.03);
286
287 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackForwardVol(t, t + 1.5, 0.80), tol);
288 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackForwardVol(t, t + 1.5, 0.90), tol);
289 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackForwardVol(t, t + 1.5, 0.95), tol);
290 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackForwardVol(t, t + 1.5, 1.15), tol);
291
292} // testForwardVarianceStickyLogMoneyness
@ ForwardForwardVariance

◆ BOOST_AUTO_TEST_CASE() [4/4]

BOOST_AUTO_TEST_CASE ( testForwardVarianceStickyLogMoneyness  )

Definition at line 294 of file dynamicblackvoltermstructure.cpp.

294 {
295
296 BOOST_TEST_MESSAGE("Testing forward-forward variance, sticky log-moneyness "
297 "dynamics of DynamicBlackVolTermStructure...");
298
299 TestData d;
300
301 Handle<DynamicBlackVolTermStructure<tag::surface> > dyn(
302 QuantLib::ext::make_shared<DynamicBlackVolTermStructure<tag::surface> >(
303 d.refVol, 0, TARGET(), ForwardForwardVariance, StickyLogMoneyness, d.riskfreeTs, d.dividendTs, d.spot_q));
304
305 dyn->enableExtrapolation();
306
307 Real tol = 1.0E-8;
308
309 // initially we should get the same volatilities
310
311 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.80), d.refVol->blackVol(0.5, 0.80), tol);
312 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.90), d.refVol->blackVol(0.5, 0.90), tol);
313 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 0.95), d.refVol->blackVol(0.5, 0.95), tol);
314 BOOST_CHECK_CLOSE(dyn->blackVol(0.5, 1.15), d.refVol->blackVol(0.5, 1.15), tol);
315
316 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.80), d.refVol->blackVol(1.5, 0.80), tol);
317 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.90), d.refVol->blackVol(1.5, 0.90), tol);
318 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 0.95), d.refVol->blackVol(1.5, 0.95), tol);
319 BOOST_CHECK_CLOSE(dyn->blackVol(1.5, 1.15), d.refVol->blackVol(1.5, 1.15), tol);
320
321 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.80), d.refVol->blackVol(5.0, 0.80), tol);
322 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.90), d.refVol->blackVol(5.0, 0.90), tol);
323 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 0.95), d.refVol->blackVol(5.0, 0.95), tol);
324 BOOST_CHECK_CLOSE(dyn->blackVol(5.0, 1.15), d.refVol->blackVol(5.0, 1.15), tol);
325
326 // move forward in time, in time direction we expect to roll down
327 // the curve with the forward variance being taken at strikes
328 // constant in moneyness
329
330 Settings::instance().evaluationDate() = TARGET().advance(d.origRefDate, 18 * Months);
331 Real t = d.refVol->timeFromReference(Settings::instance().evaluationDate());
332 Real atm0 = d.spot->value(); // original atm value
333 d.spot->setValue(0.9);
334 Real atm = d.spot->value(); // new atm value
335
336 BOOST_CHECK_CLOSE(dyn->blackVariance(1.5, atm * std::exp(-0.25)),
337 d.refVol->blackVariance(t + 1.5, atm0 * std::exp(-0.25)) -
338 d.refVol->blackVariance(t, atm0 * std::exp(-0.25)),
339 tol);
340 BOOST_CHECK_CLOSE(
341 dyn->blackVariance(1.5, atm * std::exp(0.0)),
342 d.refVol->blackVariance(t + 1.5, atm0 * std::exp(0.0)) - d.refVol->blackVariance(t, atm0 * std::exp(0.0)), tol);
343 BOOST_CHECK_CLOSE(dyn->blackVariance(1.5, atm * std::exp(0.25)),
344 d.refVol->blackVariance(t + 1.5, atm0 * std::exp(0.25)) -
345 d.refVol->blackVariance(t, atm0 * std::exp(0.25)),
346 tol);
347
348} // testForwardVarianceStickyLogMoneyness