Skip to content

yggdrasil.loki.entsoe

entsoe

ENTSO-E Transparency Platform — European power-market data as frames.

Loki's energy-data path: pull day-ahead prices, actual load, and generation for a European bidding zone from the ENTSO-E Transparency Platform <https://transparency.entsoe.eu>_ REST API and parse the publication XML straight into a tidy polars frame (one row per timestamp). Everything rides the project's own machinery — the request goes through :class:~yggdrasil.http_.HTTPSession, the frame is cached/stored through the io handlers (:class:~yggdrasil.io.holder.IO) by :class:~yggdrasil.loki.skills.EntsoeSkill.

The API is token-gated: set ENTSOE_API_TOKEN (or ENTSOE_SECURITY_TOKEN) to the free security token from your Transparency Platform account. Bidding zones are addressed by their EIC code; common zones have short aliases (DE_LU, FR, NL …) and the full EIC registry is available through :mod:yggdrasil.enums.geozone.entsoe.

This module is pure + offline-friendly: :func:build_query and :func:parse_timeseries_xml never touch the network, so the parsing is unit tested against fixture XML; only :func:fetch_frame makes the call.

token

token() -> Optional[str]

The Transparency Platform security token, or None (offline-safe).

infer_query

infer_query(text: str) -> dict[str, str]

Infer {series, zone} from a free-text energy request (for NL routing).

Maps demand words → load, production words → generation, else day_ahead_prices; and a country/zone mention → its EIC alias (default DE_LU). Country names and zone aliases are matched on word boundaries so a 2-letter alias never matches a substring of an ordinary word.

resolve_zone

resolve_zone(zone: str) -> str

A zone alias or EIC → its 16-char EIC code.

Accepts a short alias ("DE_LU", case/sep-insensitive — "de-lu" works), or an EIC code passed straight through. Raises for an unknown alias.

build_query

build_query(
    series: str,
    zone: str,
    start: datetime | date | str,
    end: datetime | date | str,
    *,
    security_token: Optional[str] = None
) -> dict[str, str]

Build the Transparency Platform query params for series over a period.

series is a key of :data:DOCUMENT_TYPES ("day_ahead_prices" / "load" / "generation"); zone an alias or EIC. Pure — no network, no token required (pass security_token to embed one). The zone lands on the right parameter for the document type (both in/out for prices, the bidding-zone domain for load, the in-domain for generation).

parse_timeseries_xml

parse_timeseries_xml(xml: str) -> list[dict[str, Any]]

Parse an ENTSO-E publication document into tidy rows.

Returns one dict per point — {timestamp, value, unit, currency, resolution, position} — with the UTC timestamp reconstructed from each Period's interval start + (position-1) * resolution. Namespace-agnostic (the publication schema's namespace changes between document types/versions), and tolerant of the two value spellings — price.amount (prices) and quantity (load/generation). An Acknowledgement_MarketDocument (the API's "no matching data" reply) yields an empty list rather than raising.

to_frame

to_frame(xml: str, *, zone: Optional[str] = None, series: Optional[str] = None)

Parse a publication document into a polars frame (timestamp-sorted).

Columns: timestamp (UTC datetime), value (float), unit, currency — plus constant zone / series columns when provided, so multi-zone fetches concat into one tidy long frame.

fetch_frame

fetch_frame(
    series: str,
    zone: str,
    start: datetime | date | str,
    end: datetime | date | str,
    *,
    security_token: Optional[str] = None
)

Fetch series for zone over a period → a polars frame.

Rides :class:~yggdrasil.http_.HTTPSession (its pooling + retry). The token comes from the argument, else ENTSOE_API_TOKEN / ENTSOE_SECURITY_TOKEN; a missing token raises a clear :class:ValueError (the skill turns that into an offline-safe message) rather than calling without auth.