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 QuantLib is free software: you can redistribute it and/or modify it
7 under the terms of the QuantLib license. You should have received a
8 copy of the license along with this program; if not, please email
9 <quantlib-dev@lists.sf.net>. The license is also available online at
10 <http://quantlib.org/license.shtml>.
11 This program is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the license for more details.
14*/
15
16/*! \file mcforwardeuropeanbsengine.hpp
17 \brief Monte Carlo engine for forward-starting strike-reset European options using BS process
18*/
19
20#ifndef quantlib_mc_forward_european_bs_engine_hpp
21#define quantlib_mc_forward_european_bs_engine_hpp
22
23#include <ql/pricingengines/forward/mcforwardvanillaengine.hpp>
24#include <ql/processes/blackscholesprocess.hpp>
25#include <utility>
26
27namespace QuantLib {
28
29 /*! \ingroup forwardengines
30 \test
31 - the correctness of the returned value is tested by
32 comparing prices to the analytic pricer for a range
33 of moneynesses
34 */
35 template <class RNG = PseudoRandom, class S = Statistics>
36 class MCForwardEuropeanBSEngine
37 : public MCForwardVanillaEngine<SingleVariate,RNG,S> {
38 public:
39 typedef
40 typename MCForwardVanillaEngine<SingleVariate,RNG,S>::path_generator_type
41 path_generator_type;
42 typedef
43 typename MCForwardVanillaEngine<SingleVariate,RNG,S>::path_pricer_type
44 path_pricer_type;
45 typedef typename MCForwardVanillaEngine<SingleVariate,RNG,S>::stats_type
46 stats_type;
47 // constructor
48 MCForwardEuropeanBSEngine(
49 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
50 Size timeSteps,
51 Size timeStepsPerYear,
52 bool brownianBridge,
53 bool antitheticVariate,
54 Size requiredSamples,
55 Real requiredTolerance,
56 Size maxSamples,
57 BigNatural seed);
58 protected:
59 ext::shared_ptr<path_pricer_type> pathPricer() const override;
60 };
61
62
63 template <class RNG = PseudoRandom, class S = Statistics>
64 class MakeMCForwardEuropeanBSEngine {
65 public:
66 explicit MakeMCForwardEuropeanBSEngine(
67 ext::shared_ptr<GeneralizedBlackScholesProcess> process);
68 // named parameters
69 MakeMCForwardEuropeanBSEngine& withSteps(Size steps);
70 MakeMCForwardEuropeanBSEngine& withStepsPerYear(Size steps);
71 MakeMCForwardEuropeanBSEngine& withBrownianBridge(bool b = false);
72 MakeMCForwardEuropeanBSEngine& withSamples(Size samples);
73 MakeMCForwardEuropeanBSEngine& withAbsoluteTolerance(Real tolerance);
74 MakeMCForwardEuropeanBSEngine& withMaxSamples(Size samples);
75 MakeMCForwardEuropeanBSEngine& withSeed(BigNatural seed);
76 MakeMCForwardEuropeanBSEngine& withAntitheticVariate(bool b = true);
77 // conversion to pricing engine
78 operator ext::shared_ptr<PricingEngine>() const;
79 private:
80 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
81 bool antithetic_ = false;
82 Size steps_, stepsPerYear_, samples_, maxSamples_;
83 Real tolerance_;
84 bool brownianBridge_ = false;
85 BigNatural seed_ = 0;
86 };
87
88
89 class ForwardEuropeanBSPathPricer : public PathPricer<Path> {
90 public:
91 ForwardEuropeanBSPathPricer(Option::Type type,
92 Real moneyness,
93 Size resetIndex,
94 DiscountFactor discount);
95 Real operator()(const Path& path) const override;
96
97 private:
98 Option::Type type_;
99 Real moneyness_;
100 Size resetIndex_;
101 DiscountFactor discount_;
102 };
103
104
105 // inline definitions
106
107 template <class RNG, class S>
108 inline
109 MCForwardEuropeanBSEngine<RNG,S>::MCForwardEuropeanBSEngine(
110 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
111 Size timeSteps,
112 Size timeStepsPerYear,
113 bool brownianBridge,
114 bool antitheticVariate,
115 Size requiredSamples,
116 Real requiredTolerance,
117 Size maxSamples,
118 BigNatural seed)
119 : MCForwardVanillaEngine<SingleVariate,RNG,S>(process,
120 timeSteps,
121 timeStepsPerYear,
122 brownianBridge,
123 antitheticVariate,
124 requiredSamples,
125 requiredTolerance,
126 maxSamples,
127 seed) {}
128
129
130 template <class RNG, class S>
131 inline
132 ext::shared_ptr<typename MCForwardEuropeanBSEngine<RNG,S>::path_pricer_type>
133 MCForwardEuropeanBSEngine<RNG,S>::pathPricer() const {
134
135 TimeGrid timeGrid = this->timeGrid();
136
137 Time resetTime = this->process_->time(this->arguments_.resetDate);
138 Size resetIndex = timeGrid.closestIndex(t: resetTime);
139
140 ext::shared_ptr<PlainVanillaPayoff> payoff =
141 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
142 this->arguments_.payoff);
143 QL_REQUIRE(payoff, "non-plain payoff given");
144
145 ext::shared_ptr<EuropeanExercise> exercise =
146 ext::dynamic_pointer_cast<EuropeanExercise>(
147 this->arguments_.exercise);
148 QL_REQUIRE(exercise, "wrong exercise given");
149
150 ext::shared_ptr<GeneralizedBlackScholesProcess> process =
151 ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
152 this->process_);
153 QL_REQUIRE(process, "Black-Scholes process required");
154
155 return ext::shared_ptr<typename
156 MCForwardEuropeanBSEngine<RNG,S>::path_pricer_type>(
157 new ForwardEuropeanBSPathPricer(
158 payoff->optionType(),
159 this->arguments_.moneyness,
160 resetIndex,
161 process->riskFreeRate()->discount(
162 t: timeGrid.back())));
163 }
164
165
166 template <class RNG, class S>
167 inline MakeMCForwardEuropeanBSEngine<RNG, S>::MakeMCForwardEuropeanBSEngine(
168 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
169 : process_(std::move(process)), steps_(Null<Size>()), stepsPerYear_(Null<Size>()),
170 samples_(Null<Size>()), maxSamples_(Null<Size>()), tolerance_(Null<Real>()) {}
171
172 template <class RNG, class S>
173 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
174 MakeMCForwardEuropeanBSEngine<RNG,S>::withSteps(Size steps) {
175 steps_ = steps;
176 return *this;
177 }
178
179 template <class RNG, class S>
180 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
181 MakeMCForwardEuropeanBSEngine<RNG,S>::withStepsPerYear(Size steps) {
182 stepsPerYear_ = steps;
183 return *this;
184 }
185
186 template <class RNG, class S>
187 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
188 MakeMCForwardEuropeanBSEngine<RNG,S>::withSamples(Size samples) {
189 QL_REQUIRE(tolerance_ == Null<Real>(),
190 "tolerance already set");
191 samples_ = samples;
192 return *this;
193 }
194
195 template <class RNG, class S>
196 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
197 MakeMCForwardEuropeanBSEngine<RNG,S>::withAbsoluteTolerance(
198 Real tolerance) {
199 QL_REQUIRE(samples_ == Null<Size>(),
200 "number of samples already set");
201 QL_REQUIRE(RNG::allowsErrorEstimate,
202 "chosen random generator policy "
203 "does not allow an error estimate");
204 tolerance_ = tolerance;
205 return *this;
206 }
207
208 template <class RNG, class S>
209 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
210 MakeMCForwardEuropeanBSEngine<RNG,S>::withMaxSamples(Size samples) {
211 maxSamples_ = samples;
212 return *this;
213 }
214
215 template <class RNG, class S>
216 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
217 MakeMCForwardEuropeanBSEngine<RNG,S>::withSeed(BigNatural seed) {
218 seed_ = seed;
219 return *this;
220 }
221
222 template <class RNG, class S>
223 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
224 MakeMCForwardEuropeanBSEngine<RNG,S>::withBrownianBridge(bool b) {
225 brownianBridge_ = b;
226 return *this;
227 }
228
229 template <class RNG, class S>
230 inline MakeMCForwardEuropeanBSEngine<RNG,S>&
231 MakeMCForwardEuropeanBSEngine<RNG,S>::withAntitheticVariate(bool b) {
232 antithetic_ = b;
233 return *this;
234 }
235
236 template <class RNG, class S>
237 inline
238 MakeMCForwardEuropeanBSEngine<RNG,S>::operator ext::shared_ptr<PricingEngine>()
239 const {
240 QL_REQUIRE(steps_ != Null<Size>() || stepsPerYear_ != Null<Size>(),
241 "number of steps not given");
242 QL_REQUIRE(steps_ == Null<Size>() || stepsPerYear_ == Null<Size>(),
243 "number of steps overspecified - set EITHER steps OR stepsPerYear");
244 return ext::shared_ptr<PricingEngine>(new
245 MCForwardEuropeanBSEngine<RNG,S>(process_,
246 steps_,
247 stepsPerYear_,
248 brownianBridge_,
249 antithetic_,
250 samples_, tolerance_,
251 maxSamples_,
252 seed_));
253 }
254
255}
256
257
258#endif
259

source code of quantlib/ql/pricingengines/forward/mcforwardeuropeanbsengine.hpp