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) 2003, 2004, 2005, 2007 StatPro Italia srl
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 mcvanillaengine.hpp
22 \brief Monte Carlo vanilla option engine
23*/
24
25#ifndef quantlib_mcvanilla_engine_hpp
26#define quantlib_mcvanilla_engine_hpp
27
28#include <ql/pricingengines/mcsimulation.hpp>
29#include <ql/instruments/vanillaoption.hpp>
30
31namespace QuantLib {
32
33 //! Pricing engine for vanilla options using Monte Carlo simulation
34 /*! \ingroup vanillaengines */
35 template <template <class> class MC, class RNG,
36 class S = Statistics, class Inst = VanillaOption>
37 class MCVanillaEngine : public Inst::engine,
38 public McSimulation<MC,RNG,S> {
39 public:
40 void calculate() const override {
41 McSimulation<MC,RNG,S>::calculate(requiredTolerance_,
42 requiredSamples_,
43 maxSamples_);
44 this->results_.value = this->mcModel_->sampleAccumulator().mean();
45 if (RNG::allowsErrorEstimate)
46 this->results_.errorEstimate =
47 this->mcModel_->sampleAccumulator().errorEstimate();
48 }
49
50 protected:
51 typedef typename McSimulation<MC,RNG,S>::path_generator_type
52 path_generator_type;
53 typedef typename McSimulation<MC,RNG,S>::path_pricer_type
54 path_pricer_type;
55 typedef typename McSimulation<MC,RNG,S>::stats_type
56 stats_type;
57 typedef typename McSimulation<MC,RNG,S>::result_type
58 result_type;
59 // constructor
60 MCVanillaEngine(ext::shared_ptr<StochasticProcess>,
61 Size timeSteps,
62 Size timeStepsPerYear,
63 bool brownianBridge,
64 bool antitheticVariate,
65 bool controlVariate,
66 Size requiredSamples,
67 Real requiredTolerance,
68 Size maxSamples,
69 BigNatural seed);
70 // McSimulation implementation
71 TimeGrid timeGrid() const override;
72 ext::shared_ptr<path_generator_type> pathGenerator() const override {
73
74 Size dimensions = process_->factors();
75 TimeGrid grid = this->timeGrid();
76 typename RNG::rsg_type generator =
77 RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
78 return ext::shared_ptr<path_generator_type>(
79 new path_generator_type(process_, grid,
80 generator, brownianBridge_));
81 }
82 result_type controlVariateValue() const override;
83 // data members
84 ext::shared_ptr<StochasticProcess> process_;
85 Size timeSteps_, timeStepsPerYear_;
86 Size requiredSamples_, maxSamples_;
87 Real requiredTolerance_;
88 bool brownianBridge_;
89 BigNatural seed_;
90 };
91
92
93 // template definitions
94
95 template <template <class> class MC, class RNG, class S, class Inst>
96 inline MCVanillaEngine<MC, RNG, S, Inst>::MCVanillaEngine(
97 ext::shared_ptr<StochasticProcess> process,
98 Size timeSteps,
99 Size timeStepsPerYear,
100 bool brownianBridge,
101 bool antitheticVariate,
102 bool controlVariate,
103 Size requiredSamples,
104 Real requiredTolerance,
105 Size maxSamples,
106 BigNatural seed)
107 : McSimulation<MC, RNG, S>(antitheticVariate, controlVariate), process_(std::move(process)),
108 timeSteps_(timeSteps), timeStepsPerYear_(timeStepsPerYear), requiredSamples_(requiredSamples),
109 maxSamples_(maxSamples), requiredTolerance_(requiredTolerance),
110 brownianBridge_(brownianBridge), seed_(seed) {
111 QL_REQUIRE(timeSteps != Null<Size>() ||
112 timeStepsPerYear != Null<Size>(),
113 "no time steps provided");
114 QL_REQUIRE(timeSteps == Null<Size>() ||
115 timeStepsPerYear == Null<Size>(),
116 "both time steps and time steps per year were provided");
117 QL_REQUIRE(timeSteps != 0,
118 "timeSteps must be positive, " << timeSteps <<
119 " not allowed");
120 QL_REQUIRE(timeStepsPerYear != 0,
121 "timeStepsPerYear must be positive, " << timeStepsPerYear <<
122 " not allowed");
123 this->registerWith(process_);
124 }
125
126 template <template <class> class MC, class RNG, class S, class Inst>
127 inline typename MCVanillaEngine<MC,RNG,S,Inst>::result_type
128 MCVanillaEngine<MC,RNG,S,Inst>::controlVariateValue() const {
129
130 ext::shared_ptr<PricingEngine> controlPE =
131 this->controlPricingEngine();
132 QL_REQUIRE(controlPE,
133 "engine does not provide "
134 "control variation pricing engine");
135
136 auto* controlArguments = dynamic_cast<typename Inst::arguments*>(controlPE->getArguments());
137
138 QL_REQUIRE(controlArguments, "engine is using inconsistent arguments");
139
140 *controlArguments = this->arguments_;
141 controlPE->calculate();
142
143 const auto* controlResults =
144 dynamic_cast<const typename Inst::results*>(controlPE->getResults());
145 QL_REQUIRE(controlResults,
146 "engine returns an inconsistent result type");
147
148 return result_type(controlResults->value);
149 }
150
151
152 template <template <class> class MC, class RNG, class S, class Inst>
153 inline TimeGrid MCVanillaEngine<MC,RNG,S,Inst>::timeGrid() const {
154 Date lastExerciseDate = this->arguments_.exercise->lastDate();
155 Time t = process_->time(lastExerciseDate);
156 if (this->timeSteps_ != Null<Size>()) {
157 return TimeGrid(t, this->timeSteps_);
158 } else if (this->timeStepsPerYear_ != Null<Size>()) {
159 Size steps = static_cast<Size>(this->timeStepsPerYear_*t);
160 return TimeGrid(t, std::max<Size>(a: steps, b: 1));
161 } else {
162 QL_FAIL("time steps not specified");
163 }
164 }
165
166}
167
168
169#endif
170

source code of quantlib/ql/pricingengines/vanilla/mcvanillaengine.hpp