QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
binomialbarrierengine.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) 2014 Thema Consulting SA
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
20/*! \file binomialbarrierengine.hpp
21 \brief Binomial Barrier option engine
22*/
23
24#ifndef quantlib_binomial_barrier_engine_hpp
25#define quantlib_binomial_barrier_engine_hpp
26
34#include <type_traits>
35#include <utility>
36
37namespace QuantLib {
38
39 //! Pricing engine for barrier options using binomial trees
40 /*! \ingroup barrierengines
41
42 \note Timesteps for Cox-Ross-Rubinstein trees are adjusted using Boyle and Lau algorithm.
43 See Journal of Derivatives, 1/1994,
44 "Bumping up against the barrier with the binomial method"
45
46 \test the correctness of the returned values is tested by
47 checking it against analytic european results.
48 */
49 template <class T, class D>
51 public:
52 /*! The maxTimeSteps parameter is used to limit timeSteps when
53 using Boyle-Lau optimization. If zero (the default) the
54 maximum number of steps is calculated by an heuristic:
55 anything when < 1000, otherwise no more than 5*timeSteps.
56 If maxTimeSteps is equal to timeSteps, Boyle-Lau is
57 disabled. Likewise if the lattice is not
58 CoxRossRubinstein Boyle-Lau is disabled and maxTimeSteps
59 ignored.
60 */
61 BinomialBarrierEngine(ext::shared_ptr<GeneralizedBlackScholesProcess> process,
62 Size timeSteps,
63 Size maxTimeSteps = 0)
64 : process_(std::move(process)), timeSteps_(timeSteps), maxTimeSteps_(maxTimeSteps) {
65 QL_REQUIRE(timeSteps>0,
66 "timeSteps must be positive, " << timeSteps <<
67 " not allowed");
68 QL_REQUIRE(maxTimeSteps==0 || maxTimeSteps>=timeSteps,
69 "maxTimeSteps must be zero or "
70 "greater than or equal to timeSteps, "
71 << maxTimeSteps << " not allowed");
72 if (maxTimeSteps_==0)
73 maxTimeSteps_ = std::max( (Size)1000, timeSteps_*5);
75 }
76 void calculate() const override;
77
78 private:
79 ext::shared_ptr<GeneralizedBlackScholesProcess> process_;
82 };
83
84
85 // template definitions
86
87 template <class T, class D>
89
90 ext::shared_ptr<StrikedTypePayoff> payoff =
91 ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
92 QL_REQUIRE(payoff, "non-striked payoff given");
93 QL_REQUIRE(payoff->strike() > 0.0, "strike must be positive");
94
95 Real s0 = process_->stateVariable()->value();
96 QL_REQUIRE(s0 > 0.0, "negative or null underlying given");
97 QL_REQUIRE(!triggered(s0), "barrier touched");
98
99 DayCounter rfdc = process_->riskFreeRate()->dayCounter();
100 DayCounter divdc = process_->dividendYield()->dayCounter();
101 DayCounter voldc = process_->blackVolatility()->dayCounter();
102 Calendar volcal = process_->blackVolatility()->calendar();
103
104 Volatility v = process_->blackVolatility()->blackVol(
105 arguments_.exercise->lastDate(), s0);
106 Date maturityDate = arguments_.exercise->lastDate();
107 Rate r = process_->riskFreeRate()->zeroRate(maturityDate,
108 rfdc, Continuous, NoFrequency);
109 Rate q = process_->dividendYield()->zeroRate(maturityDate,
110 divdc, Continuous, NoFrequency);
111 Date referenceDate = process_->riskFreeRate()->referenceDate();
112
113 // binomial trees with constant coefficient
114 Handle<YieldTermStructure> flatRiskFree(
115 ext::shared_ptr<YieldTermStructure>(
116 new FlatForward(referenceDate, r, rfdc)));
117 Handle<YieldTermStructure> flatDividends(
118 ext::shared_ptr<YieldTermStructure>(
119 new FlatForward(referenceDate, q, divdc)));
121 ext::shared_ptr<BlackVolTermStructure>(
122 new BlackConstantVol(referenceDate, volcal, v, voldc)));
123
124 Time maturity = rfdc.yearFraction(referenceDate, maturityDate);
125
126 ext::shared_ptr<StochasticProcess1D> bs(
128 process_->stateVariable(),
129 flatDividends, flatRiskFree, flatVol));
130
131 // correct timesteps to ensure a (local) minimum, using Boyle and Lau
132 // approach. See Journal of Derivatives, 1/1994,
133 // "Bumping up against the barrier with the binomial method"
134 // Note: this approach works only for CoxRossRubinstein lattices, so
135 // is disabled if T is not a CoxRossRubinstein or derived from it.
136 Size optimum_steps = timeSteps_;
137 if (std::is_base_of<CoxRossRubinstein, T>::value &&
138 maxTimeSteps_ > timeSteps_ && s0 > 0 && arguments_.barrier > 0) {
139 Real divisor;
140 if (s0 > arguments_.barrier)
141 divisor = std::pow(std::log(s0 / arguments_.barrier), 2);
142 else
143 divisor = std::pow(std::log(arguments_.barrier / s0), 2);
144 if (!close(divisor,0)) {
145 for (Size i=1; i < timeSteps_ ; ++i) {
146 Size optimum = Size(( i*i * v*v * maturity) / divisor);
147 if (timeSteps_ < optimum) {
148 optimum_steps = optimum;
149 break; // found first minimum with iterations>=timesteps
150 }
151 }
152 }
153
154 if (optimum_steps > maxTimeSteps_)
155 optimum_steps = maxTimeSteps_; // too high, limit
156 }
157
158 TimeGrid grid(maturity, optimum_steps);
159
160 ext::shared_ptr<T> tree(new T(bs, maturity, optimum_steps,
161 payoff->strike()));
162
163 ext::shared_ptr<BlackScholesLattice<T> > lattice(
164 new BlackScholesLattice<T>(tree, r, maturity, optimum_steps));
165
166 D option(arguments_, *process_, grid);
167 option.initialize(lattice, maturity);
168
169 // Partial derivatives calculated from various points in the
170 // binomial tree
171 // (see J.C.Hull, "Options, Futures and other derivatives", 6th edition, pp 397/398)
172
173 // Rollback to third-last step, and get underlying prices (s2) &
174 // option values (p2) at this point
175 option.rollback(grid[2]);
176 Array va2(option.values());
177 QL_ENSURE(va2.size() == 3, "Expect 3 nodes in grid at second step");
178 Real p2u = va2[2]; // up
179 Real p2m = va2[1]; // mid
180 Real p2d = va2[0]; // down (low)
181 Real s2u = lattice->underlying(2, 2); // up price
182 Real s2m = lattice->underlying(2, 1); // middle price
183 Real s2d = lattice->underlying(2, 0); // down (low) price
184
185 // calculate gamma by taking the first derivate of the two deltas
186 Real delta2u = (p2u - p2m)/(s2u-s2m);
187 Real delta2d = (p2m-p2d)/(s2m-s2d);
188 Real gamma = (delta2u - delta2d) / ((s2u-s2d)/2);
189
190 // Rollback to second-last step, and get option values (p1) at
191 // this point
192 option.rollback(grid[1]);
193 Array va(option.values());
194 QL_ENSURE(va.size() == 2, "Expect 2 nodes in grid at first step");
195 Real p1u = va[1];
196 Real p1d = va[0];
197 Real s1u = lattice->underlying(1, 1); // up (high) price
198 Real s1d = lattice->underlying(1, 0); // down (low) price
199
200 Real delta = (p1u - p1d) / (s1u - s1d);
201
202 // Finally, rollback to t=0
203 option.rollback(0.0);
204 Real p0 = option.presentValue();
205
206 // Store results
207 results_.value = p0;
208 results_.delta = delta;
209 results_.gamma = gamma;
210 // theta can be approximated by calculating the numerical derivative
211 // between mid value at third-last step and at t0. The underlying price
212 // is the same, only time varies.
213 results_.theta = (p2m - p0) / grid[2];
214 }
215
216}
217
218
219#endif
Binomial tree class.
Black constant volatility, no time dependence, no strike dependence.
Black-Scholes processes.
Binomial trees under the BSM model.
const Instrument::results * results_
Definition: cdsoption.cpp:63
1-D array used in linear algebra.
Definition: array.hpp:52
Size size() const
dimension of the array
Definition: array.hpp:495
Barrier-option engine base class
Pricing engine for barrier options using binomial trees.
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
BinomialBarrierEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process, Size timeSteps, Size maxTimeSteps=0)
Constant Black volatility, no time-strike dependence.
Simple binomial lattice approximating the Black-Scholes model.
Definition: bsmlattice.hpp:36
calendar class
Definition: calendar.hpp:61
Concrete date class.
Definition: date.hpp:125
day counter class
Definition: daycounter.hpp:44
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
Definition: daycounter.hpp:128
Flat interest-rate curve.
Definition: flatforward.hpp:37
Generalized Black-Scholes stochastic process.
Shared handle to an observable.
Definition: handle.hpp:41
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
time grid class
Definition: timegrid.hpp:43
discretized barrier option
#define QL_ENSURE(condition, message)
throw an error if the given post-condition is not verified
Definition: errors.hpp:130
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
flat forward rate term structure
@ NoFrequency
null frequency
Definition: frequency.hpp:37
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
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
ext::shared_ptr< QuantLib::Payoff > payoff
Definition: any.hpp:35
bool close(const Quantity &m1, const Quantity &m2, Size n)
Definition: quantity.cpp:163
STL namespace.
normal, cumulative and inverse cumulative distributions
ext::shared_ptr< YieldTermStructure > q
ext::shared_ptr< YieldTermStructure > r
ext::shared_ptr< BlackVolTermStructure > v