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

- 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:
| Zone | Negative periods | % of year | Exactly 0 | Days with a negative price | Deepest price (date, time) | Average negative price | Longest run (periods) |
|---|---|---|---|---|---|---|---|
| ES | 2,803 | 8.00% | 1,457 | 119 | -10.00 (29 Mar, 15:30) | -1.06 | 42 |
| FR | 2,200 | 6.28% | 1,111 | 115 | -498.65 (1 May, 13:30) | -12.26 | 42 |
| PT | 2,186 | 6.24% | 1,421 | 102 | -10.00 (29 Mar, 15:30) | -1.07 | 42 |
| DE-LU | 2,052 | 5.86% | 386 | 97 | -499.99 (1 May, 13:15) | -15.32 | 80 |
| GR | 1,831 | 5.23% | 1,776 | 94 | -50.00 (5 Apr, 13:00) | -2.81 | 39 |
| NL | 1,745 | 4.98% | 242 | 91 | -499.62 (1 May, 13:30) | -15.68 | 43 |
| BE | 1,344 | 3.84% | 183 | 75 | -499.29 (1 May, 13:30) | -20.01 | 43 |
| PL | 1,225 | 3.50% | 325 | 82 | -490.00 (1 May, 12:45) | -24.96 | 44 |
| CZ | 1,153 | 3.29% | 173 | 65 | -500.00 (1 May, 12:45) | -24.00 | 46 |
| SK | 1,088 | 3.11% | 181 | 60 | -500.00 (26 Apr, 13:45) | -24.81 | 42 |
| AT | 1,014 | 2.89% | 176 | 63 | -498.65 (1 May, 13:30) | -26.08 | 40 |
| SI | 948 | 2.71% | 158 | 57 | -485.77 (1 May, 13:30) | -26.34 | 40 |
| DK1 | 939 | 2.68% | 240 | 48 | -42.09 (24 May, 15:00) | -4.25 | 40 |
| HU | 894 | 2.55% | 267 | 54 | -500.00 (26 Apr, 13:15) | -33.68 | 41 |
| HR | 880 | 2.51% | 174 | 50 | -385.75 (1 May, 14:30) | -23.69 | 40 |
| RO | 687 | 1.96% | 502 | 40 | -99.75 (26 Apr, 13:00) | -9.70 | 36 |
| BG | 609 | 1.74% | 519 | 34 | -99.75 (26 Apr, 13:00) | -8.49 | 39 |
| SE3 | 497 | 1.42% | 101 | 31 | -14.49 (24 May, 14:00) | -1.47 | 45 |
| FI | 380 | 1.08% | 254 | 28 | -10.92 (24 May, 15:00) | -0.62 | 31 |
| LT | 276 | 0.79% | 107 | 20 | -15.11 (24 May, 14:00) | -1.59 | 31 |
| LV | 255 | 0.73% | 111 | 17 | -15.11 (24 May, 14:00) | -1.57 | 31 |
| NO2 | 248 | 0.71% | 18 | 24 | -34.94 (13 Jun, 15:30) | -3.42 | 37 |
| EE | 241 | 0.69% | 152 | 18 | -10.92 (24 May, 15:00) | -0.78 | 31 |
| RS | 168 | 0.48% | 736 | 8 | -45.50 (7 Jun, 15:00) | -5.47 | 36 |
| IT-North | 0 | 0.00% | 86 | 0 | — | — | 0 |
How often is not how deep

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.

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:
| Month | ES | FR | DE-LU | NL | PL |
|---|---|---|---|---|---|
| Oct 2025 | 49 | 63 | 199 | 173 | 19 |
| Nov 2025 | 17 | 1 | 0 | 0 | 4 |
| Dec 2025 | 0 | 1 | 0 | 0 | 0 |
| Jan 2026 | 50 | 0 | 10 | 0 | 36 |
| Feb 2026 | 520 | 129 | 23 | 2 | 14 |
| Mar 2026 | 486 | 155 | 139 | 76 | 155 |
| Apr 2026 | 525 | 547 | 492 | 449 | 341 |
| May 2026 | 349 | 370 | 315 | 274 | 219 |
| Jun 2026 | 355 | 361 | 199 | 191 | 112 |
| Jul 2026 | 215 | 298 | 306 | 237 | 133 |
| Aug 2026 | 149 | 177 | 226 | 233 | 122 |
| Sep 2026 | 88 | 98 | 143 | 110 | 70 |

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:
- 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.
- 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.
- 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.
- 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.
- 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.


