LongMemory.jl: Generating, Estimating, and Forecasting Long Memory Models in Julia

Benchmarks

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. Generating methods include fractional differencing, stochastic error duration, and cross-sectional aggregation. Estimators include those inspired by the log-periodogram regression and parametric ones. This notebook provides benchmarks for the LongMemory.jl package including 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:

Vera-Valdés, J.E. (2024). “LongMemory.jl: Generating, Estimating, and Forecasting Long Memory Models in Julia”. arXiv 2401.14077. https://arxiv.org/abs/2401.14077

@article{VERAVALDES2024a,
title = {LongMemory.jl: Generating, Estimating, and Forecasting Long Memory Models in Julia},
year = {2024},
author = {Vera-Valdés, J.E.},
journal = {arXiv preprint arXiv:2401.14077},
url = {https://arxiv.org/abs/2401.14077}
}

Loading packages

Loading the package and setting a seed

using LongMemory, BenchmarkTools, Random, RCall
Random.seed!(1234)
TaskLocalRNG()

Long memory generation

The fi_gen() function, which uses the cumulative method.

@benchmark fi_gen(10000, 0.2)
BenchmarkTools.Trial: 4970 samples with 1 evaluation.
 Range (minmax):  546.300 μs  8.410 ms   GC (min … max): 0.00% … 68.25%
 Time  (median):     690.000 μs                GC (median):    0.00%
 Time  (mean ± σ):   990.161 μs ± 713.281 μs   GC (mean ± σ):  6.98% ±  7.83%
  █▆▅▄▃▂▂▂▅▄▄▄▃▃▁▁▁                                ▁          ▂
  ███████████████████▇█▆▆▆▅▆▃▁▁▁▁▁▁▃▁▃▃▁▁▁▁▁▁▃▇██████▇▇▇▇▇▅▄▅ █
  546 μs        Histogram: log(frequency) by time       3.73 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)"
┌ Warning: RCall.jl: Warning: package 'fracdiff' was built under R version 4.3.3
└ @ RCall C:\Users\eduar\.julia\packages\RCall\FEbLj\src\io.jl:172
BenchmarkTools.Trial: 47 samples with 1 evaluation.
 Range (minmax):  100.973 ms129.056 ms   GC (min … max): 0.00% … 0.00%
 Time  (median):     106.095 ms                GC (median):    0.00%
 Time  (mean ± σ):   106.919 ms ±   5.563 ms   GC (mean ± σ):  0.00% ± 0.00%
    ▂█  ▂▅    ▅                                               
  █████▅██▅▁████▅▁▁▁█▁▅▁▁▅▅▅▁▁▁▁█▁▁▁▁▁▁▁▁▁▁▁▅▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▅ ▁
  101 ms           Histogram: frequency by time          129 ms <
 Memory estimate: 1.02 KiB, allocs estimate: 37.

For comparison purposes, the following benchmark is done in R using the microbenchmark package.

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) 101.0279 102.8038 105.7101 104.5915
       uq      max neval
 109.0149 115.5849    33

Note that the times are similar. Hence, for ease of use, the next benchmarks are done using BenchmarkTools.

Fractional differencing

The fi_gen() function

@benchmark fracdiff(randn(10000,1), 0.2)
BenchmarkTools.Trial: 6384 samples with 1 evaluation.
 Range (minmax):  543.000 μs  6.538 ms   GC (min … max): 0.00% … 81.09%
 Time  (median):     624.700 μs                GC (median):    0.00%
 Time  (mean ± σ):   776.078 μs ± 402.315 μs   GC (mean ± σ):  6.18% ±  9.54%
  ▅██▆▅▄▃▃▂▁▁▁ ▁           ▁          ▁ ▁                     ▂
  ███████████████▇██▇▇███▇██▇██▇▇▆▇▇█▇█████▇██▇▇▆▆▅▆▆▄▅▅▃▄▆▆▄ █
  543 μs        Histogram: log(frequency) by time       2.17 ms <
 Memory estimate: 2.58 MiB, allocs estimate: 44.

R: fracdiff::diffseries()

The R package fracdiff is used for fractional differencing using fracdiff::diffseries().

@benchmark R"fracdiff::diffseries(rnorm(10000), d = 0.2)"
BenchmarkTools.Trial: 2163 samples with 1 evaluation.
 Range (minmax):  1.751 ms42.836 ms   GC (min … max): 0.00% … 0.00%
 Time  (median):     2.037 ms               GC (median):    0.00%
 Time  (mean ± σ):   2.301 ms ±  1.334 ms   GC (mean ± σ):  0.00% ± 0.00%
  ▅▇█▇▆▅▅▄▃▃▂▁▁ ▁                                          ▁
  ███████████████▇█▇▆█▇▇▇▅▅▅▄▁▅▁▅▄▄▅▄▆▆▅▄▁▆▅▇▅▄▅▄▅▆▅▁▆▁▁▅▄ █
  1.75 ms      Histogram: log(frequency) by time      5.8 ms <
 Memory estimate: 1.02 KiB, allocs estimate: 37.

