The steps
Ingest — POST /v1/forecasts (external)
Accepts production/consumption series per control area — or per market
location (MaLo) with a malo_mapping table. Validation:
- correct interval count for the delivery day (96/92/100, DST-aware),
- every series complete (no gaps — a short series is rejected),
- only active control areas (
ACTIVE_CONTROL_AREAS); a subset is fine, missing areas are treated as zero.
Aggregate — POST /v1/process/delivery-days/{day}/aggregate
Pure functions compute net, open_position and total_open
(algorithm) and persist them.
Publish — POST /v1/process/delivery-days/{day}/publish-open-position
The total open position is rendered as a CSV and written to the trader’s
sFTP drop directory (atomically: temp name, then rename). This is the volume
the trader executes on the EPEX day-ahead auction.
Submit — POST /v1/process/delivery-days/{day}/submit-schedules
Builds one schedule per balancing group — production forecast, consumption
forecast, and all trades aggregated per direction and counterparty — and
submits them to Engrate, one call per TSO per delivery date
(per Engrate’s API model). The executed EPEX volume can be injected in the
request body; it defaults to the requested open position.
Orchestrate — POST /v1/process/orchestrate
Called regularly by a timer (a Container Apps cron job in Azure). For every
known delivery day that is not in the past, it compares the current input
hash with the hash each step last ran on, and re-runs exactly the stale
steps in order. No change → no action; the call is idempotent and cheap,
so a tight schedule is fine.
State machine per delivery day
Everything lives in the audit trail (state.json per day):
A step is stale iff its hash differs from
input_hash. Manual step calls
update the same state, so manual and orchestrated operation mix safely.