Fractional Differentiation

Stationarity with memory preservation for predictive time series

Price levels are non-stationary (trending mean), so ML models trained on them don’t generalize. Taking full returns (d=1) makes them stationary but destroys all memory of price levels. Fractional differentiation lets you pick a d between 0 and 1 that makes the series just barely stationary while keeping as much memory as possible.

From AFML Chapter 5.

Compute weights

python
import horizon as hz

weights = hz.frac_diff_weights(d=0.4, threshold=1e-5)
# Returns the filter coefficients for fractional differencing at order d

Apply fractional differencing

python
series = [100.0, 101.5, 99.8, 102.3, ...]  # price series

diffed = hz.frac_diff_ffd(series, d=0.4, threshold=1e-5)

The ffd (fixed-width window) variant truncates the filter at threshold, making it practical for long series.

Finding the right d

Start at d=0 and increase until the series passes an ADF stationarity test. Typical values for daily equity prices: d ≈ 0.3 to 0.5.

python
for d in [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]:
    diffed = hz.frac_diff_ffd(prices, d=d, threshold=1e-5)
    # run ADF test on diffed
    # stop when p-value < 0.05

When to use

  • Preprocessing price series for ML models (instead of raw returns)
  • When you want stationarity but also want the model to “remember” price levels
  • Feature engineering for strategies that need both trend and level information

Next