Project write-up · Macro / Nowcasting

Nowcasting French industrial production from open data

Live site · Source code · Full design notes

The problem

INSEE publishes France's industrial production index (IPI) about 40 days after the month ends. Plenty of data about that month is already public long before then: electricity consumption, business surveys, company insolvencies, bond spreads. France Economic Pulse uses that data to estimate the month before INSEE does (a nowcast), and rebuilds the estimate every day.

Data, aligned to when it was really known

All five sources are free, need no API key, and are fetched by a daily GitHub Actions job.

Every feature is aligned to the date it was published, not the month it describes, and the weather correction is refitted at each backtest step using only past data. Without that, the backtest would quietly use information the model couldn't have had.

Model: start from the simplest benchmark

The rule was that complexity has to earn its place. The benchmark is an AR(1) on IPI growth. The main model is a ridge regression on the features above. Gradient boosting is a challenger, kept only if it beats ridge out of sample. With about 175 months of overlapping data, a regularised linear model was the natural favourite.

Evaluation: walk-forward, never random splits

The backtest uses an expanding window from January 2016 to July 2026 (127 months): train on everything up to month t, predict t+1, step forward. Random k-fold splits would leak the future in a time series. Models are compared on RMSE, directional accuracy and a one-sided Diebold–Mariano test against the benchmark. March–July 2020 is excluded from the scores because COVID errors swamp everything else.

ModelRMSEvs AR(1)DM p-valueRight direction
AR(1) benchmark1.331.00—48%
Ridge (published)1.260.950.0759%
Gradient boosting1.351.020.6354%

Ridge has 5% lower error than the benchmark and gets the direction right about 6 times in 10. Gradient boosting does worse than the benchmark, so it stays in the table only for transparency. The published 80% range is built only from errors known at the time; over 97 months, the actual figure fell inside it 80.4% of the time.

What it doesn't show

Engineering

A daily GitHub Actions run fetches only new data, stores it as Parquet in the repository, refits the model, writes the site's data file and deploys a static Astro site in French and English. If a source is down, the site still rebuilds with its last good data and the run is flagged so I get an email.

← Back to all projects