Skip to main content
None of the following is guessed into final behaviour. Each item is configurable or isolated behind an adapter, and marked TODO(confirm...) at the exact spot in the code. Do not go live before closing every item.
The Engrate integration itself is implemented against the documented Engrate Schedule Management API (endpoint, auth, payload shape, units, one-call-per-TSO are confirmed by their docs) — the remaining points are market-setup data and conventions:
The party EICs of our four balancing groups are placeholders in config.py (AREA_MARKET_IDS). Set the real codes before any live submission — Engrate validates EICs.
50HERTZ_DE_TSO / receiver 10XDE-VE-TRANSMK are taken from Engrate’s documentation. The identifiers for Amprion, TenneT and TransnetBW follow the same pattern but must be verified against Engrate’s console or support.
Two open points: the ECC counterparty party EIC (EXCHANGE_COUNTERPARTY_EIC, unset by default), and whether the leg must be submitted at all or is auto-nominated by ECC (INCLUDE_EXCHANGE_LEG flag). The balance computation always accounts for the delivery either way.
Engrate’s production/consumption series carry the same out_party/in_party/out_area/in_area structure as trades. The service currently fills all four with our own balancing group and area; confirm this layout with Engrate.
Does the customer deliver per control area or per market location (MaLo)? Both are supported: series tagged with control_area, or tagged with malo plus a malo_mapping table in the request. If MaLo-tagged input becomes the norm, the mapping should move to configuration.
Which balancing group receives the ECC delivery is HOME_CONTROL_AREA config. The default TenneT is a placeholder, not a decision.
Confirmed by the trader’s mail and template: filename <YYYYMMDD>_EPEX_DAA.csv in the EPEX_DAA folder, header UTC_TIMESTAMP;BUY_EPEX_DAA_MW;SELL_EPEX_DAA_MW, one row per Berlin quarter hour with the UTC interval-begin timestamp (DD.MM.YYYY HH:MM), comma decimals with exactly one place (0.1 MW grid). BUY carries the quantity to procure, SELL the surplus to sell; both ≥ 0,0 and at most one of the two > 0,0 per row — guaranteed by splitting the one signed open-position series, so surpluses are no longer clamped. Pinned byte-for-byte against the template in tests/test_adapters.py. Daily pickup 09:00 with deletion; the trader validates the contracted maximum daily volumes on their side and confirms or rejects per file by mail. The contract wants backup series ≥ 4 days ahead (FORECAST_HORIZON_DAYS, orchestrator auto-generation).

Out of scope (this version)

Settlement / MaBiS, intraday trading, actual trade execution, forecasting itself (the customer provides the forecast) and REMIT reporting. The domain/adapter split is designed so these can be added without reworking the core.