Skip to content

Introduction

BESS Engine is a trading simulation engine for Battery Energy Storage Systems (BESS) on Dutch electricity markets. It optimizes charge and discharge decisions across multiple markets to maximize revenue over a project's lifetime.

What It Does

Given a battery configuration and market price data, BESS Engine determines the optimal trading schedule — when to charge, when to discharge, and how much capacity to reserve for ancillary services. It accounts for battery physics, grid constraints, degradation over time, and co-located solar or wind generation.

The engine produces detailed financial projections including NPV, IRR, and ROI across multi-year project lifetimes.

Simulation Flow

1
API Request
2
Data Loading
3
Initialization
4
Optimization
5
Degradation
6
Output
Hover or click a step to see details

Key Concepts

Simulation

A simulation takes two inputs:

  • Parameters (params) — the physical and economic description of the project: battery size, grid connection, solar/wind capacity, costs, and financial assumptions.
  • Run configuration (run) — how to run the simulation: which strategy to use, which markets to trade on, how far ahead to look, and which price scenario to use.

The engine returns a financial summary, operational statistics, and optionally a 15-minute resolution timeseries of all trading decisions.

Scenarios

A scenario is a collection of market price data — day-ahead prices, intraday prices, imbalance prices, aFRR capacity prices, and FCR prices. Scenarios are stored in the database and can be uploaded from CSV files or ZIP archives.

Each scenario corresponds to a specific country and time period (e.g., "Netherlands 2024"). Multiple simulations can run against the same scenario with different battery configurations.

Profiles

A profile is a solar or wind production timeseries at 15-minute resolution. Profiles can be:

  • Generated from ERA5 weather data by specifying location, panel/turbine type, and capacity
  • Uploaded from CSV files with timestamp and output columns

Profiles are referenced by UUID and stored in per-profile SQLite databases.

Markets

The engine supports five electricity markets split into two categories:

MarketTypeRevenue Source
Day-AheadEnergyBuy low, sell high on hourly auction prices
IntradayEnergyTrade on continuous intraday market prices
ImbalanceEnergyEarn from real-time system balancing
aFRRCapacity + EnergyReserve capacity for automatic frequency restoration
FCRCapacityReserve capacity for primary frequency containment

See Markets for detailed descriptions.

Optimization Strategies

Three strategies are available:

StrategySpeedAccuracyUse Case
rolling_lp~2-5s/yearHighProduction simulations
lp~5-15s/yearOptimalBenchmarking (perfect foresight)
greedy_multimarket<1s/yearLowerQuick estimates

The default rolling_lp strategy solves a linear program over a rolling window, executing near-term decisions before re-optimizing with updated battery state.

Architecture Overview

For the full technical architecture, see Architecture.