QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
longstaffschwartzpathpricer.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) 2006 Klaus Spanderen
5 Copyright (C) 2015 Peter Caspers
6 Copyright (C) 2015 Thema Consulting SA
7
8 This file is part of QuantLib, a free-software/open-source library
9 for financial quantitative analysts and developers - http://quantlib.org/
10
11 QuantLib is free software: you can redistribute it and/or modify it
12 under the terms of the QuantLib license. You should have received a
13 copy of the license along with this program; if not, please email
14 <quantlib-dev@lists.sf.net>. The license is also available online at
15 <http://quantlib.org/license.shtml>.
16
17 This program is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the license for more details.
20*/
21
22/*! \file longstaffschwartzpathpricer.hpp
23 \brief Longstaff-Schwarz path pricer for early exercise options
24*/
25
26#ifndef quantlib_longstaff_schwartz_path_pricer_hpp
27#define quantlib_longstaff_schwartz_path_pricer_hpp
28
29#include <ql/functional.hpp>
35#include <utility>
36#include <memory>
37
38namespace QuantLib {
39
40 //! Longstaff-Schwarz path pricer for early exercise options
41 /*! References:
42
43 Francis Longstaff, Eduardo Schwartz, 2001. Valuing American Options
44 by Simulation: A Simple Least-Squares Approach, The Review of
45 Financial Studies, Volume 14, No. 1, 113-147
46
47 \ingroup mcarlo
48
49 \test the correctness of the returned value is tested by
50 reproducing results available in web/literature
51 */
52 template <class PathType>
53 class LongstaffSchwartzPathPricer : public PathPricer<PathType> {
54 public:
56
58 ext::shared_ptr<EarlyExercisePathPricer<PathType> >,
59 const ext::shared_ptr<YieldTermStructure>& termStructure);
60
61 Real operator()(const PathType& path) const override;
62 virtual void calibrate();
63
65
66 protected:
67 virtual void post_processing(const Size i,
68 const std::vector<StateType> &state,
69 const std::vector<Real> &price,
70 const std::vector<Real> &exercise) {}
71 bool calibrationPhase_ = true;
72 const ext::shared_ptr<EarlyExercisePathPricer<PathType> >
74
76
77 std::unique_ptr<Array[]> coeff_;
78 std::unique_ptr<DiscountFactor[]> dF_;
79
80 mutable std::vector<PathType> paths_;
81 const std::vector<ext::function<Real(StateType)> > v_;
82
83 const Size len_;
84 };
85
86 template <class PathType>
88 const TimeGrid& times,
89 ext::shared_ptr<EarlyExercisePathPricer<PathType> > pathPricer,
90 const ext::shared_ptr<YieldTermStructure>& termStructure)
91 : pathPricer_(std::move(pathPricer)), coeff_(new Array[times.size() - 2]),
92 dF_(new DiscountFactor[times.size() - 1]), v_(pathPricer_->basisSystem()),
93 len_(times.size()) {
94
95 for (Size i=0; i<times.size()-1; ++i) {
96 dF_[i] = termStructure->discount(times[i+1])
97 / termStructure->discount(times[i]);
98 }
99 }
100
101 template <class PathType> inline
103 (const PathType& path) const {
104 if (calibrationPhase_) {
105 // store paths for the calibration
106 paths_.push_back(path);
107 // result doesn't matter
108 return 0.0;
109 }
110
111 Real price = (*pathPricer_)(path, len_-1);
112
113 // Initialize with exercise on last date
114 bool exercised = (price > 0.0);
115
116 for (Size i=len_-2; i>0; --i) {
117 price*=dF_[i];
118
119 const Real exercise = (*pathPricer_)(path, i);
120 if (exercise > 0.0) {
121 const StateType regValue = pathPricer_->state(path, i);
122
123 Real continuationValue = 0.0;
124 for (Size l=0; l<v_.size(); ++l) {
125 continuationValue += coeff_[i-1][l] * v_[l](regValue);
126 }
127
128 if (continuationValue < exercise) {
129 price = exercise;
130
131 // Exercised
132 exercised = true;
133 }
134 }
135 }
136
137 exerciseProbability_.add(exercised ? 1.0 : 0.0);
138
139 return price*dF_[0];
140 }
141
142 template <class PathType> inline
144 const Size n = paths_.size();
145 Array prices(n), exercise(n);
146 std::vector<StateType> p_state(n);
147 std::vector<Real> p_price(n), p_exercise(n);
148
149 for (Size i=0; i<n; ++i) {
150 p_state[i] = pathPricer_->state(paths_[i],len_-1);
151 prices[i] = p_price[i] = (*pathPricer_)(paths_[i], len_-1);
152 p_exercise[i] = prices[i];
153 }
154
155 post_processing(len_ - 1, p_state, p_price, p_exercise);
156
157 std::vector<Real> y;
158 std::vector<StateType> x;
159 for (Size i=len_-2; i>0; --i) {
160 y.clear();
161 x.clear();
162
163 //roll back step
164 for (Size j=0; j<n; ++j) {
165 exercise[j]=(*pathPricer_)(paths_[j], i);
166 if (exercise[j]>0.0) {
167 x.push_back(pathPricer_->state(paths_[j], i));
168 y.push_back(dF_[i]*prices[j]);
169 }
170 }
171
172 if (v_.size() <= x.size()) {
173 coeff_[i-1] = GeneralLinearLeastSquares(x, y, v_).coefficients();
174 }
175 else {
176 // if number of itm paths is smaller then the number of
177 // calibration functions then early exercise if exerciseValue > 0
178 coeff_[i-1] = Array(v_.size(), 0.0);
179 }
180
181 for (Size j=0, k=0; j<n; ++j) {
182 prices[j]*=dF_[i];
183 if (exercise[j]>0.0) {
184 Real continuationValue = 0.0;
185 for (Size l=0; l<v_.size(); ++l) {
186 continuationValue += coeff_[i-1][l] * v_[l](x[k]);
187 }
188 if (continuationValue < exercise[j]) {
189 prices[j] = exercise[j];
190 }
191 ++k;
192 }
193 p_state[j] = pathPricer_->state(paths_[j],i);
194 p_price[j] = prices[j];
195 p_exercise[j] = exercise[j];
196 }
197
198 post_processing(i, p_state, p_price, p_exercise);
199 }
200
201 // remove calibration paths and release memory
202 std::vector<PathType> empty;
203 paths_.swap(empty);
204 // entering the calculation phase
205 calibrationPhase_ = false;
206 }
207
208 template <class PathType> inline
210 return exerciseProbability_.mean();
211 }
212
213
214}
215
216
217#endif
1-D array used in linear algebra.
Definition: array.hpp:52
base class for early exercise path pricers
general linear least squares regression
Statistics tool based on incremental accumulation.
Longstaff-Schwarz path pricer for early exercise options.
LongstaffSchwartzPathPricer(const TimeGrid &times, ext::shared_ptr< EarlyExercisePathPricer< PathType > >, const ext::shared_ptr< YieldTermStructure > &termStructure)
Real operator()(const PathType &path) const override
QuantLib::IncrementalStatistics exerciseProbability_
EarlyExerciseTraits< PathType >::StateType StateType
const ext::shared_ptr< EarlyExercisePathPricer< PathType > > pathPricer_
const std::vector< ext::function< Real(StateType)> > v_
virtual void post_processing(const Size i, const std::vector< StateType > &state, const std::vector< Real > &price, const std::vector< Real > &exercise)
base class for path pricers
Definition: pathpricer.hpp:40
time grid class
Definition: timegrid.hpp:43
Size size() const
Definition: timegrid.hpp:164
base class for early exercise single-path pricers
Maps function, bind and cref to either the boost or std implementation.
general linear least square regression
QL_REAL Real
real number
Definition: types.hpp:50
Real DiscountFactor
discount factor between dates
Definition: types.hpp:66
std::size_t Size
size of a container
Definition: types.hpp:58
statistics tool based on incremental accumulation in the meantime, this is just a wrapper to the boos...
Definition: any.hpp:35
STL namespace.
base class for single-path pricers
Interest-rate term structure.