Day-Ahead Energy Price Forecasting

HealtheGrid

Forecasting tomorrow's electricity prices in DE-LU and ES — with calibrated uncertainty, so the operators on the other side of the bar chart actually trust the number.

Pinball Loss · q 0.45 95% Coverage 150  Features 3  GBM Ensemble
Why the name

A grid in treatment.

European day-ahead markets aren't broken — but they're stressed. Negative midday prices in Iberia, evening spikes north of €400/MWh in Germany, fuel shocks, congested cross-border flows. Better forecasts are the diagnostic that lets operators, traders and storage assets stabilise the system instead of reacting to it.

— 01

The grid has symptoms

Spikes, troughs, negative prices, congestion. Symptoms of a system absorbing renewables faster than it can balance them.

— 02

Forecasts are the diagnostic

Day-ahead price expectations are the signal every other actor — storage, demand response, generation — conditions on.

— 03

Calibrated uncertainty heals

Point predictions are easy. Honest 95% intervals are what let an operator commit capital with confidence.

— 04

Two zones, one prescription

Same model family, separately tuned for DE-LU and ES — two patients, two treatment plans.

Two bidding zones

Same continent, completely different patients.

DE-LU and ES share an evaluation window and almost nothing else. Different fuel mix, different generation curves, different price regimes — so each gets its own model.

Zone · DE-LU

Gas-coupled.
Volatile. Winter-peaking.

Marginal cost is set by gas turbines on demand peaks. Spreads of €400+/MWh inside a single day are routine.

~85k
MW peak load
€400+
Daily spread
Gas
Marginal fuel
Zone · ES

Solar-saturated.
Often negative at midday.

A textbook duck-curve, deep enough that 2025 saw zero-or-negative prices on most weekday middays.

~46k
MW peak load
~30%
Solar share
Solar
Marginal fuel
Inputs

Where the signal comes from.

Four upstream feeds — each driving a different part of the price curve.

Day-Ahead Spot
Energy-Charts API · hourly
Weather
Open-Meteo · 13 vars
Fuel & Carbon
TTF · EUA · Brent
ENTSO-E Transparency
Load forecast · wind & solar D‑1
Feature engineering

150 features, two clear winners.

Spark spread lags + short-horizon price lags do most of the work — with ENTSO-E D‑1 load & renewable signals providing the broader system picture.

150  total features Price lags · 1h → 504h Rolling stats · 24h / 7d Marginal cost proxies ENTSO-E D‑1 signals Cyclical calendar
DE-LU · top features
p50 model · gain
spark_spread
38%
price_lag_1h
12%
price_diff_1h
7%
price_pct_change_1h
5%
residual_load_mw
4%
gas_marginal_cost
4%
total_flexible_mw
4%
ES · top features
p50 model · gain
spark_spread
52%
price_lag_1h
19%
price_pct_change_1h
7%
price_diff_1h
6%
gas_marginal_cost
4%
price_rolling_max_6h
3%
price_lag_24h
3%
Modelling

Three quantile boosters, averaged & calibrated.

Each model trains independent quantile heads. The simple average is then post-hoc calibrated to a 95% prediction interval.

Training Data · 2024 — 2026
LightGBM
quantile
XGBoost
quantile
CatBoost
Quantile:alpha
SIMPLE AVERAGE · 3 MODELS
INTERVAL CALIBRATION → 95% COVERAGE
Submission · CSV

Optuna · 50 trials per zone, tuned directly on the contest's pinball loss — no proxy objective.

π

Side note: the loss is asymmetric (q=0.45), so we submit p45 in the p50 column — theoretically optimal under the metric.

What didn't work

The honest part.

Three things that broke — and what we did about them.

Recursive forecast gap

At inference, lag_1h is a prediction, not an observation — errors compound.

FixTrain on simulated recursive features.

Fuel-price APIs broken

Public APIs carry ~90 days of futures; we needed two years of TTF, EUA and Brent.

FixBackfill from monthly averages + interpolation.

Spark spread leakage

spark_spread = price − gas_cost contains the target at training time — a subtle look-ahead.

FixAt inference, use the 7-day lag as a stale-but-valid proxy for weekly-seasonal patterns.
Validation · last 7 days

Results.

95% interval coverage in both zones — ES is an order of magnitude tighter than DE-LU.

DE-LU · gas-coupled
Pinball Loss · q 0.45
0.00
EUR/MWh
MAE8.1
RMSE42.15
Coverage95%
ES · solar-saturated
Pinball Loss · q 0.45
0.00
EUR/MWh
MAE0.38
RMSE0.65
Coverage95%
ES is cleaner — solar dynamics are more predictable. DE-LU's pinball is carried by a single rare spike day.
95% Coverage · Both Zones
Ensemble validation, last 7 days, DE-LU and ES
— Actual — Ensemble p45 — 95% CI band

ENTSO-E D‑1 load forecasts and renewable generation signals are live in the pipeline
the same API that the market makers watch.
Next: cross-border flow constraints to model congestion-driven price spikes.

CodePipelineModelsFully reproducible