MarketsMay 2026–nowProjectLive
GB power price forecast
Python · FastAPI · React
- Mean error per MWh
- £15.77
- Better than best naive
- 35.3%
- Half-hours tested
- 17,552
- Battery capture
- 71.7%
Context
It started as a map of NW European gas flows, because gas sets the GB power price. It became a day-ahead forecast of GB half-hourly power prices: issued every morning, written once, and scored against the outturn when it settles.
What I did
- 01Built the data layer from free sources (Elexon, ENTSOG, National Gas, GIE, Open-Meteo, the ECB), keyed by publish time so no backtest sees data it couldn't have had.
- 02Forecast the implied heat rate rather than the price, so a gas rally passes straight through and the call reads the way a desk talks.
- 03Ran a walk-forward horse race of ridge, gradient boosting, an MLP, quantile and conformal models against three naive benchmarks and the market's own day-ahead price.
- 04Priced a battery trading on the forecast: 71.7% of the profit perfect foresight would capture.
- 05Caught a silent bug where zero-volume periods printed a £0 price and taught every model to predict nothing.
Outcome
Out of sample, it beats the best naive benchmark by 35.3%. The market's own day-ahead price is still more accurate, so it has no edge on price level.
Limitations
- No edge on price level: the day-ahead auction is more accurate (£11.90 against £15.77) and a battery trading on it captures more (76.7% against 71.7%).
- One year of out-of-sample data, scored once. A different year, or a structural break like 2022, could look different.
- The battery is a simple price-taker on one market: no imbalance, ancillary or capacity revenue, and no market impact.
- Carbon is an assumed slow-moving constant, because there is no free UK carbon price feed.
How it was tested
- Test period
- 7 October 2025 to 7 October 2026: 366 delivery days, all out of sample.
- Sample
- 17,552 half-hourly periods. Periods that traded no volume are dropped, not scored as £0.
- Training
- Walk-forward: refitted every 30 days on the trailing two years, and only ever scored on later days. Each forecast uses only data published before 09:00 the day before delivery.
- Target
- The GB half-hourly market index price (APX, via Elexon), in £/MWh.
- Error
- Mean absolute error in £/MWh. “Better than best naive” compares it with the lowest-error naive rule.
- Naive benchmarks
- Yesterday: the same half-hour the day before (£25.01). Last week: the same half-hour seven days earlier (£26.59). Flat heat rate: one constant heat rate times that day's gas and carbon cost (£24.37, the best of the three).
- Market benchmark
- The N2EX day-ahead auction price for the same half-hour, published by NESO: £11.90.
- Battery
- 1 MW / 2 MWh, price-taking, 85% round-trip efficiency, at most two cycles a day, £2/MWh throughput cost. Scheduled on the forecast, settled at the actual price. Capture is profit as a share of perfect foresight over the same 366 days.
Tools
- Python
- FastAPI
- DuckDB
- React
- Elexon API
- Machine learning