Roadmap
This roadmap outlines the planned order of development toward the v1.0 live forecast release (January 2027) and beyond. This page was last substantially revised July 2026, following a full codebase review and a reprioritisation (decided 2026-07-01) that made getting any forecast running on AWS the top priority over scientific-improvement work. That shipped as v0.1 in July 2026; the live service is now on v0.2 (deployed 13 August 2026), and work continues on the milestones below toward v1.0. Technical plans change as we learn more — treat this as a best-estimate, not a guarantee.
For how this page relates to GitHub issues,
docs/architecture/, and the rest of the docs — and which place to put new planning content — see the Documentation Guide.Status legend (used throughout these design docs): ✅ Implemented — exists in code today · 🚧 Planned — designed, not yet built · 🔬 Research — exploratory / v2.
Design documents
- Delivery tables — the five Delta Lake tables OCF delivers to NGED
(
power_forecast,power_forecast_warnings,asset_health_history,effective_capacity,substation_switching), with full field-level schemas. - Forecast building blocks — "normal" vs. "prevailing conditions" forecasts, sign conventions, and worked examples.
- Metrics & leaderboard — cross-fold validation protocol, evaluation metrics, horizon time-slices, and leaderboard grouping tags.
- Estimating the money a better forecast saves — the two £ leaderboard metrics (flexibility procurement and curtailment), the equal-risk method that avoids needing a price for a network breach, their limitations, and the open questions for NGED.
- Data sources — NGED power data + supporting files, network topology, and the weather datasets (ECMWF ENS, CAMS, ERA5, and the CEDA UKV archive that version 1 does not ingest), with the dated list of upgrades to each weather model.
- Live service — the AWS deployment: the
live_forecastsinference asset, the champion-model container, the costed AWS architecture options, production monitoring, and the handling of NWP model upgrades. - Handover to NGED — the operating model after the Network Innovation Allowance (NIA) project ends (the working assumption is that NGED runs the service on its own AWS account): the operator-contract design constraint, and the handover workstreams (runbooks, alert-on-absence, infra-as-code, confirming NGED's cloud and security standards, and game days).
- XGBoost improvements — the v0.5 experiment backlog: four effort tiers, ordered best bang-for-the-buck within each tier, targeting the 3–10 day user band.
- Extending the training history — using estimates of past weather, CAMS for irradiance and ERA5 for other variables, to train on the power data that predates the ECMWF ENS archive: the era-confounding hazard that dictates the ingest's scope, the reconciliation and pooling variants, how a weather product with a few months of history could enter the forecast, the COVID covariate, and why scoring against estimates of past weather is a diagnostic rather than a promotion criterion.
- A staged probabilistic forecast — 🔬 a design under test: a stage 1 that turns weather into power, a stage 2 that calibrates, uses lagged power, and blends weather products, and coupling that restores coherent ensemble members. The experiments that test it are on the ML experiments pages.
- Experiments run by an LLM agent — a large language model (LLM) agent searching for improvements to the XGBoost forecasting model in two phases: experiments run overnight from a plan agreed the day before, then a careful search in which the agent runs as a separate Unix user that never sees the leaderboard's validation window. The page also summarises what published research agents found. A person re-implements every idea that survives either phase.
- Engineering health — scientific-rigor tests and cleanup.
- Capacity estimation — the v0.7 head-to-head between candidate estimators of the time-varying effective capacity of metered generators: a convex (CVXPY) censored quantile-envelope estimator, a differentiable-physics variational estimator, and cheap baselines — the winner ships in v1.
- Net-demand disaggregation — the canonical v2 research arc: graph-structured disaggregation of net substation power into latent demand and DER generation, the convex dictionary baseline, MVA metering, prior art, and the novelty claims.
- Switching events — the canonical treatment of switching events and estimating latent demand under the normal running arrangement: the v0.6 unsupervised statistical detector and the v2 mixture models (the graph is a data structure).
Milestones
The milestone sections below show the order in which this work is planned. Each maps 1:1 to a GitHub epic issue.
v0.1 — "Naive" MVP (internal only)
Epic: #137 — deploy the
naive forecast on AWS. ✅ Shipped July 2026 (v0.1.0), superseded on AWS by v0.2 on 13 August
2026.
Goal: A simple XGBoost forecast that lets us test infrastructure end-to-end and establish a baseline. Intentionally does not detect switching events or estimate effective capacity — hence "naive" (assumes the grid is always in perfect health). The data pipeline, per-series XGBoost models, and CV leaderboard were already built; the remaining work was deployment, now running on AWS — see Live service.

v0.2 — Code Quality & Documentation
Epic: #138 — code quality,
reproducibility, and observability hardening. ✅ Shipped 13 August 2026 (v0.2.0) — running on
AWS.
- More unit tests, including feature-level lag-leakage and forecaster-level determinism tests ✅
(#62; exercised by
test_nullify_leaky_lags,test_engineer_features_weather_lag_leakage_preventionandtest_random_seed_makes_training_deterministic, alongside new package coverage fordynamical_data(#163) andgeo(#164)). The CV-windowing no-lookahead, leaderboard-fairness and fold-level determinism guardrail tests remain unwritten — see Engineering health - CI on GitHub (ruff + ty + pytest on every PR) ✅ (per-PR gate + nightly network tests; see Testing → Continuous integration)
- Improve documentation ✅ (#139)
- Verify daylight savings time handling is correct ✅
(#84;
test_apply_local_time_features_dst_transitionscovers both the spring-forward and fall-back transition instants) - Reproducibility stamping: git SHA + Delta table versions on every MLflow run ✅ (implemented in
ml_core.repro; every MLflow run carries the stamp) - Drop Hydra in favour of plain YAML + importlib + pydantic ✅ (
contracts.config_schemasowns the_target_round-trip; dropping the two dependencies also unpinnedantlr4-python3-runtime, which had been breaking Dagster's asset-selection strings) - Asset check on
live_forecastsreporting missed NWP runs at forecast time (#424) ✅ (live_forecasts_are_healthy: it also reads the slot's rows back off disk, so every production asset now has a check — including the one NGED consume) - Start the intervention log ✅ (started with the v0.1 AWS period; its measurement window opens at v1.0, but it cannot be reconstructed retrospectively, which is why it exists now)
v0.3 — Leaderboard / Performance Analysis
Epic: #6
- Implement the ML energy forecasting "leaderboard" (cross-fold validation metrics in MLflow), ready for systematic cross-validation runs ✓ (CV assets added)
- Metrics: MBE, MAE, NMAE, RMSE, Pinball loss, PICP, interval width, CRPS, Spread-Skill Ratio — all ✅ (definitions in the evaluation-metrics reference; plan and remaining 🚧 items in Metrics & leaderboard)
- Time-slice filters: nowcasting (0–6 h), day-ahead (6–36 h), medium range (Day 2–7), extended range (Day 8–14), peak events (top 5%)
- Baseline forecasters (the manual heuristic and climatology, with persistence in v0.9 as #1087) so leaderboard scores are interpretable
- Cost-savings metrics (£) — two figures per leaderboard row, for flexibility procurement and for curtailment, scored against manual review and against a perfect forecast; see Estimating the money a better forecast saves. Expected to be the metrics NGED read first, so they land early in this milestone.
- Production monitoring of the live service (
production_monitoringmetrics scope) - Failure-scenario evaluation — the evaluation machinery must precede the v0.5 experiments it is
meant to judge, or v0.5 picks a champion blind to how it behaves when inputs degrade:
- Canonical failure-scenario suite: named, versioned degradation transforms (#437) — see Scoring under failure scenarios
- Degradation smoke-tests in CI (#436)
- Score every leaderboard CV run under each scenario, against
manual_heuristic(#438)
- Phase 1 of agentic ML research — Claude runs experiments overnight, each testing one
hypothesis and ending in a verdict; an experiment whose output fits the scorer may post its scores
to the leaderboard as a
study/MLflow experiment, and the scorer drops the checks that exist only to stop deliberate cheating (#1031); see Experiments run by an LLM agent - One-command rollback for
promoted_model(#440), plus the runbooks that pin down what "one command" means (#448)
v0.4 — Automatic Data Cleaning
Epic: #150
- Automatic cleaning of NGED's power data. Versions 0.1 to 0.3 do none: the models train on, and the live service forecasts from, uncleaned telemetry. What has been measured about the trial area's faults, including the one commissioning cut-off already established, is in cleaning the trial-area telemetry
power_forecast_warningsPhase 1 —STALE NWPandSTALE POWER, withwarning_source(#439)power_forecast_warningsPhase 2 — the meter-error warning types, which are this milestone's cleaning detections surfaced to NGED (#441)- The
asset_health_historytable — the historical view of the same detections (#442)
v0.5 — XGBoost Upgrades ("Quick Wins")
Epic: #145
Establish a strong XGBoost baseline before investing in capacity estimation and switching event detection.
The full experiment backlog — four effort tiers, ordered best bang-for-the-buck within each tier — is in XGBoost improvements.
This milestone also carries the ingest of estimates of past weather (ERA5: #143, moved here from v0.7) and the pre-training experiments that ingest unlocks (#167) — see Extending the training history. The version-1 plan is CAMS for irradiance and ERA5 for other variables, and CEDA UKV is not ingested (see the CEDA UKV against ERA5 study). Our power data reaches back to late 2019 while the ENS archive starts 2024-04-01, and Dynamical.org's ENS back-fill is not expected until ~November 2027, so an estimate of past weather is how the seasonal experiments on this page get more than one winter to learn from. The Tier-1 and Tier-2 config wins do not wait for it.
This milestone also carries the quantile-ensemble pipeline (per-member quantile forecasts pooled into delivered percentiles — Phase D of Delivering the probabilistic metrics; theory in Probabilistic forecasting from NWP ensembles), which builds directly on the lead-time-feature and ensemble-member-training wins in that backlog.
It also carries the degradation half of the inherent-stability work, which is gated on that same quantile pipeline:
- Degradation-conditional interval calibration — conformal prediction per regime (#443), so the bands widen honestly when the inputs degrade rather than staying over-confident
- The weather-blind guarantee: outage-shaped training augmentation (#445), which is what makes "never worse than the manual heuristic" true rather than hopeful
- Clear-sky as the zero-data floor (#444), extending #168
- Make
live_forecastsdegrade rather than raise when NWP is absent (#446) — deliberately gated on the two items above, since degrading earlier would emit output no scenario has tested
Phase 2 of agentic ML research: once an XGBoost model beats manual_heuristic on the continuous
ranked probability score (CRPS), an LLM agent screens the XGBoost backlog, and possibly larger ideas
from other roadmap pages, as a separate Unix user that never sees the leaderboard's validation
window (#1169). The
maintainer leans towards screening every idea. Experiments run by an LLM agent
gives the published evidence, and a design in which the agent screens ideas on data before the
leaderboard's validation window, an idea is implemented again whenever the idea's score is close to
a competitor's, and a person re-implements every idea that survives in a reviewed pull request.
v0.6 — Switching Events
Epic: #151. Internal only for first month, then shared with NGED. (v0.6 vs v0.7: we don't yet know which of switching events and capacity estimation will actually land first — but naming one v0.6 and the other v0.7 beats the ambiguity of "v0.6 or v0.7"; we'll swap them later if reality disagrees.)
- Build the shared switching infrastructure: the stage-1 weather/calendar baseline, normalised residuals, the labelled event table, and the synthetic-injection harness — see Switching events & latent demand
- Ingest the NGED supporting files this needs (substation adjacency, switching logs)
- Make the forecaster switching-aware with residual, event-age, and pooled-neighbour features, and run the v1 label-exclusion experiments — the feature-based mainline
- Conditional — see the decision
point:
the discrete detector (changepoint detection and attribution), training-data cleaning from
detected events, and the
substation_switchingDelta table
v0.7 — Dynamic Generator Capacity
Epic: #141. Internal only for first month, then shared with NGED.
Dynamic effective capacity estimation for metered generators (capacity estimation)
The estimator is chosen by racing candidates head-to-head on the same data, and the winner ships in v1. What they estimate is the effective capacity of the metered wind and solar PV generators over time, which bumps up and down with maintenance, faults, and build-out. The contenders are a convex (CVXPY) censored quantile-envelope estimator, a differentiable-physics (PyTorch) variational estimator, and cheap baselines. The judging criteria — including uncertainty quality and robustness to missing inputs, scored against the same failure-scenario vocabulary the forecasting leaderboard uses — are on the capacity estimation page.
Capacity estimation is the first model family we must actively build for missingness. A differentiable-physics estimator degrades most gracefully of all, and that should count in the judging.
A deliberate secondary goal of the contest is building hands-on CVXPY experience, to inform v2 tooling choices and our advice to NGED.
The "clever" latent-demand and abnormal-running-arrangement inversion is explicitly not in scope here. That inversion is v2 research.
The remaining work items for metered-generator capacity:
- Two-pass approach: first pass estimates effective capacity; second pass normalises the time series by effective capacity before training the power forecast model
- Ingest CAMS (Copernicus Atmosphere Monitoring Service) solar radiation — satellite-derived irradiance, used to estimate solar PV capacity (data sources). Wind-farm capacity estimation takes its wind from the planned estimate of past weather for variables other than irradiance, which is ERA5 in the version-1 plan
- Populate the
effective_capacityDelta table
CAMS is an offline source: it feeds historical capacity estimation, and the production serving path does not depend on it, so its near-real-time freshness is not the reason we chose it. The reasons are that its values accumulate over the metering interval rather than sampling an instant, that it draws on 3-hourly aerosol analyses, and that it offers steps down to 1 minute — which is what the dynamic thermal model would need.
The ingest is small. CAMS serves one point per request rather than a grid, but the v1 trial area needs at most 32 requests, and 6 of those requests cover its solar farms. CM SAF SARAH-3 stays on the list as a v2 comparison.
Dynamic effective capacity estimation for substations:
- For now, while we're forecasting substations top-down, just use the 99th percentile per year as the effective capacity. Later, in v2, the system should already capture everything we need to know about substation capacity, as a function of all the weather, demand, and topology drivers of the substation's behaviour.
"Prevailing conditions" building block (needs both the v0.6 switching and v0.7 capacity blocks):
- Produce example Python code for NGED to construct a "prevailing conditions" forecast from OCF's building blocks
v0.8 — Improve Live Service
Epic: #323
The bucket for operational improvements to the running live service — efficiency, robustness, and operability polish discovered during early live running, as distinct from the forecast-skill milestones above. Items so far:
- Replace the polling schedules with Dagster sensors (#324): cheap "is there new data?" detection runs on the control-plane box, and Fargate tasks launch only when there is real work to do. Design context: Production Deployment — Design.
- Codify the AWS infrastructure as infra-as-code (#326): the Terraform-vs-CDK question and the sequencing (start at access-phasing Stage 2) are in the live-service plan; the account-portability requirement is in Handover to NGED.
- Consider seven pieces of industry best practice we currently lack (#449): input-drift detection, shadow deployment of a challenger model, a schema-evolution policy for the delivery contract (which may need pulling forward to v0.6), statistical process control on forecast error, naming poka-yoke among the design principles, a retraining cadence and trigger, and monitoring how NGED uses the delivered forecasts — each discussed in Design Principles → Industry best practices we have not yet absorbed. A holding issue: the task is to consider them once the live service has run for a while, not a commitment to build them.
v0.9 — Nice-to-haves if we have time
Epic: #361
Genuinely optional experiments worth trying if the schedule allows, sitting between the operational polish of v0.8 and the v1.0 trial-service milestone. Nothing downstream depends on any of them — if we are short on time, none of it blocks v1.0. Each lands as its own registered leaderboard CV run or controlled ad-hoc ablation, so we keep the result either way.
- Neural net vs XGBoost as a leaderboard CV run
(#362): does a simple
neural net — an MLP with a per-series embedding and quantile-regression heads — beat
gradient-boosted trees? XGBoost suits the current per-series regime (one model per series, on the
order of 10⁴–10⁵ rows), and the recurring "trees are bad at maths" pain is already handled cheaply
by the physics and residual features on the XGBoost improvements page.
So the decisive, cheap test is the sibling of the global model per
time_series_typewin: a global MLP against a global XGBoost on the identical feature frame, run once that win's prerequisites (per-series target normalisation, static per-series features, and init-time-anchored features) exist, so the comparison isolates the model family. A negative result de-risks the neural approaches on the post-v2 research list before we spend research time on the fancier ones. The spike must also state and test how it handles missing inputs: XGBoost gets NaN routing for free and an MLP does not, so a zero-filled MLP would lose the comparison for a reason that has nothing to do with model family (zero is a real physical value — see Encoders → Handling missing inputs), and it should be scored under the failure-scenario suite like any other CV run. - Additional NWP source, e.g. ICON-EU (#363): explore whether adding ICON-EU from Dynamical.org improves forecast skill over ECMWF ENS alone — the v1 nice-to-have version of the broader v2.1 multi-source item. The v0.5 perfect-weather ceiling sizes the forecast-error headroom, but that ceiling does not bound resolution, so ICON-EU's ~6.5 km grid could still beat a coarser estimate of past weather, such as the 31 km ERA5, on representativeness. Because ICON-EU's history starts early 2026 (shorter than the canonical CV folds) it is assessed via a controlled ad-hoc ablation, not the leaderboard, until it has ~1–2 complete years of history. A product calibrator, under research, could let ICON-EU into the forecast sooner. See Evaluating a data source whose history is shorter than the folds.
- Handle NWP model upgrades (#851): an upgraded weather model arrives on time and passes validation, so nothing in the live service notices it, yet the promoted model was trained on the old version. The plan records the NWP model cycle on every row, keeps a dated list of upgrades, treats an upgrade as a degradation that widens the uncertainty bands, and retrains early. It starts with a study measuring how fast a model recovers after the Met Office's January 2026 upgrade of UKV. See Live service → NWP model upgrades.
v1.0 — Stable Live Service for NGED's Trial Area
Epic: #133
Target: January 2027
- All features listed above (v0.1–v0.8), plus fixes discovered during live running
- 32 time series in the NGED trial area (scope)
- Five Delta Lake output tables delivered to NGED every 6 hours:
power_forecast— [−1, +1] ensemble power forecastspower_forecast_warnings— meter, generator, and feed-health warnings pertime_series_id(the nine warning types)asset_health_history— complete historical record of each time series's health stateeffective_capacity— half-hourly probabilistic effective-capacity estimates (mean + std after the v0.7 upgrade, #247; a static scalar per series in v0.1)substation_switching— estimated power diverted between substation pairs (mean + std)

v2.0 — Scale-Up
Epic: #156 (WP5: delivery of the v2 live service)
Required:
- Scale to approximately 2,500 time series: all of NGED's primary substations (1,161), BSPs (271), GSPs (52), and most customer meters (~1,000)
- Estimate the installed capacity of unmetered solar PV and wind on each primary substation (by disaggregating net primary substation power flows)
Stretch goals:
- Forecast unmetered solar and wind power at each primary substation
- Disaggregate additional DERs (price-sensitive assets like batteries) from substation power flow
- Build a REST API on top of the Delta Lake delivery mechanism (purely additive — see when a REST API would earn its keep)
v2.1 — XGBoost Improvements at Full Scale
v2.1 is about a month of XGBoost work, once the v2 live service runs for all 2,500 time series. v2.1 picks up whatever XGBoost improvements v0.5 left undone, and adds further NWP sources as features, or through a product calibrator if the study of that design shows promise.
Model cards for promoted models
Deferred until after v2 ships. Every model promoted to production should get a model card recording detailed feature importance, calibration behaviour, and the population it was trained and validated against — the record an operator or an auditor needs to trust a specific promoted model. The Energy Systems Catapult DNO Forecasting Forum names model cards under the same "Explainability" characteristic as the feature attributions below, as what supports operator trust and incident investigation. A model card is a heavier, promotion-time record, distinct from the lightweight per-training-run feature attributions every model gets (see Log feature importances for every trained model). Model cards are a stretch beyond what v2 needs in order to ship live, so this workstream starts once the v2 service is running.
After v2.1 — Research (Advanced ML)
The research items run roughly in the order listed. The weather encoder trains through the differentiable-physics modules, so the encoder comes after the physics and disaggregation work.
- Differentiable physics for power forecasting (not just capacity estimation): use DP models to directly forecast power, handling MVA metering natively (see the graph-structured engine and MVA metering), and to calibrate each weather product in weather space by gradient descent (see the weather-space arm)
- Graph-structured disaggregation: Model substations, metered generators, and unmetered generator fleets as nodes in an electrical/spatial graph, with edges representing physical connections. The graph is a data structure — a structural prior on who can exchange load and which sites share weather: each substation is reconstructed as a sum of per-site differentiable-physics modules with inferred capacities, and cross-site gains come from hierarchical parameter sharing. (See Net-demand disaggregation — the canonical page for this arc, including the convex dictionary baseline it must beat — and the switching-events approaches.)
- Top-down forecast coherence checking: check whether independently-produced primary, BSP, and GSP forecasts sum consistently up the substation hierarchy — a lighter check than the comparison below, worth running first because it needs no new modelling, only the forecasts v2 already produces. The Energy Systems Catapult DNO Forecasting Forum names hierarchy coherence as its own forecast characteristic, for exactly this reason.
- Bottom-up vs top-down substation forecasts: compare a substation forecast built by summing the forecasts of the assets behind that substation (metered generators, disaggregated demand, and disaggregated unmetered generation) against a forecast of the substation's own net power taken directly, to see which is more accurate.
- Latent-demand recovery under switching: reconstruct the demand each substation would have metered under the normal running arrangement, using a time-varying neighbourhood mixture (optionally type-resolved into demand / PV / wind) over the network graph. This neighbourhood-mixture approach reconstructs the topology-normalised demand NGED requires, and goes beyond the v0.6 statistical detector — which only flags and masks switching periods. See Switching events & latent demand.
- Synthetic telemetry from fitted models, for the problems whose labels are missing: three of
this project's problems are scored against labels that are incomplete or absent — disaggregating
unmetered distributed energy resources (DERs), detecting switching events, and estimating the
effective capacity of metered generators. Fitting the per-site generation modules (differentiable
physics) and the shared demand-profile basis (the
BasisLoadNode), then running them forward on real weather and summing the sites, produces a simulated substation whose generation, demand, and capacity are all written down by construction. Editing the simulated sum writes the labels the other two problems need. Reassign a site from one substation's sum to a named neighbour over a known window to label a switching event; step a site's capacity down on a known date to label a capacity change. Both edits are exact in simulation, where the real-data harnesses can only approximate them by scaling a fraction of net power. The hazard is circularity: an estimator scored on data generated by its own model family measures whether the parameters are identifiable, not whether that model family matches reality. Two consequences follow. Parameters must be drawn afresh rather than frozen at their fitted values wherever the fitted value is the quantity under test — a capacity estimator scored against its own earlier answer measures only that the fit reproduces, and simulating with the same biased irradiance hides the weather-bias aliasing that page names as the dominant systematic error. And a passing score never stands alone, because the simulated telemetry carries none of the meter noise the switching detector's thresholds are normalised against. The simulator therefore supplements the real-data harnesses rather than replacing them: injection into real telemetry stays the primary evidence for switching detection, and the other disaggregation spokes stay the primary evidence for disaggregation. - JEPA (Joint Embedding Predictive Architecture, à la Yann LeCun): adapt to demand forecasting using JEPA's encoder and predictor as the "load" module in the graph-structured disaggregation engine
- Pre-trained neural network encoders: "weather encoder" and "time encoder" pre-trained on large datasets, then fine-tuned for substation forecasting
- Multi-sequence alignment with axial attention: find "similar" historical days and feed them as additional context to the forecasting model
- CRPS training objective: train the ensemble power forecast model to directly optimise CRPS for sharper probabilistic forecasts (issue #1156 plans a test, run only if cheaper calibration steps leave the forecast poorly calibrated)
- Modelling DER response to market signals (stretch goal, only if time remains well after v2): extend the differentiable-physics DER modules to react to a price signal directly — battery charge/discharge and other price-sensitive dispatch as a function of the market signal, rather than as unexplained residual behaviour
Handover to NGED (post-NIA operating model)
Epic: #309 — see Handover to NGED for the design.
The working assumption is that, after the NIA project, NGED runs the Flexpectation service on its own AWS account (see Requirements → Operating model & handover). This handover is not a single late milestone: it sets a standing design constraint from today (NGED staff who did not develop the code must be able to run the service day to day, working from the runbooks — the operator contract), one workstream that must start early (confirming NGED's cloud and security standards, because the Tailscale-based access design has to fit those standards), and a cluster of late-project work (runbook hardening, game days, and progressive transfer of control). The gate: OCF runs the full v2 service for a few months before NGED decides on the operating model after the NIA project.