QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
fdhestonvanillaengine.cpp
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) 2008 Andreas Gaida
5 Copyright (C) 2008, 2009 Ralph Schreyer
6 Copyright (C) 2008, 2009, 2015 Klaus Spanderen
7 Copyright (C) 2015 Johannes Göttker-Schnetmann
8
9 This file is part of QuantLib, a free-software/open-source library
10 for financial quantitative analysts and developers - http://quantlib.org/
11
12 QuantLib is free software: you can redistribute it and/or modify it
13 under the terms of the QuantLib license. You should have received a
14 copy of the license along with this program; if not, please email
15 <quantlib-dev@lists.sf.net>. The license is also available online at
16 <http://quantlib.org/license.shtml>.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the license for more details.
21*/
22
33#include <utility>
34
35namespace QuantLib {
36
37 FdHestonVanillaEngine::FdHestonVanillaEngine(const ext::shared_ptr<HestonModel>& model,
38 Size tGrid,
39 Size xGrid,
40 Size vGrid,
41 Size dampingSteps,
42 const FdmSchemeDesc& schemeDesc,
43 ext::shared_ptr<LocalVolTermStructure> leverageFct,
44 const Real mixingFactor)
47 VanillaOption::results>(model),
48 tGrid_(tGrid), xGrid_(xGrid), vGrid_(vGrid), dampingSteps_(dampingSteps),
49 schemeDesc_(schemeDesc), leverageFct_(std::move(leverageFct)),
50 quantoHelper_(ext::shared_ptr<FdmQuantoHelper>()), mixingFactor_(mixingFactor) {}
51
52 FdHestonVanillaEngine::FdHestonVanillaEngine(const ext::shared_ptr<HestonModel>& model,
53 DividendSchedule dividends,
54 Size tGrid,
55 Size xGrid,
56 Size vGrid,
57 Size dampingSteps,
58 const FdmSchemeDesc& schemeDesc,
59 ext::shared_ptr<LocalVolTermStructure> leverageFct,
60 const Real mixingFactor)
63 VanillaOption::results>(model),
64 dividends_(std::move(dividends)),
65 tGrid_(tGrid), xGrid_(xGrid), vGrid_(vGrid), dampingSteps_(dampingSteps),
66 schemeDesc_(schemeDesc), leverageFct_(std::move(leverageFct)),
67 quantoHelper_(ext::shared_ptr<FdmQuantoHelper>()), mixingFactor_(mixingFactor) {}
68
69 FdHestonVanillaEngine::FdHestonVanillaEngine(const ext::shared_ptr<HestonModel>& model,
70 ext::shared_ptr<FdmQuantoHelper> quantoHelper,
71 Size tGrid,
72 Size xGrid,
73 Size vGrid,
74 Size dampingSteps,
75 const FdmSchemeDesc& schemeDesc,
76 ext::shared_ptr<LocalVolTermStructure> leverageFct,
77 const Real mixingFactor)
80 VanillaOption::results>(model),
81 tGrid_(tGrid), xGrid_(xGrid), vGrid_(vGrid), dampingSteps_(dampingSteps),
82 schemeDesc_(schemeDesc), leverageFct_(std::move(leverageFct)),
83 quantoHelper_(std::move(quantoHelper)), mixingFactor_(mixingFactor) {}
84
85 FdHestonVanillaEngine::FdHestonVanillaEngine(const ext::shared_ptr<HestonModel>& model,
86 DividendSchedule dividends,
87 ext::shared_ptr<FdmQuantoHelper> quantoHelper,
88 Size tGrid,
89 Size xGrid,
90 Size vGrid,
91 Size dampingSteps,
92 const FdmSchemeDesc& schemeDesc,
93 ext::shared_ptr<LocalVolTermStructure> leverageFct,
94 const Real mixingFactor)
97 VanillaOption::results>(model),
98 dividends_(std::move(dividends)),
99 tGrid_(tGrid), xGrid_(xGrid), vGrid_(vGrid), dampingSteps_(dampingSteps),
100 schemeDesc_(schemeDesc), leverageFct_(std::move(leverageFct)),
101 quantoHelper_(std::move(quantoHelper)), mixingFactor_(mixingFactor) {}
102
104
105 // 1. Mesher
106 const ext::shared_ptr<HestonProcess> process = model_->process();
107 const Time maturity = process->time(arguments_.exercise->lastDate());
108
109 // 1.1 The variance mesher
110 const Size tGridMin = 5;
111 const Size tGridAvgSteps = std::max(tGridMin, tGrid_/50);
112 const ext::shared_ptr<FdmHestonLocalVolatilityVarianceMesher> vMesher
113 = ext::make_shared<FdmHestonLocalVolatilityVarianceMesher>(
114 vGrid_, process, leverageFct_, maturity, tGridAvgSteps, 0.0001, mixingFactor_);
115
116 const Volatility avgVolaEstimate = vMesher->volaEstimate();
117
118 // 1.2 The equity mesher
119 const ext::shared_ptr<StrikedTypePayoff> payoff =
120 ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
121
122 ext::shared_ptr<Fdm1dMesher> equityMesher;
123 if (strikes_.empty()) {
124 equityMesher = ext::shared_ptr<Fdm1dMesher>(
126 xGrid_,
128 process->s0(), process->dividendYield(),
129 process->riskFreeRate(), avgVolaEstimate),
130 maturity, payoff->strike(),
131 Null<Real>(), Null<Real>(), 0.0001, 2.0,
132 std::pair<Real, Real>(payoff->strike(), 0.1),
135 }
136 else {
137 QL_REQUIRE(dividends_.empty(),
138 "multiple strikes engine does not work with discrete dividends");
139 equityMesher = ext::shared_ptr<Fdm1dMesher>(
141 xGrid_,
143 process->s0(), process->dividendYield(),
144 process->riskFreeRate(), avgVolaEstimate),
145 maturity, strikes_, 0.0001, 1.5,
146 std::pair<Real, Real>(payoff->strike(), 0.075)));
147 }
148
149 const ext::shared_ptr<FdmMesher> mesher(
150 new FdmMesherComposite(equityMesher, vMesher));
151
152 // 2. Calculator
153 const ext::shared_ptr<FdmInnerValueCalculator> calculator(
154 new FdmLogInnerValue(arguments_.payoff, mesher, 0));
155
156 // 3. Step conditions
157 const ext::shared_ptr<FdmStepConditionComposite> conditions =
159 dividends_, arguments_.exercise,
160 mesher, calculator,
161 process->riskFreeRate()->referenceDate(),
162 process->riskFreeRate()->dayCounter());
163
164 // 4. Boundary conditions
165 const FdmBoundaryConditionSet boundaries;
166
167 // 5. Solver
168 FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
169 calculator, maturity,
171
172 return solverDesc;
173 }
174
176
177 // cache lookup for precalculated results
178 for (auto& cachedArgs2result : cachedArgs2results_) {
179 if (cachedArgs2result.first.exercise->type() == arguments_.exercise->type() &&
180 cachedArgs2result.first.exercise->dates() == arguments_.exercise->dates()) {
181 ext::shared_ptr<PlainVanillaPayoff> p1 =
182 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
183 arguments_.payoff);
184 ext::shared_ptr<PlainVanillaPayoff> p2 =
185 ext::dynamic_pointer_cast<PlainVanillaPayoff>(cachedArgs2result.first.payoff);
186
187 if ((p1 != nullptr) && p1->strike() == p2->strike() &&
188 p1->optionType() == p2->optionType()) {
189 QL_REQUIRE(dividends_.empty(),
190 "multiple strikes engine does not work with discrete dividends");
191 results_ = cachedArgs2result.second;
192 return;
193 }
194 }
195 }
196
197 const ext::shared_ptr<HestonProcess> process = model_->process();
198
199 ext::shared_ptr<FdmHestonSolver> solver(new FdmHestonSolver(
200 Handle<HestonProcess>(process),
204
205 const Real v0 = process->v0();
206 const Real spot = process->s0()->value();
207
208 results_.value = solver->valueAt(spot, v0);
209 results_.delta = solver->deltaAt(spot, v0);
210 results_.gamma = solver->gammaAt(spot, v0);
211 results_.theta = solver->thetaAt(spot, v0);
212
213 cachedArgs2results_.resize(strikes_.size());
214 const ext::shared_ptr<StrikedTypePayoff> payoff =
215 ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
216 for (Size i=0; i < strikes_.size(); ++i) {
217 cachedArgs2results_[i].first.exercise = arguments_.exercise;
218 cachedArgs2results_[i].first.payoff =
219 ext::make_shared<PlainVanillaPayoff>(
220 payoff->optionType(), strikes_[i]);
221 const Real d = payoff->strike()/strikes_[i];
222
224 results.value = solver->valueAt(spot*d, v0)/d;
225 results.delta = solver->deltaAt(spot*d, v0);
226 results.gamma = solver->gammaAt(spot*d, v0)*d;
227 results.theta = solver->thetaAt(spot*d, v0)/d;
228 }
229 }
230
232 cachedArgs2results_.clear();
236 }
237
239 const std::vector<Real>& strikes) {
240 strikes_ = strikes;
241 cachedArgs2results_.clear();
242 }
243
244
245 MakeFdHestonVanillaEngine::MakeFdHestonVanillaEngine(ext::shared_ptr<HestonModel> hestonModel)
246 : hestonModel_(std::move(hestonModel)),
247 schemeDesc_(ext::make_shared<FdmSchemeDesc>(FdmSchemeDesc::Hundsdorfer())) {}
248
250 const ext::shared_ptr<FdmQuantoHelper>& quantoHelper) {
251 quantoHelper_ = quantoHelper;
252 return *this;
253 }
254
257 tGrid_ = tGrid;
258 return *this;
259 }
260
263 xGrid_ = xGrid;
264 return *this;
265 }
266
269 vGrid_ = vGrid;
270 return *this;
271 }
272
275 dampingSteps_ = dampingSteps;
276 return *this;
277 }
278
281 const FdmSchemeDesc& schemeDesc) {
282 schemeDesc_ = ext::make_shared<FdmSchemeDesc>(schemeDesc);
283 return *this;
284 }
285
288 ext::shared_ptr<LocalVolTermStructure>& leverageFct) {
289 leverageFct_ = leverageFct;
290 return *this;
291 }
292
295 const std::vector<Date>& dividendDates,
296 const std::vector<Real>& dividendAmounts) {
297 dividends_ = DividendVector(dividendDates, dividendAmounts);
298 return *this;
299 }
300
301 MakeFdHestonVanillaEngine::operator
302 ext::shared_ptr<PricingEngine>() const {
303 return ext::make_shared<FdHestonVanillaEngine>(
304 hestonModel_,
305 dividends_,
306 quantoHelper_,
307 tGrid_, xGrid_, vGrid_, dampingSteps_,
308 *schemeDesc_,
309 leverageFct_);
310 }
311
312}
Bates stochastic process, Heston process plus compound Poisson process plus log-normal jump diffusion...
FdmSolverDesc getSolverDesc(Real equityScaleFactor) const
std::vector< std::pair< VanillaOption::arguments, VanillaOption::results > > cachedArgs2results_
const ext::shared_ptr< FdmQuantoHelper > quantoHelper_
const ext::shared_ptr< LocalVolTermStructure > leverageFct_
FdHestonVanillaEngine(const ext::shared_ptr< HestonModel > &model, Size tGrid=100, Size xGrid=100, Size vGrid=50, Size dampingSteps=0, const FdmSchemeDesc &schemeDesc=FdmSchemeDesc::Hundsdorfer(), ext::shared_ptr< LocalVolTermStructure > leverageFct={}, Real mixingFactor=1.0)
void enableMultipleStrikesCaching(const std::vector< Real > &strikes)
static ext::shared_ptr< GeneralizedBlackScholesProcess > processHelper(const Handle< Quote > &s0, const Handle< YieldTermStructure > &rTS, const Handle< YieldTermStructure > &qTS, Volatility vol)
static ext::shared_ptr< FdmStepConditionComposite > vanillaComposite(const DividendSchedule &schedule, const ext::shared_ptr< Exercise > &exercise, const ext::shared_ptr< FdmMesher > &mesher, const ext::shared_ptr< FdmInnerValueCalculator > &calculator, const Date &refDate, const DayCounter &dayCounter)
Base class for some pricing engine on a particular model.
Shared handle to an observable.
Definition: handle.hpp:41
Heston model for the stochastic volatility of an asset.
Definition: hestonmodel.hpp:42
MakeFdHestonVanillaEngine & withDampingSteps(Size dampingSteps)
MakeFdHestonVanillaEngine & withQuantoHelper(const ext::shared_ptr< FdmQuantoHelper > &quantoHelper)
MakeFdHestonVanillaEngine & withTGrid(Size tGrid)
MakeFdHestonVanillaEngine(ext::shared_ptr< HestonModel > hestonModel)
MakeFdHestonVanillaEngine & withCashDividends(const std::vector< Date > &dividendDates, const std::vector< Real > &dividendAmounts)
ext::shared_ptr< FdmQuantoHelper > quantoHelper_
MakeFdHestonVanillaEngine & withVGrid(Size vGrid)
ext::shared_ptr< FdmSchemeDesc > schemeDesc_
MakeFdHestonVanillaEngine & withFdmSchemeDesc(const FdmSchemeDesc &schemeDesc)
MakeFdHestonVanillaEngine & withLeverageFunction(ext::shared_ptr< LocalVolTermStructure > &leverageFct)
MakeFdHestonVanillaEngine & withXGrid(Size xGrid)
ext::shared_ptr< LocalVolTermStructure > leverageFct_
template class providing a null value for a given type.
Definition: null.hpp:76
basic option arguments
Definition: option.hpp:57
Vanilla option (no discrete dividends, no barriers) on a single asset.
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Date d
Finite-differences Heston vanilla option engine.
1-d mesher for the Black-Scholes process (in ln(S))
1-d mesher for the Black-Scholes process (in ln(S))
One-dimensional grid mesher for the variance part of the Heston model.
layer of abstraction to calculate the inner value
memory layout of a fdm linear operator
FdmMesher which is a composite of Fdm1dMesher.
composite of fdm step conditions
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real Volatility
volatility
Definition: types.hpp:78
std::size_t Size
size of a container
Definition: types.hpp:58
Real v0
ext::shared_ptr< QuantLib::Payoff > payoff
Definition: any.hpp:35
std::vector< ext::shared_ptr< Dividend > > DividendSchedule
std::vector< ext::shared_ptr< Dividend > > DividendVector(const std::vector< Date > &dividendDates, const std::vector< Real > &dividends)
helper function building a sequence of fixed dividends
Definition: dividend.cpp:35
OperatorTraits< FdmLinearOp >::bc_set FdmBoundaryConditionSet
STL namespace.