/src/quantlib/ql/stochasticprocess.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2003 Ferdinando Ametrano |
5 | | Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb |
6 | | Copyright (C) 2004, 2005 StatPro Italia srl |
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 stochasticprocess.hpp |
23 | | \brief stochastic processes |
24 | | */ |
25 | | |
26 | | #ifndef quantlib_stochastic_process_hpp |
27 | | #define quantlib_stochastic_process_hpp |
28 | | |
29 | | #include <ql/time/date.hpp> |
30 | | #include <ql/patterns/observable.hpp> |
31 | | #include <ql/math/matrix.hpp> |
32 | | |
33 | | namespace QuantLib { |
34 | | |
35 | | //! multi-dimensional stochastic process class. |
36 | | /*! This class describes a stochastic process governed by |
37 | | \f[ |
38 | | d\mathrm{x}_t = \mu(t, x_t)\mathrm{d}t |
39 | | + \sigma(t, \mathrm{x}_t) \cdot d\mathrm{W}_t. |
40 | | \f] |
41 | | */ |
42 | | class StochasticProcess : public Observer, public Observable { |
43 | | public: |
44 | | //! discretization of a stochastic process over a given time interval |
45 | | class discretization { |
46 | | public: |
47 | 1.00k | virtual ~discretization() = default; |
48 | | virtual Array drift(const StochasticProcess&, |
49 | | Time t0, |
50 | | const Array& x0, |
51 | | Time dt) const = 0; |
52 | | virtual Matrix diffusion(const StochasticProcess&, |
53 | | Time t0, |
54 | | const Array& x0, |
55 | | Time dt) const = 0; |
56 | | virtual Matrix covariance(const StochasticProcess&, |
57 | | Time t0, |
58 | | const Array& x0, |
59 | | Time dt) const = 0; |
60 | | }; |
61 | 1.00k | ~StochasticProcess() override = default; |
62 | | //! \name Stochastic process interface |
63 | | //@{ |
64 | | //! returns the number of dimensions of the stochastic process |
65 | | virtual Size size() const = 0; |
66 | | //! returns the number of independent factors of the process |
67 | | virtual Size factors() const; |
68 | | //! returns the initial values of the state variables |
69 | | virtual Array initialValues() const = 0; |
70 | | /*! \brief returns the drift part of the equation, i.e., |
71 | | \f$ \mu(t, \mathrm{x}_t) \f$ |
72 | | */ |
73 | | virtual Array drift(Time t, |
74 | | const Array& x) const = 0; |
75 | | /*! \brief returns the diffusion part of the equation, i.e. |
76 | | \f$ \sigma(t, \mathrm{x}_t) \f$ |
77 | | */ |
78 | | virtual Matrix diffusion(Time t, |
79 | | const Array& x) const = 0; |
80 | | /*! returns the expectation |
81 | | \f$ E(\mathrm{x}_{t_0 + \Delta t} |
82 | | | \mathrm{x}_{t_0} = \mathrm{x}_0) \f$ |
83 | | of the process after a time interval \f$ \Delta t \f$ |
84 | | according to the given discretization. This method can be |
85 | | overridden in derived classes which want to hard-code a |
86 | | particular discretization. |
87 | | */ |
88 | | virtual Array expectation(Time t0, |
89 | | const Array& x0, |
90 | | Time dt) const; |
91 | | /*! returns the standard deviation |
92 | | \f$ S(\mathrm{x}_{t_0 + \Delta t} |
93 | | | \mathrm{x}_{t_0} = \mathrm{x}_0) \f$ |
94 | | of the process after a time interval \f$ \Delta t \f$ |
95 | | according to the given discretization. This method can be |
96 | | overridden in derived classes which want to hard-code a |
97 | | particular discretization. |
98 | | */ |
99 | | virtual Matrix stdDeviation(Time t0, |
100 | | const Array& x0, |
101 | | Time dt) const; |
102 | | /*! returns the covariance |
103 | | \f$ V(\mathrm{x}_{t_0 + \Delta t} |
104 | | | \mathrm{x}_{t_0} = \mathrm{x}_0) \f$ |
105 | | of the process after a time interval \f$ \Delta t \f$ |
106 | | according to the given discretization. This method can be |
107 | | overridden in derived classes which want to hard-code a |
108 | | particular discretization. |
109 | | */ |
110 | | virtual Matrix covariance(Time t0, |
111 | | const Array& x0, |
112 | | Time dt) const; |
113 | | /*! returns the asset value after a time interval \f$ \Delta t |
114 | | \f$ according to the given discretization. By default, it |
115 | | returns |
116 | | \f[ |
117 | | E(\mathrm{x}_0,t_0,\Delta t) + |
118 | | S(\mathrm{x}_0,t_0,\Delta t) \cdot \Delta \mathrm{w} |
119 | | \f] |
120 | | where \f$ E \f$ is the expectation and \f$ S \f$ the |
121 | | standard deviation. |
122 | | */ |
123 | | virtual Array evolve(Time t0, |
124 | | const Array& x0, |
125 | | Time dt, |
126 | | const Array& dw) const; |
127 | | /*! applies a change to the asset value. By default, it |
128 | | returns \f$ \mathrm{x} + \Delta \mathrm{x} \f$. |
129 | | */ |
130 | | virtual Array apply(const Array& x0, |
131 | | const Array& dx) const; |
132 | | //@} |
133 | | |
134 | | //! \name utilities |
135 | | //@{ |
136 | | /*! returns the time value corresponding to the given date |
137 | | in the reference system of the stochastic process. |
138 | | |
139 | | \note As a number of processes might not need this |
140 | | functionality, a default implementation is given |
141 | | which raises an exception. |
142 | | */ |
143 | | virtual Time time(const Date&) const; |
144 | | //@} |
145 | | |
146 | | //! \name Observer interface |
147 | | //@{ |
148 | | void update() override; |
149 | | //@} |
150 | | protected: |
151 | 1.00k | StochasticProcess() = default; |
152 | | explicit StochasticProcess(ext::shared_ptr<discretization>); |
153 | | ext::shared_ptr<discretization> discretization_; |
154 | | }; |
155 | | |
156 | | |
157 | | //! 1-dimensional stochastic process |
158 | | /*! This class describes a stochastic process governed by |
159 | | \f[ |
160 | | dx_t = \mu(t, x_t)dt + \sigma(t, x_t)dW_t. |
161 | | \f] |
162 | | */ |
163 | | class StochasticProcess1D : public StochasticProcess { |
164 | | public: |
165 | | //! discretization of a 1-D stochastic process |
166 | | class discretization { |
167 | | public: |
168 | 1.00k | virtual ~discretization() = default; |
169 | | virtual Real drift(const StochasticProcess1D&, |
170 | | Time t0, Real x0, Time dt) const = 0; |
171 | | virtual Real diffusion(const StochasticProcess1D&, |
172 | | Time t0, Real x0, Time dt) const = 0; |
173 | | virtual Real variance(const StochasticProcess1D&, |
174 | | Time t0, Real x0, Time dt) const = 0; |
175 | | }; |
176 | | //! \name 1-D stochastic process interface |
177 | | //@{ |
178 | | //! returns the initial value of the state variable |
179 | | virtual Real x0() const = 0; |
180 | | //! returns the drift part of the equation, i.e. \f$ \mu(t, x_t) \f$ |
181 | | virtual Real drift(Time t, Real x) const = 0; |
182 | | /*! \brief returns the diffusion part of the equation, i.e. |
183 | | \f$ \sigma(t, x_t) \f$ |
184 | | */ |
185 | | virtual Real diffusion(Time t, Real x) const = 0; |
186 | | /*! returns the expectation |
187 | | \f$ E(x_{t_0 + \Delta t} | x_{t_0} = x_0) \f$ |
188 | | of the process after a time interval \f$ \Delta t \f$ |
189 | | according to the given discretization. This method can be |
190 | | overridden in derived classes which want to hard-code a |
191 | | particular discretization. |
192 | | */ |
193 | | virtual Real expectation(Time t0, Real x0, Time dt) const; |
194 | | /*! returns the standard deviation |
195 | | \f$ S(x_{t_0 + \Delta t} | x_{t_0} = x_0) \f$ |
196 | | of the process after a time interval \f$ \Delta t \f$ |
197 | | according to the given discretization. This method can be |
198 | | overridden in derived classes which want to hard-code a |
199 | | particular discretization. |
200 | | */ |
201 | | virtual Real stdDeviation(Time t0, Real x0, Time dt) const; |
202 | | /*! returns the variance |
203 | | \f$ V(x_{t_0 + \Delta t} | x_{t_0} = x_0) \f$ |
204 | | of the process after a time interval \f$ \Delta t \f$ |
205 | | according to the given discretization. This method can be |
206 | | overridden in derived classes which want to hard-code a |
207 | | particular discretization. |
208 | | */ |
209 | | virtual Real variance(Time t0, Real x0, Time dt) const; |
210 | | /*! returns the asset value after a time interval \f$ \Delta t |
211 | | \f$ according to the given discretization. By default, it |
212 | | returns |
213 | | \f[ |
214 | | E(x_0,t_0,\Delta t) + S(x_0,t_0,\Delta t) \cdot \Delta w |
215 | | \f] |
216 | | where \f$ E \f$ is the expectation and \f$ S \f$ the |
217 | | standard deviation. |
218 | | */ |
219 | | virtual Real evolve(Time t0, Real x0, Time dt, Real dw) const; |
220 | | /*! applies a change to the asset value. By default, it |
221 | | returns \f$ x + \Delta x \f$. |
222 | | */ |
223 | | virtual Real apply(Real x0, Real dx) const; |
224 | | //@} |
225 | | protected: |
226 | 0 | StochasticProcess1D() = default; |
227 | | explicit StochasticProcess1D(ext::shared_ptr<discretization>); |
228 | | ext::shared_ptr<discretization> discretization_; |
229 | | private: |
230 | | // StochasticProcess interface implementation |
231 | | Size size() const override; |
232 | | Array initialValues() const override; |
233 | | Array drift(Time t, const Array& x) const override; |
234 | | Matrix diffusion(Time t, const Array& x) const override; |
235 | | Array expectation(Time t0, const Array& x0, Time dt) const override; |
236 | | Matrix stdDeviation(Time t0, const Array& x0, Time dt) const override; |
237 | | Matrix covariance(Time t0, const Array& x0, Time dt) const override; |
238 | | Array evolve(Time t0, const Array& x0, Time dt, const Array& dw) const override; |
239 | | Array apply(const Array& x0, const Array& dx) const override; |
240 | | }; |
241 | | |
242 | | |
243 | | // inline definitions |
244 | | |
245 | 0 | inline Size StochasticProcess1D::size() const { |
246 | 0 | return 1; |
247 | 0 | } |
248 | | |
249 | 0 | inline Array StochasticProcess1D::initialValues() const { |
250 | 0 | Array a(1, x0()); |
251 | 0 | return a; |
252 | 0 | } |
253 | | |
254 | 0 | inline Array StochasticProcess1D::drift(Time t, const Array& x) const { |
255 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
256 | 0 | QL_REQUIRE(x.size() == 1, "1-D array required"); |
257 | 0 | #endif |
258 | 0 | Array a(1, drift(t, x[0])); |
259 | 0 | return a; |
260 | 0 | } |
261 | | |
262 | 0 | inline Matrix StochasticProcess1D::diffusion(Time t, const Array& x) const { |
263 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
264 | 0 | QL_REQUIRE(x.size() == 1, "1-D array required"); |
265 | 0 | #endif |
266 | 0 | Matrix m(1, 1, diffusion(t, x[0])); |
267 | 0 | return m; |
268 | 0 | } |
269 | | |
270 | | inline Array StochasticProcess1D::expectation( |
271 | 0 | Time t0, const Array& x0, Time dt) const { |
272 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
273 | 0 | QL_REQUIRE(x0.size() == 1, "1-D array required"); |
274 | 0 | #endif |
275 | 0 | Array a(1, expectation(t0, x0[0], dt)); |
276 | 0 | return a; |
277 | 0 | } |
278 | | |
279 | | inline Matrix StochasticProcess1D::stdDeviation( |
280 | 0 | Time t0, const Array& x0, Time dt) const { |
281 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
282 | 0 | QL_REQUIRE(x0.size() == 1, "1-D array required"); |
283 | 0 | #endif |
284 | 0 | Matrix m(1, 1, stdDeviation(t0, x0[0], dt)); |
285 | 0 | return m; |
286 | 0 | } |
287 | | |
288 | | inline Matrix StochasticProcess1D::covariance( |
289 | 0 | Time t0, const Array& x0, Time dt) const { |
290 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
291 | 0 | QL_REQUIRE(x0.size() == 1, "1-D array required"); |
292 | 0 | #endif |
293 | 0 | Matrix m(1, 1, variance(t0, x0[0], dt)); |
294 | 0 | return m; |
295 | 0 | } |
296 | | |
297 | | inline Array StochasticProcess1D::evolve(Time t0, const Array& x0, |
298 | 0 | Time dt, const Array& dw) const { |
299 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
300 | 0 | QL_REQUIRE(x0.size() == 1, "1-D array required"); |
301 | 0 | QL_REQUIRE(dw.size() == 1, "1-D array required"); |
302 | 0 | #endif |
303 | 0 | Array a(1, evolve(t0,x0[0],dt,dw[0])); |
304 | 0 | return a; |
305 | 0 | } |
306 | | |
307 | | inline Array StochasticProcess1D::apply(const Array& x0, |
308 | 0 | const Array& dx) const { |
309 | 0 | #if defined(QL_EXTRA_SAFETY_CHECKS) |
310 | 0 | QL_REQUIRE(x0.size() == 1, "1-D array required"); |
311 | 0 | QL_REQUIRE(dx.size() == 1, "1-D array required"); |
312 | 0 | #endif |
313 | 0 | Array a(1, apply(x0[0],dx[0])); |
314 | 0 | return a; |
315 | 0 | } |
316 | | |
317 | | } |
318 | | |
319 | | |
320 | | #endif |