Trading FCPO calendar spreads as a mean-reverting process
A calendar spread is the price difference between two delivery months of the same contract, such as the near and third month of FCPO. Outright palm oil prices trend with weather, biodiesel policy and crude oil. The spread between two months is pulled back by something more mechanical: storage costs and the cost of carrying oil from one month to the next. That pull is what a mean-reversion model tries to capture.
The Ornstein–Uhlenbeck model
The Ornstein–Uhlenbeck (OU) process is the standard model for something that wanders but keeps getting pulled back to a level:
- θ (theta) is the fair level the spread reverts to.
- κ (kappa) is how fast it reverts. Bigger means faster.
- σ (sigma) is how noisy it is from day to day.
Fitting it with one regression
On daily data, an OU process is simply an AR(1) regression of today's spread on yesterday's:
From the slope and intercept you get every OU parameter: κ = −ln b, θ = a / (1 − b), and the long-run standard deviation σeq = sd(ε) / √(1 − b²). If b is not between 0 and 1, the spread is not mean-reverting in that window, and the honest answer is not to trade it.
I fit this on a rolling window, typically 60 days, so the fair level can drift as the market changes.
The z-score is the signal
A z-score of +2 means the spread is two long-run standard deviations above fair value. The simple rule is to sell the spread when z is high, buy it when z is low, and exit when it comes back near zero.
Why half-life matters more than the entry level
The half-life, ln 2 / κ, is how many days it takes for half of a deviation to disappear. This is the filter I find most useful:
- A half-life of 3–15 days means reversion is fast enough to trade before something else changes.
- A half-life of 60 days means the "mean reversion" is mostly noise in the fit. A z-score of 2 can stay at 2 for months.
- A very short half-life of under 2 days is often bid-ask bounce, which you cannot capture after costs.
Adding an ADF stationarity test as a second gate on entries removes more false signals. Exits are left ungated, because you always want to be able to get out.
Things that break the model
- Expiry and rolls: the near month's behaviour changes as delivery approaches, so roll before the last trading weeks.
- Regime changes: an Indonesian export policy change or a stock shock can move the fair level for good. The rolling window adapts, but only after losses.
- Costs: at RM25 per point per lot, a few points of slippage each way is a real share of a typical spread move.
For education only. Not trading advice.