ED.CURTAIL.ECON
Strict OMIE-based economic curtailment for must-run renewables (solar/wind/vre).
Signature
ED.CURTAIL.ECON([tech], [start], [end], [agg], [zone], [headers])Description
Strict economic curtailment derived from OMIE day-ahead bid curves. For each hourly slot the marginal clearing price is MAX(price WHERE side='V', status='C') — any sell bid offered at or below that price would have cleared at the marginal, but didn't for non-economic reasons (capacity withheld, bid-curve detail, RRTT pre-emption). The function returns:
- mwh_eligible = Σ(qty × granularity_min/60) for side='V', status='O', price ≤ slot_marginal_price, by tech via uof_tech_map.
- mwh_cleared = Σ(qty × granularity_min/60) for side='V', status='C', by tech via uof_tech_map.
- mwh_curtailed = mwh_eligible − mwh_cleared (per-bucket; always ≥ 0 by construction, no clamping needed).
- marginal_eur_mwh_avg = AVG of the per-slot marginal price across the bucket. **Slot-weighted**: one entry per slot (averaged over slots with mwh_eligible > 0), not row-weighted — so a slot with many bids counts once.
- n_slots = number of distinct slots that contributed.
**Why renewables-only**: flexible techs (thermal_gas, nuclear, hydro, coal, cogen, bombeo, bess) safety-bid large fractions of their volume near the OMIE price-cap. Their unmatched offered reflects strategic bidding, not curtailment in the APPA sense. They return 400 with an explanatory message.
**vre expansion** = solar + wind + renewable_other + vre_unspecified — the Régimen Especial aggregator UOFs in OMIE.
**Interconnects excluded**: MIEU/MIP/MIE appear only as status='C' (no offered counterpart) and are excluded from both eligible and cleared volumes.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
| tech | string | "vre" | Must-run renewable: "solar", "wind", or "vre" (default; = solar+wind+renewable_other+vre_unspecified). Flexible thermal/nuclear/hydro/coal/cogen/bombeo/bess return 400 — see ED.OMIE.BIDS (upcoming) for raw data on those. |
| start | date | — | YYYY-MM-DD. Omit for end − 1 year. |
| end | date | — | YYYY-MM-DD. Omit for the first day after the last available month (OMIE publishes monthly with ~90-day lag). |
| agg | 1..7 | 6 | 1=hourly, 2=daily, 3=monthly, 4=quarterly, 5=semiannual, 6=annual (default), 7=total. String aliases H/D/M/Q/S/Y/T also accepted. |
| zone | "es" | "pt" | "iberian" | "es" | Geographic filter. es → pais IN ('ES','MI') (default), pt → pais IN ('PT','MI'), iberian → pais IN ('ES','PT','MI') (includes the MIBEL pais='MI' bucket). |
| headers | 0 | 1 | 0 | Set 1 for a header row. |
Valid values for `tech`
| Code | Description |
|---|---|
| solar | Solar PV only. Filters uof_tech_map.tech = 'solar'. |
| wind | Wind only. Filters uof_tech_map.tech = 'wind'. |
| vre | Combined must-run renewables. Filters uof_tech_map.tech IN ('solar','wind','renewable_other','vre_unspecified') — covers the Régimen Especial aggregator UOFs in OMIE. |
Returns
Spill matrix — 7 columns: [bucket, tech, mwh_eligible, mwh_cleared, mwh_curtailed, marginal_eur_mwh_avg, n_slots]. One row per (bucket, tech) pair. For agg="T" bucket is the literal string "TOTAL".
Examples
=ED.CURTAIL.ECON()— Last 12 months VRE curtailment ES, yearly (all defaults)=ED.CURTAIL.ECON("solar", "2024-01-01", "2024-12-31", 3)— Monthly solar curtailment 2024 ES=ED.CURTAIL.ECON("wind", , , 6)— Yearly wind curtailment ES last 12 months=ED.CURTAIL.ECON("vre", "2020-01-01", "2025-12-31", 6, "iberian")— Yearly VRE curtailment Iberian Peninsula 2020-2025=ED.CURTAIL.ECON("vre", "2025-01-01", "2025-12-31", 3, "es", 1)— Monthly VRE 2025 ES with header rowNotes
- **Strict per-slot construction**: only offers at or below the slot clearing price count as 'eligible to clear'. This avoids double-counting strategic high-priced bids (which would never have cleared) as curtailment. The discovery + derivation is documented in
agent-history/memory/knowledge/omie-bid-curves-discovery.md. - **Publication lag**: OMIE publishes monthly bid-curve data with ~90-day confidentiality lag. Queries for too-recent dates return 404 with the last-available month in the body (
last_available_mes). - **Restricted to must-run renewables**: tech values
thermal_gas,nuclear,hydro,coal,cogen,biomass,bombeo,bess,allreturn 400. Their unmatched offered reflects strategic bidding (safety bids near price-cap), not economic curtailment. For raw offer/cleared data across all techs, seeED.OMIE.BIDS. - **Interconnects excluded**: MIEU/MIP/MIE appear only as
status='C'(no offered counterpart) in OMIE data and are excluded from both eligible and cleared volumes. - **Slots without cleared rows are skipped**: when no
status='C'exists for a slot, no marginal price can be derived; that slot contributes nothing tomwh_eligibleormwh_cleared. This is conservative — typical days have continuous clearing. - **
vreexpansion** = solar + wind + renewable_other + vre_unspecified (the Régimen Especial aggregator UOFs in OMIE —vre_unspecifiedis the bulk of pre-classification rows). - **Cross-validation against ESIOS 10462** (
curtailment_pct) does NOT apply — that indicator measures technical curtailment by RRTT, semantically different. Comparison would mislead.