QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
fdhestonhullwhitevanillaengine.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) 2009 Klaus Spanderen
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
32#include <utility>
33
34namespace QuantLib {
35
37 const ext::shared_ptr<HestonModel>& hestonModel,
38 ext::shared_ptr<HullWhiteProcess> hwProcess,
39 Real corrEquityShortRate,
40 Size tGrid,
41 Size xGrid,
42 Size vGrid,
43 Size rGrid,
44 Size dampingSteps,
45 bool controlVariate,
46 const FdmSchemeDesc& schemeDesc)
49 VanillaOption::results>(hestonModel),
50 hwProcess_(std::move(hwProcess)),
51 corrEquityShortRate_(corrEquityShortRate), tGrid_(tGrid),
52 xGrid_(xGrid), vGrid_(vGrid), rGrid_(rGrid), dampingSteps_(dampingSteps),
53 schemeDesc_(schemeDesc), controlVariate_(controlVariate) {}
54
56 const ext::shared_ptr<HestonModel>& hestonModel,
57 ext::shared_ptr<HullWhiteProcess> hwProcess,
58 DividendSchedule dividends,
59 Real corrEquityShortRate,
60 Size tGrid,
61 Size xGrid,
62 Size vGrid,
63 Size rGrid,
64 Size dampingSteps,
65 bool controlVariate,
66 const FdmSchemeDesc& schemeDesc)
69 VanillaOption::results>(hestonModel),
70 hwProcess_(std::move(hwProcess)), dividends_(std::move(dividends)),
71 corrEquityShortRate_(corrEquityShortRate), tGrid_(tGrid),
72 xGrid_(xGrid), vGrid_(vGrid), rGrid_(rGrid), dampingSteps_(dampingSteps),
73 schemeDesc_(schemeDesc), controlVariate_(controlVariate) {}
74
76
77 // 1. cache lookup for precalculated results
78 for (auto& cachedArgs2result : cachedArgs2results_) {
79 if (cachedArgs2result.first.exercise->type() == arguments_.exercise->type() &&
80 cachedArgs2result.first.exercise->dates() == arguments_.exercise->dates()) {
81 ext::shared_ptr<PlainVanillaPayoff> p1 =
82 ext::dynamic_pointer_cast<PlainVanillaPayoff>(
83 arguments_.payoff);
84 ext::shared_ptr<PlainVanillaPayoff> p2 =
85 ext::dynamic_pointer_cast<PlainVanillaPayoff>(cachedArgs2result.first.payoff);
86
87 if ((p1 != nullptr) && p1->strike() == p2->strike() &&
88 p1->optionType() == p2->optionType()) {
89 QL_REQUIRE(dividends_.empty(),
90 "multiple strikes engine does not work with discrete dividends");
91 results_ = cachedArgs2result.second;
92 return;
93 }
94 }
95 }
96
97 // 2. Mesher
98 const ext::shared_ptr<HestonProcess> hestonProcess=model_->process();
99 const Time maturity=hestonProcess->time(arguments_.exercise->lastDate());
100
101 // 2.1 The variance mesher
102 const Size tGridMin = 5;
103 const ext::shared_ptr<FdmHestonVarianceMesher> varianceMesher(
104 new FdmHestonVarianceMesher(vGrid_, hestonProcess,
105 maturity,std::max(tGridMin,tGrid_/50)));
106
107 // 2.2 The equity mesher
108 const ext::shared_ptr<StrikedTypePayoff> payoff =
109 ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
110 QL_REQUIRE(payoff, "wrong payoff type given");
111
112 ext::shared_ptr<Fdm1dMesher> equityMesher;
113 if (strikes_.empty()) {
114 equityMesher = ext::shared_ptr<Fdm1dMesher>(
116 xGrid_,
118 hestonProcess->s0(), hestonProcess->dividendYield(),
119 hestonProcess->riskFreeRate(),
120 varianceMesher->volaEstimate()),
121 maturity, payoff->strike(),
122 Null<Real>(), Null<Real>(), 0.0001, 1.5,
123 std::pair<Real, Real>(payoff->strike(), 0.1),
124 dividends_));
125 }
126 else {
127 QL_REQUIRE(dividends_.empty(),
128 "multiple strikes engine does not work with discrete dividends");
129 equityMesher = ext::shared_ptr<Fdm1dMesher>(
131 xGrid_,
133 hestonProcess->s0(), hestonProcess->dividendYield(),
134 hestonProcess->riskFreeRate(),
135 varianceMesher->volaEstimate()),
136 maturity, strikes_, 0.0001, 1.5,
137 std::pair<Real, Real>(payoff->strike(), 0.075)));
138 }
139
140 //2.3 The short rate mesher
141 const ext::shared_ptr<OrnsteinUhlenbeckProcess> ouProcess(
143 const ext::shared_ptr<Fdm1dMesher> shortRateMesher(
144 new FdmSimpleProcess1dMesher(rGrid_, ouProcess, maturity));
145
146 const ext::shared_ptr<FdmMesher> mesher(
147 new FdmMesherComposite(equityMesher, varianceMesher,
148 shortRateMesher));
149
150 // 3. Calculator
151 const ext::shared_ptr<FdmInnerValueCalculator> calculator(
152 new FdmLogInnerValue(arguments_.payoff, mesher, 0));
153
154 // 4. Step conditions
155 const ext::shared_ptr<FdmStepConditionComposite> conditions =
157 dividends_, arguments_.exercise,
158 mesher, calculator,
159 hestonProcess->riskFreeRate()->referenceDate(),
160 hestonProcess->riskFreeRate()->dayCounter());
161
162 // 5. Boundary conditions
163 const FdmBoundaryConditionSet boundaries;
164
165 // 6. Solver
166 const FdmSolverDesc solverDesc = { mesher, boundaries, conditions,
167 calculator, maturity,
169
170 const ext::shared_ptr<FdmHestonHullWhiteSolver> solver(
174 solverDesc, schemeDesc_));
175
176 const Real spot = hestonProcess->s0()->value();
177 const Real v0 = hestonProcess->v0();
178 results_.value = solver->valueAt(spot, v0, 0);
179 results_.delta = solver->deltaAt(spot, v0, 0, spot*0.01);
180 results_.gamma = solver->gammaAt(spot, v0, 0, spot*0.01);
181 results_.theta = solver->thetaAt(spot, v0, 0);
182
183 cachedArgs2results_.resize(strikes_.size());
184 for (Size i=0; i < strikes_.size(); ++i) {
185 cachedArgs2results_[i].first.exercise = arguments_.exercise;
186 cachedArgs2results_[i].first.payoff =
187 ext::make_shared<PlainVanillaPayoff>(
188 payoff->optionType(), strikes_[i]);
189 const Real d = payoff->strike()/strikes_[i];
190
192 results.value = solver->valueAt(spot*d, v0, 0)/d;
193 results.delta = solver->deltaAt(spot*d, v0, 0, spot*d*0.01);
194 results.gamma = solver->gammaAt(spot*d, v0, 0, spot*d*0.01)*d;
195 results.theta = solver->thetaAt(spot*d, v0, 0)/d;
196 }
197
198 if (controlVariate_) {
199 ext::shared_ptr<PricingEngine> analyticEngine(
200 new AnalyticHestonEngine(*model_, 164));
201 ext::shared_ptr<Exercise> exercise(
202 new EuropeanExercise(arguments_.exercise->lastDate()));
203
204 VanillaOption option(payoff, exercise);
205 option.setPricingEngine(analyticEngine);
206 Real analyticNPV = option.NPV();
207
208 ext::shared_ptr<FdHestonVanillaEngine> fdEngine(
211 schemeDesc_));
212 fdEngine->enableMultipleStrikesCaching(strikes_);
213 option.setPricingEngine(fdEngine);
214
215 Real fdNPV = option.NPV();
216 results_.value += analyticNPV - fdNPV;
217 for (Size i=0; i < strikes_.size(); ++i) {
218 VanillaOption controlVariateOption(
219 ext::shared_ptr<StrikedTypePayoff>(
220 new PlainVanillaPayoff(payoff->optionType(),
221 strikes_[i])), exercise);
222 controlVariateOption.setPricingEngine(analyticEngine);
223 analyticNPV = controlVariateOption.NPV();
224
225 controlVariateOption.setPricingEngine(fdEngine);
226 fdNPV = controlVariateOption.NPV();
227 cachedArgs2results_[i].second.value += analyticNPV - fdNPV;
228 }
229 }
230 }
231
233 cachedArgs2results_.clear();
237 }
238
240 const std::vector<Real>& strikes) {
241 strikes_ = strikes;
242 update();
243 }
244
245}
analytic Heston-model engine
analytic Heston-model engine based on Fourier transform
European exercise.
Definition: exercise.hpp:96
std::vector< std::pair< VanillaOption::arguments, VanillaOption::results > > cachedArgs2results_
const ext::shared_ptr< HullWhiteProcess > hwProcess_
FdHestonHullWhiteVanillaEngine(const ext::shared_ptr< HestonModel > &model, ext::shared_ptr< HullWhiteProcess > hwProcess, Real corrEquityShortRate, Size tGrid=50, Size xGrid=100, Size vGrid=40, Size rGrid=20, Size dampingSteps=0, bool controlVariate=true, const FdmSchemeDesc &schemeDesc=FdmSchemeDesc::Hundsdorfer())
void enableMultipleStrikesCaching(const std::vector< Real > &strikes)
Finite-differences Heston vanilla option engine.
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
Real NPV() const
returns the net present value of the instrument.
Definition: instrument.hpp:167
void setPricingEngine(const ext::shared_ptr< PricingEngine > &)
set the pricing engine to be used.
Definition: instrument.cpp:35
template class providing a null value for a given type.
Definition: null.hpp:76
basic option arguments
Definition: option.hpp:57
Ornstein-Uhlenbeck process class.
Plain-vanilla payoff.
Definition: payoffs.hpp:105
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 Hull-White vanilla option engine.
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.
One-dimensional grid mesher.
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
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
OperatorTraits< FdmLinearOp >::bc_set FdmBoundaryConditionSet
STL namespace.
One-dimensional simple uniform grid mesher.