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 Pkg
Pkg.activate(pwd())
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.

d = 0.2; T = 10^4

# Cummulative product
function fi_cum(T::Int, d::Float64)
    k = 1:(T-1)
    coef = zeros(T)
    coefs = [1; cumprod((k .- d .- 1) ./ k)]

    return coefs
end

# Recursive algorithm
function fi_rec(T::Int, d::Float64)
    
    coefs = zeros(T)
    coefs[1] = 1
    for t in 1:T-1
        coefs[t+1] = coefs[t] * ( (t - d - 1) / t )
    end

    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 (minmax):  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 (minmax):  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 (minmax):  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.

R"library(fracdiff)"
@benchmark R"fracdiff::fracdiff.sim(10000, d = 0.2)"
BenchmarkTools.Trial: 46 samples with 1 evaluation.
 Range (minmax):  101.318 ms163.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.

R"library(microbenchmark)"
R"microbenchmark(fracdiff::fracdiff.sim(10000, d = 0.2), times = 33)"
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 (minmax):  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 (minmax):  1.672 ms40.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.

R"library(LongMemoryTS)"
@benchmark R"LongMemoryTS::fdiff(rnorm(10000), 0.2)"
BenchmarkTools.Trial: 948 samples with 1 evaluation.
 Range (minmax):  3.280 ms44.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.
R"microbenchmark(LongMemoryTS::fdiff(rnorm(10000), 0.2), times = 1000)"
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

t = 200
x = randn(t,1)
d = 0.2

fd_LongMemoryjl = fracdiff(x, d)
fd_fracdiff = R"fracdiff::diffseries($x, d = $d)"[1:t]
fd_LongMemoryTS = R"LongMemoryTS::fdiff($x, d = $d)"[1:t]

[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_LongMemoryjl  fd_fracdiff 
false

LongMemory.jl versus LongMemoryTS in R

fd_LongMemoryjl  fd_LongMemoryTS
true

Cross-sectional aggregation benchmark

Benchmarking asympotic algorithm

@benchmark csa_gen(T, 1.4, 1.4)
BenchmarkTools.Trial: 4087 samples with 1 evaluation.
 Range (minmax):  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 (minmax):  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

x = fi_gen(1000, 0.4);

Julia version

@benchmark gph_est(x; m = 0.5)
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
 Range (minmax):  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 (minmax):  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 (minmax):  5.370 ms47.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_LongMemoryjl = gph_est(x; m = 0.5)
gph_LongMemoryTS = R"LongMemoryTS::gph(X = $x, m = floor(1000^0.5))"[1]
gph_fracdiff = R"fracdiff::fdGPH($x)$d"[1]

[gph_LongMemoryjl gph_LongMemoryTS gph_fracdiff]
1×3 Matrix{Float64}:
 0.388724  0.388832  0.388832