This repo pulls GB half-hourly imbalance system prices from the Elexon BMRS Insights API, builds a short-horizon nowcast, then converts that signal into charge and discharge decisions for a SOC-limited battery. It backtests the dispatch and reports £ PnL.
The aim is to show an end-to-end workflow you would use in energy analysis: data access, clean time indexing, forecasting, decision rules, constraint-aware simulation, clear outputs.
| Notebook | What it does |
|---|---|
notebooks/01_pull_system_prices.ipynb |
Pulls one settlement date, builds timestamps, writes the raw day file to data/raw/ as a sanity check |
notebooks/02_build_price_history.ipynb |
Pulls a date range, caches each day to data/raw/, builds data/processed/prices.parquet |
notebooks/03_baseline_forecast.ipynb |
Creates lag and calendar features, runs a lag-48 baseline (yesterday same settlement period), reports MAE |
notebooks/04_train_model.ipynb |
Trains a gradient-boosted model with time-series cross-validation, compares MAE vs baseline, saves preds.parquet |
notebooks/05_backtest.ipynb |
Turns predictions into a dispatch signal using rolling quantiles, simulates SOC and efficiency, reports PnL and plots |
- Source: Elexon BMRS Insights API
- Frequency: half-hour settlement periods
- Series: uses the system price series returned by the Insights endpoint
If you want SBP and SSP explicitly, swap the endpoint and widen the pull.
- Baseline: lag-48
- Model:
HistGradientBoostingRegressor - Validation: 5-fold time split
Battery assumptions:
- 1 MW / 2 MWh battery
- 90% round-trip efficiency
- Signal: charge, discharge, hold based on rolling quantiles of recent predicted prices
- Constraints: SOC limited, no simultaneous charge and discharge
- Baseline MAE: 40.56 £/MWh
- Model MAE (5-fold time split): 24.92 £/MWh
- Total PnL: £12,526.36
- Charge periods: 354
- Discharge periods: 279
This is a simplified backtest intended to demonstrate workflow and reasoning. It ignores transaction costs, bid/offer spreads, imperfect fills, stacking across multiple markets, site constraints, network constraints.
- Add transaction costs, bid/offer, execution rules, then re-run sensitivities
- Extend to multi-market stacking (for example DA, intraday, balancing) with one consistent constraint set
- Build a half-hourly forward curve shaping module: start from monthly and quarterly prices, apply profile factors (seasonality, day-of-week, peak/off-peak), document monthly and quarterly shape updates
- Add risk outputs that match procurement decisions: scenario PnL, drawdowns, stress periods, hedge effectiveness