All articles
Article9 min read

Fractional Differentiation

Log prices have memory but no stationarity, log returns have stationarity but no memory. Fractional differentiation lets you pick a d between 0 and 1, and on BTC the ADF test doesn't pick it as cleanly as you'd hope.

In quant finance, we use log returns instead of prices because prices are not stationary, and stationarity is necessary for an ML algorithm. But prices have a memory that we lose when we compute the log return.

In chapter 5 of Advances in Financial Machine Learning, López de Prado introduces fractional differentiation. A differentiation of order d=0d = 0 gives the log price (memory, but no stationarity), and d=1d = 1 gives the log return (stationarity, but no memory). The whole idea is to choose a dd between 0 and 1 to find a trade-off between stationarity and memory. That's what we will look at today, on BTC/USD daily closes.

1. Definition

Let StS_t be the log price at time tt. The backshift operator BB moves a series one step back in time:

BSt=St−1,BkSt=St−kB S_t = S_{t-1}, \qquad B^k S_t = S_{t-k}

With it, the log return is just (1−B)(1 - B) applied to the log price:

(1−B)St=St−St−1(1 - B) S_t = S_t - S_{t-1}

And applying it twice gives the difference of the differences: (1−B)2St=St−2St−1+St−2(1 - B)^2 S_t = S_t - 2 S_{t-1} + S_{t-2}. So in general, we want:

Xt=(1−B)d StX_t = (1 - B)^d \, S_t

This is nice for an integer dd: the binomial theorem gives a finite sum. But our goal is a dd between 0 and 1, and for a real dd we need the generalized binomial series, which is infinite.

Let's check the two ends:

  • d=0d = 0: ω0=1\omega_0 = 1 and every other weight is 0, so Xt=StX_t = S_t, the log price.
  • d=1d = 1: ω0=1\omega_0 = 1, ω1=−1\omega_1 = -1, and the factor (d−k+1)(d - k + 1) is 0 from k=2k = 2 on, so Xt=St−St−1X_t = S_t - S_{t-1}, the log return.

For an integer dd, the weights eventually hit zero and the sum is finite. For a dd in between, they never do: every past price keeps a small weight, and that is the memory. But what happens in the middle?

2. Fixed window

As you can see, ωk\omega_k is an infinite series, and of course our series is finite. To compute XtX_t, we can either fix a number l∗l^* of weights (the fixed window), or expand the window as we get more and more data. We make the same choice as López de Prado and use the fixed window. But how do we fix l∗l^*?

López de Prado puts a threshold τ=10−5\tau = 10^{-5} on ∣ωk∣|\omega_k|, and drops every weight below it:

l∗=max⁡{k:∣ωk∣≥τ},X~t=∑k=0l∗ωk St−kfor t≥l∗l^* = \max \left\{ k : |\omega_k| \geq \tau \right\}, \qquad \tilde{X}_t = \sum_{k=0}^{l^*} \omega_k \, S_{t-k} \quad \text{for } t \geq l^*

The same weights are applied to every point, so the series stays consistent through time, but the first l∗l^* points are lost.

The smaller the threshold, the bigger l∗l^*. Let's see the behavior of ωk\omega_k and l∗l^*:

The smaller d, the slower the weights decay, and the longer the window.
dl∗l^* (τ = 1e-4)l∗l^* (τ = 1e-5)
0.15024,075
0.24963,381
0.254442,803
0.33872,274
0.42811,457
0.5199926
0.6139589
0.796371
0.7578292
0.863227
0.937124

With a threshold of 1e-5, d=0.25d = 0.25 needs 2,803 points, so 7.7 years of daily data, before the first value. If you don't have enough points, that's a problem. Our BTC/USD history starts in October 2013, so at d=0.25d = 0.25 and τ=10−5\tau = 10^{-5} we only keep the last 5 years, and we will see that it shows.

3. Quantify the stationarity

To check whether the series is stationary, we use the Augmented Dickey-Fuller test, with the same settings as in the book.

The idea is to find the lowest dd where the unit root is rejected. But rejecting the unit root doesn't mean the series is stationary, and this is what we will see below.

We also plot the correlation between X~t\tilde{X}_t and the log price on the same dates. The correlation stands for the memory: at d=0d = 0 it is 1, at d=1d = 1 it is 0, and we want to keep as much of it as we can.

