QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
mcvarianceswapengine.hpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006 Warren Chou
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20/*! \file mcvarianceswapengine.hpp
21 \brief Monte Carlo variance-swap engine
22*/
23
24#ifndef quantlib_mc_varianceswap_engine_hpp
25#define quantlib_mc_varianceswap_engine_hpp
26
31#include <utility>
32
33namespace QuantLib {
34
35 //! Variance-swap pricing engine using Monte Carlo simulation,
36 /*! as described in Demeterfi, Derman, Kamal & Zou,
37 "A Guide to Volatility and Variance Swaps", 1999
38
39 \ingroup forwardengines
40
41 \todo define tolerance of numerical integral and incorporate it
42 in errorEstimate
43
44 \test returned fair variances checked for consistency with
45 implied volatility curve.
46 */
47 template <class RNG = PseudoRandom, class S = Statistics>
49 public McSimulation<SingleVariate,RNG,S> {
50 public:
51 typedef
54 typedef
59 // constructor
60 MCVarianceSwapEngine(ext::shared_ptr<GeneralizedBlackScholesProcess> process,
61 Size timeSteps,
62 Size timeStepsPerYear,
63 bool brownianBridge,
64 bool antitheticVariate,
65 Size requiredSamples,
66 Real requiredTolerance,
67 Size maxSamples,
68 BigNatural seed);
69 // calculate variance via Monte Carlo
70 void calculate() const override {
75 this->mcModel_->sampleAccumulator().mean();
76
77 DiscountFactor riskFreeDiscount =
78 process_->riskFreeRate()->discount(arguments_.maturityDate);
79 Real multiplier;
80 switch (arguments_.position) {
81 case Position::Long:
82 multiplier = 1.0;
83 break;
84 case Position::Short:
85 multiplier = -1.0;
86 break;
87 default:
88 QL_FAIL("Unknown position");
89 }
90 multiplier *= riskFreeDiscount * arguments_.notional;
91
93 multiplier * (results_.variance - arguments_.strike);
94
95 if (RNG::allowsErrorEstimate) {
96 Real varianceError =
97 this->mcModel_->sampleAccumulator().errorEstimate();
98 results_.errorEstimate = multiplier * varianceError;
99 }
100 }
101
102 protected:
103 // McSimulation implementation
104 ext::shared_ptr<path_pricer_type> pathPricer() const override;
105 TimeGrid timeGrid() const override;
106
107 ext::shared_ptr<path_generator_type> pathGenerator() const override {
108
109 Size dimensions = process_->factors();
110
111 TimeGrid grid = timeGrid();
112 typename RNG::rsg_type gen =
113 RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
114
115 return ext::shared_ptr<path_generator_type>(
116 new path_generator_type(process_, grid, gen,
118 }
119 // data members
120 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
126 };
127
128
129 //! Monte Carlo variance-swap engine factory
130 template <class RNG = PseudoRandom, class S = Statistics>
132 public:
133 MakeMCVarianceSwapEngine(ext::shared_ptr<GeneralizedBlackScholesProcess> process);
134 // named parameters
143 // conversion to pricing engine
144 operator ext::shared_ptr<PricingEngine>() const;
145 private:
146 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
147 bool antithetic_ = false;
150 bool brownianBridge_ = false;
152 };
153
154 class VariancePathPricer : public PathPricer<Path> {
155 public:
156 VariancePathPricer(ext::shared_ptr<GeneralizedBlackScholesProcess> process)
157 : process_(std::move(process)) {}
158 Real operator()(const Path& path) const override;
159
160 private:
161 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
162 };
163
164 // inline definitions
165
166 template <class RNG, class S>
168 ext::shared_ptr<GeneralizedBlackScholesProcess> process,
169 Size timeSteps,
170 Size timeStepsPerYear,
171 bool brownianBridge,
172 bool antitheticVariate,
173 Size requiredSamples,
174 Real requiredTolerance,
175 Size maxSamples,
176 BigNatural seed)
177 : McSimulation<SingleVariate, RNG, S>(antitheticVariate, false), process_(std::move(process)),
178 timeSteps_(timeSteps), timeStepsPerYear_(timeStepsPerYear), requiredSamples_(requiredSamples),
179 maxSamples_(maxSamples), requiredTolerance_(requiredTolerance),
180 brownianBridge_(brownianBridge), seed_(seed) {
181 QL_REQUIRE(timeSteps != Null<Size>() ||
182 timeStepsPerYear != Null<Size>(),
183 "no time steps provided");
184 QL_REQUIRE(timeSteps == Null<Size>() ||
185 timeStepsPerYear == Null<Size>(),
186 "both time steps and time steps per year were provided");
187 QL_REQUIRE(timeSteps != 0,
188 "timeSteps must be positive, " << timeSteps <<
189 " not allowed");
190 QL_REQUIRE(timeStepsPerYear != 0,
191 "timeStepsPerYear must be positive, " << timeStepsPerYear <<
192 " not allowed");
193 }
194
195
196 template <class RNG, class S>
198
199 Time t = this->process_->time(this->arguments_.maturityDate);
200
201 if (timeSteps_ != Null<Size>()) {
202 return TimeGrid(t, this->timeSteps_);
203 } else if (timeStepsPerYear_ != Null<Size>()) {
204 Size steps = static_cast<Size>(timeStepsPerYear_*t);
205 return TimeGrid(t, std::max<Size>(steps, 1));
206 } else {
207 QL_FAIL("time steps not specified");
208 }
209 }
210
211
212 template <class RNG, class S>
213 inline
214 ext::shared_ptr<
217
218 return ext::shared_ptr<
220 new VariancePathPricer(process_));
221 }
222
223
224 template <class RNG, class S>
226 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
227 : process_(std::move(process)), steps_(Null<Size>()), stepsPerYear_(Null<Size>()),
228 samples_(Null<Size>()), maxSamples_(Null<Size>()), tolerance_(Null<Real>()) {}
229
230 template <class RNG, class S>
233 steps_ = steps;
234 return *this;
235 }
236
237 template <class RNG, class S>
240 stepsPerYear_ = steps;
241 return *this;
242 }
243
244 template <class RNG, class S>
247 QL_REQUIRE(tolerance_ == Null<Real>(),
248 "tolerance already set");
249 samples_ = samples;
250 return *this;
251 }
252
253 template <class RNG, class S>
256 QL_REQUIRE(samples_ == Null<Size>(),
257 "number of samples already set");
258 QL_REQUIRE(RNG::allowsErrorEstimate,
259 "chosen random generator policy "
260 "does not allow an error estimate");
261 tolerance_ = tolerance;
262 return *this;
263 }
264
265 template <class RNG, class S>
268 maxSamples_ = samples;
269 return *this;
270 }
271
272 template <class RNG, class S>
275 seed_ = seed;
276 return *this;
277 }
278
279 template <class RNG, class S>
282 brownianBridge_ = brownianBridge;
283 return *this;
284 }
285
286 template <class RNG, class S>
289 antithetic_ = b;
290 return *this;
291 }
292
293 template <class RNG, class S>
295 operator ext::shared_ptr<PricingEngine>() const {
296 QL_REQUIRE(steps_ != Null<Size>() || stepsPerYear_ != Null<Size>(),
297 "number of steps not given");
298 QL_REQUIRE(steps_ == Null<Size>() || stepsPerYear_ == Null<Size>(),
299 "number of steps overspecified");
300 return ext::shared_ptr<PricingEngine>(
301 new MCVarianceSwapEngine<RNG,S>(process_,
302 steps_,
303 stepsPerYear_,
304 brownianBridge_,
305 antithetic_,
306 samples_, tolerance_,
307 maxSamples_,
308 seed_));
309 }
310
311
312 namespace detail {
313
314 class Integrand {
315 public:
316 Integrand(Path path, ext::shared_ptr<GeneralizedBlackScholesProcess> process)
317 : path_(std::move(path)), process_(std::move(process)) {}
319 Size i = static_cast<Size>(t/path_.timeGrid().dt(0));
320 Real sigma = process_->diffusion(t,path_[i]);
321 return sigma*sigma;
322 }
323 private:
325 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
326 };
327
328 }
329
330
331 inline Real VariancePathPricer::operator()(const Path& path) const {
332 QL_REQUIRE(path.length() > 0, "the path cannot be empty");
333 Time t0 = path.timeGrid().front();
334 Time t = path.timeGrid().back();
335 Time dt = path.timeGrid().dt(0);
336 SegmentIntegral integrator(static_cast<Size>(t/dt));
338 return integrator(f,t0,t)/t;
339 }
340
341}
342
343
344#endif
Black-Scholes processes.
Variance-swap pricing engine using Monte Carlo simulation,.
McSimulation< SingleVariate, RNG, S >::path_generator_type path_generator_type
ext::shared_ptr< path_generator_type > pathGenerator() const override
McSimulation< SingleVariate, RNG, S >::stats_type stats_type
MCVarianceSwapEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process, Size timeSteps, Size timeStepsPerYear, bool brownianBridge, bool antitheticVariate, Size requiredSamples, Real requiredTolerance, Size maxSamples, BigNatural seed)
ext::shared_ptr< path_pricer_type > pathPricer() const override
McSimulation< SingleVariate, RNG, S >::path_pricer_type path_pricer_type
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
TimeGrid timeGrid() const override
Monte Carlo variance-swap engine factory.
MakeMCVarianceSwapEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
MakeMCVarianceSwapEngine & withSeed(BigNatural seed)
MakeMCVarianceSwapEngine & withAbsoluteTolerance(Real tolerance)
MakeMCVarianceSwapEngine & withSamples(Size samples)
MakeMCVarianceSwapEngine & withSteps(Size steps)
MakeMCVarianceSwapEngine & withMaxSamples(Size samples)
MakeMCVarianceSwapEngine & withStepsPerYear(Size steps)
MakeMCVarianceSwapEngine & withAntitheticVariate(bool b=true)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
MakeMCVarianceSwapEngine & withBrownianBridge(bool b=true)
base class for Monte Carlo engines
MonteCarloModel< MC, RNG, S >::path_generator_type path_generator_type
ext::shared_ptr< MonteCarloModel< MC, RNG, S > > mcModel_
void calculate(Real requiredTolerance, Size requiredSamples, Size maxSamples) const
basic calculate method provided to inherited pricing engines
MonteCarloModel< MC, RNG, S >::path_pricer_type path_pricer_type
template class providing a null value for a given type.
Definition: null.hpp:76
single-factor random walk
Definition: path.hpp:40
Size length() const
Definition: path.hpp:94
const TimeGrid & timeGrid() const
time grid
Definition: path.hpp:142
base class for path pricers
Definition: pathpricer.hpp:40
Integral of a one-dimensional function.
time grid class
Definition: timegrid.hpp:43
Time back() const
Definition: timegrid.hpp:171
Time dt(Size i) const
Definition: timegrid.hpp:154
Time front() const
Definition: timegrid.hpp:170
Size size() const
Definition: timegrid.hpp:164
VariancePathPricer(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
Real operator()(const Path &path) const override
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
base class for variance-swap engines
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Integrand(Path path, ext::shared_ptr< GeneralizedBlackScholesProcess > process)
const DefaultType & t
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
ext::function< Real(Real)> b
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
std::size_t Size
size of a container
Definition: types.hpp:58
Real sigma
framework for Monte Carlo engines
Definition: any.hpp:35
unsigned QL_BIG_INTEGER BigNatural
large positive integer
Definition: types.hpp:46
STL namespace.
Integral of a one-dimensional function using segment algorithm.
default Monte Carlo traits for single-variate models
Definition: mctraits.hpp:39
Variance swap.