Scenario run
Whole-GB fleet, cannibalisation fixed point solved to convergence. Prices, fleet build-out and BESS dispatch are solved jointly — not in sequence.
Convergence
KM iteration λk=2/(k+2) · stop ‖π(k+1)−π(k)‖∞ < £1/MWh (or stable single-digit band) · μ-regularised fallback
GB fleet map
Schematic coastline · dot area ∝ MW · operational construction consented
Registry
Seed registry compiled from public sources — see FLEET_SOURCES.md. Replace with NESO TEC / Elexon feed when licensed.
| Site | Operator | MW | MWh | Class | Zone | Year | Status |
|---|
Price duration curve
Sample week — wholesale price
Sample week — dispatch
Revenue stack by duration class — £/MW/yr
Revenue tracks
| Class | Fleet MW | Wholesale (eq) | Naive wholesale | Bias | FR | CM | BM | Total £/MW/yr | Cycles/day | Spread capture |
|---|
Sensitivities (TechSpec quarterly set: gas ±30% · build ±20% · carbon ±40%)
Compare runs (any completed scenario-years, side by side)
Revenue uncertainty (Monte Carlo weather draws — P10/P50/P90, TechSpec §8)
Cannibalisation curves (WP01 sweep: per-MW revenue vs fleet size)
Manage runs — every stored run (all kinds): label, report, data pack, delete
| Created | Kind | Scenario · years | Wk | Anchor | Label | Status | Actions |
|---|
Labels are display names only — the audit manifest is never modified. Deleting a run removes its stored results permanently.
Analyse a new candidate site
The candidate joins the whole-GB fixed point as an extra asset class — its revenue is evaluated at the with-candidate equilibrium, never against exogenous prices (WP01 §7.1).
Revenue stack
Project finance
Grid connection (CEAtlas) indicative
Revenue track over asset life
Equilibrium price shift
NPV tornado (what does the IC ask? — single-knob NPV drivers, one shared basis)
Portfolio (all analysed sites — per-asset attribution)
| ⇄ | Site | MW | Dur | Zone | Scenario · year | Eq £/kW·yr | Total £/kW·yr | Bias | DSCR | P90 DSCR | Min DSCR | NPV £m |
|---|
No sites analysed yet — every analysis is saved to the portfolio automatically.
Revenue track overlay (stacked total £/MW/yr over asset life)
Methodology — a model you can interrogate
Cannibalisation fixed point (moat-critical)
Wholesale prices and whole-fleet BESS dispatch are solved to a self-consistent equilibrium π* = Ψ(Φ(π*)) by Krasnoselski–Mann iteration with harmonic step λk = 2/(k+2) (WP01, Algorithm 1). Plain or relaxed Picard iteration provably fails for GB fleets beyond ~2 GW. The naive (price-taker) forecast is always reported alongside the equilibrium — the bias between them is the number that decides DSCRs.
Dispatch
Per-cohort half-hourly LP: SoC dynamics with one-way efficiencies √η, self-discharge, degradation as a marginal cost (£2.50/MWh discharged, LFP default), one-sided cyclic boundary eT ≥ ½E, least-cycling lexicographic tie-break. Whole-GB fleet aggregated into BESS_<year>_<duration> cohorts from the site registry.
What is reduced-form in v1 (disclosed, per the TechSpec's own phasing)
- Balancing Mechanism: statistical proxy per TNUoS zone × duration class — NOT dispatch-based. Iteration 40: the zone factors are measured from the CE index trailing-year EBOCF offer-leg zonal split (which inverted the old hand-set Scottish-premium guess — measured skip rates put Z4 at 0.48× and London/SE at 1.41× the GB mean; thin-sample zones default 1.0, per-zone counts disclosed). Iteration 41 (executing the pre-registered rule): the per-class bases are now CALIBRATED to the index trailing-year measured EBOCF values (1h £8.2k / 2h £11.8k de-trended; the one-way line floors the 4h class at £0 against a measured NEGATIVE net — an honest structural hard-fail; 8h is unmeasured and stays a placeholder, disclosed).
- Frequency response (DC/DM/DR): saturation price model re-anchored (iteration 41) to the NESO EAC trailing-year volume-weighted clearing prices (DC two-leg £5.39, DM-L £6.08, DM-H £1.25, DR-L £14.20/MW/h) with participations refit to the measured per-class FR revenue — the θDC 2021→2024 collapse rate (£17 → £3.5/MW/h per leg) is preserved; DR-H cleared negative over the trailing year and is unremunerated (disclosed). The FR verdict cells below therefore wear a fit (in-sample) badge, never "pass" — they were fit to those targets.
- Capacity Market: cleared price × NESO duration de-rating; bounded random walk for future auctions.
- Calibration constants kD = 1.0 (BM/CM/FR are modelled explicitly, so kD ≠ 1 would double-count). The Dispatch-Spec calibration harness is implemented: the 2h cycles/day check runs against the public Modo 1.2–1.5 band (PASS/FAIL in the backtest panel below) with the CE GB BESS index pilot as cross-check, and the spread-capture reference now comes from the CE index (primary-data proxy basis, disclosed below) — no third-party benchmark licence.
- Forward-run demand/wind/solar profiles are synthetic-but-calibrated: the no-BESS price duration curve is fitted to WP01 GB targets (mean £88, P50 £70, P95 £216, max £676/MWh) under the default wp01 anchor; the selectable realised-2024 anchor replaces the curve base with the Elexon-calibrated 2024 fit (in-sample), and the selectable trailing-12m anchor recalibrates the same machinery to the trailing 12 months of realised Elexon prices through the latest settled day (window disclosed per run; staleness flagged after 35 days — see the Forward anchor freshness card below). Realised Elexon MID prices drive the backtest and both realised anchors. Realised NESO/Elexon demand-wind-solar profiles (public no-auth APIs, cached in-repo) are integrated and selectable for the 2022–25 backtests, with a fitted 2-parameter affine basis alignment (in-sample, disclosed per run) that closes the realised TSD-basis level gap to ~4–6% on the window mean; synthetic remains the default because the remaining gap is curve SHAPE on the realised basis (P50 cold, P95 hot — measured numbers in the run caveats). An experimental shape-fit calibration (k, σ freed; payload calibrated_shape) closes 2022 to sub-1% but pins a parameter at a bound every year and was not adopted under the pre-registered rule. On 2023/24 the below-band calibrated cycles coincide with price spreads matching realised within 10% (payload spread_diagnostics) — spread amplitude is ruled out as the shortfall there, and double-counting of history's storage response, dispatch-cost assumptions and band composition are indistinguishable to that diagnostic; 2022's spreads run 37% wide with cycles still below band (unresolved, dispatch-side). The cycles check is excluded from the realised-default-flip rule unless evaluated on a no-BESS counterfactual basis. FORWARD runs remain on synthetic-but-calibrated profiles; live forward profile feeds are the remaining data step.
Uncertainty & finance conventions
- Exceedance convention for revenue bands: PXX is the value exceeded in XX% of Monte Carlo draws, so P90 is the conservative (low) band. Price statistics (e.g. the P95 price) remain percentile-convention scarcity tails.
- Monte Carlo design: N bootstrap weather realisations, each solved to its own cannibalisation equilibrium; bands carry standard errors of the mean.
- Finance targets: P50 DSCR target 1.40× and P90 (exceedance) lender covenant 1.10×.
- Multi-year revenue track: candidate finance runs on the cannibalisation-aware year-by-year revenue trajectory against the growing fleet, with the minimum DSCR and its binding year reported.
Validation invariants (every solve; violations halt the pipeline)
SoC bounds · round-trip consistency · price sanity −£200 ≤ π ≤ £5,000/MWh · zero-storage limit · KKT residuals · cross-solver oracle (CEMeridian vs HiGHS, 1e-6 rel)
CE GB BESS index — the product's own benchmark from open primary data
The product's benchmarks are computed from Elexon BMRS and NESO open data under their open licences — no third-party benchmark licence. The battery-BMU registry (cecadence/data/bess_bmus.py, pinned committed cache) cross-references the Elexon BMU register, NESO EAC auction results (technologyType Batteries) and the NESO CM register storage duration classes (postcode join, disclosed per row). The pilot index window measures, from primary data only: fleet cycles/day (B1610 metered volumes ÷ energy capacity), a wholesale revenue proxy per MW (metered volumes × MID half-hourly prices — an ex-post proxy, not traded positions), BM revenue per MW (EBOCF bid-offer cashflows) and FR revenue per MW (EAC clearing price × executed quantity per product), plus revenue shares by stream. Full provenance, conventions and the measured numbers ship in docs/evidence/bess_index_pilot.json (regenerate: scripts/build_bess_index.py). Pilot Q1-2026 measured (168-BMU registry, ~6.7 GW deduplicated; 149 active BMUs / 6.2 GW): 2h-class cycles 1.04/day (vs the public Modo 1.2–1.5 band, kept as the public-research cross-reference), spread capture 24.2%, BM £23.8k/MW/yr (EBOCF), FR £13.4k/MW/yr (EAC, per-product), wholesale net metered-at-MID proxy £4.8k/MW/yr for the 2h class — the wholesale figure is a disclosed FLOOR (metered volumes embed BM/FR throughput marked at MID), one quarter, initial settlement. BM/FR numerators cover exactly the ACTIVE unit set of the per-MW denominator, and duration classes ignore future CM delivery years (iteration-39 review corrections; the excluded revenue is quantified in the pilot JSON). Iteration 40 extends the index to the trailing four fully-settled quarters (2025-Q2…2026-Q1: one registry, per-quarter active-unit scoping handles mid-period commissioning, active-MW-day weighted aggregation) and adds the Capacity Market stream from the CM register's awarded de-rated obligations × auction clearing prices (delivery years overlap-weighted; initial-auction basis). The card below renders the measured per-duration-class annual numbers from docs/evidence/bess_index_trailing.json (regenerate: scripts/build_bess_index.py --trailing).
📄 The latest measured quarter is published as the CECadence Quarterly GB BESS Index report ↗ — on-brand, print-to-PDF, built from this same open data.
loading CE GB BESS index…
Calibration harness — model (2026 CE-CENTRAL) vs CE index trailing year
The Dispatch-Spec calibration harness (cecadence/calibration.py) grades the model's per-duration-class BM and FR revenue lines and cycles/day against the index-measured trailing year, like-for-like by stream, with the CALIBRATION_TOLERANCES verdicts (per-duration revenue 15%/20% soft/hard; cycles 10%/15%, 25% reject). kD stays 1.0 — the harness validates the explicit reduced forms and publishes pass/fail honestly; the index wholesale floor and spread capture are context, never graded (basis mismatch, disclosed). Model side: scripts/build_index_calibration.py (claim-grade 26-week 2026 CE-CENTRAL run, wp01 anchor).
loading calibration verdicts…
Backtest evidence — measured record (2022–25, 26-week horizon)
Pre-computed through the same run_backtest pipeline as the live form below, on the pinned public-data caches; every cell is reproducible live. Generated stamp and honest caveats travel with the data. 2025 is the pre-registered HELD-OUT validation year: every rule (alignment bounds/quantiles, check targets, cycles rules, week sampling, coverage gates, fuel-multiplier derivation) was frozen in committed code before any 2025 backtest input was fetched, and the results publish regardless of outcome — protocol in docs/evidence/heldout_2025_protocol.md.
loading evidence summary…
Forward anchor freshness — trailing-12m calibration
The selectable realised_trailing price anchor is the supply curve recalibrated to the trailing 12 months of realised Elexon MID prices through the latest settled day (the same equilibrium-refit machinery as the realised-2024 anchor; in-sample for the window). Every anchored result discloses its calibration window; a window end older than 35 days flags runs STALE (they still work) until the calibration is refreshed here.
loading trailing-anchor calibration…
Backtest vs realised (Elexon MID) — run it live
The model is re-run for a historical year with the fleet that actually existed (site registry, no scenario top-up) and compared against realised GB half-hourly market-index prices from the public Elexon Insights API — annual mean within 5% is the credibility target (measured PASS/FAIL per year on the Evidence card above; the held-out 2025 year FAILS in both modes (P95 tail in both; synthetic also misses the 5% mean at +12.0%), published unmodified per the pre-registered protocol). Model-side profiles default to the calibrated WP01 synthetic basis the supply curve is anchored to; realised historic demand/wind/solar (NESO data portal + Elexon FUELHH, cached in-repo) is selectable — a fitted affine basis alignment (in-sample for prices, disclosed in the payload) closes the measured cold level gap to ~4–6% on the window mean, but P50 stays cold and the P95 tail runs hot, so synthetic remains the default (the run's caveats carry the measured numbers). On 2023/24, below-band calibrated cycles coincide with price spreads matching realised — spread amplitude is ruled out as the cause, while double-counting of history's storage response, dispatch-cost assumptions and band composition are indistinguishable to that diagnostic (the dispatch-check table carries the applicability note verbatim); 2022 is unresolved (spreads 37% wide).
No backtest run this session — run one above to check the model against realised Elexon prices.
Latest run manifest
No runs yet.