Independent project / Updated October 2026
GridShift.
A decision behind the dashboard.
What could a different operating schedule have changed in electricity cost, for exactly the same energy consumption?
Explore historical prices refreshed daily through GitHub Actions. The app shows the latest validated retrieval, coverage and refresh status. The full PostgreSQL, dbt and Prefect pipeline runs locally.
The operating question
A flexible piece of equipment needs to run continuously within an allowed daily window. GridShift compares its baseline start with the lowest-cost feasible historical schedule.
The analytical choices
- Hold energy consumption constant so the comparison isolates timing.
- Calculate costs from interval overlap, including negative prices and partial hours.
- Require complete price coverage across the allowed operating window.
- Use UTC for arithmetic and Berlin time for operating inputs, accounting for daylight saving.
The example on this page
Change the equipment power and baseline start. This simplified illustration uses twelve synthetic hourly prices and a fixed four-hour run. At 100 kW, starting at 06:00 costs €50; starting at 08:00 costs €20. Both consume 400 kWh.
The full application evaluates starts every 15 minutes against ingested historical data. This embedded example demonstrates the calculation; it is not connected to the live pipeline.
Same energy. Better timing.
Move a four-hour run within 06:00–18:00.
Same 400 kWh · Continuous four-hour operation
Synthetic prices for illustration. Wholesale energy only; fees and taxes excluded. This example is not a live market feed.
Daily cloud refresh
A separate GitHub Actions workflow is scheduled for 07:17 UTC each day. It fetches the latest seven complete UTC days and validates timestamps, price units, finite values and uninterrupted coverage before publishing a snapshot to the private repository.
Streamlit reads the validated snapshot without connecting to a database or fetching prices during a visitor’s session. The rolling seven-day dataset updates independently of the local PostgreSQL database.
When a refresh fails
Prices and their checksum manifest are published together. Failed retrievals or validation checks preserve the last good dataset, while the dashboard displays the latest recorded attempt and warns when data becomes stale.
The data reliability panel shows retrieval time, coverage and validation results. These are Python snapshot checks; the dbt models and Prefect scheduler belong to the full local pipeline. Scheduled updates can be delayed, so the displayed timestamps show what data is actually available.
The full local pipeline
Python retrieves Energy-Charts prices and archives the original response. PostgreSQL stores validated intervals. dbt builds and checks the analytical models before a transaction publishes the new snapshot.
Prefect schedules refreshes. A failed validation leaves the previous published data intact, while the dashboard makes freshness and coverage visible.
What has been verified
Automated checks cover repeatable loads, source revisions, failed-publication recovery, known cost examples, missing intervals, negative prices, daylight-saving days and UI recalculation.
Cloud refresh checks cover invalid source data, network errors and interrupted writes, confirming that the previous validated snapshot stays intact. Interaction tests cover changes to dates, power, duration and operating hours in both dashboard versions. Generation and demand analysis remain future work.
Request a source walkthrough