Between 1 October 2025 and 30 September 2026, the day-ahead electricity price in Spain was below zero in 2,803 fifteen-minute periods, which is 8.00% of the year. France followed with 2,200, Portugal with 2,186 and DE-LU with 2,052. IT-North had none. The deepest price was −€499.99/MWh in DE-LU on 1 May 2026 at 13:15, close to the auction's lower limit of −€500/MWh. This article explains how the market works, how the numbers were counted and what they do and do not tell us.

The step-by-step walkthrough with the code and every result is in the video: Watch on YouTube.

How electricity is traded

Electricity is traded on several levels. Producers and suppliers sign long-term contracts (forwards and futures) years, months or weeks ahead to fix a price early. On the day before delivery comes the day-ahead market (DAM), one auction for next-day electricity. On the day itself, intraday markets (auctions called IDA, and continuous trading) let traders correct their positions. Close to real time, grid operators buy flexibility in the balancing markets (FCR, aFRR and mFRR) to keep the system in balance. Each level has its own prices and rules. This article looks only at the day-ahead market.

How the day-ahead auction works

  • Offers and bids. Producers send offers: how much electricity they can deliver and at what minimum price. Buyers send bids: how much they want and at what maximum price. This is done for every period of the next day.
  • 15-minute periods. Since 1 October 2025 a period is 15 minutes, so a day has 96 periods. Before that date a period was one hour. Most of Europe is matched in one coupled auction that closes around midday on the day before; the results come shortly after.
  • Merit order and one price. Offers are sorted from the cheapest to the most expensive. Wind and solar cost almost nothing to run, so they offer first, then nuclear and hydro, coal, gas and finally peak units. Demand is added up until it is covered, and the offer that covers the last megawatt sets the clearing price. Every accepted seller in the zone is paid that price, and every accepted buyer pays it.
  • Bidding zones. The price is set per bidding zone, for example DE-LU, FR or IT-North. Neighbouring zones get the same price only when the border between them has spare capacity; when it is congested, the prices separate. In practice many borders are congested much of the time, so prices often differ.
  • What a negative price is. In a period with a negative price, sellers pay buyers to take the electricity. It happens when low demand meets offers that sit below zero. The auction has a lower limit of −€500/MWh, so prices cannot fall further.

The question and the data

The question is simple: in how many 15-minute periods was the day-ahead price below zero, in each bidding zone, over one year? The window is 1 October 2025 to 30 September 2026, starting on the day the 15-minute market began. One year has 365 days × 96 periods = 35,040 periods per zone. The prices come from the yearly files published by Energy-Charts (Fraunhofer ISE), based on ENTSO-E data. The analysis covers 25 main bidding zones; CH, which trades an hourly product, and the extra Italian sub-zones are left out.

Results

Negative day-ahead 15-minute periods, top 12 zones
Negative day-ahead 15-minute periods, top 12 zones
  • Spain had the most negative periods: 2,803 (8.00% of the year, on 119 different days).
  • France 2,200 (6.28%, 115 days), Portugal 2,186 (6.24%, 102 days) and DE-LU 2,052 (5.86%, 97 days).
  • Greece 1,831, NL 1,745, BE 1,344 and PL 1,225.
  • At the other end: LT 276, LV 255, NO2 248, EE 241 and RS 168. IT-North had no negative period.

All 25 zones:

ZoneNegative periods% of yearExactly 0Days with a negative priceDeepest price (date, time)Average negative priceLongest run (periods)
ES2,8038.00%1,457119-10.00 (29 Mar, 15:30)-1.0642
FR2,2006.28%1,111115-498.65 (1 May, 13:30)-12.2642
PT2,1866.24%1,421102-10.00 (29 Mar, 15:30)-1.0742
DE-LU2,0525.86%38697-499.99 (1 May, 13:15)-15.3280
GR1,8315.23%1,77694-50.00 (5 Apr, 13:00)-2.8139
NL1,7454.98%24291-499.62 (1 May, 13:30)-15.6843
BE1,3443.84%18375-499.29 (1 May, 13:30)-20.0143
PL1,2253.50%32582-490.00 (1 May, 12:45)-24.9644
CZ1,1533.29%17365-500.00 (1 May, 12:45)-24.0046
SK1,0883.11%18160-500.00 (26 Apr, 13:45)-24.8142
AT1,0142.89%17663-498.65 (1 May, 13:30)-26.0840
SI9482.71%15857-485.77 (1 May, 13:30)-26.3440
DK19392.68%24048-42.09 (24 May, 15:00)-4.2540
HU8942.55%26754-500.00 (26 Apr, 13:15)-33.6841
HR8802.51%17450-385.75 (1 May, 14:30)-23.6940
RO6871.96%50240-99.75 (26 Apr, 13:00)-9.7036
BG6091.74%51934-99.75 (26 Apr, 13:00)-8.4939
SE34971.42%10131-14.49 (24 May, 14:00)-1.4745
FI3801.08%25428-10.92 (24 May, 15:00)-0.6231
LT2760.79%10720-15.11 (24 May, 14:00)-1.5931
LV2550.73%11117-15.11 (24 May, 14:00)-1.5731
NO22480.71%1824-34.94 (13 Jun, 15:30)-3.4237
EE2410.69%15218-10.92 (24 May, 15:00)-0.7831
RS1680.48%7368-45.50 (7 Jun, 15:00)-5.4736
IT-North00.00%860——0

