Persistent storage for energy portfolios — assets, grid topology, and bitemporal time series, in one connected database.
EnergyDB is a database for energy portfolios. It stores three things together in one connected system:
| Layer | Description | Real-World Example |
|---|---|---|
| 🌳 Asset hierarchy | Arbitrary-depth tree of portfolios, sites, and assets | "Offshore-1 → WindTurbine T01 → power" |
| 🔗 Grid topology | Typed edges (lines, transformers, pipes, interconnections) connecting any two assets | "Cable-1: BusA → BusB" |
| ⏱️ Bitemporal time series | Actuals and versioned forecasts attached to any node or edge, queryable as-of any point in time | "power_flow on Cable-1, valid Wed 12:00, known Mon 18:00" |
Structure lives in PostgreSQL, values live in ClickHouse, and stable UUID identity lets Python objects round-trip to the database without losing any structural state. (A separate change_time audit field tracks corrections without polluting the bitemporal model.)
EnergyDB extends TimeDB with persistent storage for EnergyDataModel hierarchies.
Most time-series systems are agnostic about what their series represent — they treat data as opaque (series_id, timestamp, value) triples. EnergyDB knows it is a portfolio, and links every series back to the asset or grid edge it describes.
- 🔁 Round-trip persistence: Every
Elementkeeps its UUID7 from in-memory object to row primary key — renames, moves, and property edits become silentUPDATEs, never delete-then-insert. - 📋 Diffable structural changes:
dry_run=Truepreviews every insert, rename, move, and delete before you apply — no surprise data loss onreplace_subtree. - ⏱️ Bitemporal queries: Forecast revisions, corrections, and time-of-knowledge backtests, powered by TimeDB.
- 🧭 Lazy fluent navigation:
client.get_node("Portfolio", "Site", "T01").read(...)resolves to one indexed SQL query, regardless of subtree size. - ⚖️ Unit conversion at the boundary: Declare canonical units once; pint rescales every read and write automatically.
pip install energydbRequires Python 3.12+, PostgreSQL (asset hierarchy + series catalog), and ClickHouse (time-series values).
from datetime import UTC, datetime
import energydb as edb
import pandas as pd
client = edb.Client() # reads TIMEDB_PG_DSN / TIMEDB_CH_URL from env
client.create() # PostgreSQL schema + ClickHouse series_values table
# 1. Declare a turbine and the series it will hold (metadata only).
t01 = edb.wind.WindTurbine(
name="T01", lat=55.01, lon=3.02, capacity=3.5, hub_height=80,
timeseries=[
edb.TimeSeries(name="power", unit="MW",
data_type=edb.DataType.ACTUAL),
],
)
# 2. Wrap it in a site and a portfolio.
site = edb.Site(name="Offshore-1", lat=55.0, lon=3.0, members=[t01])
portfolio = edb.Portfolio(name="my-portfolio", members=[site])
# 3. Persist structure (nodes, edges, series declarations). Idempotent.
client.register_tree(portfolio)
# 4. Write a day of hourly values for the turbine's power series.
start = datetime(2026, 1, 1, tzinfo=UTC)
df = pd.DataFrame({
"valid_time": pd.date_range(start, periods=24, freq="1h", tz="UTC"),
"value": [2.5 + 0.05 * i for i in range(24)],
})
client.get_node("my-portfolio", "Offshore-1", "T01").write(
df, name="power", data_type="actual",
)
# 5. Read back — single asset, or across the whole portfolio.
client.get_node("my-portfolio", "Offshore-1", "T01").read(name="power", data_type="actual")
client.get_node("my-portfolio").read(name="power", data_type="actual")
# 6. Reconstruct the full EDM tree from the database.
tree = client.get_tree("my-portfolio", include_series=True)Want to try EnergyDB without a local setup? Open our Quickstart in Colab — the first cell automatically installs PostgreSQL + ClickHouse inside the VM.
Note: Data persists only within the active Colab session. Additional notebooks are available in the
examples/directory.
- 📖 Official Documentation
- ⚙️ Installation Guide
- 🐍 Python SDK Documentation
- 🌐 Reference
- 💡 Examples & Notebooks
| Project | Description |
|---|---|
| TimeDB | Bitemporal time-series database with auditability and overlapping-forecast support |
| TimeDataModel | Pythonic data model for time series |
| EnergyDataModel | Data model for energy assets (solar, wind, battery, grid, ...) |
Contributions are welcome! If you're interested in improving EnergyDB, please see our Development Guide for local setup instructions.
Licensed under the Apache-2.0 License.
Find a bug or have a feature request? Open an Issue.