using Pkg
Pkg.activate(pwd())
LongMemory.jl: Generating, Estimating, and Forecasting Long Memory Models in Julia
Benchmarks
J. Eduardo Vera-Valdés (eduardo@math.aau.dk)
Abstract
LongMemory.jl is a package for time series long memory modelling in Julia. The package provides functions for generating long memory, estimating the parameters of the models, and simulation. We compare the LongMemory.jl properties against current alternatives. The package is closely related to the R packages LongMemoryTS and fracdiff.
Citation
If you use this package in your research, please cite it as:
@article{VeraValdes2024longmemory,
title={LongMemory.jl: Generating, Estimating, and Forecasting Long Memory Models in Julia},
author={Vera-Vald{\'e}s, J Eduardo},
year={2024},
}
Activating the environment and loading the packages
using LongMemory, Plots, DataFrames, CSV, BenchmarkTools, RCall, Random
Random.seed!(1234)
Benchmarking recursive versus cummulative algorithms
Benchmarking the recursive and cummulative methods to compute the fractional differencing coefficients.
= 0.2; T = 10^4
d
# Cummulative product
function fi_cum(T::Int, d::Float64)
= 1:(T-1)
k = zeros(T)
coef = [1; cumprod((k .- d .- 1) ./ k)]
coefs
return coefs
end
# Recursive algorithm
function fi_rec(T::Int, d::Float64)
= zeros(T)
coefs 1] = 1
coefs[for t in 1:T-1
+1] = coefs[t] * ( (t - d - 1) / t )
coefs[tend
return coefs
end
# Comparing results
fi_cum(T,d) ≈ fi_rec(T,d)
true
Benchmarking the fractional differencing generation by the recursive method.
@benchmark fi_rec(T, d)
BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 12.000 μs … 4.829 ms ┊ GC (min … max): 0.00% … 98.48% Time (median): 34.800 μs ┊ GC (median): 0.00% Time (mean ± σ): 35.242 μs ± 105.543 μs ┊ GC (mean ± σ): 11.35% ± 4.00% ▇█▁ ▃▃ ▃▅▆▆▅▆▅▄▄▃▃▃▃▂▂▂▁▁▁▁ ▂ ████████▇▆▅▅▅▆▄▄▄███████████████████████▇▇▇▆▆▆▇▇▆▆▇▆▆▆▇▅▇▆▅▆ █ 12 μs Histogram: log(frequency) by time 78.5 μs < Memory estimate: 78.17 KiB, allocs estimate: 2.
Benchmarking the fractional differencing generation by the cummulative method.
@benchmark fi_cum(T, d)
BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 25.600 μs … 4.362 ms ┊ GC (min … max): 0.00% … 96.28% Time (median): 48.300 μs ┊ GC (median): 0.00% Time (mean ± σ): 87.541 μs ± 167.927 μs ┊ GC (mean ± σ): 13.79% ± 7.69% █▇▅▄▄▄▃▁▁ ▁▁▃▅▆▆▅▄▃▃▂▂▂▂▂▂▂▁▁ ▂ █████████▇▇▄▅▅▂▇▇█████████████████████▇▆▆▇▄▆▂▄▄▄▄▅▂▆▆▅▄▅▄▄▅▄ █ 25.6 μs Histogram: log(frequency) by time 259 μs < Memory estimate: 312.69 KiB, allocs estimate: 8.
Fractional differencing generation benchmarking
Julia: benchmarking the fi_gen() function, which uses the cummulative method.
@benchmark fi_gen(10000, 0.2)
BenchmarkTools.Trial: 5503 samples with 1 evaluation. Range (min … max): 541.300 μs … 24.785 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 625.300 μs ┊ GC (median): 0.00% Time (mean ± σ): 901.710 μs ± 645.383 μs ┊ GC (mean ± σ): 6.28% ± 8.87% ██▆▄▃▃▂▂▁▂▁▂▁▃▂▂▂▃▃▃▂▁ ▁ ▁ ████████████████████████▇▇▇▇▇▇▆▆▅▆▆▅▆▆████▇██▇▆▅▆▆▅▆▅▆▅▅▄▄▃▅▄ █ 541 μs Histogram: log(frequency) by time 2.93 ms < Memory estimate: 2.58 MiB, allocs estimate: 44.
R: benchmarking the fracdiff.sim() function.
Loading the R packages. The R package fracdiff is used for fractional differencing generation using fracdiff::fracdiff.sim(). Benchmarking the fractional differencing generation by the R package fracdiff using RCall.
"library(fracdiff)"
R@benchmark R"fracdiff::fracdiff.sim(10000, d = 0.2)"
BenchmarkTools.Trial: 46 samples with 1 evaluation. Range (min … max): 101.318 ms … 163.066 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 104.129 ms ┊ GC (median): 0.00% Time (mean ± σ): 109.212 ms ± 12.934 ms ┊ GC (mean ± σ): 0.00% ± 0.00% █▅ ▃ ██▇█▁▃▃▅▆▁▁▁▁▁▁▁▁▃▁▃▃▁▃▁▁▁▁▃▁▁▁▁▁▁▁▁▁▁▁▁▃▁▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃ ▁ 101 ms Histogram: frequency by time 163 ms < Memory estimate: 1.02 KiB, allocs estimate: 37.
Benchmarking in R using microbenchmark.
"library(microbenchmark)"
R"microbenchmark(fracdiff::fracdiff.sim(10000, d = 0.2), times = 33)" R
RObject{VecSxp}
Unit: milliseconds
expr min lq mean median
fracdiff::fracdiff.sim(10000, d = 0.2) 103.5634 107.7762 123.4763 123.1038
uq max neval
130.227 178.6668 33
Fractional differencing benchmarking
Julia: benchmarking the fracdiff() function.
@benchmark fracdiff(randn(10000,1), 0.2)
BenchmarkTools.Trial: 5965 samples with 1 evaluation. Range (min … max): 551.000 μs … 6.567 ms ┊ GC (min … max): 0.00% … 8.02% Time (median): 673.400 μs ┊ GC (median): 0.00% Time (mean ± σ): 829.168 μs ± 356.867 μs ┊ GC (mean ± σ): 3.87% ± 7.60% █▇▂ ▄▇███▇▄▃▃▂▂▂▂▂▂▂▂▂▃▃▃▂▂▂▂▂▂▁▁▁▁▂▁▂▂▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 551 μs Histogram: frequency by time 2.14 ms < Memory estimate: 2.58 MiB, allocs estimate: 44.
R: benchmarking the fracdiff::diffseries() function.
@benchmark R"fracdiff::diffseries(rnorm(10000), d = 0.2)"
BenchmarkTools.Trial: 1812 samples with 1 evaluation. Range (min … max): 1.672 ms … 40.389 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 2.313 ms ┊ GC (median): 0.00% Time (mean ± σ): 2.744 ms ± 1.500 ms ┊ GC (mean ± σ): 0.00% ± 0.00% ▅█▇▅▂▁ ▄▅███████▇▆▄▄▄▄▄▄▄▄▄▄▄▅▅▄▅▄▄▃▃▂▃▃▂▂▂▂▂▂▂▃▂▂▂▂▂▂▁▂▂▂▂▁▂▂▁▂▂ ▃ 1.67 ms Histogram: frequency by time 6.58 ms < Memory estimate: 1.02 KiB, allocs estimate: 37.
R: benchmarking the LongMemoryTS::fdiff() function.
"library(LongMemoryTS)"
R@benchmark R"LongMemoryTS::fdiff(rnorm(10000), 0.2)"
BenchmarkTools.Trial: 948 samples with 1 evaluation. Range (min … max): 3.280 ms … 44.236 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 4.672 ms ┊ GC (median): 0.00% Time (mean ± σ): 5.251 ms ± 2.584 ms ┊ GC (mean ± σ): 0.00% ± 0.00% █▆▇▄▂ ▄▇█████▇██▅▆▇▇▇▇▇▅▆▆▆▄▄▄▃▃▃▃▃▃▃▂▂▃▃▂▂▂▃▂▂▃▂▂▂▂▂▁▁▁▂▁▂▁▁▂▁▂ ▃ 3.28 ms Histogram: frequency by time 12.2 ms < Memory estimate: 1.02 KiB, allocs estimate: 37.
"microbenchmark(LongMemoryTS::fdiff(rnorm(10000), 0.2), times = 1000)" R
RObject{VecSxp}
Unit: milliseconds
expr min lq mean median
LongMemoryTS::fdiff(rnorm(10000), 0.2) 3.137701 3.704051 4.648603 4.323702
uq max neval
5.253502 19.3061 1000
Comparing accuracy of the fractional differencing functions
= 200
t = randn(t,1)
x = 0.2
d
= fracdiff(x, d)
fd_LongMemoryjl = R"fracdiff::diffseries($x, d = $d)"[1:t]
fd_fracdiff = R"LongMemoryTS::fdiff($x, d = $d)"[1:t]
fd_LongMemoryTS
[fd_LongMemoryjl fd_fracdiff fd_LongMemoryTS]
200×3 Matrix{Float64}:
0.424018 0.358036 0.424018
0.0943704 0.0415847 0.0943704
-0.260219 -0.307726 -0.260219
1.22739 1.18305 1.22739
-1.09719 -1.13931 -1.09719
0.311951 0.271513 0.311951
-0.412623 -0.451713 -0.412623
-0.959909 -0.997882 -0.959909
-0.272796 -0.30982 -0.272796
1.32768 1.29147 1.32768
⋮
-1.27219 -1.29201 -1.27219
2.48577 2.46598 2.48577
-1.09873 -1.11851 -1.09873
-1.43191 -1.45166 -1.43191
0.0780798 0.0583464 0.0780798
-0.035271 -0.0549842 -0.035271
0.540485 0.520792 0.540485
0.528766 0.509093 0.528766
0.922279 0.902625 0.922279
LongMemory.jl versus fracdiff in R
≈ fd_fracdiff fd_LongMemoryjl
false
LongMemory.jl versus LongMemoryTS in R
≈ fd_LongMemoryTS fd_LongMemoryjl
true
Cross-sectional aggregation benchmark
Benchmarking asympotic algorithm
@benchmark csa_gen(T, 1.4, 1.4)
BenchmarkTools.Trial: 4087 samples with 1 evaluation. Range (min … max): 745.000 μs … 29.833 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 1.013 ms ┊ GC (median): 0.00% Time (mean ± σ): 1.209 ms ± 637.666 μs ┊ GC (mean ± σ): 2.96% ± 7.29% ▃█▆▁ ▂▄█████▇▆▄▃▄▃▃▂▂▃▃▄▃▄▄▄▅▄▄▃▃▃▃▂▂▂▂▂▁▁▁▁▂▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 745 μs Histogram: frequency by time 2.67 ms < Memory estimate: 2.58 MiB, allocs estimate: 44.
Benchmarking the finite version algorithm
@benchmark csa_gen(T, T, 1.4, 1.4)
BenchmarkTools.Trial: 4 samples with 1 evaluation. Range (min … max): 1.137 s … 1.718 s ┊ GC (min … max): 1.82% … 33.43% Time (median): 1.313 s ┊ GC (median): 15.48% Time (mean ± σ): 1.370 s ± 257.709 ms ┊ GC (mean ± σ): 18.27% ± 13.80% █ █ █ █ █▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█ ▁ 1.14 s Histogram: frequency by time 1.72 s < Memory estimate: 2.25 GiB, allocs estimate: 21.
Benchmark long memory estimation
Data generation
= fi_gen(1000, 0.4); x
Julia version
@benchmark gph_est(x; m = 0.5)
BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 29.300 μs … 6.527 ms ┊ GC (min … max): 0.00% … 73.86% Time (median): 41.700 μs ┊ GC (median): 0.00% Time (mean ± σ): 57.908 μs ± 156.797 μs ┊ GC (mean ± σ): 4.49% ± 1.76% ▇█▄▂ ▂█████▇▅▄▃▃▃▃▃▃▄▄▃▃▃▃▃▃▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 29.3 μs Histogram: frequency by time 160 μs < Memory estimate: 66.48 KiB, allocs estimate: 43.
LongMemoryTS
@benchmark R"LongMemoryTS::gph($x, m = floor(1000^0.5))"
BenchmarkTools.Trial: 10000 samples with 1 evaluation. Range (min … max): 141.500 μs … 8.129 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 184.600 μs ┊ GC (median): 0.00% Time (mean ± σ): 227.592 μs ± 188.092 μs ┊ GC (mean ± σ): 0.00% ± 0.00% ▂█▆▂ ▂▄████▇▅▄▄▃▃▃▃▃▂▂▂▂▂▃▃▃▃▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂ 142 μs Histogram: frequency by time 579 μs < Memory estimate: 2.66 KiB, allocs estimate: 104.
Fracdiff
@benchmark R"fracdiff::fdGPH($x)"
BenchmarkTools.Trial: 565 samples with 1 evaluation. Range (min … max): 5.370 ms … 47.422 ms ┊ GC (min … max): 0.00% … 0.00% Time (median): 7.415 ms ┊ GC (median): 0.00% Time (mean ± σ): 8.828 ms ± 4.323 ms ┊ GC (mean ± σ): 0.00% ± 0.00% ▅█▃ ▅████▆▅▅▄▄▅▄▅▃▃▃▃▃▃▃▂▂▁▁▁▁▁▂▂▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂ ▃ 5.37 ms Histogram: frequency by time 35.5 ms < Memory estimate: 2.66 KiB, allocs estimate: 104.
Comparing the estimation results
= gph_est(x; m = 0.5)
gph_LongMemoryjl = R"LongMemoryTS::gph(X = $x, m = floor(1000^0.5))"[1]
gph_LongMemoryTS = R"fracdiff::fdGPH($x)$d"[1]
gph_fracdiff
[gph_LongMemoryjl gph_LongMemoryTS gph_fracdiff]
1×3 Matrix{Float64}:
0.388724 0.388832 0.388832