1
1
using DifferentialEquations
2
2
3
- export AbstractStochasticProcess, GBMProcess, HestonProcess, get_drift, get_diffusion, get_analytic_solution, get_sde_function
3
+ export AbstractStochasticProcess, GBMProcess, HestonProcess, get_sde_function, combine_sde_functions, GBMTimeDependent, get_sde_problem
4
+
5
+ function combine_sde_functions (sde_functions:: Tuple{Vararg{SDEFunction}} )
6
+ n = length (sde_functions) # Number of 1D SDEs
7
+
8
+ # Construct multi-dimensional drift function
9
+ f = (u, p, t) -> begin
10
+ return map (i -> sde_functions[i]. f ([u[i]], p, t)[1 ], 1 : n)
11
+ end
12
+
13
+ # Construct multi-dimensional diffusion function
14
+ g = (u, p, t) -> begin
15
+ return map (i -> sde_functions[i]. g ([u[i]], p, t)[1 ], 1 : n)
16
+ end
17
+
18
+ # Check if all SDEFunctions have an analytic solution
19
+ if all (sf -> sf. analytic != = nothing , sde_functions)
20
+ # Construct a multi-dimensional analytical solution
21
+ analytic = (u0, p, t, W) -> begin
22
+ return map (i -> sde_functions[i]. analytic ([u0[i]], p, t, W[i])[1 ], 1 : n)
23
+ end
24
+ else
25
+ analytic = nothing # No combined analytic solution if any function lacks it
26
+ end
27
+
28
+ return SDEFunction (f, g, analytic= analytic)
29
+ end
30
+
31
+ function get_sde_problem (processes, Γ, u0, tspan, p; kwargs... )
32
+ sde_functions = get_sde_function .(processes)
33
+ combined_sde_function = combine_sde_functions (sde_functions)
34
+ noise = CorrelatedWienerProcess (Γ, tspan[1 ], zeros (length (processes)))
35
+
36
+ return SDEProblem (combined_sde_function, u0, tspan, p; noise= noise, kwargs... )
37
+ end
38
+
4
39
5
40
# Abstract type for stochastic processes
6
41
"""
@@ -21,6 +56,16 @@ struct GBMProcess <: AbstractStochasticProcess
21
56
σ
22
57
end
23
58
59
+ function get_sde_function (process:: GBMProcess )
60
+ drift (u, p, t) = process. μ .* u
61
+
62
+ diffusion (u, p, t) = process. σ .* u
63
+
64
+ analytic_solution (u₀, p, t, W) = u₀ .* exp .((process. μ - (process. σ^ 2 ) / 2 ) .* t .+ process. σ * W)
65
+
66
+ return SDEFunction (drift, diffusion, analytic = analytic_solution)
67
+ end
68
+
24
69
# Define the Heston process
25
70
"""
26
71
HestonProcess <: AbstractStochasticProcess
@@ -40,84 +85,44 @@ struct HestonProcess <: AbstractStochasticProcess
40
85
ρ
41
86
end
42
87
43
- # Drift function for GBM
44
- """
45
- drift(process::GBMProcess, u, t)
46
-
47
- Computes the drift term of the GBM process at time `t` for state `u`.
48
- Drift equation: `du/dt = μ * u`
49
- """
50
- function drift (process:: GBMProcess , u, t)
51
- return process. μ .* u # Element-wise broadcasting for array compatibility
52
- end
53
-
54
- # Drift function for Heston
55
- """
56
- drift(process::HestonProcess, u, t)
57
-
58
- Computes the drift term of the Heston process at time `t` for state `u = (S, V)`.
59
- Drift equations:
60
- - `dS/dt = μ * S`
61
- - `dV/dt = κ * (θ - V)`
62
- """
63
- function drift (process:: HestonProcess , u, t)
64
- S, V = u
65
- return [process. μ * S, process. κ * (process. θ - V)] # Drift for (Stock price, Variance)
66
- end
67
-
68
- # Diffusion function for GBM
69
- """
70
- diffusion(process::GBMProcess, u, t)
71
-
72
- Computes the diffusion term of the GBM process at time `t` for state `u`.
73
- Diffusion equation: `dW_t = σ * u * dB_t`
74
- """
75
- function diffusion (process:: GBMProcess , u, t)
76
- return process. σ .* u # Element-wise broadcasting for array compatibility
77
- end
78
-
79
- # Diffusion function for Heston
80
- """
81
- diffusion(process::HestonProcess, u, t)
82
-
83
- Computes the diffusion term of the Heston process at time `t` for state `u = (S, V)`.
84
- Diffusion equations:
85
- - `dS_t = σ * sqrt(V) * dB_t`
86
- - `dV_t = ξ * sqrt(V) * dW_t`, with correlation `ρ`.
87
- """
88
- function diffusion (process:: HestonProcess , u, t)
89
- S, V = u
90
- return [process. σ * S * sqrt (V), process. σ * sqrt (V)] # Diffusion for (Stock price, Variance)
88
+ function get_sde_function (process:: HestonProcess )
89
+ function drift (u, p, t)
90
+ S, V = u
91
+ return [process. μ * S, process. κ * (process. θ - V)]
92
+ end
93
+
94
+ function diffusion (u, p, t)
95
+ S, V = u
96
+ return [process. σ * S * sqrt (V), process. σ * sqrt (V)]
97
+ end
98
+
99
+ return SDEFunction (drift, diffusion)
91
100
end
92
101
93
- # Higher-order functions to return drift! and diffusion!
94
- """
95
- get_drift!(process::AbstractStochasticProcess)
96
-
97
- Returns the in-place drift function `drift!` for the given process.
98
- """
99
- function get_drift (process:: P ) where P<: AbstractStochasticProcess
100
- return (u, p, t) -> drift (process, u, t)
102
+ struct GBMTimeDependent
103
+ μ
104
+ σ
105
+ mean_σ²
101
106
end
102
107
103
- """
104
- get_diffusion!(process::AbstractStochasticProcess)
108
+ function get_sde_function (process :: GBMTimeDependent )
109
+ drift (u, p, t) = process . μ .* u
105
110
106
- Returns the in-place diffusion function `diffusion!` for the given process.
107
- """
108
- function get_diffusion (process:: P ) where P<: AbstractStochasticProcess
109
- return (u, p, t) -> diffusion (process, u, t)
110
- end
111
+ diffusion (u, p, t) = sqrt (process. mean_σ² (t)) .* u
111
112
112
- function get_analytic_solution (process:: P ) where P <: AbstractStochasticProcess
113
- return Nothing ()
114
- end
113
+ # observe that the noise here is integrated.
114
+ # That is, W is not such that dX = mu dt + sigma_t dW_t but it is W' such that W'_t = t (int_0^t sigma_s dW_t) / (int_0^t sigma_s^2)
115
+ function analytic_solution (u₀, p, t, W)
116
+ I_t = sqrt (process. mean_σ² (t)) ./ t ./ t
117
+ return u₀ .* exp .((process. μ .- 0.5 * I_t^ 2 ) .* t .+ I_t .* W)
118
+ end
115
119
116
- function get_analytic_solution (:: GBMProcess )
117
- return (u₀, p, t, W) -> u₀ * exp ((0.05 - (0.2 ^ 2 ) / 2 ) * t + 0.2 * W)
120
+ return SDEFunction (drift, diffusion, analytic = analytic_solution)
118
121
end
119
122
120
- function get_sde_function (process:: P ) where P<: AbstractStochasticProcess
121
- return SDEFunction (get_drift (process), get_diffusion (process), analytic= get_analytic_solution (process))
123
+ # dX_t = (θ_t - a t) dt + σ_t dW_t
124
+ struct OUTimeDependent
125
+ θ
126
+ a
127
+ σ
122
128
end
123
-
0 commit comments