# Parallelize 'rugarch' functions

=

The futurize package allows you to easily turn sequential code into parallel code by piping the sequential code to the `futurize()` function. Easy!

# TL;DR

    library(futurize)
    plan(multisession)
    library(rugarch)

    data(sp500ret, package = "rugarch")
    spec <- ugarchspec()
    roll <- ugarchroll(spec, sp500ret, n.start = 1000, refit.window = "moving", refit.every = 100) |> futurize()

# Introduction

This vignette demonstrates how to use this approach to parallelize rugarch functions such as `ugarchroll()`, `ugarchdistribution()`, and `ugarchboot()`.

The rugarch package provides a comprehensive set of methods for Generalized Autoregressive Conditional Heteroskedasticity (GARCH) modeling. Many of its functions, especially those involving rolling estimation or bootstrapping, are computationally intensive and benefit greatly from parallelization.

## Example: Rolling GARCH estimation

The `ugarchroll()` function performs rolling estimation and forecasting. This can be time-consuming as it involves multiple fits of the GARCH model.

    library(futurize)
    plan(multisession)
    library(rugarch)

    data(sp500ret, package = "rugarch")
    spec <- ugarchspec()

    ## Perform rolling estimation
    roll <- ugarchroll(spec, sp500ret, n.start = 1000,
                       refit.window = "moving", refit.every = 100) |> futurize()

## Example: GARCH parameter distribution

The `ugarchdistribution()` function simulates and estimates the parameter distribution of a GARCH model.

    library(futurize)
    plan(multisession)
    library(rugarch)

    data(sp500ret, package = "rugarch")
    spec <- ugarchspec()
    fit <- ugarchfit(spec, sp500ret)

    ## Estimate parameter distribution
    dist <- ugarchdistribution(fit, n.sim = 100, n.hist = 10) |> futurize()

# Supported Functions

The following rugarch functions are supported by `futurize()`:

- `arfimacv()` with `seed = TRUE` as the default
- `arfimadistribution()` with `seed = TRUE` as the default
- `arfimaroll()` with `seed = TRUE` as the default
- `autoarfima()` with `seed = TRUE` as the default
- `multifilter()` with `seed = TRUE` as the default
- `multifit()` with `seed = TRUE` as the default
- `multiforecast()` with `seed = TRUE` as the default
- `ugarchboot()` with `seed = TRUE` as the default
- `ugarchdistribution()` with `seed = TRUE` as the default
- `ugarchroll()` with `seed = TRUE` as the default

# Without futurize: Manual PSOCK cluster setup

For comparison, here is what it takes to parallelize `ugarchroll()` using the parallel package directly, without futurize:

    library(rugarch)
    library(parallel)

    data(sp500ret, package = "rugarch")
    spec <- ugarchspec()

    ## Set up a PSOCK cluster
    ncpus <- 4L
    cl <- makeCluster(ncpus)

    ## Run rolling estimation in parallel
    roll <- ugarchroll(spec, sp500ret, n.start = 1000,
                       refit.window = "moving", refit.every = 100,
                       cluster = cl)

    ## Tear down the cluster
    stopCluster(cl)

This requires you to manually create and manage the cluster lifecycle. If you forget to call `stopCluster()`, or if your code errors out before reaching it, you leak background R processes. You also have to decide upfront how many CPUs to use and what cluster type to use. Switching to another parallel backend, e.g. a Slurm cluster, would require a completely different setup. With futurize, all of this is handled for you - just pipe to `futurize()` and control the backend with `plan()`.