QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
mclongstaffschwartzengine.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 Klaus Spanderen
5 Copyright (C) 2007 StatPro Italia srl
6 Copyright (C) 2015, 2016 Peter Caspers
7 Copyright (C) 2015 Thema Consulting SA
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
23/*! \file mclongstaffschwartzengine.hpp
24 \brief Longstaff Schwartz Monte Carlo engine for early exercise options
25*/
26
27#ifndef quantlib_mc_longstaff_schwartz_engine_hpp
28#define quantlib_mc_longstaff_schwartz_engine_hpp
29
30#include <ql/exercise.hpp>
33#include <ql/optional.hpp>
34
35namespace QuantLib {
36
37 //! Longstaff-Schwarz Monte Carlo engine for early exercise options
38 /*! References:
39
40 Francis Longstaff, Eduardo Schwartz, 2001. Valuing American Options
41 by Simulation: A Simple Least-Squares Approach, The Review of
42 Financial Studies, Volume 14, No. 1, 113-147
43
44 \test the correctness of the returned value is tested by
45 reproducing results available in web/literature
46 */
47 template <class GenericEngine, template <class> class MC,
48 class RNG, class S = Statistics, class RNG_Calibration = RNG>
50 public McSimulation<MC,RNG,S> {
51 public:
52 typedef typename MC<RNG>::path_type path_type;
59 typedef
62
63 /*! If the parameters brownianBridge and antitheticVariate are
64 not given they are chosen to be identical to the respective
65 parameters for pricing; the seed for calibration is chosen
66 to be zero if the pricing seed is zero and otherwise as the
67 pricing seed plus some offset to avoid identical paths in
68 calibration and pricing; note however that this has no effect
69 for low discrepancy RNGs usually, it is therefore recommended
70 to use pseudo random generators for the calibration phase always
71 (and possibly quasi monte carlo in the subsequent pricing). */
72 MCLongstaffSchwartzEngine(ext::shared_ptr<StochasticProcess> process,
73 Size timeSteps,
74 Size timeStepsPerYear,
75 bool brownianBridge,
76 bool antitheticVariate,
77 bool controlVariate,
78 Size requiredSamples,
79 Real requiredTolerance,
80 Size maxSamples,
81 BigNatural seed,
82 Size nCalibrationSamples = Null<Size>(),
83 ext::optional<bool> brownianBridgeCalibration = ext::nullopt,
84 ext::optional<bool> antitheticVariateCalibration = ext::nullopt,
85 BigNatural seedCalibration = Null<Size>());
86
87 void calculate() const override;
88
89 protected:
90 virtual ext::shared_ptr<LongstaffSchwartzPathPricer<path_type> >
91 lsmPathPricer() const = 0;
92
93 TimeGrid timeGrid() const override;
94 ext::shared_ptr<path_pricer_type> pathPricer() const override;
95 ext::shared_ptr<path_generator_type> pathGenerator() const override;
96
97 ext::shared_ptr<StochasticProcess> process_;
100 const bool brownianBridge_;
109
110 mutable ext::shared_ptr<LongstaffSchwartzPathPricer<path_type> >
112 mutable ext::shared_ptr<MonteCarloModel<MC, RNG_Calibration, S> >
114 };
115
116 template <class GenericEngine,
117 template <class>
118 class MC,
119 class RNG,
120 class S,
121 class RNG_Calibration>
123 MCLongstaffSchwartzEngine(ext::shared_ptr<StochasticProcess> process,
124 Size timeSteps,
125 Size timeStepsPerYear,
126 bool brownianBridge,
127 bool antitheticVariate,
128 bool controlVariate,
129 Size requiredSamples,
130 Real requiredTolerance,
131 Size maxSamples,
132 BigNatural seed,
133 Size nCalibrationSamples,
134 ext::optional<bool> brownianBridgeCalibration,
135 ext::optional<bool> antitheticVariateCalibration,
136 BigNatural seedCalibration)
137 : McSimulation<MC, RNG, S>(antitheticVariate, controlVariate), process_(std::move(process)),
138 timeSteps_(timeSteps), timeStepsPerYear_(timeStepsPerYear), brownianBridge_(brownianBridge),
139 requiredSamples_(requiredSamples), requiredTolerance_(requiredTolerance),
140 maxSamples_(maxSamples), seed_(seed),
141 nCalibrationSamples_((nCalibrationSamples == Null<Size>()) ? 2048 : nCalibrationSamples),
142 // NOLINTNEXTLINE(readability-implicit-bool-conversion)
143 brownianBridgeCalibration_(brownianBridgeCalibration ? *brownianBridgeCalibration :
144 brownianBridge),
145 antitheticVariateCalibration_(
146 // NOLINTNEXTLINE(readability-implicit-bool-conversion)
147 antitheticVariateCalibration ? *antitheticVariateCalibration : antitheticVariate),
148 seedCalibration_(seedCalibration != Null<Real>() ? seedCalibration :
149 (seed == 0 ? 0 : seed + 1768237423L)) {
150 QL_REQUIRE(timeSteps != Null<Size>() ||
151 timeStepsPerYear != Null<Size>(),
152 "no time steps provided");
153 QL_REQUIRE(timeSteps == Null<Size>() ||
154 timeStepsPerYear == Null<Size>(),
155 "both time steps and time steps per year were provided");
156 QL_REQUIRE(timeSteps != 0,
157 "timeSteps must be positive, " << timeSteps <<
158 " not allowed");
159 QL_REQUIRE(timeStepsPerYear != 0,
160 "timeStepsPerYear must be positive, " << timeStepsPerYear <<
161 " not allowed");
162 this->registerWith(process_);
163 }
164
165 template <class GenericEngine, template <class> class MC, class RNG,
166 class S, class RNG_Calibration>
167 inline ext::shared_ptr<typename MCLongstaffSchwartzEngine<
168 GenericEngine, MC, RNG, S, RNG_Calibration>::path_pricer_type>
170 RNG_Calibration>::pathPricer() const {
171
172 QL_REQUIRE(pathPricer_, "path pricer unknown");
173 return pathPricer_;
174 }
175
176 template <class GenericEngine, template <class> class MC, class RNG,
177 class S, class RNG_Calibration>
178 inline void MCLongstaffSchwartzEngine<GenericEngine, MC, RNG, S,
179 RNG_Calibration>::calculate() const {
180 // calibration
181 pathPricer_ = this->lsmPathPricer();
182 Size dimensions = process_->factors();
183 TimeGrid grid = this->timeGrid();
184 typename RNG_Calibration::rsg_type generator =
185 RNG_Calibration::make_sequence_generator(
186 dimensions * (grid.size() - 1), seedCalibration_);
187 ext::shared_ptr<path_generator_type_calibration>
188 pathGeneratorCalibration =
189 ext::make_shared<path_generator_type_calibration>(
190 process_, grid, generator, brownianBridgeCalibration_);
191 mcModelCalibration_ =
192 ext::shared_ptr<MonteCarloModel<MC, RNG_Calibration, S> >(
194 pathGeneratorCalibration, pathPricer_, stats_type(),
195 this->antitheticVariateCalibration_));
196
197 mcModelCalibration_->addSamples(nCalibrationSamples_);
198 pathPricer_->calibrate();
199 // pricing
200 McSimulation<MC,RNG,S>::calculate(requiredTolerance_,
201 requiredSamples_,
202 maxSamples_);
203 this->results_.value = this->mcModel_->sampleAccumulator().mean();
204 this->results_.additionalResults["exerciseProbability"] =
205 this->pathPricer_->exerciseProbability();
206 if (RNG::allowsErrorEstimate) {
207 this->results_.errorEstimate =
208 this->mcModel_->sampleAccumulator().errorEstimate();
209 }
210 }
211
212 template <class GenericEngine, template <class> class MC, class RNG,
213 class S, class RNG_Calibration>
214 inline TimeGrid
216 RNG_Calibration>::timeGrid() const {
217 std::vector<Time> requiredTimes;
218 if (this->arguments_.exercise->type() == Exercise::American) {
219 Date lastExerciseDate = this->arguments_.exercise->lastDate();
220 requiredTimes.push_back(process_->time(lastExerciseDate));
221 } else {
222 for (Size i = 0; i < this->arguments_.exercise->dates().size();
223 ++i) {
224 Time t = process_->time(this->arguments_.exercise->date(i));
225 if (t > 0.0)
226 requiredTimes.push_back(t);
227 }
228 }
229 if (this->timeSteps_ != Null<Size>()) {
230 return TimeGrid(requiredTimes.begin(), requiredTimes.end(),
231 this->timeSteps_);
232 } else if (this->timeStepsPerYear_ != Null<Size>()) {
233 Size steps = static_cast<Size>(this->timeStepsPerYear_ *
234 requiredTimes.back());
235 return TimeGrid(requiredTimes.begin(), requiredTimes.end(),
236 std::max<Size>(steps, 1));
237 } else {
238 QL_FAIL("time steps not specified");
239 }
240 }
241
242 template <class GenericEngine, template <class> class MC, class RNG,
243 class S, class RNG_Calibration>
244 inline ext::shared_ptr<typename MCLongstaffSchwartzEngine<
245 GenericEngine, MC, RNG, S, RNG_Calibration>::path_generator_type>
247 RNG_Calibration>::pathGenerator() const {
248
249 Size dimensions = process_->factors();
250 TimeGrid grid = this->timeGrid();
251 typename RNG::rsg_type generator =
252 RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
253 return ext::shared_ptr<path_generator_type>(
254 new path_generator_type(process_,
255 grid, generator, brownianBridge_));
256 }
257
258}
259
260
261#endif
const Instrument::results * results_
Definition: cdsoption.cpp:63
Concrete date class.
Definition: date.hpp:125
template base class for option pricing engines
std::map< std::string, ext::any > additionalResults
Definition: instrument.hpp:123
Longstaff-Schwarz Monte Carlo engine for early exercise options.
virtual ext::shared_ptr< LongstaffSchwartzPathPricer< path_type > > lsmPathPricer() const =0
ext::shared_ptr< StochasticProcess > process_
McSimulation< MC, RNG, S >::path_generator_type path_generator_type
McSimulation< MC, RNG_Calibration, S >::path_generator_type path_generator_type_calibration
McSimulation< MC, RNG, S >::path_pricer_type path_pricer_type
ext::shared_ptr< path_generator_type > pathGenerator() const override
McSimulation< MC, RNG, S >::stats_type stats_type
ext::shared_ptr< LongstaffSchwartzPathPricer< path_type > > pathPricer_
ext::shared_ptr< path_pricer_type > pathPricer() const override
MCLongstaffSchwartzEngine(ext::shared_ptr< StochasticProcess > process, Size timeSteps, Size timeStepsPerYear, bool brownianBridge, bool antitheticVariate, bool controlVariate, Size requiredSamples, Real requiredTolerance, Size maxSamples, BigNatural seed, Size nCalibrationSamples=Null< Size >(), ext::optional< bool > brownianBridgeCalibration=ext::nullopt, ext::optional< bool > antitheticVariateCalibration=ext::nullopt, BigNatural seedCalibration=Null< Size >())
ext::shared_ptr< MonteCarloModel< MC, RNG_Calibration, S > > mcModelCalibration_
base class for Monte Carlo engines
MonteCarloModel< MC, RNG, S >::path_generator_type path_generator_type
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
General-purpose Monte Carlo model for path samples.
template class providing a null value for a given type.
Definition: null.hpp:76
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
time grid class
Definition: timegrid.hpp:43
Size size() const
Definition: timegrid.hpp:164
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
Option exercise classes and payoff function.
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
Longstaff-Schwarz path pricer for early exercise options.
framework for Monte Carlo engines
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
STL namespace.
Maps optional to either the boost or std implementation.