How often is not how deep

Average negative price
Average negative price

The number of negative periods says nothing about how deep the prices are. Spain has the most periods, but their average is only about −€1.06/MWh. DE-LU has fewer periods, but the average is −€15.32/MWh, NL −€15.68, BE −€20.01, PL −€24.96 and HU −€33.68.

Deepest price of the year
Deepest price of the year

The deepest prices are at the lower limit of the auction: CZ, SK and HU −€500.00, DE-LU −€499.99, NL −€499.62, BE −€499.29, FR and AT −€498.65. But ES and PT never went below −€10.00 and GR never below −€50.00. The data do not tell us why.

Zero is not negative

A price of exactly zero is a different thing from a negative price. GR had 1,776 periods at exactly €0.00 and 1,831 below zero; ES 1,457 at zero and 2,803 below; PT 1,421 and 2,186; FR 1,111 and 2,200. RS had 736 periods at zero and 168 below. IT-North had 86 periods at exactly zero and none below.

The longest streak

The longest run of negative periods in a row was in DE-LU: 80 periods, which is 20 hours. In most other zones the longest run was between 31 and 46 periods.

When: months, hours and dates

Negative prices are seasonal. Across the 25 zones, April 2026 had the most (6,780 negative zone-periods). In DE-LU, FR and NL there were almost none from November to January (at most 10 per month); ES had 17 in November, none in December and 50 in January, and PL up to 36. Spain is the exception in winter, with 520 already in February. Negative periods per month in five zones:

MonthESFRDE-LUNLPL
Oct 2025496319917319
Nov 2025171004
Dec 202501000
Jan 202650010036
Feb 202652012923214
Mar 202648615513976155
Apr 2026525547492449341
May 2026349370315274219
Jun 2026355361199191112
Jul 2026215298306237133
Aug 2026149177226233122
Sep 2026889814311070
Share of negative periods between 10:00 and 17:00
Share of negative periods between 10:00 and 17:00

Within the day, negative periods cluster around midday. In these five zones, between 85% and 87% of all negative periods fall between 10:00 and 17:00. The busiest hour is 13:00–14:00 in DE-LU, FR and NL, 14:00–15:00 in ES and 12:00–13:00 in PL.

The lowest price of each zone (IT-North had no negative price) came on a weekend or a public holiday, between 12:45 and 15:30:

  • 29 March 2026 (Sunday): ES, PT
  • 5 April 2026 (Easter Sunday): GR
  • 26 April 2026 (Sunday): SK, HU, RO, BG
  • 1 May 2026 (public holiday): FR, DE-LU, NL, BE, PL, CZ, AT, SI, HR
  • 24 May 2026 (Whit Sunday): DK1, SE3, FI, LT, LV, EE
  • 7 June 2026 (Sunday): RS
  • 13 June 2026 (Saturday): NO2

Why prices go negative

Prices fall below zero when there is more electricity on offer that cannot, or will not, be switched off than demand and export capacity can absorb. There are five typical reasons, and they often act together:

  1. A lot of wind and solar at the same time as low demand. Solar output is highest around midday, when demand is often low, above all on weekends and holidays.
  2. Inflexible power plants. Stopping and restarting a large plant costs money and time, and some plants must run to supply heat. Their operators may accept a negative price for a few hours rather than stop.
  3. Payments that do not depend on the market price. In some support schemes a renewable producer is paid for every megawatt-hour, whatever the price. Several countries are changing these rules.
  4. Limited export capacity and little flexibility. If neighbours are also in surplus, or the cross-border lines are congested, the surplus cannot leave. Batteries, pumped storage and flexible demand can absorb some of it, but where they are scarce, prices fall further.
  5. Offers below zero. Plants with income from other sources can offer a negative price, so many offers sit just below zero. That is why in some zones the lowest prices are only a few euros below zero.

The results fit this picture: the lowest prices came around midday, on weekends and holidays. But these are general mechanisms. The data alone do not prove which of them explains the difference between one zone and another.

How the numbers were counted

The video walks through the code cell by cell. Here is the complete code; it needs only pandas and the Python standard library.

Step 1: download and parse the yearly files

For every country and year the code downloads one JSON file and picks out the day-ahead price series. Three things had to be handled along the way. First, file names differ by country (DE uses year_15min, the others year). Second, in the 2025 files each zone has two day-ahead series, an hourly one until the end of September and a 15-minute one from 1 October, so every series starting with Day Ahead Auction is kept and its empty parts are dropped. Third, the time axis is not uniform (the step changes from 60 to 15 minutes), so the timestamps are always taken from the file, in UTC milliseconds, and never generated.

import json, re, urllib.request
import pandas as pd

countries = ["de","fr","at","ch","be","nl","pl","cz","sk","hu","ro","bg","gr","hr","si","rs",
             "es","pt","it","dk","se","no","fi","ee","lv","lt"]

