QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
mcsimulation.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) 2003 Ferdinando Ametrano
5 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
6 Copyright (C) 2007 StatPro Italia srl
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22/*! \file mcsimulation.hpp
23 \brief framework for Monte Carlo engines
24*/
25
26#ifndef quantlib_montecarlo_engine_hpp
27#define quantlib_montecarlo_engine_hpp
28
29#include <ql/grid.hpp>
31
32namespace QuantLib {
33
34 //! base class for Monte Carlo engines
35 /*! Eventually this class might offer greeks methods. Deriving a
36 class from McSimulation gives an easy way to write a Monte
37 Carlo engine.
38
39 See McVanillaEngine as an example.
40 */
41
42 template <template <class> class MC, class RNG, class S = Statistics>
44 public:
52
53 virtual ~McSimulation() = default;
54 //! add samples until the required absolute tolerance is reached
56 Size maxSamples = QL_MAX_INTEGER,
57 Size minSamples = 1023) const;
58 //! simulate a fixed number of samples
60 //! error estimated using the samples simulated so far
62 //! access to the sample accumulator for richer statistics
64 //! basic calculate method provided to inherited pricing engines
65 void calculate(Real requiredTolerance,
66 Size requiredSamples,
67 Size maxSamples) const;
68 protected:
69 McSimulation(bool antitheticVariate,
70 bool controlVariate)
71 : antitheticVariate_(antitheticVariate),
72 controlVariate_(controlVariate) {}
73 virtual ext::shared_ptr<path_pricer_type> pathPricer() const = 0;
74 virtual ext::shared_ptr<path_generator_type> pathGenerator()
75 const = 0;
76 virtual TimeGrid timeGrid() const = 0;
77 virtual ext::shared_ptr<path_pricer_type> controlPathPricer() const {
78 return ext::shared_ptr<path_pricer_type>();
79 }
80 virtual ext::shared_ptr<path_generator_type>
82 return ext::shared_ptr<path_generator_type>();
83 }
84 virtual ext::shared_ptr<PricingEngine> controlPricingEngine() const {
85 return ext::shared_ptr<PricingEngine>();
86 }
88 return Null<result_type>();
89 }
90 template <class Sequence>
91 static Real maxError(const Sequence& sequence) {
92 return *std::max_element(sequence.begin(), sequence.end());
93 }
94 static Real maxError(Real error) {
95 return error;
96 }
97
98 mutable ext::shared_ptr<MonteCarloModel<MC,RNG,S> > mcModel_;
100 };
101
102
103 // inline definitions
104 template <template <class> class MC, class RNG, class S>
107 Size maxSamples,
108 Size minSamples) const {
109 Size sampleNumber =
110 mcModel_->sampleAccumulator().samples();
111 if (sampleNumber<minSamples) {
112 mcModel_->addSamples(minSamples-sampleNumber);
113 sampleNumber = mcModel_->sampleAccumulator().samples();
114 }
115
116 Size nextBatch;
117 Real order;
118 result_type error(mcModel_->sampleAccumulator().errorEstimate());
119 while (maxError(error) > tolerance) {
120 QL_REQUIRE(sampleNumber<maxSamples,
121 "max number of samples (" << maxSamples
122 << ") reached, while error (" << error
123 << ") is still above tolerance (" << tolerance << ")");
124
125 // conservative estimate of how many samples are needed
126 order = maxError(Real(error*error))/tolerance/tolerance;
127 nextBatch =
128 Size(std::max<Real>(static_cast<Real>(sampleNumber)*order*0.8 - static_cast<Real>(sampleNumber),
129 static_cast<Real>(minSamples)));
130
131 // do not exceed maxSamples
132 nextBatch = std::min(nextBatch, maxSamples-sampleNumber);
133 sampleNumber += nextBatch;
134 mcModel_->addSamples(nextBatch);
135 error = result_type(mcModel_->sampleAccumulator().errorEstimate());
136 }
137
138 return result_type(mcModel_->sampleAccumulator().mean());
139 }
140
141
142 template <template <class> class MC, class RNG, class S>
145
146 Size sampleNumber = mcModel_->sampleAccumulator().samples();
147
148 QL_REQUIRE(samples>=sampleNumber,
149 "number of already simulated samples (" << sampleNumber
150 << ") greater than requested samples (" << samples << ")");
151
152 mcModel_->addSamples(samples-sampleNumber);
153
154 return result_type(mcModel_->sampleAccumulator().mean());
155 }
156
157
158 template <template <class> class MC, class RNG, class S>
159 inline void McSimulation<MC,RNG,S>::calculate(Real requiredTolerance,
160 Size requiredSamples,
161 Size maxSamples) const {
162
163 QL_REQUIRE(requiredTolerance != Null<Real>() ||
164 requiredSamples != Null<Size>(),
165 "neither tolerance nor number of samples set");
166
167 //! Initialize the one-factor Monte Carlo
168 if (this->controlVariate_) {
169
170 result_type controlVariateValue = this->controlVariateValue();
171 QL_REQUIRE(controlVariateValue != Null<result_type>(),
172 "engine does not provide "
173 "control-variation price");
174
175 ext::shared_ptr<path_pricer_type> controlPP =
176 this->controlPathPricer();
177 QL_REQUIRE(controlPP,
178 "engine does not provide "
179 "control-variation path pricer");
180
181 ext::shared_ptr<path_generator_type> controlPG =
182 this->controlPathGenerator();
183
184 this->mcModel_ =
185 ext::shared_ptr<MonteCarloModel<MC,RNG,S> >(
187 pathGenerator(), this->pathPricer(), stats_type(),
188 this->antitheticVariate_, controlPP,
189 controlVariateValue, controlPG));
190 } else {
191 this->mcModel_ =
192 ext::shared_ptr<MonteCarloModel<MC,RNG,S> >(
194 pathGenerator(), this->pathPricer(), S(),
195 this->antitheticVariate_));
196 }
197
198 if (requiredTolerance != Null<Real>()) {
199 if (maxSamples != Null<Size>())
200 this->value(requiredTolerance, maxSamples);
201 else
202 this->value(requiredTolerance);
203 } else {
204 this->valueWithSamples(requiredSamples);
205 }
206
207 }
208
209 template <template <class> class MC, class RNG, class S>
212 return mcModel_->sampleAccumulator().errorEstimate();
213 }
214
215 template <template <class> class MC, class RNG, class S>
216 inline const typename McSimulation<MC,RNG,S>::stats_type&
218 return mcModel_->sampleAccumulator();
219 }
220
221}
222
223
224#endif
base class for Monte Carlo engines
virtual ext::shared_ptr< path_pricer_type > pathPricer() const =0
result_type valueWithSamples(Size samples) const
simulate a fixed number of samples
virtual result_type controlVariateValue() const
result_type errorEstimate() const
error estimated using the samples simulated so far
MonteCarloModel< MC, RNG, S >::stats_type stats_type
virtual ext::shared_ptr< path_generator_type > pathGenerator() const =0
virtual ext::shared_ptr< path_pricer_type > controlPathPricer() const
MonteCarloModel< MC, RNG, S >::path_generator_type path_generator_type
result_type value(Real tolerance, Size maxSamples=QL_MAX_INTEGER, Size minSamples=1023) const
add samples until the required absolute tolerance is reached
virtual TimeGrid timeGrid() const =0
static Real maxError(const Sequence &sequence)
MonteCarloModel< MC, RNG, S >::result_type result_type
McSimulation(bool antitheticVariate, bool controlVariate)
virtual ext::shared_ptr< PricingEngine > controlPricingEngine() const
static Real maxError(Real error)
const stats_type & sampleAccumulator() const
access to the sample accumulator for richer statistics
virtual ~McSimulation()=default
ext::shared_ptr< MonteCarloModel< MC, RNG, S > > mcModel_
virtual ext::shared_ptr< path_generator_type > controlPathGenerator() const
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.
MC< RNG >::path_pricer_type path_pricer_type
MC< RNG >::path_generator_type path_generator_type
path_pricer_type::result_type result_type
template class providing a null value for a given type.
Definition: null.hpp:76
time grid class
Definition: timegrid.hpp:43
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Grid constructors.
#define QL_MAX_INTEGER
Definition: qldefines.hpp:174
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
General-purpose Monte Carlo model.
Definition: any.hpp:35
RiskStatistics Statistics
default statistics tool
Definition: statistics.hpp:35