QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
mcamericanengine.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006 Klaus Spanderen
5 Copyright (C) 2007 StatPro Italia srl
6 Copyright (C) 2016 Peter Caspers
7 Copyright (C) 2022 Jonghee Lee
8
9 This file is part of QuantLib, a free-software/open-source library
10 for financial quantitative analysts and developers - http://quantlib.org/
11
12 QuantLib is free software: you can redistribute it and/or modify it
13 under the terms of the QuantLib license. You should have received a
14 copy of the license along with this program; if not, please email
15 <quantlib-dev@lists.sf.net>. The license is also available online at
16 <http://quantlib.org/license.shtml>.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the license for more details.
21*/
22
27#ifndef quantlib_mc_american_engine_hpp
28#define quantlib_mc_american_engine_hpp
29
30#include <ql/qldefines.hpp>
31#include <ql/payoff.hpp>
32#include <ql/exercise.hpp>
33#include <ql/optional.hpp>
34#include <ql/methods/montecarlo/lsmbasissystem.hpp>
35#include <ql/processes/blackscholesprocess.hpp>
36#include <ql/pricingengines/mclongstaffschwartzengine.hpp>
37#include <ql/pricingengines/vanilla/mceuropeanengine.hpp>
38#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
39
40namespace QuantLib {
41
43
50 template <class RNG = PseudoRandom, class S = Statistics,
51 class RNG_Calibration = RNG>
53 : public MCLongstaffSchwartzEngine<VanillaOption::engine,
54 SingleVariate,RNG,S,RNG_Calibration> {
55 public:
56 MCAmericanEngine(const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
57 Size timeSteps,
58 Size timeStepsPerYear,
59 bool antitheticVariate,
60 bool controlVariate,
61 Size requiredSamples,
62 Real requiredTolerance,
63 Size maxSamples,
64 BigNatural seed,
65 Size polynomialOrder,
66 LsmBasisSystem::PolynomialType polynomialType,
67 Size nCalibrationSamples = Null<Size>(),
68 const ext::optional<bool>& antitheticVariateCalibration = ext::nullopt,
69 BigNatural seedCalibration = Null<Size>());
70
71 void calculate() const override;
72
73 protected:
74 ext::shared_ptr<LongstaffSchwartzPathPricer<Path> > lsmPathPricer() const override;
75
76 Real controlVariateValue() const override;
77 ext::shared_ptr<PricingEngine> controlPricingEngine() const override;
78 ext::shared_ptr<PathPricer<Path> > controlPathPricer() const override;
79
80 private:
83 };
84
86 public:
87 AmericanPathPricer(ext::shared_ptr<Payoff> payoff,
88 Size polynomialOrder,
89 LsmBasisSystem::PolynomialType polynomialType);
90
91 Real state(const Path& path, Size t) const override;
92 Real operator()(const Path& path, Size t) const override;
93
94 std::vector<ext::function<Real(Real)> > basisSystem() const override;
95
96 protected:
97 Real payoff(Real state) const;
98
100 const ext::shared_ptr<Payoff> payoff_;
101 std::vector<ext::function<Real(Real)> > v_;
102 };
103
104
106 template <class RNG = PseudoRandom, class S = Statistics,
107 class RNG_Calibration = RNG>
109 public:
110 MakeMCAmericanEngine(ext::shared_ptr<GeneralizedBlackScholesProcess>);
111 // named parameters
125
126 // conversion to pricing engine
127 operator ext::shared_ptr<PricingEngine>() const;
128 private:
129 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
130 bool antithetic_ = false, controlVariate_ = false;
137 ext::optional<bool> antitheticCalibration_;
139 };
140
141 template <class RNG, class S, class RNG_Calibration>
143 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
144 Size timeSteps,
145 Size timeStepsPerYear,
146 bool antitheticVariate,
147 bool controlVariate,
148 Size requiredSamples,
149 Real requiredTolerance,
150 Size maxSamples,
151 BigNatural seed,
152 Size polynomialOrder,
153 LsmBasisSystem::PolynomialType polynomialType,
154 Size nCalibrationSamples,
155 const ext::optional<bool>& antitheticVariateCalibration,
156 BigNatural seedCalibration)
157 : MCLongstaffSchwartzEngine<VanillaOption::engine, SingleVariate, RNG, S, RNG_Calibration>(
158 process,
159 timeSteps,
160 timeStepsPerYear,
161 false,
162 antitheticVariate,
163 controlVariate,
164 requiredSamples,
165 requiredTolerance,
166 maxSamples,
167 seed,
168 nCalibrationSamples,
169 false,
170 antitheticVariateCalibration,
171 seedCalibration),
172 polynomialOrder_(polynomialOrder), polynomialType_(polynomialType) {}
173
174 template <class RNG, class S, class RNG_Calibration>
177 RNG_Calibration>::calculate();
178 if (this->controlVariate_) {
179 // control variate might lead to small negative
180 // option values for deep OTM options
181 this->results_.value = std::max(0.0, this->results_.value);
182 }
183 }
184
185 template <class RNG, class S, class RNG_Calibration>
186 inline ext::shared_ptr<LongstaffSchwartzPathPricer<Path> >
188 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
189 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
190 this->process_);
191 QL_REQUIRE(process, "generalized Black-Scholes process required");
192
193 ext::shared_ptr<EarlyExercise> exercise =
194 ext::dynamic_pointer_cast<EarlyExercise>(
195 this->arguments_.exercise);
196 QL_REQUIRE(exercise, "wrong exercise given");
197 QL_REQUIRE(!exercise->payoffAtExpiry(),
198 "payoff at expiry not handled");
199
200 ext::shared_ptr<AmericanPathPricer> earlyExercisePathPricer(
201 new AmericanPathPricer(this->arguments_.payoff,
202 polynomialOrder_, polynomialType_));
203
204 return ext::make_shared<LongstaffSchwartzPathPricer<Path> > (
205
206 this->timeGrid(),
207 earlyExercisePathPricer,
208 *(process->riskFreeRate()));
209 }
210
211 template <class RNG, class S, class RNG_Calibration>
212 inline ext::shared_ptr<PathPricer<Path> >
214 ext::shared_ptr<StrikedTypePayoff> payoff =
215 ext::dynamic_pointer_cast<StrikedTypePayoff>(
216 this->arguments_.payoff);
217 QL_REQUIRE(payoff, "StrikedTypePayoff needed for control variate");
218
219 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
220 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
221 this->process_);
222 QL_REQUIRE(process, "generalized Black-Scholes process required");
223
224 return ext::shared_ptr<PathPricer<Path> >(
226 payoff->optionType(),
227 payoff->strike(),
228 process->riskFreeRate()->discount(this->timeGrid().back()))
229 );
230 }
231
232 template <class RNG, class S, class RNG_Calibration>
233 inline ext::shared_ptr<PricingEngine>
235 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
236 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
237 this->process_);
238 QL_REQUIRE(process, "generalized Black-Scholes process required");
239
240 return ext::shared_ptr<PricingEngine>(
241 new AnalyticEuropeanEngine(process));
242 }
243
244 template <class RNG, class S, class RNG_Calibration>
245 inline Real
247 ext::shared_ptr<PricingEngine> controlPE =
248 this->controlPricingEngine();
249
250 QL_REQUIRE(controlPE,
251 "engine does not provide "
252 "control variation pricing engine");
253
254 auto* controlArguments = dynamic_cast<VanillaOption::arguments*>(controlPE->getArguments());
255 *controlArguments = this->arguments_;
256 controlArguments->exercise = ext::shared_ptr<Exercise>(
257 new EuropeanExercise(this->arguments_.exercise->lastDate()));
258
259 controlPE->calculate();
260
261 const auto* controlResults =
262 dynamic_cast<const VanillaOption::results*>(controlPE->getResults());
263
264 return controlResults->value;
265 }
266
267 template <class RNG, class S, class RNG_Calibration>
269 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
270 : process_(std::move(process)), steps_(Null<Size>()), stepsPerYear_(Null<Size>()),
271 samples_(Null<Size>()), maxSamples_(Null<Size>()), tolerance_(Null<Real>()),
272 antitheticCalibration_(ext::nullopt), seedCalibration_(Null<Size>()) {}
273
274 template <class RNG, class S, class RNG_Calibration>
277 polynomialOrder_ = polynomialOrder;
278 return *this;
279 }
280
281 template <class RNG, class S, class RNG_Calibration>
284 polynomialType_ = polynomialType;
285 return *this;
286 }
287
288 template <class RNG, class S, class RNG_Calibration>
291 steps_ = steps;
292 return *this;
293 }
294
295 template <class RNG, class S, class RNG_Calibration>
298 Size steps) {
299 stepsPerYear_ = steps;
300 return *this;
301 }
302
303 template <class RNG, class S, class RNG_Calibration>
306 QL_REQUIRE(tolerance_ == Null<Real>(),
307 "tolerance already set");
308 samples_ = samples;
309 return *this;
310 }
311
312 template <class RNG, class S, class RNG_Calibration>
315 Real tolerance) {
316 QL_REQUIRE(samples_ == Null<Size>(),
317 "number of samples already set");
318 QL_REQUIRE(RNG::allowsErrorEstimate,
319 "chosen random generator policy "
320 "does not allow an error estimate");
321 tolerance_ = tolerance;
322 return *this;
323 }
324
325 template <class RNG, class S, class RNG_Calibration>
328 Size samples) {
329 maxSamples_ = samples;
330 return *this;
331 }
332
333 template <class RNG, class S, class RNG_Calibration>
336 Size samples) {
337 calibrationSamples_ = samples;
338 return *this;
339 }
340
341 template <class RNG, class S, class RNG_Calibration>
344 seed_ = seed;
345 return *this;
346 }
347
348 template <class RNG, class S, class RNG_Calibration>
351 bool b) {
352 antithetic_ = b;
353 return *this;
354 }
355
356 template <class RNG, class S, class RNG_Calibration>
359 controlVariate_ = b;
360 return *this;
361 }
362
363 template <class RNG, class S, class RNG_Calibration>
365 RNG, S, RNG_Calibration>::withAntitheticVariateCalibration(bool b) {
366 antitheticCalibration_ = b;
367 return *this;
368 }
369
370 template <class RNG, class S, class RNG_Calibration>
373 BigNatural seed) {
374 seedCalibration_ = seed;
375 return *this;
376 }
377
378 template <class RNG, class S, class RNG_Calibration>
380 operator ext::shared_ptr<PricingEngine>() const {
381 QL_REQUIRE(steps_ != Null<Size>() || stepsPerYear_ != Null<Size>(),
382 "number of steps not given");
383 QL_REQUIRE(steps_ == Null<Size>() || stepsPerYear_ == Null<Size>(),
384 "number of steps overspecified");
385 return ext::shared_ptr<PricingEngine>(new
387 steps_,
388 stepsPerYear_,
389 antithetic_,
390 controlVariate_,
391 samples_, tolerance_,
392 maxSamples_,
393 seed_,
394 polynomialOrder_,
395 polynomialType_,
396 calibrationSamples_,
397 antitheticCalibration_,
398 seedCalibration_));
399 }
400
401}
402
403#endif
std::vector< ext::function< Real(Real)> > basisSystem() const override
Real state(const Path &path, Size t) const override
Real payoff(Real state) const
Real operator()(const Path &path, Size t) const override
std::vector< ext::function< Real(Real)> > v_
const ext::shared_ptr< Payoff > payoff_
Pricing engine for European vanilla options using analytical formulae.
base class for early exercise path pricers
European exercise.
Definition: exercise.hpp:96
American Monte Carlo engine.
const LsmBasisSystem::PolynomialType polynomialType_
ext::shared_ptr< LongstaffSchwartzPathPricer< Path > > lsmPathPricer() const override
void calculate() const override
MCAmericanEngine(const ext::shared_ptr< GeneralizedBlackScholesProcess > &process, Size timeSteps, Size timeStepsPerYear, bool antitheticVariate, bool controlVariate, Size requiredSamples, Real requiredTolerance, Size maxSamples, BigNatural seed, Size polynomialOrder, LsmBasisSystem::PolynomialType polynomialType, Size nCalibrationSamples=Null< Size >(), const ext::optional< bool > &antitheticVariateCalibration=ext::nullopt, BigNatural seedCalibration=Null< Size >())
ext::shared_ptr< PricingEngine > controlPricingEngine() const override
Real controlVariateValue() const override
ext::shared_ptr< PathPricer< Path > > controlPathPricer() const override
Longstaff-Schwarz Monte Carlo engine for early exercise options.
Monte Carlo American engine factory.
MakeMCAmericanEngine & withBasisSystem(LsmBasisSystem::PolynomialType)
MakeMCAmericanEngine & withSeedCalibration(BigNatural seed)
MakeMCAmericanEngine & withAntitheticVariateCalibration(bool b=true)
MakeMCAmericanEngine & withStepsPerYear(Size steps)
MakeMCAmericanEngine & withSamples(Size samples)
ext::optional< bool > antitheticCalibration_
MakeMCAmericanEngine & withPolynomialOrder(Size polynomialOrder)
MakeMCAmericanEngine & withCalibrationSamples(Size calibrationSamples)
MakeMCAmericanEngine & withControlVariate(bool b=true)
LsmBasisSystem::PolynomialType polynomialType_
MakeMCAmericanEngine & withAbsoluteTolerance(Real tolerance)
MakeMCAmericanEngine & withMaxSamples(Size samples)
MakeMCAmericanEngine & withSeed(BigNatural seed)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
MakeMCAmericanEngine & withAntitheticVariate(bool b=true)
MakeMCAmericanEngine & withSteps(Size steps)
MakeMCAmericanEngine(ext::shared_ptr< GeneralizedBlackScholesProcess >)
template class providing a null value for a given type.
Definition: null.hpp:76
basic option arguments
Definition: option.hpp:57
ext::shared_ptr< Exercise > exercise
Definition: option.hpp:65
single-factor random walk
Definition: path.hpp:40
Vanilla option (no discrete dividends, no barriers) on a single asset.
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
const boost::none_t & nullopt
Definition: optional.cpp:27
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 single-variate models
Definition: mctraits.hpp:39