parts = {}   # zone -> list of Series (hourly part and 15-minute part)
for cc in countries:
    for year in (2025, 2026):
        name = "year_15min" if cc == "de" else "year"
        url = f"https://www.energy-charts.info/charts/price_spot_market/data/{cc}/{name}_{year}.json"
        req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
        data = json.load(urllib.request.urlopen(req, timeout=90))
        axis = next(s["xAxisValues"] for s in data if s.get("xAxisValues"))   # time axis, UTC milliseconds
        for s in data:
            n = s["name"]["en"] if isinstance(s["name"], dict) else s["name"][0]["en"]
            if n.startswith("Day Ahead Auction") and "EXAA" not in n:
                zone = re.search(r"\(([^)]+)\)$", n).group(1)
                parts.setdefault(zone, []).append(pd.Series(s["data"], index=axis).dropna())

Step 2: merge, convert the time, trim and check

The parts of each zone are merged, the time is converted to Europe/Berlin and the data are cut to 1 October 2025 – 30 September 2026. The check is exactly 35,040 rows, which is 365 days × 96 (the two daylight-saving days balance each other out).

df = pd.DataFrame({z: pd.concat(p).groupby(level=0).first() for z, p in parts.items()})
df.index = pd.to_datetime(df.index, unit="ms", utc=True).tz_convert("Europe/Berlin")
df = df.sort_index().loc["2025-10-01":"2026-09-30"]

print(df.index.min(), df.index.max(), len(df))   # expected 35,040 rows
print(df.isna().sum()[lambda s: s > 0])          # which zones have gaps
2025-10-01 00:00:00+02:00 2026-09-30 23:45:00+02:00 35040
CH             26280
IT-Calabria       96
IT-Sicily         96
dtype: int64

The check also shows the gaps: CH is 75% empty because it trades an hourly product, and two Italian sub-zones are missing one day (7 August 2026). Missing values are never filled with zero, because zero is a real price and would change the averages and the count of zero-price periods.

Step 3: select the 25 main zones

main = ["DE-LU","FR","AT","BE","NL","PL","CZ","SK","HU","RO","BG","GR","HR","SI","RS",
        "ES","PT","IT-North","DK1","SE3","NO2","FI","EE","LV","LT"]
df = df[main].copy()

Step 4: the metrics

First every period with a price below zero is marked, and separately every period with a price of exactly zero. Then one table is built with a row per zone: negative periods, share of the year, periods at exactly zero, days with at least one negative price, the deepest price and when, the average of the negative prices and the longest run. All counts are in 15-minute periods.

neg = df < 0          # True where the price is below zero
zero = df == 0        # exactly zero

def longest_run(s):
    runs = (s != s.shift()).cumsum()
    return s.groupby(runs).sum().max()

res = pd.DataFrame({
    "neg_qh":     neg.sum(),                                  # negative quarter-hours
    "neg_pct":    neg.mean() * 100,                           # share of the year in %
    "zero_qh":    zero.sum(),                                 # exactly zero
    "neg_days":   neg.groupby(df.index.date).any().sum(),     # days with at least one negative price
    "min_price":  df.min(),                                   # deepest price
    "min_time":   df.idxmin(),                                # when
    "avg_neg":    df.where(neg).mean(),                       # average of the negative prices
    "longest_qh": neg.apply(longest_run),                     # longest run, in quarter-hours
}).sort_values("neg_qh", ascending=False)

by_month = neg.groupby([neg.index.year, neg.index.month]).sum()   # negative quarter-hours per month
by_hour = neg.groupby(neg.index.hour).sum()                       # negative quarter-hours by hour of day

Limits

  • RS trades an hourly product, so its counts come in blocks of four periods.
  • The counts are periods, not hours.
  • The analysis shows when prices were negative, not why. Explaining differences between zones needs generation data: wind, solar and load.

Takeaways

  • Spain, France, Portugal and DE-LU had the most negative 15-minute periods (2,803, 2,200, 2,186 and 2,052).
  • How often prices are negative and how deep they go are two different things: Spain averages −€1.06/MWh, DE-LU −€15.32 and HU −€33.68.
  • Negative prices appear around midday on weekends and holidays, when solar and wind meet low demand: 85–87% of negative periods fall between 10:00 and 17:00.

Method and sources

Day-ahead auction prices for 25 bidding zones from the yearly price data files of energy-charts.info, retrieved on 9 October 2026: ENTSO-E data via Energy-Charts.info; delivery period 1 October 2025 – 30 September 2026, times CET/CEST. All counts are 15-minute periods. Negative = price below €0.00/MWh; zero = exactly €0.00/MWh. Zone codes: DE-LU Germany–Luxembourg, FR France, AT Austria, BE Belgium, NL Netherlands, PL Poland, CZ Czechia, SK Slovakia, HU Hungary, RO Romania, BG Bulgaria, GR Greece, HR Croatia, SI Slovenia, RS Serbia, ES Spain, PT Portugal, IT-North Italy (North), DK1 Denmark (West), SE3 Sweden (Central), NO2 Norway (South), FI Finland, EE Estonia, LV Latvia, LT Lithuania.