1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5 Copyright (C) 2003, 2004 Ferdinando Ametrano
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21/*! \file mc_discr_arith_av_price.hpp
22 \brief Monte Carlo engine for discrete arithmetic average price Asian
23*/
24
25#ifndef quantlib_mc_discrete_arithmetic_average_price_asian_engine_hpp
26#define quantlib_mc_discrete_arithmetic_average_price_asian_engine_hpp
27
28#include <ql/exercise.hpp>
29#include <ql/pricingengines/asian/analytic_discr_geom_av_price.hpp>
30#include <ql/pricingengines/asian/mc_discr_geom_av_price.hpp>
31#include <ql/processes/blackscholesprocess.hpp>
32#include <utility>
33
34namespace QuantLib {
35
36 //! Monte Carlo pricing engine for discrete arithmetic average price Asian
37 /*! Monte Carlo pricing engine for discrete arithmetic average price
38 Asian options. It can use MCDiscreteGeometricAPEngine (Monte Carlo
39 discrete arithmetic average price engine) and
40 AnalyticDiscreteGeometricAveragePriceAsianEngine (analytic discrete
41 arithmetic average price engine) for control variation.
42
43 \ingroup asianengines
44
45 \test the correctness of the returned value is tested by
46 reproducing results available in literature.
47 */
48 template <class RNG = PseudoRandom, class S = Statistics>
49 class MCDiscreteArithmeticAPEngine
50 : public MCDiscreteAveragingAsianEngineBase<SingleVariate,RNG,S> {
51 public:
52 typedef
53 typename MCDiscreteAveragingAsianEngineBase<SingleVariate,RNG,S>::path_generator_type
54 path_generator_type;
55 typedef
56 typename MCDiscreteAveragingAsianEngineBase<SingleVariate,RNG,S>::path_pricer_type
57 path_pricer_type;
58 typedef typename MCDiscreteAveragingAsianEngineBase<SingleVariate,RNG,S>::stats_type
59 stats_type;
60 // constructor
61 MCDiscreteArithmeticAPEngine(
62 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
63 bool brownianBridge,
64 bool antitheticVariate,
65 bool controlVariate,
66 Size requiredSamples,
67 Real requiredTolerance,
68 Size maxSamples,
69 BigNatural seed);
70 protected:
71 ext::shared_ptr<path_pricer_type> pathPricer() const override;
72 ext::shared_ptr<path_pricer_type> controlPathPricer() const override;
73 ext::shared_ptr<PricingEngine> controlPricingEngine() const override {
74 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
75 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
76 this->process_);
77 QL_REQUIRE(process, "Black-Scholes process required");
78 return ext::shared_ptr<PricingEngine>(new
79 AnalyticDiscreteGeometricAveragePriceAsianEngine(process));
80 }
81 };
82
83
84 class ArithmeticAPOPathPricer : public PathPricer<Path> {
85 public:
86 ArithmeticAPOPathPricer(Option::Type type,
87 Real strike,
88 DiscountFactor discount,
89 Real runningSum = 0.0,
90 Size pastFixings = 0);
91 Real operator()(const Path& path) const override;
92
93 private:
94 PlainVanillaPayoff payoff_;
95 DiscountFactor discount_;
96 Real runningSum_;
97 Size pastFixings_;
98 };
99
100
101 // inline definitions
102
103 template <class RNG, class S>
104 inline
105 MCDiscreteArithmeticAPEngine<RNG,S>::MCDiscreteArithmeticAPEngine(
106 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
107 bool brownianBridge,
108 bool antitheticVariate,
109 bool controlVariate,
110 Size requiredSamples,
111 Real requiredTolerance,
112 Size maxSamples,
113 BigNatural seed)
114 : MCDiscreteAveragingAsianEngineBase<SingleVariate,RNG,S>(process,
115 brownianBridge,
116 antitheticVariate,
117 controlVariate,
118 requiredSamples,
119 requiredTolerance,
120 maxSamples,
121 seed) {}
122
123 template <class RNG, class S>
124 inline
125 ext::shared_ptr<
126 typename MCDiscreteArithmeticAPEngine<RNG,S>::path_pricer_type>
127 MCDiscreteArithmeticAPEngine<RNG,S>::pathPricer() const {
128
129 ext::shared_ptr<PlainVanillaPayoff> payoff =
130 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
131 this->arguments_.payoff);
132 QL_REQUIRE(payoff, "non-plain payoff given");
133
134 ext::shared_ptr<EuropeanExercise> exercise =
135 ext::dynamic_pointer_cast<EuropeanExercise>(
136 this->arguments_.exercise);
137 QL_REQUIRE(exercise, "wrong exercise given");
138
139 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
140 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
141 this->process_);
142 QL_REQUIRE(process, "Black-Scholes process required");
143
144 return ext::shared_ptr<typename
145 MCDiscreteArithmeticAPEngine<RNG,S>::path_pricer_type>(
146 new ArithmeticAPOPathPricer(
147 payoff->optionType(),
148 payoff->strike(),
149 process->riskFreeRate()->discount(d: exercise->lastDate()),
150 this->arguments_.runningAccumulator,
151 this->arguments_.pastFixings));
152 }
153
154 template <class RNG, class S>
155 inline
156 ext::shared_ptr<
157 typename MCDiscreteArithmeticAPEngine<RNG,S>::path_pricer_type>
158 MCDiscreteArithmeticAPEngine<RNG,S>::controlPathPricer() const {
159
160 ext::shared_ptr<PlainVanillaPayoff> payoff =
161 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
162 this->arguments_.payoff);
163 QL_REQUIRE(payoff, "non-plain payoff given");
164
165 ext::shared_ptr<EuropeanExercise> exercise =
166 ext::dynamic_pointer_cast<EuropeanExercise>(
167 this->arguments_.exercise);
168 QL_REQUIRE(exercise, "wrong exercise given");
169
170 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
171 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
172 this->process_);
173 QL_REQUIRE(process, "Black-Scholes process required");
174
175 // for seasoned option the geometric strike might be rescaled
176 // to obtain an equivalent arithmetic strike.
177 // Any change applied here MUST be applied to the analytic engine too
178 return ext::shared_ptr<typename
179 MCDiscreteArithmeticAPEngine<RNG,S>::path_pricer_type>(
180 new GeometricAPOPathPricer(
181 payoff->optionType(),
182 payoff->strike(),
183 process->riskFreeRate()->discount(this->timeGrid().back())));
184 }
185
186 template <class RNG = PseudoRandom, class S = Statistics>
187 class MakeMCDiscreteArithmeticAPEngine {
188 public:
189 explicit MakeMCDiscreteArithmeticAPEngine(
190 ext::shared_ptr<GeneralizedBlackScholesProcess> process);
191 // named parameters
192 MakeMCDiscreteArithmeticAPEngine& withBrownianBridge(bool b = true);
193 MakeMCDiscreteArithmeticAPEngine& withSamples(Size samples);
194 MakeMCDiscreteArithmeticAPEngine& withAbsoluteTolerance(Real tolerance);
195 MakeMCDiscreteArithmeticAPEngine& withMaxSamples(Size samples);
196 MakeMCDiscreteArithmeticAPEngine& withSeed(BigNatural seed);
197 MakeMCDiscreteArithmeticAPEngine& withAntitheticVariate(bool b = true);
198 MakeMCDiscreteArithmeticAPEngine& withControlVariate(bool b = true);
199 // conversion to pricing engine
200 operator ext::shared_ptr<PricingEngine>() const;
201 private:
202 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
203 bool antithetic_ = false, controlVariate_ = false;
204 Size samples_, maxSamples_;
205 Real tolerance_;
206 bool brownianBridge_ = true;
207 BigNatural seed_ = 0;
208 };
209
210 template <class RNG, class S>
211 inline MakeMCDiscreteArithmeticAPEngine<RNG, S>::MakeMCDiscreteArithmeticAPEngine(
212 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
213 : process_(std::move(process)), samples_(Null<Size>()), maxSamples_(Null<Size>()),
214 tolerance_(Null<Real>()) {}
215
216 template <class RNG, class S>
217 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
218 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withSamples(Size samples) {
219 QL_REQUIRE(tolerance_ == Null<Real>(),
220 "tolerance already set");
221 samples_ = samples;
222 return *this;
223 }
224
225 template <class RNG, class S>
226 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
227 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withAbsoluteTolerance(
228 Real tolerance) {
229 QL_REQUIRE(samples_ == Null<Size>(),
230 "number of samples already set");
231 QL_REQUIRE(RNG::allowsErrorEstimate,
232 "chosen random generator policy "
233 "does not allow an error estimate");
234 tolerance_ = tolerance;
235 return *this;
236 }
237
238 template <class RNG, class S>
239 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
240 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withMaxSamples(Size samples) {
241 maxSamples_ = samples;
242 return *this;
243 }
244
245 template <class RNG, class S>
246 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
247 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withSeed(BigNatural seed) {
248 seed_ = seed;
249 return *this;
250 }
251
252 template <class RNG, class S>
253 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
254 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withBrownianBridge(bool b) {
255 brownianBridge_ = b;
256 return *this;
257 }
258
259 template <class RNG, class S>
260 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
261 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withAntitheticVariate(bool b) {
262 antithetic_ = b;
263 return *this;
264 }
265
266 template <class RNG, class S>
267 inline MakeMCDiscreteArithmeticAPEngine<RNG,S>&
268 MakeMCDiscreteArithmeticAPEngine<RNG,S>::withControlVariate(bool b) {
269 controlVariate_ = b;
270 return *this;
271 }
272
273 template <class RNG, class S>
274 inline
275 MakeMCDiscreteArithmeticAPEngine<RNG,S>::operator ext::shared_ptr<PricingEngine>()
276 const {
277 return ext::shared_ptr<PricingEngine>(new
278 MCDiscreteArithmeticAPEngine<RNG,S>(process_,
279 brownianBridge_,
280 antithetic_, controlVariate_,
281 samples_, tolerance_,
282 maxSamples_,
283 seed_));
284 }
285
286
287
288}
289
290
291#endif
292

source code of quantlib/ql/pricingengines/asian/mc_discr_arith_av_price.hpp