QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
mc_discr_arith_av_price_heston.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 This file is part of QuantLib, a free-software/open-source library
5 for financial quantitative analysts and developers - http://quantlib.org/
6
7 QuantLib is free software: you can redistribute it and/or modify it
8 under the terms of the QuantLib license. You should have received a
9 copy of the license along with this program; if not, please email
10 <quantlib-dev@lists.sf.net>. The license is also available online at
11 <http://quantlib.org/license.shtml>.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the license for more details.
16*/
17
18/*! \file mc_discr_arith_av_price_heston.hpp
19 \brief Heston MC engine for discrete arithmetic average price Asian
20*/
21
22#ifndef quantlib_mc_discrete_arithmetic_average_price_asian_heston_engine_hpp
23#define quantlib_mc_discrete_arithmetic_average_price_asian_heston_engine_hpp
24
25#include <ql/exercise.hpp>
30#include <utility>
31
32namespace QuantLib {
33
34 //! Heston MC pricing engine for discrete arithmetic average price Asian
35 /*!
36 By default, the MC discretization will use 1 time step per fixing date, but
37 this can be controlled via timeSteps or timeStepsPerYear parameter, which
38 will provide additional timesteps. The grid tries to space as evenly as it
39 can and does not guarantee to match an exact number of steps, the precise
40 grid used can be found in results_.additionalResults["TimeGrid"]
41
42 Some performance metrics/graphs for the Control Variate are shown in the
43 pull request: https://github.com/lballabio/QuantLib/pull/966
44
45 \ingroup asianengines
46 \test the correctness of the returned value is tested by
47 reproducing results available in literature.
48 */
49 template <class RNG = PseudoRandom,
50 class S = Statistics, class P = HestonProcess>
52 : public MCDiscreteAveragingAsianEngineBase<MultiVariate,RNG,S> {
53 public:
57 // constructor
59 const ext::shared_ptr<P>& process,
60 bool antitheticVariate,
61 Size requiredSamples,
62 Real requiredTolerance,
63 Size maxSamples,
64 BigNatural seed,
65 Size timeSteps = Null<Size>(),
66 Size timeStepsPerYear = Null<Size>(),
67 bool controlVariate = false);
68 protected:
69 ext::shared_ptr<path_pricer_type> pathPricer() const override;
70
71 // Use the experimental analytic geometric asian option as a control variate.
72 ext::shared_ptr<path_pricer_type> controlPathPricer() const override;
73 ext::shared_ptr<PricingEngine> controlPricingEngine() const override {
74 ext::shared_ptr<P> process = ext::dynamic_pointer_cast<P>(this->process_);
75 QL_REQUIRE(process, "Heston-like process required");
76
77 return ext::shared_ptr<PricingEngine>(new
79 }
80 };
81
82
83 template <class RNG = PseudoRandom,
84 class S = Statistics, class P = HestonProcess>
86 public:
87 explicit MakeMCDiscreteArithmeticAPHestonEngine(ext::shared_ptr<P> process);
88 // named parameters
97 // conversion to pricing engine
98 operator ext::shared_ptr<PricingEngine>() const;
99 private:
100 ext::shared_ptr<P> process_;
101 bool antithetic_ = false, controlVariate_ = false;
105 };
106
107
108 class ArithmeticAPOHestonPathPricer : public PathPricer<MultiPath> {
109 public:
111 Real strike,
112 DiscountFactor discount,
113 std::vector<Size> fixingIndices,
114 Real runningSum = 0.0,
115 Size pastFixings = 0);
116 Real operator()(const MultiPath& multiPath) const override;
117
118 private:
121 std::vector<Size> fixingIndices_;
124 };
125
126
127 // inline definitions
128
129 template <class RNG, class S, class P>
130 inline
132 const ext::shared_ptr<P>& process,
133 bool antitheticVariate,
134 Size requiredSamples,
135 Real requiredTolerance,
136 Size maxSamples,
137 BigNatural seed,
138 Size timeSteps,
139 Size timeStepsPerYear,
140 bool controlVariate)
142 false,
143 antitheticVariate,
144 controlVariate,
145 requiredSamples,
146 requiredTolerance,
147 maxSamples,
148 seed,
149 timeSteps,
150 timeStepsPerYear) {
151 QL_REQUIRE(timeSteps == Null<Size>() || timeStepsPerYear == Null<Size>(),
152 "both time steps and time steps per year were provided");
153 }
154
155 template <class RNG, class S, class P>
156 inline ext::shared_ptr<
159
160 // Keep track of the fixing indices, the path pricer will need to sum only these
161 TimeGrid timeGrid = this->timeGrid();
162 std::vector<Time> fixingTimes = timeGrid.mandatoryTimes();
163 std::vector<Size> fixingIndexes;
164 fixingIndexes.reserve(fixingTimes.size());
165 for (Real fixingTime : fixingTimes) {
166 fixingIndexes.push_back(timeGrid.closestIndex(fixingTime));
167 }
168
169 ext::shared_ptr<PlainVanillaPayoff> payoff =
170 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
171 this->arguments_.payoff);
172 QL_REQUIRE(payoff, "non-plain payoff given");
173
174 ext::shared_ptr<EuropeanExercise> exercise =
175 ext::dynamic_pointer_cast<EuropeanExercise>(
176 this->arguments_.exercise);
177 QL_REQUIRE(exercise, "wrong exercise given");
178
179 ext::shared_ptr<P> process =
180 ext::dynamic_pointer_cast<P>(this->process_);
181 QL_REQUIRE(process, "Heston like process required");
182
183 return ext::shared_ptr<typename
186 payoff->optionType(),
187 payoff->strike(),
188 process->riskFreeRate()->discount(exercise->lastDate()),
189 fixingIndexes,
190 this->arguments_.runningAccumulator,
191 this->arguments_.pastFixings));
192 }
193
194 template <class RNG, class S, class P>
195 inline ext::shared_ptr<
198
199 // Keep track of the fixing indices, the path pricer will need to prod only these
200 TimeGrid timeGrid = this->timeGrid();
201 std::vector<Time> fixingTimes = timeGrid.mandatoryTimes();
202 std::vector<Size> fixingIndexes;
203 fixingIndexes.reserve(fixingTimes.size());
204 for (Real fixingTime : fixingTimes) {
205 fixingIndexes.push_back(timeGrid.closestIndex(fixingTime));
206 }
207
208 ext::shared_ptr<PlainVanillaPayoff> payoff =
209 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
210 this->arguments_.payoff);
211 QL_REQUIRE(payoff, "non-plain payoff given");
212
213 ext::shared_ptr<EuropeanExercise> exercise =
214 ext::dynamic_pointer_cast<EuropeanExercise>(
215 this->arguments_.exercise);
216 QL_REQUIRE(exercise, "wrong exercise given");
217
218 ext::shared_ptr<P> process =
219 ext::dynamic_pointer_cast<P>(this->process_);
220 QL_REQUIRE(process, "Heston like process required");
221
222 // TODO: Currently the analytic pricer does not support seasoned asian
223 // options (coming soon). Once that is available, we will be able to
224 // pass seasoning details to the path pricer (NB. NEED to pass them to
225 // the analytic pricer as well in that case).
226
227 return ext::shared_ptr<typename
230 payoff->optionType(),
231 payoff->strike(),
232 process->riskFreeRate()->discount(exercise->lastDate()),
233 fixingIndexes));
234 }
235
236 template <class RNG, class S, class P>
238 MakeMCDiscreteArithmeticAPHestonEngine(ext::shared_ptr<P> process)
239 : process_(std::move(process)), samples_(Null<Size>()), maxSamples_(Null<Size>()),
240 steps_(Null<Size>()), stepsPerYear_(Null<Size>()), tolerance_(Null<Real>()) {}
241
242 template<class RNG, class S, class P>
245 QL_REQUIRE(tolerance_ == Null<Real>(),
246 "tolerance already set");
247 samples_ = samples;
248 return *this;
249 }
250
251 template <class RNG, class S, class P>
254 Real tolerance) {
255 QL_REQUIRE(samples_ == Null<Size>(),
256 "number of samples already set");
257 QL_REQUIRE(RNG::allowsErrorEstimate,
258 "chosen random generator policy "
259 "does not allow an error estimate");
260 tolerance_ = tolerance;
261 return *this;
262 }
263
264 template <class RNG, class S, class P>
267 maxSamples_ = samples;
268 return *this;
269 }
270
271 template <class RNG, class S, class P>
274 seed_ = seed;
275 return *this;
276 }
277
278 template <class RNG, class S, class P>
281 antithetic_ = b;
282 return *this;
283 }
284
285 template<class RNG, class S, class P>
288 QL_REQUIRE(stepsPerYear_ == Null<Size>(),
289 "number of steps per year already set");
290 steps_ = steps;
291 return *this;
292 }
293
294 template<class RNG, class S, class P>
297 QL_REQUIRE(steps_ == Null<Size>(),
298 "number of steps already set");
299 stepsPerYear_ = steps;
300 return *this;
301 }
302
303 template<class RNG, class S, class P>
306 controlVariate_ = b;
307 return *this;
308 }
309
310 template <class RNG, class S, class P>
311 inline MakeMCDiscreteArithmeticAPHestonEngine<RNG,S,P>::operator ext::shared_ptr<PricingEngine>() const {
312 return ext::shared_ptr<PricingEngine>(new
314 antithetic_,
315 samples_,
316 tolerance_,
317 maxSamples_,
318 seed_,
319 steps_,
320 stepsPerYear_,
321 controlVariate_));
322 }
323}
324
325#endif
Analytic engine for discrete geometric average price Asian in the Heston model.
Pricing engine for European discrete geometric average price Asian.
Real operator()(const MultiPath &multiPath) const override
Heston MC pricing engine for discrete arithmetic average price Asian.
MCDiscreteAveragingAsianEngineBase< MultiVariate, RNG, S >::path_generator_type path_generator_type
MCDiscreteAveragingAsianEngineBase< MultiVariate, RNG, S >::path_pricer_type path_pricer_type
ext::shared_ptr< PricingEngine > controlPricingEngine() const override
ext::shared_ptr< path_pricer_type > controlPathPricer() const override
MCDiscreteAveragingAsianEngineBase< MultiVariate, RNG, S >::stats_type stats_type
MCDiscreteArithmeticAPHestonEngine(const ext::shared_ptr< P > &process, bool antitheticVariate, Size requiredSamples, Real requiredTolerance, Size maxSamples, BigNatural seed, Size timeSteps=Null< Size >(), Size timeStepsPerYear=Null< Size >(), bool controlVariate=false)
ext::shared_ptr< path_pricer_type > pathPricer() const override
Pricing engine for discrete average Asians using Monte Carlo simulation.
McSimulation< MC, RNG, S >::path_generator_type path_generator_type
McSimulation< MC, RNG, S >::path_pricer_type path_pricer_type
MakeMCDiscreteArithmeticAPHestonEngine & withSamples(Size samples)
MakeMCDiscreteArithmeticAPHestonEngine & withStepsPerYear(Size steps)
MakeMCDiscreteArithmeticAPHestonEngine & withSeed(BigNatural seed)
MakeMCDiscreteArithmeticAPHestonEngine & withControlVariate(bool b=false)
MakeMCDiscreteArithmeticAPHestonEngine & withAntitheticVariate(bool b=true)
MakeMCDiscreteArithmeticAPHestonEngine & withSteps(Size steps)
MakeMCDiscreteArithmeticAPHestonEngine & withAbsoluteTolerance(Real tolerance)
MakeMCDiscreteArithmeticAPHestonEngine & withMaxSamples(Size samples)
Correlated multiple asset paths.
Definition: multipath.hpp:39
template class providing a null value for a given type.
Definition: null.hpp:76
base class for path pricers
Definition: pathpricer.hpp:40
Plain-vanilla payoff.
Definition: payoffs.hpp:105
time grid class
Definition: timegrid.hpp:43
Size closestIndex(Time t) const
returns the index i such that grid[i] is closest to t
Definition: timegrid.cpp:80
const std::vector< Time > & mandatoryTimes() const
Definition: timegrid.hpp:151
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Option exercise classes and payoff function.
ext::function< Real(Real)> b
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
Heston stochastic process.
ext::shared_ptr< QuantLib::Payoff > payoff
Heston MC engine for discrete geometric average price Asian.
Monte Carlo pricing engine for discrete average Asians.
Definition: any.hpp:35
RiskStatistics Statistics
default statistics tool
Definition: statistics.hpp:35
unsigned QL_BIG_INTEGER BigNatural
large positive integer
Definition: types.hpp:46
GenericPseudoRandom< MersenneTwisterUniformRng, InverseCumulativeNormal > PseudoRandom
default traits for pseudo-random number generation
Definition: rngtraits.hpp:71
STL namespace.
default Monte Carlo traits for multi-variate models
Definition: mctraits.hpp:50