This repo contais a Julia script to generate realizations of a class of stationary Gaussian stochastic processes with extremely long memory.
In detail the script can be used to generate realizations
with
Standard tools to generate stationary processes can become slow when the memory time is very large. The scheme that I use here approximates the true process as a finite sum of Ornstein-Uhlenbeck processes. This may be much more efficient than convolution in the time domain (as in ARFIMA(0,d,0)) or using a Fourier method. The advantage of the specific form for the correlation function is that it has the following integral representation
When we apply a numerical quadrature scheme to the integral it reduces to a finite sum over exponentials (in
with weights
This strategy allows for an efficient generation of realizations of stationary Gaussian processes with very long memory (i.e.
First create a LongMemoryProcess
struct.
lmp = LongMemoryProcess(y, θ_max)
To generate a single realization along a vector of times t one can then simply call
Xₜ = lmp(t)
You can check the accuracy by comparing the true correlation function with the fitted function (that is the correlation function of the approximated process).
y = -0.9; θ_max = 1.0; t_f = 1e8;
lmp = LongMemoryProcess(y, θ_max);
relative_error = abs(cf(y, θ_max, t_f) - cf_fit(lmp, t_f)) / cf(y, θ_max, t_f) # 9.013557696260914e-7
Calling cf
requires the incomplete gamma function via SpecialFunctions.jl. If you need more speed and less accuracy you can decrease the number of Ornstein-Uhlenbeck processes with the optional argument n
(the default value is n = 401
).
number_of_OU_processes = 61;
lmp = LongMemoryProcess(y, θ_max, n = number_of_OU_processes);
relative_error = abs(cf(y, θ_max, t_f) - cf_fit(lmp, t_f)) / cf(y, θ_max, t_f) # 0.0035874732157112664
If you want to plug in the process as noise in a differential equation you can use an SDE solver and integrate the Ornstein-Uhlenbeck processes along. The individual Ornstein-Uhlenbeck processes obey the SDE
and the full process is just their sum
LongMemoryProcess
struct.
θ = lmp.θ; σ = lmp.σ;
To obtain a valid initial condition for
X₀, x₀ = lmp(Vector([0.]); return_full=true);
X₀[end] == sum(x₀) # true
If you found this project useful for your work please directly cite this GitHub repository.