QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
fdmultiperiodengine.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) 2005 Joseph Wang
5 Copyright (C) 2007, 2009 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 fdmultiperiodengine.hpp
22 \brief base engine for options with events happening at specific times
23*/
24
25#ifndef quantlib_fd_multi_period_engine_hpp
26#define quantlib_fd_multi_period_engine_hpp
27
31#include <ql/event.hpp>
32#include <ql/exercise.hpp>
33
34namespace QuantLib {
35
37
38 /*! \deprecated Use the new finite-differences framework instead.
39 Deprecated in version 1.32.
40 */
41 template <template <class> class Scheme = CrankNicolson>
42 class [[deprecated("Use the new finite-differences framework instead")]]
45 protected:
47
49 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
50 Size timeSteps = 100, Size gridPoints = 100,
51 bool timeDependent = false);
52 mutable std::vector<ext::shared_ptr<Event> > events_;
53 mutable std::vector<Time> stoppingTimes_;
58
59 virtual void setupArguments(
60 const PricingEngine::arguments* args,
61 const std::vector<ext::shared_ptr<Event> >& schedule) const {
63 FDVanillaEngine::setupArguments(args);
65 events_ = schedule;
66 stoppingTimes_.clear();
67 Size n = schedule.size();
68 stoppingTimes_.reserve(n);
69 for (Size i=0; i<n; ++i)
70 stoppingTimes_.push_back(process_->time(events_[i]->date()));
71 }
72
73 void setupArguments(const PricingEngine::arguments* a) const override {
75 FDVanillaEngine::setupArguments(a);
77 const auto* args = dynamic_cast<const OneAssetOption::arguments*>(a);
78 QL_REQUIRE(args, "incorrect argument type");
79 events_.clear();
80
81 Size n = args->exercise->dates().size();
82 stoppingTimes_.resize(n);
83 for (Size i=0; i<n; ++i)
84 stoppingTimes_[i] =
85 process_->time(args->exercise->date(i));
86 }
87
88 virtual void calculate(PricingEngine::results*) const;
90 mutable ext::shared_ptr<StandardStepCondition > stepCondition_;
92 mutable ext::shared_ptr<model_type> model_;
93 virtual void executeIntermediateStep(Size step) const = 0;
94 virtual void initializeStepCondition() const;
95 virtual void initializeModel() const;
97 return stoppingTimes_[i];
98 }
99 };
100
101
102 // template definitions
103
105
106 template <template <class> class Scheme>
108 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
109 Size timeSteps, Size gridPoints, bool timeDependent)
110 : FDVanillaEngine(process, timeSteps, gridPoints, timeDependent),
111 timeStepPerPeriod_(timeSteps) {}
112
113 template <template <class> class Scheme>
115 PricingEngine::results* r) const {
116 auto* results = dynamic_cast<OneAssetOption::results*>(r);
117 QL_REQUIRE(results, "incorrect argument type");
118 Time beginDate, endDate;
119 Size dateNumber = stoppingTimes_.size();
120 bool lastDateIsResTime = false;
121 Integer firstIndex = -1;
122 Integer lastIndex = static_cast<Integer>(dateNumber) - 1;
123 bool firstDateIsZero = false;
124 Time firstNonZeroDate = getResidualTime();
125
126 Real dateTolerance = 1e-6;
127
128 if (dateNumber > 0) {
129 QL_REQUIRE(getDividendTime(0) >= 0,
130 "first date (" << getDividendTime(0)
131 << ") cannot be negative");
132 if(getDividendTime(0) < getResidualTime() * dateTolerance ){
133 firstDateIsZero = true;
134 firstIndex = 0;
135 if(dateNumber >= 2)
136 firstNonZeroDate = getDividendTime(1);
137 }
138
139 if (std::fabs(getDividendTime(lastIndex) - getResidualTime())
140 < dateTolerance) {
141 lastDateIsResTime = true;
142 lastIndex = Integer(dateNumber) - 2;
143 }
144
145 if (!firstDateIsZero)
146 firstNonZeroDate = getDividendTime(0);
147
148 if (dateNumber >= 2) {
149 for (Size j = 1; j < dateNumber; j++)
150 QL_REQUIRE(getDividendTime(j-1) < getDividendTime(j),
151 "dates must be in increasing order: "
152 << getDividendTime(j-1)
153 << " is not strictly smaller than "
154 << getDividendTime(j));
155 }
156 }
157
158 Time dt = getResidualTime()/(timeStepPerPeriod_*(dateNumber+1));
159
160 // Ensure that dt is always smaller than the first non-zero date
161 if (firstNonZeroDate <= dt)
162 dt = firstNonZeroDate/2.0;
163
164 setGridLimits();
165 initializeInitialCondition();
166 initializeOperator();
167 initializeBoundaryConditions();
168 initializeModel();
169 initializeStepCondition();
170
171 prices_ = intrinsicValues_;
172 if(lastDateIsResTime)
173 executeIntermediateStep(dateNumber - 1);
174
175 Integer j = lastIndex;
176 do {
177 if (j == Integer(dateNumber) - 1)
178 beginDate = getResidualTime();
179 else
180 beginDate = getDividendTime(j+1);
181
182 if (j >= 0)
183 endDate = getDividendTime(j);
184 else
185 endDate = dt;
186
187 model_->rollback(prices_.values(),
188 beginDate, endDate,
189 timeStepPerPeriod_, *stepCondition_);
190 if (j >= 0)
191 executeIntermediateStep(j);
192 } while (--j >= firstIndex);
193
194 model_->rollback(prices_.values(), dt, 0, 1, *stepCondition_);
195
196 if(firstDateIsZero)
197 executeIntermediateStep(0);
198
199 results->value = prices_.valueAtCenter();
200 results->delta = prices_.firstDerivativeAtCenter();
201 results->gamma = prices_.secondDerivativeAtCenter();
202 results->additionalResults["priceCurve"] = prices_;
203 }
204
205 template <template <class> class Scheme>
207 stepCondition_ = ext::shared_ptr<StandardStepCondition>(
209 }
210
211 template <template <class> class Scheme>
213 model_ = ext::shared_ptr<model_type>(
214 new model_type(finiteDifferenceOperator_,BCs_));
215 }
216
218
219}
220
221
222#endif
FDMultiPeriodEngine(const ext::shared_ptr< GeneralizedBlackScholesProcess > &process, Size timeSteps=100, Size gridPoints=100, bool timeDependent=false)
QL_DEPRECATED_ENABLE_WARNING ext::shared_ptr< model_type > model_
virtual QL_DEPRECATED_ENABLE_WARNING void setupArguments(const PricingEngine::arguments *args, const std::vector< ext::shared_ptr< Event > > &schedule) const
virtual void calculate(PricingEngine::results *) const
QL_DEPRECATED_DISABLE_WARNING ext::shared_ptr< StandardStepCondition > stepCondition_
void setupArguments(const PricingEngine::arguments *a) const override
FiniteDifferenceModel< Scheme< TridiagonalOperator > > model_type
virtual void executeIntermediateStep(Size step) const =0
QL_DEPRECATED_DISABLE_WARNING SampledCurve prices_
virtual void initializeStepCondition() const
std::vector< ext::shared_ptr< Event > > events_
Generic finite difference model.
null step condition
Results from single-asset option calculation
basic option arguments
Definition: option.hpp:57
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Base class for events associated with a given date.
Option exercise classes and payoff function.
default choices for template instantiations
Finite-differences vanilla-option engine.
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
QL_INTEGER Integer
integer number
Definition: types.hpp:35
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
Option on a single asset.
ext::shared_ptr< YieldTermStructure > r
#define QL_DEPRECATED_DISABLE_WARNING
Definition: qldefines.hpp:216
#define QL_DEPRECATED_ENABLE_WARNING
Definition: qldefines.hpp:217