project-020 · Forecasting · energy
Day-ahead quarter-hour load with daily, weekly and annual seasonality
An energy supplier serving a portfolio of business clients must submit tomorrow's 96 quarter-hour volumes by a day-ahead gate (assumed 10:00 the day before, a hypothetical setting). Which forecasting approach handles the overlapping daily, weekly and annual cycles well enough to reduce imbalance volume against a weekly seasonal naive?
At a glance
Data
ElectricityLoadDiagrams20112014 (UCI) (public) · 370 client columns x 140,256 quarter-hour records (listed as 140,256 'features' on the UCI page), 2011-2014; one semicolon-separated text file.
Details on dataBaseline
Weekly seasonal naive (same quarter-hour, same weekday, one week earlier) and daily seasonal naive using the most recent available day (two days earlier because of the…
Details on baselineValidation
Daily rolling origins at 10:00 over the final year, expanding window; each origin forecasts the 96 intervals of the next calendar day using data up to 00:00 of the…
Details on validationMetric
MAE and WAPE per quarter-hour of day, MASE scaled by in-sample weekly seasonal-naive error, peak-interval absolute error.
Details on metric
Success criterion
Across rolling daily origins over the final year, the chosen method reduces mean absolute imbalance (kWh per day) versus weekly seasonal naive by a margin larger than twice its origin-level standard error, and does not lose on Portuguese public holidays or daylight-saving days by more than 10%.
Context
Load data at sub-hourly resolution carries several seasonal periods at once (96 intervals per day, 672 per week, roughly 35,000 per year). Single-season methods cannot represent all of them; options include MSTL decomposition, TBATS, or regression on Fourier terms plus lags. The horizon starts 14 hours after the gate and ends 38 hours after it; with meter data assumed to arrive one day late, the newest usable value is from 00:00 of the origin day, so every target is 24 to 48 hours away from the last observation.
Data
- Dataset
- ElectricityLoadDiagrams20112014 (UCI) (public)
- Licence
- CC BY 4.0 (as stated on the UCI page)
- Size
- 370 client columns x 140,256 quarter-hour records (listed as 140,256 'features' on the UCI page), 2011-2014; one semicolon-separated text file.
- Verification
- identity verified
Access
Direct download from UCI, no login; the zip is about 250 MB (678 MB unzipped), so download once, convert to Parquet, and record the checksum. Fallback if the download is blocked: none verified; do not substitute a mirror without checking its provenance.
Grain
Raw: quarter-hour timestamp (Portuguese local time) x client, values in kW (divide by 4 for kWh per interval). Modelling grain: portfolio total of clients with complete history from 2012-01-01, per quarter hour.
| Column | Meaning |
|---|---|
| timestamp (first column) | Quarter-hour in Portuguese local time, 'yyyy-mm-dd hh:mm:ss' |
| MT_001 ... MT_370 | Client consumption in kW for the interval (column naming to be confirmed on load) |
| zero values before a client's start | Client not yet connected (page note), not zero consumption |
| DST change days | March: 1:00-2:00 recorded as zeros; October: 1:00-2:00 holds two hours aggregated (page note) |
EDA and data-quality rules
Drop clients with pre-start zeros after 2012-01-01 from the portfolio, or start their contribution at connection; document which.
Repair DST artefacts explicitly: impute the March zero hour from adjacent weeks; split the October aggregated hour; never let these enter training as real values.
Convert kW to kWh per interval before computing energy totals.
Check each day has exactly 96 intervals after the DST repair.
Baseline
Weekly seasonal naive (same quarter-hour, same weekday, one week earlier) and daily seasonal naive using the most recent available day (two days earlier because of the gate).
Features
For LightGBM: quarter-hour of day, weekday, Portuguese public holiday flags from the holidays package (known
in advance), Fourier terms for the annual cycle, lags that end before 00:00 of the origin day (for example 2 days and 7 days at
the same quarter hour), and rolling means ending at the data cutoff. No temperature is available in this dataset;
record that as a limitation rather than inventing a weather feed.
Candidate methods
MSTL decomposition (periods 96 and 672) with AutoETS on the seasonally adjusted series (statsforecast)
Handles several seasonal periods explicitly and remains interpretable: each seasonal component can be plotted and checked.
LightGBM with calendar, annual Fourier terms and gate-safe lags
Can learn holiday and weekday interactions that additive decomposition misses; must respect the data cutoff at 00:00 of the origin day. TBATS is a documented alternative left out for runtime at this resolution.
Validation design
Daily rolling origins at 10:00 over the final year, expanding window; each origin forecasts the 96 intervals of the next calendar day using data up to 00:00 of the origin day (meter data assumed to arrive with a one-day lag, a stated assumption). Hyperparameters fixed from the preceding year.
Leakage checks
Unit test that every lag feature refers to a timestamp before 00:00 of its origin day; check holiday flags come from a calendar, not from observed low load.
Bias and representativeness
Bias by quarter-hour of day and by weekday; a model that is unbiased overall can systematically under-forecast the morning ramp.
Robustness checks
Evaluate separately on DST days and on holidays; re-run with 2013 as the evaluation year to see whether the winner changes.
Technical metrics
MAE and WAPE per quarter-hour of day, MASE scaled by in-sample weekly seasonal-naive error, peak-interval absolute error.
Business interpretation
Daily imbalance volume (sum of absolute interval errors in kWh) and an imbalance cost with hypothetical asymmetric prices (shortfall dearer than surplus); show how the asymmetry would shift the optimal bid away from the mean forecast (links to project-022).
Error slices
Quarter-hour of day (night, morning ramp, midday, evening peak).
Weekday vs weekend vs public holiday.
DST change days.
Season (summer vs winter).
Implementation steps
Download once, convert to Parquet, write tests for 96 intervals per day and DST repairs.
Select the portfolio and aggregate in kWh; plot one week and one year to see the seasonal layers.
Implement both baselines with the gate-aware data cut.
Fit MSTL + AutoETS and LightGBM in the daily rolling loop; store forecasts with origin.
Score per quarter-hour and slice; compute daily imbalance volume and hypothetical cost.
Recommend a method and a fallback, with the DST and holiday handling written down.
Reproduction
Learner script with a cached, checksummed download; a 3-month evaluation window runs on a laptop in minutes, the full year optionally.
Limitations
No weather variable: temperature-driven load changes are unexplained and show up as residual error.
The portfolio is an arbitrary subset of anonymous clients, not a real supplier's book.
The gate time and data lag are assumptions; a different market design changes the horizon.
Production and monitoring
Daily job before the gate; publish 96 values with a version id; monitor interval-level bias and daily imbalance; alert when the DST repair rule fires; fallback to weekly seasonal naive if the job fails or data arrive incomplete.
Interview questions
How would you model three seasonal periods at 15-minute resolution, and what does each option cost?
Your forecast is issued at 10:00 for tomorrow. Which lags can you use?
The March DST day shows an hour of zeros. What do you do and why?
Postmortem and alternatives
Likely findings: holidays and bridge days dominate the largest errors; MSTL handles the weekly shape well but misses holiday interactions. Alternatives: add a weather feed with archived forecasts, or a hybrid (MSTL seasonal components as features for LightGBM).
Rubric3 criteria
| Criterion | Meets | Exceeds |
|---|---|---|
| Data repair | DST artefacts, pre-start zeros and units handled with tests. | Quantifies how unrepaired DST days would have biased the evaluation. |
| Gate-aware validation | Daily origins with the data cutoff enforced and tested. | Shows the error difference between a gate-aware and a naive next-day setup. |
| Seasonality reasoning | Seasonal components plotted and checked against the error by quarter hour. | Explains which seasonal layer each candidate fails on and why. |
References5
- MSTL: A Seasonal-Trend Decomposition Algorithm for Time Series with Multiple Seasonal Patterns
MSTL for several seasonal periods.
- Forecasting Time Series With Complex Seasonal Patterns Using Exponential Smoothing
TBATS for complex seasonality; the alternative not chosen for runtime.
- STL: A Seasonal-Trend Decomposition Procedure Based on Loess
STL decomposition that MSTL extends.
- StatsForecast documentation (Nixtla)
MSTL and AutoETS implementations.
- Forecasting: Principles and Practice (3rd edition)
Decomposition and complex seasonality chapters for interpretation.