The system receives electricity prices, demand forecasts, asset constraints, and intraday updates, then creates a cost-minimizing energy schedule.
- Backend: Python, FastAPI
- Optimization: Google OR-Tools
- Database: PostgreSQL
- Event streaming: Apache Kafka
- Frontend: React, Vite, Recharts
- Local deployment: Docker Compose
The ingestion service accepts and validates input data:
- hourly electricity prices
- demand forecasts
- energy asset constraints
- intraday demand updates
The optimization service builds a 24-hour day-ahead schedule. It decides how much energy should come from:
- grid electricity
- gas
- battery discharge
It also decides when the battery should be charged. The objective is to minimize total energy cost while satisfying demand and respecting operational constraints.
Main constraints:
- demand must be covered every hour
- battery state of charge must stay between 0 and capacity
- max charge and discharge limits must be respected
- gas output must not exceed its maximum capacity
- the battery cannot charge and discharge at the same time
The intraday service simulates real-time correction during the operating day. It receives updated actual demand, compares it with the day-ahead schedule, calculates the deviation, and creates a corrective action.
The service stores intraday actions in PostgreSQL and publishes them to Kafka.
The React dashboard displays:
- input data
- day-ahead schedule
- battery state of charge
- intraday corrections
- test scenario results
price_signalsdemand_forecastsecs_scheduleintraday_updatesintraday_actions
POST /pricesPOST /forecastPOST /assetsPOST /intradayGET /pricesGET /forecastGET /assetsGET /intradayGET /health
POST /optimize/day-aheadGET /schedule/{date}GET /health
POST /optimize/intradayGET /intraday/actions/{date}GET /health
pricesdemand_forecastsenergy_assetsday_ahead_schedulesintraday_actionssimulation_runstest_results
Create a local environment file:
cp .env.example .env