τ = 1e-4: the unit root is rejected from d = 0.25, with a correlation of 0.97.
τ = 1e-5: the unit root is rejected from d = 0.2, but the correlation curve is bumpy.
dADF (τ = 1e-4)Corr (τ = 1e-4)ADF (τ = 1e-5)Corr (τ = 1e-5)
0.15−2.210.990−2.420.844
0.2−2.520.981−3.170.806
0.25−3.110.969−4.260.779
0.3−3.800.955−5.670.613
0.4−6.190.916−9.720.458
0.5−10.230.850−14.900.354
1−49.65−0.007−49.65−0.007

With a threshold of 1e-4, the test accepts d=0.25d = 0.25, with a correlation of 0.97: on paper, almost all the memory of the price, and no unit root. With 1e-5, it accepts d=0.2d = 0.2, but the correlation curve is unclear, because the long windows leave very few points (1,361 at d=0.2d = 0.2, against 4,246 with 1e-4).

4. What it looks like in practice

Let's plot the series at d=0.25d = 0.25, the value the ADF test picks:

d = 0.25. With τ = 1e-4, the series follows the price. With τ = 1e-5, it starts in mid-2021.

At d=0.25d = 0.25, this isn't stationary at all. With τ=10−4\tau = 10^{-4} we see the whole drift of the price, and with τ=10−5\tau = 10^{-5} we don't have enough data to say anything.

Let's go further, to d=0.55d = 0.55:

d = 0.55. With τ = 1e-4, a slow drift is still there. With τ = 1e-5, the series is flat.

At d=0.55d = 0.55 it is more stationary, but there is a drift again with τ=10−4\tau = 10^{-4}, while with τ=10−5\tau = 10^{-5} it looks right.

5. Where the drift comes from

The drift has a simple cause: the truncation. For d>0d > 0, the full infinite series of weights sums to zero, since (1−1)d=0(1 - 1)^d = 0. Once the window is cut at l∗l^*, the weights we keep no longer do:

X~t=(∑k=0l∗ωk)⏟> 0St  −  ∑k=1l∗ωk(St−St−k)\tilde{X}_t = \underbrace{\left(\sum_{k=0}^{l^*} \omega_k\right)}_{> \, 0} S_t \; - \; \sum_{k=1}^{l^*} \omega_k \left(S_t - S_{t-k}\right)

The first term is a fraction of today's log price, so a piece of the trend leaks straight into the series. The second term is a weighted sum of past log returns, which is the "memory" we were looking for. The bigger τ\tau, the shorter the window, and the bigger the leak:

dτSum of kept weightsCorr with log priceCorr once the leak is removed
0.251e-40.1780.9690.038
0.251e-50.1120.7790.379
0.551e-40.0300.8000.036
0.551e-50.0130.332−0.080

At d=0.25d = 0.25 and τ=10−4\tau = 10^{-4}, 17.8% of the log price goes straight into the series, and it accounts for nearly all the 0.97 correlation: subtract it, and the correlation drops to 0.04. BTC went from $100 to $100,000, so 17.8% of its log price moves by more than 1.2, which is the drift on the chart. The ADF test, with one lag and a constant, doesn't see a trend that slow.

So the correlation with the log price is a flattering measure of memory: a large part of it is just the level that the truncation lets through.

6. Conclusion

It seems that the ADF methodology presented by López de Prado isn't a reliable way to find the "stationary point" on BTC:

  • with τ=10−4\tau = 10^{-4}, the dd it picks still carries the trend of the price;
  • with τ=10−5\tau = 10^{-5}, the windows are so long that the low dd values are computed on a few years of data only.

I tried the KPSS test too, whose null hypothesis is the opposite (the series is stationary). It doesn't help much: with τ=10−4\tau = 10^{-4}, it rejects stationarity for every dd except d=1d = 1, which fits the leak above. With τ=10−5\tau = 10^{-5}, it only stops rejecting around d=0.3d = 0.3 to 0.50.5, and not even consistently (at the 5% level, only d=0.45d = 0.45 passes), on series that are again short.

Maybe the best way to get a good trade-off between stationarity and memory is to choose dd and τ\tau qualitatively, by looking at the series, rather than with a statistical test.

Check the series, not just the test

Before you feed a fractionally differentiated series to a model, plot it next to the price, and check how many points the window leaves you. An ADF statistic below −2.86 doesn't mean the trend is gone.

The next question is how to use this series in an ML model. That one is still open for me, and the intuition behind it isn't obvious, so it will be for another article.

Want to try it on real data?

Angolin serves the full BTC history at 1d, 1h and 1m granularity, and the historical universe of each exchange, delisted pairs included, to avoid survivorship bias.

More articles