R: LongMemoryTS:fdiff()

Loading the R package LongMemoryTS. The LongMemoryTS::fdiff() function is used for fractional differencing.

R"library(LongMemoryTS)"
@benchmark R"LongMemoryTS::fdiff(rnorm(10000), 0.2)"
BenchmarkTools.Trial: 1256 samples with 1 evaluation.
 Range (minmax):  3.113 ms34.072 ms   GC (min … max): 0.00% … 0.00%
 Time  (median):     3.713 ms               GC (median):    0.00%
 Time  (mean ± σ):   3.965 ms ±  1.155 ms   GC (mean ± σ):  0.00% ± 0.00%
    ▄▆▆██▇▃▂▁▂                                              
  ▃▆███████████▆▅▅▅▅▄▄▃▃▄▃▃▃▃▃▃▃▂▂▁▂▃▃▂▃▂▃▁▃▃▂▂▁▂▂▂▂▂▂▂▃▂▃ ▄
  3.11 ms        Histogram: frequency by time        6.92 ms <
 Memory estimate: 1.02 KiB, allocs estimate: 37.

Comparing accuracy

t = 20
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]
20×3 Matrix{Float64}:
  1.2558       0.845984   1.2558
  0.628208     0.300358   0.628208
 -0.0297641   -0.324829  -0.0297641
  0.49543      0.220036   0.49543
  1.46452      1.20289    1.46452
 -0.891909    -1.14307   -0.891909
  0.0139176   -0.22887    0.0139176
 -1.11488     -1.35073   -1.11488
 -0.342751    -0.572705  -0.342751
  1.19236      0.967514   1.19236
 -0.201157    -0.421504  -0.201157
  1.85728      1.64094    1.85728
 -0.79888     -1.01161   -0.79888
 -0.162949    -0.372412  -0.162949
 -0.369188    -0.575659  -0.369188
 -0.00385477  -0.207572  -0.00385477
  1.84698      1.64581    1.84698
 -0.28165     -0.480454  -0.28165
 -0.772948    -0.969543  -0.772948
  1.08411      0.889586   1.08411

Long memory estimation

Data generation.

x = fi_gen(1000, 0.4);

The gph_est() function

@benchmark gph_est(x; m = 0.5)
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
 Range (minmax):  28.200 μs  5.917 ms   GC (min … max): 0.00% … 35.65%
 Time  (median):     35.200 μs                GC (median):    0.00%
 Time  (mean ± σ):   44.094 μs ± 121.568 μs   GC (mean ± σ):  4.81% ±  1.84%
     ▂▃▃█▆                                                     
  ▂▃▅█████▆▄▄▄▄▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▂
  28.2 μs         Histogram: frequency by time         84.1 μs <
 Memory estimate: 66.48 KiB, allocs estimate: 43.

LongMemoryTS: gph()

@benchmark R"LongMemoryTS::gph($x, m = floor(1000^0.5))"
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
 Range (minmax):  138.100 μs46.531 ms   GC (min … max): 0.00% … 0.00%
 Time  (median):     166.900 μs               GC (median):    0.00%
 Time  (mean ± σ):   349.421 μs ±  1.242 ms   GC (mean ± σ):  0.00% ± 0.00%
  █▄▃▃▃▃▂▁▁                                                  ▁
  ████████████▇█▇▇▆▇▇▇▆▆▆▅▅▄▆▅▅▅▄▄▆▅▄▆▄▅▁▃▄▅▃▄▄▄▅▄▃▃▄▄▃▅▄▄▃▄ █
  138 μs        Histogram: log(frequency) by time      3.04 ms <
 Memory estimate: 2.66 KiB, allocs estimate: 104.

fracdiff: fdGPH()

@benchmark R"fracdiff::fdGPH($x)"
BenchmarkTools.Trial: 705 samples with 1 evaluation.
 Range (minmax):  5.053 ms38.156 ms   GC (min … max): 0.00% … 0.00%
 Time  (median):     6.061 ms               GC (median):    0.00%
 Time  (mean ± σ):   7.083 ms ±  3.266 ms   GC (mean ± σ):  0.00% ± 0.00%
  ▂█                                                         
  ██▇▄▃▂▃▄▅▃▃▃▂▂▁▁▁▁▁▁▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▂ ▂
  5.05 ms        Histogram: frequency by time        31.1 ms <
 Memory estimate: 2.66 KiB, allocs estimate: 104.

Comparing accuracy

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.390362  0.390564  0.390564