BESS Bench

Day-ahead arbitrage backtesting · Swedish bidding zones

Nord Pool spot prices 2023–2025 · SE3 / SE4

Configure a battery and run a backtest.
Model and assumptions

Each day is solved as an independent linear program with perfect foresight of that day's prices: maximize Σ pᵢ · (dᵢ − cᵢ) · Δtᵢ over charge/discharge power per settlement period, subject to the power rating, the SoC window, and SoC dynamics. The round-trip efficiency is split symmetrically (√η per direction). The state of charge carries over between days (day 1 starts at min SoC), so the backtest is one continuous simulation.

Assumptions: price-taker (dispatch does not move the market), no degradation cost, no grid fees or taxes, no trading fees, day-ahead market only. Perfect foresight makes this an upper bound on day-ahead arbitrage revenue — a real forecast-driven strategy captures 70–90% of it. A tiny tie-break penalty (0.01 SEK/MWh) keeps the solver from charging and discharging in the same period when indifferent.

KPI definitions

Total revenue — Σ price × (discharge − charge) × period length, grid-side, SEK.
Revenue per installed MWh — total revenue ÷ nameplate energy capacity.
Equivalent full cycles — grid-side discharged energy ÷ nameplate capacity.
Average daily revenue — total revenue ÷ days in range.

Data

Nord Pool day-ahead auction prices for SE3 and SE4, 2023-01-01 to 2025-12-31, in SEK/MWh (converted at daily ECB rates). Hourly resolution until 2025-09-30, 15-minute periods from 2025-10-01 when the single day-ahead coupling moved to 15-minute MTU; DST days have 23/25 hours. Prices are cached as static JSON and loaded lazily per month; the cache is built from Nord Pool data via elprisetjustnu.se, with an ENTSO-E Transparency (document A44) fetch mode included for regeneration against the primary source.