Forecast Gas: How We Calculate Weighted Degree Days
Forecast Gas publishes heating and cooling degree days (HDD and CDD) from every run of the major global weather models, weighted three ways: by population, by natural gas heating demand, and by natural gas burned for power. This page describes exactly how those numbers are made, so they can be reproduced and compared.
Status. All three weightings, observed degree days and normals are live. Use gas-heating weights for HDD and power-burn weights for CDD; population weights are the conventional comparison.
1. Degree days, per grid cell
For each model run, each forecast day and each grid cell, we take the day's maximum and minimum 2-meter temperature and follow the NOAA convention:
- Daily mean temperature: T̄ = (Tmax + Tmin) / 2, in °F
- HDD = max(0, 65 − T̄)
- CDD = max(0, T̄ − 65)
Tmax and Tmin come from the models' own maximum and minimum temperature fields over the local day, not from 3- or 6-hourly snapshots, which miss the true daily extremes. TDD (total degree days) is HDD + CDD.
The local day
A day runs from midnight to midnight in local solar time (UTC plus longitude ÷ 15 hours). Across the Lower 48 this is within about an hour of local standard time, the basis of the NWS climate day. Every forecast uses the same definition. (Observed values follow NOAA's station days; see section 6.)
Models report their maximum and minimum temperature over fixed intervals: 1, 3 or 6 hours, depending on the model and the lead time. Each interval belongs to the local day that contains its midpoint. An interval cannot be split, so a day's window can run up to half an interval longer or shorter than 24 hours. That happens where a model switches interval length, for example ECMWF at 144 hours. We also take the instantaneous temperature at each interval's end into account, because a model's interval maximum occasionally sits a fraction of a degree below it.
Complete days only
A day is published only if the model's intervals cover it without a gap. The first and last days of most runs are only partly covered, so they are left out rather than published as if they were whole. A grid cell with any missing interval that day counts as missing. A region is published only when at least 99.9% of its weight has valid data.
Ensembles, member by member
For ensembles (ECMWF ENS, 51 members; GEFS, 31 members; GEPS, 21 members), degree days are computed for each member at every grid cell, then weighted, and only then summarized: mean, spread and percentiles across members. Averaging the members' temperatures first undercounts degree days for the same reason averaging across a region does. In week two it amounts to 0.5–1 degree day per day for the Lower 48. Multi-day totals are summed for each member before the statistics are taken.
Degree days are calculated at every grid cell before any averaging. Because a degree day is zero on one side of 65°F, averaging temperatures across a region first and then computing degree days undercounts demand whenever part of the region is above 65°F and part below, which is common in spring and fall. Computing first and averaging second avoids that error.
2. From grid cells to places people live
We do not use county centroids. Instead we use the 2020 Census population-weighted centers of about 240,000 block groups. Each block group's degree days are interpolated bilinearly from the four surrounding model grid cells. In large Western counties, where a geometric centroid can sit in empty desert or mountains, this puts the temperature where the population actually is.
3. Three weighting schemes
Each block group (or power plant) carries a weight w. The degree days for any region are the weighted average over the points in it:
DD(region) = Σ wₚ · DDₚ / Σ wₚ
Population-weighted (pop)
w = 2020 Census population of the block group. This is the conventional measure, following the same convention as the population-weighted degree days from NOAA's Climate Prediction Center. CPC weights weather stations rather than grid points, so the two will not match exactly.
Gas-heating-weighted (gas_hdd)
Built to track the part of residential and commercial gas demand that responds to temperature.
- State totals. From EIA monthly state data, we take residential and commercial gas deliveries and subtract each state's July–August baseload (water heating, cooking and other year-round use). What remains, averaged over the last five complete years, is the state's heating-sensitive gas use.
- Within each state:
- The residential portion is spread across block groups in proportion to occupied housing units that heat with utility gas (Census ACS 5-year, table B25040).
- The commercial portion is spread in proportion to population.
wₚ = Res_s · Gₚ / Σ₍ₛ₎ G + Com_s · Pₚ / Σ₍ₛ₎ P
where G is gas-heated households and P is population. The result is that, for example, Florida's many electrically heated homes carry little gas weight, while a Chicago suburb carries a lot.
Power-burn-weighted (power_cdd)
Built to track gas burned by power plants for air-conditioning load.
- w = each plant's average June–September natural gas consumption for electricity generation (EIA-923, last three complete years), placed at the plant's own coordinates (EIA-860).
- Population-weighted CDDs overstate places where hydropower or other fuels carry the summer load. Weighting by gas burn puts the weight where incremental cooling demand turns into gas demand.
- Plants are located from EIA-860M's current generator list. Gas burned at plants since retired has no current location. In the 2026a weights, 94% of June–September gas burn is placed, and the rest is left out.
In the 2026a weights, Florida carries 6.5% of the population weight but 0.4% of the gas-heating weight and 10.8% of the power-burn weight. The Midwest carries 19% of population, 32% of gas heating and 12% of power burn. South Central carries 16%, 9% and 31%.
4. Geographic levels
Every point belongs to one county, state, Census division, EIA storage region (East, Midwest, Mountain, Pacific, South Central) and the Lower 48. All levels are built from the same points with the same weights, so they are exactly consistent: a region's value always equals its states' values combined by their total weights, and a state's value equals the weighted combination of its counties. Every published weight set is checked for this before release.
5. Models and grids
| Model | Members | Runs | Length |
|---|---|---|---|
| ECMWF ENS | 51 | 00, 06, 12, 18 UTC | 15 days (00/12 UTC), 6 days (06/18 UTC) |
| NOAA GEFS | 31 | 00, 12 UTC | 16 days (days 11–16 at 0.5°, see below) |
| NOAA GFS | 1 | 00, 06, 12, 18 UTC | 15 days |
| Canada GEM | 1 | 00, 12 UTC | 10 days |
| DWD ICON | 1 | 00, 06, 12, 18 UTC | 7.5 days (00/12 UTC), 5 days (06/18 UTC) |
| UK Met Office | 1 | 00, 06, 12, 18 UTC | 7 days (00/12 UTC), 2 days (06/18 UTC) |
| ECMWF AIFS | 1 | 00, 06, 12, 18 UTC | 15 days (calibrated, see below) |
| Canada GEPS | 21 | 00, 12 UTC | 16 days |
Weights are built as sparse matrices for each model's own grid, whatever its spacing (regular, Gaussian or cropped), and cached by a fingerprint of the grid's coordinates. A change of grid therefore can never reuse the wrong weights. Applying the weights is a single matrix multiplication per forecast field, so every run and every ensemble member is processed identically. A run is processed only after the model has finished writing all of it.
GEFS days 11–16 and the Canadian ensemble
NOAA publishes GEFS at 0.25° to 240 hours and at 0.5° to 384 hours. Forecast Gas keeps the 0.25° output for the days it covers and takes the remaining days from the 0.5° files in NOAA's open-data bucket, fetching only the 2-m maximum and minimum records. The two parts are weighted on their own grids and joined at the regional level, member by member (member i is the same member in both; at 240 hours the two grids agree to 0.01 K). A day comes from the 0.5° files only if the 0.25° output did not complete it. The first ten days are published as soon as they are ready and the rest when the 0.5° files land.
Canada's Global Ensemble Prediction System (GEPS) comes from the MSC Datamart: the control and 20 perturbed members, 00 and 12 UTC, with the 2-m maximum and minimum over every six hours to 384 hours on a 0.5° grid. It needs no calibration of its daily extremes and goes through the same local-day, member-by-member pipeline. It gives week two a third independent ensemble.
AI models: calibrated daily extremes
ECMWF AIFS gives 2-m temperature only at 00, 06, 12 and 18 UTC, with no daily maximum or minimum. The highest of four samples almost never catches the afternoon peak, and the lowest rarely catches the dawn minimum, so degree days from the raw samples run short on CDD and long on HDD. Forecast Gas adds back the part of the day's cycle that the samples miss:
Tmax = highest sample + max(0, a_max + b_max × r)
Tmin = lowest sample − max(0, a_min + b_min × r)
Here r is the day's sampled range. The coefficients are fitted for every grid cell. a carries geography: at a given longitude the four UTC hours fall at fixed local times, so how far the true peak sits above the nearest sample depends mainly on where the cell is. b carries the weather: a cloudy or well-mixed day has a compressed sampled range, and its true extremes sit closer to the samples. The correction can only widen the day, never pull a high below the model's own sample.
The coefficients are learned every day from the six latest ECMWF ENS 00/12 UTC runs. ECMWF ENS has both true interval extremes and 6-hourly temperature on the same grid, so its temperature, thinned to the four synoptic hours and put through the same local-day code as AIFS, is exactly what a 6-hourly model would have given, and its own extremes are the answer. On a held-out run (the newest, fitted without it) the correction cut the Tmax error from 1.6 °F to 0.7 °F and the Tmin error from 0.9 °F to 0.6 °F per cell, and the Lower 48 population-weighted CDD bias from -0.23 to -0.002 per day. AIFS output is not published when the calibration is more than a week old.
Run-to-run change
"Change vs previous run" compares the latest full-length run with that model's previous run of the same length (ECMWF 12 UTC against 00 UTC, not against the 6-day 06 UTC run); "vs 24 hours earlier" compares it with the run from the same hour a day before. Both use the ensemble mean for ensembles and cover only the days the two runs share.
In the dashboard's model comparison, week 1 and week 2 use exactly the same calendar dates for every model, anchored to the ECMWF ENS run's first full day. If ECMWF is unavailable, the first available model supplies the anchor. A model missing any day in a week has no weekly total; its day coverage is shown instead. The separately labeled run totals retain each model's own forecast length and are not a comparison over identical dates.
6. Observed degree days and normals
Observed degree days come from nClimGrid-Daily, NOAA's gridded daily maximum and minimum temperature for the contiguous US at about 5 km (1/24°), built from thousands of GHCN-Daily stations. Forecast Gas carries the record from 1991. It is made the same way as the forecasts. Degree days are taken at every 5-km cell, then carried to the same population points with the same weights, so observed and forecast numbers for a region measure the same thing. Ocean cells and cells outside the border have no data. Each point uses only neighbouring cells that have data. The few points just off the grid's edge (the Florida Keys, the eastern tip of Maine) take the nearest land cell.
NOAA publishes each month as preliminary data, updated daily with about a three-day lag, and replaces it with a final version a few weeks after the month ends. Preliminary days are labeled, and are recomputed automatically when the final data arrive.
Normals are the 1991–2020 average of these same observed daily degree days for each region and calendar day, smoothed across the year with a 7-day Gaussian window so that a single unusual year does not leave a spike on its date. A trailing ten-year normal (the last ten complete years) is also published. The normals average degree days, never temperatures, so they carry no averaging error. Because they are built from the same cells, points and weights as the observed values, any departure from normal reflects the weather, not a difference in method.
Two differences from the forecasts remain, and they are stated here so they are not mistaken for signal:
- The observation day. nClimGrid values are station days: each covers "the 24-hour period ending in the early morning of the specified day". The forecasts use the local calendar day. The difference is largest for the daily maximum at stations that observe in the morning.
- Resolution. nClimGrid is 5 km and the models are 25 km or coarser. Taking degree days on a finer grid keeps more of the local variation, so on shoulder-season days observed degree days run slightly higher than the same weather on a model's grid would give.
Model accuracy
Every 00 and 12 UTC run is scored against the observed record once its forecast days have been observed. For each model and lead (days from the run's start date), Forecast Gas reports the mean absolute error, which measures how far off the forecasts were in either direction, and the mean error (bias), over the last 30 and 90 observed days. Ensembles are scored on their mean. Comparing models against each other is fair, because all are scored against the same truth. The two differences above (observation day and resolution) can show up in the bias of every model alike, so a small shared bias is not necessarily a model error.
7. Versioning
Population, gas-heating households and gas consumption change every year. Each weight set is frozen under a vintage label (for example, 2026a) and stored with a record of the input files it was built from. Historical archives, including the observed record and the normals, are processed with a single vintage so that changes over time reflect weather, not reweighting.
8. Data sources
- 2020 Census: block-group centers of population
- Census ACS 5-year estimates, table B25040: house heating fuel by block group
- EIA natural gas monthly: residential and commercial deliveries by state
- EIA-923 and EIA-860: plant-level gas consumption for electricity and plant locations
- NOAA nClimGrid-Daily: observed daily maximum and minimum temperature, 5 km, 1951 to now (doi:10.25921/c4gt-r169)
- Model output: ECMWF (ENS), NOAA (GEFS, GFS), Environment and Climate Change Canada (GEM, GEPS), Deutscher Wetterdienst (ICON) and the UK Met Office
All inputs are public.
9. Known limitations
- Commercial demand: it is distributed by population. Business floor space would be better but isn't published at block-group level.
- Coastal points: bilinear interpolation can draw partly on ocean grid cells, whose temperatures are moderated by the water. An optional land mask restricts interpolation to land cells.
- Elevation: at 0.25° resolution, a grid cell's elevation can differ from the city's. The raw weighted degree days are published as-is. Station-calibrated versions are a separate, labeled product.
- Connecticut: the ACS now uses planning regions instead of counties. Block groups are matched on tract and block group, and county-level output for Connecticut uses the 2020 counties.
Storage estimate
The weekly net change in Lower 48 working gas (EIA's Weekly Natural Gas Storage Report, Saturday-to-Friday weeks) is regressed on that week's observed gas-heating-weighted HDD and power-burn-weighted CDD, an annual cycle (two harmonics) and a linear trend, over report weeks since 2021. The mean residual of the last eight weeks is added to each estimate, because supply-side shifts (production, LNG feedgas, pipeline maintenance) persist for weeks and weather cannot see them.
For a week not yet reported, observed days come from nClimGrid and the remaining days from the newest ECMWF run covering them. The published error is rolling-origin: each of the last 104 weeks is estimated from a model fitted only on earlier weeks, and the ± range on each estimate is that root-mean-square error.
The EIA report-week tables sum every model's daily degree days over the same Saturday-to-Friday weeks, observed days first, and compare them with the same weeks in the last five years and with the 1991–2020 normal.
Supply and demand
The monthly balance comes from EIA's Natural Gas Monthly (dry production, pipeline imports, consumption by sector, LNG exports by terminal and pipeline exports) and, for the months after the last reported one, from EIA's Short-Term Energy Outlook. Monthly volumes are converted to Bcf/d by the days in the month. The monthly data is not used in the weekly storage estimate: tested week by week over two years, adding it (with only the months known at the time) did not improve on the estimate's own eight-week correction.
Historical context
The context view ranks a forecast total against the same calendar days observed in every year since 1991 (29 February folded into 28 February), with the 5-year average and last year. The run-trend view recomputes one fixed window from every recent run of a model, so a forecast that is steadily cooling or warming run over run shows up as a slope.
Next ECMWF ENS run: the revision outlook
Every other model's run for a cycle reaches Forecast Gas two to five hours before ECMWF ENS does. We measured this from our data store's write times: for 00 UTC, ICON lands around 04:15, GFS and GEM around 05:20, GEFS and AIFS around 05:40, UKMET around 06:35, and ECMWF ENS around 09:00. The revision outlook uses that window to estimate how the next ECMWF ENS run will change the Lower 48 week-1 total (the seven days starting at the new run's first full day), before it arrives. It uses four inputs:
- Cycle: whether the next run is 00 or 12 UTC. ECMWF ENS alternates. In summer 2026 its 12 UTC runs cut week-1 CDD by about 0.9 on average and its 00 UTC runs added about 0.6 back. Its 00 UTC runs have also run warmer against observed values.
- Gap: where the other models' new runs sit against the ECMWF ENS run in hand. ECMWF tends to move toward them.
- Early change: how the other models changed from their own previous run.
- Momentum: how the ECMWF ENS run in hand changed from the one before it. Part of each change is noise that the next run takes back.
The coefficients are fitted by least squares with a light ridge. Every score shown is walk-forward: each run is predicted by a fit that saw only earlier runs, and is compared with "no change". Because the models arrive one at a time, each arrival stage (ICON alone; with GFS and GEM; with GEFS; with UKMET) has its own fit and error range. A live call uses the stage, among those fully arrived, with the best backtest, and a stage that cannot beat "no change" issues no number. AIFS joins the stages once it has enough history.
Every call is written to an append-only log when issued and scored against the ECMWF ENS run when it lands. The track record shows the live calls separately from the backtest. Week 2 has no call yet: on the history so far (54 runs), no version of the model beat "no change" reliably.
Bias adjustment of forecast days in the storage estimate
For report weeks not yet observed, the storage estimate uses ECMWF ENS forecast days after removing the model's recent bias at each lead day. The bias is the mean of forecast minus observed over forecasts that verified in the previous 30 days, applied through day 10. Tested walk-forward on summer 2026 ECMWF ENS population-weighted degree days, this cut CDD error at day 6 from 0.93 to 0.66 and helped at every lead through day 10. It made no difference beyond day 10. Each day on the storage page keeps its raw value alongside the adjusted one.
Storage odds
Each projected report week is also run through the storage model once for every member of the newest ECMWF ENS run: observed days are fixed, and each member's bias-adjusted forecast days replace the ensemble mean. Each member's estimate is then spread by the model's 104 rolling-origin errors, so the odds include both the weather uncertainty and the model's own. The page shows the chance the change comes in above the 5-year average for the same week and above last year's, with the full distribution in 5-Bcf bins. For the weeks closest to the report, the model's own error, not the weather, is most of the spread.
Weather scenarios, priced in Bcf
Weathertrader's cluster engine groups the 50 perturbed ECMWF ENS members by their North American 500-hPa pattern (k-means with k = 2, 3 or 4) for days 1–5, 6–10 and 11–15. It follows each scenario from run to run by pattern correlation, and lists the members in each. Forecast Gas joins those members to its own member-by-member degree days. (Member position i in the cluster files is ECMWF perturbed member i+1; we checked this against the stored 2-m temperatures to within 0.07 K.) For each scenario it computes the following:
- Degree days: the scenario's gas-heating HDD and power-burn CDD for the window, and the change from the whole ensemble.
- Bcf impact: the storage model is linear in weekly HDD and CDD, so the scenario's extra degree days are worth exactly the model's Bcf per HDD and per CDD.
- By region: each EIA region's part of that impact. The Lower 48 value is the demand-weighted average of the five regions, and the weights are recovered exactly from the data. The scenario is labelled by the Lower 48 direction and the region contributing most.
- If it verifies: the estimate for each EIA report whose week overlaps the window, as the mean of the scenario members' storage estimates.
- Share by run: how the scenario's share has changed over recent runs.
ECMWF ENS gives 14 whole local days, so the last window is days 11–14.
Forecast stability, days 6–10
For each 00/12 UTC ECMWF ENS run, three things are measured on the Lower 48 population-weighted TDD total for days 6–10:
- Model disagreement: the spread of the other models' forecasts from the same cycle, per day, over the days each one covers.
- Ensemble spread: the standard deviation of the ECMWF ENS members' totals.
- Run-to-run jumps: the root-mean-square change of this window's total over the last four runs.
Each is converted to a z-score against the previous 60 runs only. The score is 0.5 × disagreement + 0.25 × spread + 0.25 × jumps, with the weights fixed before any testing.
The score is tested against one thing only: how far the days 6–10 total moves over the next 24 hours. In summer 2026, over 91 runs, the most unsettled third of scores saw moves 1.44 times those of the steadiest third (Spearman +0.28). It says how much the outlook is likely to move, not which way. Tested against the forecast's eventual error, the result was inconclusive, so the indicator makes no claim about busts.
Two things are shown as context and are not part of the score: weathertrader's herding index, and the split between the weather scenarios.
Weeks 3–4: the GEFS 35-day ensemble
NOAA's GEFS extends its 00 UTC run to 35 days (840 hours) for all 31 members, on a 0.5° grid. Forecast Gas reads it directly from NOAA's open-data bucket on AWS. From each 6-hourly file it fetches only two records, the 2-m maximum and minimum temperature over the preceding six hours (about 0.46 MB of each 15 MB file), and runs them through the same local-day, member-by-member pipeline as every other model. No calibration is needed. Days 17–35 are produced late and reach the bucket about 28 hours after the run starts, so the outlook updates once a day.
For days 1–9, the 0.5° extended run agrees with weathertrader's 0.25° GEFS to within about 0.1 degree day per day. The extended run is kept out of the side-by-side model views, where it would duplicate GEFS, and has its own page. For each week of the newest run (weeks 1–4 and the six days of week 5), that page shows:
- the ensemble-mean total and the members' 10th–90th percentile range
- the share of members above the 1991–2020 normal
- the normal, the 5-year average and last year for the same dates
- the week's rank among all years since 1991
- how the forecast for those dates moved over recent runs
- for weeks 3 and 4, each EIA region's departure from normal
Its record scores every archived run whose week has since been observed, against simply forecasting the normal. The archive covers daily runs for the last month and one run a week over the past year.
Over the past year (47–69 runs per week), the record shows GEFS 35-day ahead of forecasting the normal at every week. By week 4, the skill left is modest for population TDD (+0.04) and gas-heating HDD (+0.09), and real for power-burn CDD (+0.27). Its weeks 3–4 bias changes sign with the season: gas-heating HDD ran +11 too high in winter and −11 too low (too warm) in fall. Removing a trailing 90-day bias made weeks 3–4 worse by 7–15% when tested walk-forward, so the forecasts are not adjusted. Instead, the page shows the same season's bias from the record as a caution.
Calibrated forecasts
Every model has its own 2-m temperature bias. It differs between the daily maximum and the minimum, from place to place, and from season to season, and it is not small: over summer 2026 the day-1 cooling degree days of the seven models ran from 0.8 too low to 1.3 too high for the Lower 48, most of each model's day-1 error. The raw forecasts stay as published. Next to them, Forecast Gas publishes a calibrated version of every run.
Where the bias is removed. A degree day is zero on one side of 65°F, so a bias cannot be subtracted from weighted degree days without going wrong whenever part of a region sits near the base. It is removed from the temperatures instead, at every grid cell, and the degree days are then taken exactly as for the raw forecast:
Tmax′ = Tmax − b_max(cell, lead) Tmin′ = Tmin − b_min(cell, lead)
How the bias is measured. For each model, cell and lead day, b is the mean error of the forecasts that verified in the last 30 days (00 and 12 UTC runs; the ensemble mean for ensembles), averaged with the neighbouring leads and shrunk toward zero where the sample is short. A lead with fewer than 15 verifying days gets no correction: a few days are one weather pattern, not a bias, and the Canadian ensemble, fitted on its first ten days, came out worse beyond day 4. It is refitted whenever new observed days arrive, so it follows the season. GEFS days 11–16 have their own fit on their own grid. The 35-day GEFS is not calibrated: a trailing bias made its weeks 3–4 worse (see above).
What it is measured against. nClimGrid-Daily, the same record the observed degree days and the normals come from, brought to each model's grid through the population points: a cell's truth is the observed temperature at the block groups that draw on that cell, weighted by population and by each one's bilinear share. The correction therefore pulls a cell toward the temperature where its people live, and cells that no point draws on are left alone. Because nClimGrid uses station observation days (section 6), the correction also absorbs the difference between a model's local day and the observed record's day. Calibrated forecasts are meant to be compared with the observed record and the normals; raw forecasts show what the model itself said.
Spread. Raw ensemble members sit too close together in the first days. Measured on the Lower 48 mean temperature against the observed record, the published 10th–90th percentile range of ECMWF ENS held the outcome about a third of the time at day 1 and about 60% at day 5, where a reliable range holds it 80% of the time. Part of that is the members sharing one model's errors, and part is that no member knows how the observed record will differ from a model's day. In the calibrated version, each member's departure from the ensemble mean is multiplied at every cell by a factor for its lead: the error the mean has had over the same 30 days (bias removed) divided by the members' spread, smoothed across leads and limited to 0.8–3. The mean is unchanged.
The floor under every one of these numbers. The spread factor is limited to 3 and that limit binds at days 0–2, where the measured ratio asks for 3.8 to 7.8. It is left binding deliberately. Debias each model's ensemble-mean Lower 48 mean temperature and take the RMS error by lead (30 days to 2026-10-17), and every model has the same floor at day 0 and the same flat curve to about day 4:
| Day 0 | Day 1 | Day 2 | Day 3 | Day 4 | Day 5 | Day 7 | Day 10 | |
|---|---|---|---|---|---|---|---|---|
| ECMWF ENS | 1.60 | 1.57 | 1.57 | 1.61 | 1.60 | 1.60 | 2.18 | 2.30 |
| GFS | 1.73 | 1.84 | 1.89 | 1.82 | 1.93 | 2.27 | 2.51 | 2.96 |
| GEFS | 1.76 | 1.85 | 1.85 | 1.77 | 1.88 | 2.04 | 1.85 | 2.43 |
| GEM | 1.60 | 1.64 | 1.65 | 1.65 | 1.68 | 1.76 | 1.95 | 3.05 |
| ICON | 1.64 | 1.61 | 1.53 | 1.72 | 1.81 | 1.92 | ||
| AIFS | 1.55 | 1.58 | 1.61 | 1.67 | 1.69 | 1.67 | 2.42 | 2.68 |
| GEPS | 1.61 | 1.69 | 1.72 | 1.72 | 1.71 | 1.82 | 2.15 | 2.79 |
Seven centres, different assimilation and physics, one of them a neural network, cannot share a day-0 forecast error of 1.6°F. The error is not in the models: at day 0 the model has already seen the weather. It is the comparison — nClimGrid's station observation day against the forecasts' local solar day (section 6), and its 5 km cells against a 25 km grid. Roughly 1.6°F RMS of every short-lead verification on this site is that mismatch rather than forecast error.
Separating the two. fgas errorfloor splits the measured error into the part that belongs to the observed day and the part each model owns, and /verification shows the result. Write a model's debiased error on a date as e(m, L, d) = r(d) + f(m, L, d). The term r belongs to the observed day, so it is the same constant for every model verifying that date and drops out of the variance across models exactly, whatever its size; f is the model's own forecast error. So the across-model variance estimates what differs between models, and the variance of the across-model mean, less that quantity over the number of models, estimates what they share. Measured over 90 days to 2026-10-17, 00 and 12 UTC, eight models:
| Lead | 0 | 1 | 2 | 3 | 5 | 7 | 10 | 14 |
|---|---|---|---|---|---|---|---|---|
| Variance the models share | 1.34 | 1.40 | 1.42 | 1.44 | 1.60 | 2.09 | 3.84 | 6.34 |
| Variance each model owns | 0.06 | 0.11 | 0.17 | 0.25 | 0.66 | 1.10 | 3.30 | 5.79 |
| Shared share | 0.95 | 0.93 | 0.89 | 0.86 | 0.71 | 0.66 | 0.54 | 0.52 |
| Mean cross-model correlation | 0.96 | 0.95 | 0.93 | 0.90 | 0.76 | 0.71 | 0.61 | 0.60 |
The part each model owns grows ninetyfold from day 0 to day 14, which is what forecast error does. The shared part starts at the floor and grows far more slowly. At day 0 the models' own error is 0.25°F against 1.16°F shared: 95% of day-0 error variance is one error, not eight.
The floor is read at day 0, where a model has already seen the weather, and held constant, because the observed record's daily window does not depend on how far ahead the forecast is. It is capped at the smallest total error variance any model has there, so no model's residual goes negative; it comes to 1.07°F. It is an upper bound: error the models share because they share initial conditions and miss the same patterns cannot be told from shared measurement error by comparing models alone, and past day 5 the shared term clearly carries some of it.
What it implies for each model, as a share of its measured error variance and as the spread factor the ensemble would be aiming at if it aimed at the error it owns:
| Day 0 | Day 1 | Day 2 | Day 3 | Day 5 | Day 7 | Day 10 | |
|---|---|---|---|---|---|---|---|
| ECMWF ENS, measurement share | 78% | 81% | 79% | 74% | 74% | 43% | 34% |
| ECMWF ENS, spread ÷ measured error | ×5.28 | ×4.01 | ×3.07 | ×2.36 | ×1.31 | ×1.14 | ×0.87 |
| ECMWF ENS, spread ÷ forecast error | ×2.45 | ×1.74 | ×1.42 | ×1.20 | ×0.67 | ×0.86 | ×0.71 |
| GEPS, spread ÷ forecast error | ×2.99 | ×2.52 | ×2.10 | ×1.58 | ×1.01 | ×0.89 | ×0.92 |
Read against the error it owns, ECMWF ENS is genuinely too confident in the first three days — by a factor of 1.2 to 2.5, not the 2.4 to 5.3 the measured error suggests — and from day 4 out its members are already further apart than its own error warrants, where the current factor is still inflating them. The published spread is not changed on this basis yet: the factor would have to aim at forecast error while the published range went on covering the observed value, which means carrying the measurement term as its own component the way the storage model already carries its error, and that is a change to a published probabilistic product rather than a correction. The numbers are published first.
Two consequences, and they are limits on what this page can claim. Spreading the members apart until the range covers that mismatch would have them assert weather uncertainty that does not exist at day 0, and would count the mismatch twice, because the storage model already adds its own error term to the member distribution; so the limit stays, the published range stays a range of forecast uncertainty, and the reliability figures below should be read as coverage of a target the ensemble structurally cannot cover, not as pure overconfidence. And at short leads the models are separated by less than the floor: ECMWF ENS, the plain consensus and the blend are within 2% of each other at days 1–3 on heating degree days, which is a statement about the measurement, not about the models. Resolving this needs the error decomposed into its irreducible and lead-dependent parts, or a truth record on the forecasts' own daily window; neither is done.
Walk-forward. A run is only ever calibrated from forecasts that had verified before it was issued. Calibrated files added to runs already in the archive used the fit as it would have stood four days before each run, and are marked by their processing delay, as backfilled raw runs are.
The skill-weighted blend. The dashboard's consensus was a plain mean of the models, so a model running hot and one running cold cancelled only by luck. The blend weights each model at each lead by 1 ÷ its mean squared error over the 45 days that had verified four days earlier. A model with verified forecasts on fewer than ten days at a lead has not earned a weight there and counts as an average model; where no model has weights yet all count the same. It is published where at least three models have the day. The plain consensus is still shown.
Which version each model enters as. A model joins the blend calibrated only where the calibrated forecast has actually been beating the raw one at that lead. The comparison uses the same 45-day window and four-day lag as the weights, and only the runs both versions have, so neither can win on an easier sample; the raw forecast keeps a tie and has to be beaten by 2% of its mean squared error, which stops the published line changing version on noise. This is not a formality: the correction is fitted to the last 30 days, so it goes stale through a seasonal turn, and in October 2026 it was adding error for most models (below). As of 2026-10-17 the heating-degree-day blend took GEM and GEPS calibrated at every lead through day 6 — the two models with the largest standing biases — ECMWF ENS calibrated only at days 14–15, and every other model raw. The choice is published in the accuracy record with the weights, and /verification names the models the blend is currently taking calibrated.
The pooled ensemble. The calibrated members of ECMWF ENS (51), GEFS (31) and GEPS (21) from one cycle are pooled, each member counted once, for days at least two of the three cover. Pooling raw members would mix three temperature biases into the spread; pooling calibrated ones adds three models' different errors to it, which is the uncertainty a single ensemble lacks. The storage page shows the odds from the pooled ensemble next to the odds issued from ECMWF ENS alone. The storage estimate itself is unchanged.
What it measured. Walk-forward, 00 and 12 UTC runs verified through 2026-09-29 (late July to late September, so almost all cooling degree days; a winter has not been scored). Every calibrated run used only forecasts that had verified before it. Lower 48 population-weighted total degree days per day, mean absolute error, raw → calibrated on the same runs:
| Model | Days 1–3 | Days 4–7 | Days 8–10 | Days 11–15 |
|---|---|---|---|---|
| ECMWF ENS | 0.62 → 0.54 | 0.69 → 0.58 | 0.82 → 0.80 | 1.09 → 1.05 |
| GEFS | 0.96 → 0.72 | 1.03 → 0.67 | 0.74 → 0.75 | not yet scored |
| GFS | 1.36 → 0.69 | 1.55 → 1.02 | 1.72 → 1.47 | 1.92 → 1.75 |
| GEM | 0.90 → 0.60 | 0.93 → 0.76 | 1.12 → 1.06 | |
| ICON | 0.73 → 0.56 | 1.00 → 0.65 | ||
| UKMET | 0.98 → 0.53 | 1.22 → 0.66 |
The gain is the bias: GFS ran 1.3 degree days a day too warm and GEM 0.8 too cool, and both come out within 0.4. It is large through day 7 and small after day 8, where the error is mostly the weather pattern and no longer the model's bias. GEPS has too few calibrated runs to score (its archive begins 2026-09-07).
The combinations, on the runs all of them have:
| Days 1–3 | Days 4–7 | Days 8–10 | Days 11–15 | |
|---|---|---|---|---|
| ECMWF ENS, raw | 0.62 | 0.70 | 0.71 | 0.85 |
| Plain mean of raw models | 0.68 | 0.70 | 0.72 | 0.80 |
| Plain mean of calibrated models | 0.51 | 0.59 | 0.76 | 0.91 |
| Calibrated blend | 0.50 | 0.58 | 0.73 | 0.85 |
On that sample, through day 7 the blend had 17–26% less error than the plain consensus and beat every single model, raw or calibrated. In week 2 it did not beat the plain consensus: over that sample the raw models' biases happened to cancel (GFS and GEFS warm, GEM cool), and calibration removes that cancellation along with the biases. Weighting by skill is worth a few percent over equal weights. An earlier version left out models that had not yet earned a weight and was worse than the plain mean of the calibrated models; a model without a weight now counts as an average one.
The gain did not last, and that is why the blend now chooses. The sample above is late July to late September 2026 — almost all cooling degree days, in a season that barely moves. Re-measured as heating degree days began to accumulate, the correction had not merely stopped helping, it had changed sign. ECMWF ENS total degree days, days 1–3, raw → calibrated: 0.68 → 0.46 in August, 0.64 → 0.76 in September, 0.70 → 0.76 in October. The cause is the fit's own window: 30 trailing days is a reasonable estimate of a standing bias and a poor one through a seasonal turn, the same mechanism that made a trailing correction worse for the 35-day GEFS in weeks 3–4.
So the blend stopped assuming calibration helps and started measuring it, model by model and lead by lead (above). Matched on initialization, cycle, valid date and lead, 00 and 12 UTC, Lower 48 population-weighted heating degree days per day, 2026-09-01 to 2026-10-17 (n = 270, 332, 219, 222 by lead group):
| Days 1–3 | Days 4–7 | Days 8–10 | Days 11–15 | |
|---|---|---|---|---|
| ECMWF ENS, raw | 0.491 | 0.629 | 0.836 | 1.126 |
| ECMWF ENS, calibrated | 0.524 | 0.683 | 0.873 | 1.108 |
| Plain mean of raw models | 0.495 | 0.648 | 0.915 | 1.333 |
| Plain mean of calibrated models | 0.539 | 0.679 | 0.895 | 1.382 |
| Blend, every model calibrated | 0.521 | 0.662 | 0.924 | 1.266 |
| Blend, version chosen per model | 0.501 | 0.631 | 0.909 | 1.254 |
Choosing beats calibrating everything at every lead group, and the margin widens over October alone (0.984 against 1.021 at days 1–3, 1.330 against 1.398 at days 4–7). Against the plain consensus the blend is now ahead from day 4 out. Two things it does not yet do: at days 1–3 the plain mean of the raw models is still a hair better (0.495), and raw ECMWF ENS alone is the best forecast of heating degree days at every lead group except days 11–15. Blending in weaker models costs accuracy at short leads, and no weighting on 47 days of heating degree days should be trusted to fix that; the honest reading is that ECMWF ENS is the one to watch for week 1 and the blend earns its place from day 4. A winter has still not been scored.
For the ensembles, the share of days the Lower 48 mean temperature fell inside the published 10th–90th percentile range (80% is reliable), raw → calibrated: ECMWF ENS 36% → 56% at day 1, 43% → 67% over days 1–5, 75% → 81% over days 6–10 and 88% → 79% over days 11–15; GEFS 35% → 66% over days 1–5. The ranges of the first three days are still too narrow. The continuous ranked probability score of ECMWF ENS improved by 18% over days 1–5 and 12% over days 6–10 and was 4% worse over days 11–15. On the same runs and days, the pooled ensemble (ECMWF ENS and GEFS; GEPS had almost no calibrated runs yet) scored 4% better than calibrated ECMWF ENS alone over days 1–5, 2% worse over days 6–10 and 6% better over days 11–15, with its ranges holding the outcome 66%, 81% and 80% of the time against 55%, 73% and 67%. For total degree days over days 11–15, raw ECMWF ENS was still the best of the three.
Archive retention
Every run keeps its summary (all regions, states, the Lower 48) permanently. County rows make up about 97% of a run's member file and are only read by the map explorer's county view, so runs older than 45 days have their member files rewritten without them (fgas prune, daily). This bounds the archive's growth without losing any history that the backtests or records use.
The daily brief
The morning and evening publication windows open at 6:55 am and 6:55 pm Eastern. Each edition waits for that day's intended ECMWF ENS run (00Z or 12Z), with hourly retries after ingestion. If the run has not arrived after 11 am or 11 pm, a fallback uses the latest available run and is explicitly labeled as delayed. Edition dates follow Eastern time, including after midnight UTC. Each brief records its expected and actual run and its inputs' processing timestamps. It is written from the site's own numbers and covers:
- the latest runs' changes, in degree days and in Bcf
- the last EIA report against our last estimate before its release
- the next report's estimate and odds
- the call for the next ECMWF run, and how the last call did
- week-2 stability and scenarios
- the weeks 3–4 lean and its record
- the last week of observed weather
Nothing in it is typed by hand. Every edition is written once and never rewritten, and every storage estimate is logged when issued, so the archive shows what was said at the time.
Storage release calendar and winter reconstruction
Storage report dates and pre-release scoring cutoffs use 10:30 am in America/New_York, with
the published 2025–2026 exceptions from EIA's release calendar.
Daylight saving time and holiday shifts affect the actual UTC cutoff. Older historical
release dates use the regular Thursday schedule; their exceptions have not been reconstructed.
The winter storage evaluation is a reconstruction, kept distinct from the immutable live briefs and issued estimates. At seven, three and zero days before each Friday week end, an estimate is reconstructed for noon Eastern. The storage fit and its eight-week residual correction use only EIA reports whose release times precede that cutoff, with training from 2021 and at least 60 released weeks. Observed days are assumed available after three days; the remaining days use the newest assumed-available 00Z forecast covering each date, including earlier runs to fill gaps. GFS arrival is assumed to be six hours after initialization; the full 35-day GEFS arrival is assumed to be 28 hours after initialization.
Historical observations and EIA storage values are today's revised versions. Their original vintages and actual historical forecast-arrival timestamps are not available in this archive, so these results do not claim to reproduce information exactly as known at issue time. Weeks with missing data or insufficient training are counted as skipped. Each forecast score also reports the all-observed weather model's error on the same weeks, using the same fit and release cutoff, so differences in sample or available training do not distort the comparison.
Verification view
The Verification page compares two recent weather models on the exact same initialization, cycle, valid date and lead day, for the Lower 48 with population weights. Its 30- and 90-day windows refer to observed dates, ending at the latest available observation. Each lead can have a different sample. The 1991–2020 normal is scored on those same samples; skill is 1 minus forecast MAE divided by normal MAE, and is unavailable when the normal has missing values or zero error. Counts are forecast run/day pairs, which can share observed dates; they are not independent observations. The other model leaderboards continue to use each model's available sample and can therefore have different counts.
Each model's calibrated version, and three combinations (the plain mean of the raw models, the plain mean of the calibrated models, and the skill-weighted blend), can be chosen in the same matched comparison. Their scores are walk-forward by construction.
Ensembles as ensembles. The mean absolute error says nothing about whether a published range or probability can be trusted, so each ensemble (raw, calibrated, and pooled) is also scored on its members, by lead day and by lead band (days 1–5, 6–10, 11–15):
- CRPS, the probabilistic counterpart of the mean absolute error, in the same units, with the correction for a finite ensemble; and its skill against a climatological ensemble made of the same calendar day in each year 1991–2020.
- Spread ÷ error: the members' standard deviation against the root-mean-square error of their mean. One is reliable; below one is too confident.
- Inside the 10–90 range: how often the outcome fell inside the published 10th–90th percentile range. Reliable is 80%.
- Outside all members: how often the outcome fell outside the whole ensemble, against the 2 ÷ (members + 1) a reliable ensemble would give.
- Above normal: for each share of members above the 1991–2020 normal, how often the outcome was above normal, with the Brier skill against always quoting the sample's own frequency. Weekly totals get the same table.
Cases are run/day pairs that share weather, and 90 days is one season, so these are indications, not settled rates.
The issued storage record uses the latest logged estimate strictly before each report's actual release time. It shows original issue times, observed-day coverage and hours before release. Its summary covers up to 52 settled reports, and missing inventory weeks are excluded rather than treated as weekly changes. The estimate ledger preserves issued numbers; EIA truth uses the currently downloaded inventory record, including revisions. Lead time varies, so these scores are assessed separately from the fixed-horizon winter reconstruction. A missing or short record does not imply demonstrated accuracy.
The historical HDD chart scores each model against the normal on its own available archive, with day 1 denoting the first complete daily value in each run. It does not claim a matched comparison between models. The winter storage table pairs every model/horizon score with the all-observed benchmark on the same weeks. Legacy storage replay summaries are withheld until rebuilt with the released-report training cutoffs and forecast availability assumptions.