Beta — Data under validation. Values may contain errors.

ED.UNIT.RANGE

Generation time series for one production unit — average power (MW) or total energy (MWh).

Generation

Signature

ED.UNIT.RANGE(up, [start], [end], [agg], [headers], [noDate], [unit])

Description

Time series of generation for a single production unit. ENTSO-E A73 publishes at native 15-min cadence. Aggregation is controlled by agg: 0=native, 5min/10min/15min, 1=hourly, 2=daily (default), 3=monthly, 4=quarterly, 5=semiannual, 6=annual, 7=total. agg=0/RAW returns the real 15-min grid (96 slots a day, reconstructed from the run-length document) and agg=7/T returns a single total value — same semantics as ED.RANGE.

**Unit (unit parameter):** by default each bucket holds the mean power in MW over the bucket, weighted by how long each published value was in force. That is the right number for capacity-factor and dispatch analysis but it is NOT the energy generated — "annual generation 800 MW" does not mean 800 MWh, it means 800 MW × 8760 h ≈ 7 TWh. Pass unit="MWh" for the energy delivered in each bucket: the integral of the same curve, so it agrees with the MW figure by construction. The unit_generation table is 100% MW-stored, so unit="MWh" always works — there is no already-MWh edge case (unlike prices or pre-MWh metrics in ED.RANGE).

**How the 15-min data is read (important).** ENTSO-E publishes A73 with curveType A03 — run-length encoded. A position missing from the document means *"the same value as the previous point"*, not zero and not "no data": a plant sitting at 985 MW all day may publish two points, not 96. EnergyData stores the document exactly as published and expands it at read time — every point is weighted by how long it was in force, so MW and MWh are two views of the same curve and can no longer contradict each other. Averaging the stored points as if they were equal samples over-reports MW by up to +777 % on a CCGT; the older per-hour-average-then-sum route under-reported MWh by up to 74 % because it dropped hours that published no point. If you pull per-plant data from another provider, check which of the three you get.

**coverage_pct.** The REST response carries a coverage_pct (0-1) for the whole window plus a coverage array per bucket: the share of each period actually backed by published data. A value is carried forward only to the end of its own UTC day's publication — never across midnight, never backwards, never past the point where that day's data stops — so an ingest gap stays a gap with a low coverage_pct instead of turning into a plausible-looking number, and a bucket with nothing behind it is omitted rather than filled. Expect 1.000 for recent data; about 0.958 between 2025-05-31 and 2026-04-12 (hour 23 UTC was not collected) and about 0.240 before 2025-05-31 (an upstream resolution bug compressed each day into its first ~6 hours). Windows spanning those periods are still affected — coverage_pct is how you spot it.

**Calendar-bucket edge.** With agg=2/D and coarser, a value in force across civil midnight is credited entirely to the bucket it started in (about 1 % of intervals). It is immaterial for plants that run around the clock and visible only for units that switch off overnight; agg=1/H and agg=0/RAW are unaffected. If you need calendar-day energy at settlement precision, aggregate the hourly series yourself.

A window with no data returns #N/A, never 0: a zero here would read as "the plant produced nothing", which is a different — and false — statement.

Parameters

NameTypeDefaultDescription
up*string—Unit code (e.g. ALZ1).
startdate—Start. Defaults: omit end for today (Madrid, with a small overnight cutoff), omit start for 30 days before end.
enddate—End. Omit for today.
agg0-7 | string2 (daily)Aggregation is controlled by agg: 0=native, 5min/10min/15min, 1=hourly, 2=daily (default), 3=monthly, 4=quarterly, 5=semiannual, 6=annual, 7=total. 0/RAW returns the real 15-min grid, reconstructed from the run-length document (with unit="MWh" it returns the hourly MWh series — the smallest meaningful energy bucket); 7/T returns a single total value instead of a spill, or #N/A if the window holds no data.
headers0 | 10Set 1 for header row.
noDate0 | 10Set 1 to omit the period column.
unit"MW" | "MWh""MW"Output unit. "MW" returns the duration-weighted mean power in each bucket (default). "MWh" returns the energy delivered in each bucket — the integral of that same curve.

* Required.

Returns

Spill array — [period, value] rows (agg=7/T returns a single value, or #N/A if the window holds no data). Buckets with no data behind them are omitted rather than returned as 0. Value unit depends on unit (MW or MWh).

Examples

=ED.UNIT.RANGE("VAL2", "2025-01-01",, 3)— Vandellós II monthly average power (MW)
=ED.UNIT.RANGE("ALZ1", "2025-07-01", "2025-07-01", 1)— Almaraz I hourly for one day (MW)
=ED.UNIT.RANGE("ALZ1", "2025-07-01", "2025-07-01", 0)— Almaraz I 15-min grid for one day (96 rows in MW, run-length expanded)
=ED.UNIT.RANGE("BES5", "2020-01-01",, 6, 1)— Beselga 5 annual with headers (MW)
=ED.UNIT.RANGE("VAN2", "2025-01-01",, 6, , , "MWh")— Vandellós II annual energy delivered (MWh)
=ED.UNIT.RANGE("ALZ1", "2025-01-01", "2025-12-31", 3, , , "MWh")— Almaraz I monthly energy 2025 (MWh)
=ED.UNIT.RANGE("ALZ1", "2025-01-01", "2025-12-31", 7, , , "MWh")— Almaraz I total 2025 generation (MWh) — single value, no spill

Notes

  • **One plant, several identifiers.** A unit can report under more than one ENTSO-E identifier at once, and only some of those are separate meters. Turbines of a combined cycle (…TG1, …TG2, …TV) are separate meters and are added together, so you get the plant's output rather than one turbine's. Two cases are not: a plant-level identifier published alongside its own turbines (it repeats one turbine's readings), and the same identifier spelled two ways (they agree on every shared reading). Until 2026-09-11 those were added up as well, which double-counted them: on 2026-05-17 Almaraz I — a ~1 000 MW reactor — read 1 817.64 MW. They are now counted once, in every aggregation — daily and coarser, hourly, and the raw 15-minute grid all give the same answer. Measured over the whole history, this affects 489 of 162 180 unit-days and moves 55 of the 409 rows behind ED.UPS, almost all by well under 1 %.
  • MW and MWh are two views of one curve: MW is Σ(value × time in force) ÷ Σ(time in force), MWh is Σ(value × time in force) ÷ 3600. They agree by construction — before this they could differ by ×2 to ×8 on the same series.
  • The unit_generation table is 100% MW-stored, so unit="MWh" always works — no 400 error like for prices (EUR/MWh) or pre-MWh metrics in ED.RANGE.
  • With agg=0/RAW and unit="MWh" the route returns the hourly MWh series rather than per-15-min energy (mirrors ED.RANGE: per-sample energy deltas add cost without analytical gain).
  • Several ENTSO-E EICs can map to one up_code. Sub-units that publish **at the same time** (some combined cycles report one EIC per turbine) are **added together**, so the plant reads as the plant. EICs that simply **replace one another** over time — from one day to the next or within the same day — are stitched into a single timeline and averaged over it, so a hand-over does not halve the value.
  • The underlying REST endpoint (/api/data/unit/range) also accepts tz= (madrid default / cet / utc) with the same semantics as /api/data/range, and returns coverage_pct plus a per-bucket coverage array; the Excel function does not expose a tz argument yet.

Related functions