1. What this module is, and why it exists
This volume is the trader seat’s home. It starts at Trader Pools (§2), opens the book behind one pool, and walks Rules, Forecast and Outcomes under Allocation, the Desk, nominations, BESS and the Dashboard. Off-taker screens live in V5 · OffTaker. IPP screens live in V4 · IPP. The shared three-seat picture stays in V3 · Strategy.
Creating a pool (licence, rights, treatments) is §2B. The pool as an entity stays in V2 §5. This volume then opens the book when you need to trade.
1.1 The trader's problem
An energy trader in the South African wheeling market sits between generators and consumers:
- You buy energy from IPPs (independent power producers — solar farms, wind farms, firm/dispatchable blocks) under PPAs, at contracted c/kWh prices.
- You sell that energy to off-takers (factories, malls, municipalities) and to other traders, under sell-side PPAs, at higher c/kWh prices.
- You pay wheeling charges to move the energy across the grid, and you lose a few percent of every MWh to distribution losses on the way.
- Your profit is the spread: sell price − buy price − wheeling, hour by hour.
The catch is that none of this is flat. Solar produces at midday and nothing at night. Your factory load runs 24/7; your mall load peaks in the daytime; a firm evening block must be served no matter what. Time-of-use tariffs make an evening kWh worth far more than a midday one. So the questions that decide whether you make money are inherently hourly:
- Which supply serves which demand, in each of the ~8,760 hours of the year?
- How much supply goes unsold (spill — cost with no revenue)?
- How much demand goes unmet (shortfall — expensive grid top-ups or penalties)?
- What margin does each hour actually earn, and how much of it evaporates if generation comes in below forecast?
- How much flexible energy should you nominate for next month, when nominating too little means expensive grid top-ups and too much means paid-for energy that spills?
- If you own a battery, when should it charge and when should it discharge, given that every stored kWh loses a little to efficiency and wears the warranty?
Doing this on a spreadsheet is where portfolios go to die. This module does it with a deterministic engine and puts the answers on eight screens.
1.2 What the module does
You group your contracts and sites into pools (supply on one side, demand on the other), and the engine allocates every forecast hour of energy from supply to demand, pricing each flow with the same conventions the settlement system uses. Every result is stored as tagged, auditable allocation lines — so coverage, margin, spill and shortfall are never estimates; they are sums over hourly lines you can drill into. On top of the engine sit the decision screens summarised below.
Auditable allocation lines
An allocation line is one immutable row for one SAST hour: which member of which pool supplied which member of which pool, how much energy was sent and delivered, the buy / sell / wheeling legs in c/kWh, the Rand margin, and which rules produced it. Headline KPIs in Performance and the Dashboard are simply sums (or ratios) over those rows — open a run's Allocations tab (§8) and you can take any number apart.
Four common kinds (illustrative values, same conventions as settlement):
| Kind | Plain meaning | Tiny example |
|---|---|---|
ALLOCATION |
Energy that actually flowed from a supply member to a demand member | 12h · Solar · IPP-A → Industrial · Factory · 16 710 sent · 16 142 delivered · buy 65.0 · sell 120.0 · whl 15.0 · **R 6 088** · merit_order
— midday solar wheeled to a factory; margin is (sell − buy − wheeling) ×
delivered kWh |
SPILL |
Supply nobody bought that hour — you still paid for it | 02h · Wind · PPA-W · 3 000 unsold · spill value 10.0c · sunk cost **−R 2 160**
— night wind with no offtake; recovery (if any) never fully offsets the
buy cost |
SHORTFALL |
Demand nobody supplied — firm buyers then take grid top-up | 19h · Firm · Evening Buyer · 2 000 unserved · top-up 225.0c · **−R 1 300**
— evening firm gap filled at Eskom rates; the loss shows as negative
margin |
BESS_CHARGE /
BESS_DISCHARGE |
Battery movement (only when the book dispatched storage) | Charge at 12h from free solar spill (margin
0 — it only positions); discharge at
19h against the firm gap, with buy = stored marginal cost
and sell = discharge value — the arbitrage is the line's margin |
Because every line is tagged, "coverage is 94%" means these hours and members were covered; "spill cost R 2 160" means this exact unsold row. Re-running creates a new run; old lines stay for audit (§1.3).
Decision screens on top of the engine
- Simulation workbench (§9) — safe what-if: run the book as today (baseline) and again with a pretend buy/sell candidate and terms (variant). Compare deltas (margin, spill, shortfall, concentration) without touching live membership, forecasts or nominations; promote only when you like the story.
- Nomination workbench (§10) — for flexible supply members, propose an hour-by-hour monthly declaration using asymmetric under-/over-nomination costs (newsvendor / critical quantile), show the full rationale, let you override any hour, then submit into settlement only after you approve.
- BESS dispatch view (§11) — hour-by-hour charge/discharge schedule against the book's real spill and shortfall, subject to SoC, power, efficiency, cycle-cap and minimum spread; every move (and every profitable-looking pair it declined) is recorded with a rationale.
- Risk dashboard (§12) — drillable panels for portfolio margin, risk (P50 vs P90), prices, concentration, limits/alerts, battery tiles and nomination performance — all refreshed from the latest snapshot so you diagnose what and where, not just that something is wrong.
Off-taker and IPP seats reuse the same engine with buy- or sell-shaped screens (§12–§14); the trader path above is the fullest tour of what "Strategy" means.
1.3 Design principles you will feel in the UI
A run is one complete execution of the allocation
engine: given a scenario, a calendar month and a forecast grade (P50 or
P90), the engine walks every SAST hour, matches supply to demand under
the book's rules, and writes the resulting allocation
lines (§1.2). The run is
then frozen — coverage, margin, spill and shortfall are simply sums over
those lines. You create runs from the Allocation tab’s
Forecast mode (§6),
open any one in §8
to inspect the proof, and treat the newest non-superseded
COMPLETE run for a scenario / grade / period as the current
answer for that case. Four deliberate decisions shape how runs (and the
screens around them) behave:
Runs are immutable. Once an allocation run completes, its lines never change. Re-running the same scenario and period creates a new run and marks the old one superseded (kept, greyed out). Why: audit trail. You can always answer "what did the book say last Tuesday?", and a settlement dispute can be defended with the exact run that informed a decision.
Every number is a sum over tagged lines. Each line records which member of which pool supplied which member of which pool, in which hour, at which prices, and which rules produced it. Why: when a KPI looks wrong, you drill down to the exact PPA pair and hour instead of arguing about a rollup. The same line-by-line convention reconciles with settlement.
Every run pins its inputs with a hash. The run header shows an inputs hash — a SHA-256 fingerprint of everything the run consumed (members, prices, rules, forecasts, period — and the battery's dispatch parameters). Same hash ⇒ byte-identical results. Why: reproducibility. "Why did run X say margin was R 100/MWh?" — "Here is its hash; re-run with those inputs and you get the same lines."
Scenarios never mix. Every run is labelled by the kind of input it consumed — not by a cosmetic tag. The four labels mean:
Label What the run does Why it is labelled that way FORECASTAllocates the book's rolling supply-forecast shapes against demand profiles for the chosen month and grade It is the operating plan — "what we expect to happen" — and is the default current position in Performance NOMINATEDRe-runs the engine using the submitted nomination rows as the declared volumes, not the free forecast It answers "what did we say we would deliver?" so you can compare declared position to the forecast plan ACTUALAllocates using settled meter data for the period (when that data exists) It is labelled for realised performance — outcome review after the fact, not forward planning SIMULATIONAllocates against hypothetical inputs (a candidate PPA, a tweaked shape, an isolated what-if) The name marks it as non-live: it never supersedes your forecast or nominated current, so a sandbox case cannot contaminate the book's real position A simulation never replaces your forecast; a later nominated run does not overwrite the forecast current simply because it is newer. Filter and compare within one scenario (§6.3).
The operating-plan forecast itself has an explicit source order. A human
:MANUALupload still wins; a weather-driven:MODELseries sits below that and above the synthesised per-technology shape. Hours the model covers take dated values; hours beyond the horizon keep the shape. The operator-facing account of where those model numbers come from lives in V4 §17.
The same philosophy extends to nomination and batteries: every nomination the optimiser proposes carries its full rationale (the scenarios it considered, the asymmetric costs, the quantile it aimed for, and what the naive alternatives would have cost), and every hour the battery moves — and every profitable-looking hour it deliberately did not — is recorded and shown. You are never asked to trust a number you cannot take apart.
1.4 Concepts to have in hand before you start
| Concept | What it means here | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Hourly grain, SAST | The engine works in hours. All hours you see on screen are SAST (South Africa Standard Time, UTC+2, no daylight saving) — the timezone of meters and tariffs. | ||||||||||||||||
| TOU (time-of-use) | Tariff periods — peak / standard / off-peak — set by the SAST calendar. Contract prices can carry per-period multipliers, so the same PPA prices an evening kWh higher than a midday one. | ||||||||||||||||
| P50 / P90 | Forecast grades. P50 is the median ("expected") generation; P90 is the conservative case you are 90% confident of reaching at least. P90 ≤ P50 always. The gap between the two is where your risk number comes from (§12.3). Worked example. If P50 is 10,000 MWh, then in a typical year you expect to wheel 10 GWh. If P90 is 9,200 MWh, then you can confidently commit to wheeling at least 9.2 GWh in almost every year. Risk Gap (MWh) = P50 − P90 Risk Gap (%) = (P50 − P90) ÷ P50 × 100 |
||||||||||||||||
| DLF (distribution loss factor) | Physics: energy injected at the generator loses a few percent in the network. A DLF of 0.966 means 1,000 kWh sent becomes 966 kWh delivered. You buy the sent energy and sell the delivered energy — the engine, like settlement, keeps both numbers on every line. | ||||||||||||||||
| Wheeling | The c/kWh network charge for moving energy from source to sink, charged on delivered energy. It comes straight out of your margin. | ||||||||||||||||
| Spill | Supply nobody bought in an hour. You still paid for it (take-or-pay especially), so it is sunk cost unless the member has a spill value (e.g. a recovery price).
|
||||||||||||||||
| Shortfall | Demand nobody supplied in an hour. Firm demand must then be topped up from the grid at the member's Eskom top-up price — usually your most expensive energy.
Shortfall pricing options:
|
||||||||||||||||
| Nomination | A monthly declaration of how much a flexible supply member will deliver, hour by hour. Settlement holds you to it: under-deliver and you buy the gap at grid rates; over-nominate and you pay for energy that spills. Getting the number right is what the Nominations workbench (§10) is for. | Nomination workflow: | | 1. Trader forecasts demand. | 2. Trader checks the IPP generation forecast. | 3. Trader builds an MW profile. | 4. Trader submits the declaration. | 5. The declaration becomes the settlement baseline. | | ||||||||||||||||
| SoC (state of charge) | How full a battery is, in kWh (or % of usable capacity). A battery's whole value is moving energy through time — charge cheap, discharge dear — subject to its SoC window, power limits, efficiency losses and warranty cycle cap (§11). SoC (%) = (Remaining Capacity ÷ Full Charge Capacity) × 100 Example. If a 10 MWh BESS has degraded to 9 MWh and currently holds 4.5 MWh:
|
||||||||||||||||
2. Trader pools — the directory
You need to find the pool that needs action before opening its work. A trader pool groups the rights, contracts and protections under which your organisation buys and sells energy. One organisation can operate several pools. You work on one pool at a time.
Open Wheeling → Trader Pools
(/org/trader-pools). Creating or editing the registration
record is taught in §2B.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool. You should see the directory table, then the pool’s Operations view with five workspace tabs.
2.1 The directory
The financial verdict sits above search. Each table row shows the pool name, contracts and members, lifecycle status, coverage and next step. A pool with a forecast also shows its margin, spill, delivery window, forecast target date, generation time and source allocation run. A future target date is a forecast date; Generated tells you when the record was produced.
Attention first ranks a forecast loss ahead of high spill, other forecast issues, missing members and missing forecasts. A risk reason links to its repair: Commercial for unsold supply, Allocation for missing members, Performance for a forecast, or Operations for a missing SAWEM trading unit. Needs attention filters these rows; search, status and comparison choices survive a visit to the workspace and a return through Pools.
Not assessed · no members means there is nothing to forecast. Not assessed · awaiting forecast means members exist but no snapshot is available. These rows show — for coverage and financial rates. A measured zero appears only when there is an assessment. Active describes the registration lifecycle; it does not mean the pool earns money or is ready for every market capability.
Filters & columns opens status, sorting and optional margin, risk and PPA columns. Selecting a PPA count opens the matching Deals register. Portfolio summary & coverage notes expands the fleet metrics. How to read this links to this manual.
A missing SAWEM (South African Wholesale Electricity Market) trading unit concerns that pool’s market participation. It does not prevent PPA pool creation. Organisation accreditation, pool lifecycle and market registration are separate checks. If the organisation cannot trade, complete its accreditation in V2 §2.
2.2 The detail drawer
Select a pool name to open Operations. Pool details opens the branded right-hand drawer with the operating record, regulator preview, available Trading Units, verdict and Edit & complete pool record. Close it with the X, Escape or backdrop. Archive asks for confirmation and marks a pool Suspended; Activate restores an eligible non-active pool.
2.3 Getting in — the trader strategy area
flowchart LR
A[Trader Pools directory] --> B[Select a pool name]
B --> C[Operations]
C --> D[Choose a workspace tab]
D --> E[Review evidence and act]
E --> A
- Open Trader Pools and find the pool by name.
- Select its name to open Operations at
/org/trader-pools/pools/:id/operations. - Choose the workspace tab for the task. Check the pool name and period first.
- Use Pools to return with your directory search and comparison choices.
Your pool’s strategy book owns forecasts, allocations and risk
records. It is created automatically when needed. An unavailable or
foreign pool returns you to the directory. Legacy
/org/trader-pools/:id/strategy links still enter the
corresponding workspace task.
2.4 The strategy tabs
| Tab | Job | Taught in |
|---|---|---|
| Operations | Nominations, battery dispatch and operating registration | §10–§11 |
| Performance | Latest forecast, financial position, flow and exposure | §4 |
| Allocation | Members, rules, forecast runs and settled allocations | §5–§8 |
| Commercial | Buying, selling, indicative simulations and pool contracts | §9 |
| Dashboard | Pool history, risk limits and ranked next actions | §12 |
Older links and chapter anchors retain the names Overview (now Performance), Book (Allocation) and Desk or Simulations (Commercial). A book remains the underlying portfolio record; it is not a separate workspace tab.
Commercial shows a calendar delivery month; Performance shows the latest snapshot’s allocation-run window. They may differ. Read the visible dates and model basis before comparing energy or margin. The Performance headline is the deterministic snapshot result; its separate Monte-Carlo fan shows a distribution and a median, which can produce a different number.
View pool contracts opens an owned, pool-filtered register. Open a contract, then Back to Contracts to retain the pool and register filters. Back to pool returns to the originating workspace and delivery month.
Where this is taught. Registration drafts and applying edits: §2B. Market Trading Units: V2 §5.
2B. Onboarding a trader pool — the licence file
A factory or a wind plant is a place with a meter. A trader pool is not. It is a licensed trader’s trading book: a bundle of rights, treatments and protections under which you buy from generators and sell to consumers. Until that book exists on this platform, there is no directory card, no Strategy book, and nothing to forecast.
The papers do not arrive on one afternoon. If you had to type everything in one sitting, you would lose the work the first time you closed the tab.
Think of a new shop joining the merchant’s list. You start a licence file on the first visit and add stamps as the papers arrive. You do not open the shop until the core stamps are there. That file is the trader pool draft. The live pool is created only when you press Create trader pool.
This is not standing up a generator plant. A plant has a pin, a meter and a technology. This workspace is the pool’s licence, operating and commercial file.
Where this is taught. Generator-site onboarding (site, meter, technology, connection): V2 §4 · V4 §3. Off-taker site onboarding: V5 §2.3. The pool as an entity, accreditation and market Trading Units: V2 §5.
The create path is not a five-step modal.
Add New on Trader Pools
writes a draft and opens a full-page workspace at
/org/trader-pools/onboarding/<case id>.
Edit on an existing card opens the
same workspace, prefilled from that pool — not a blank
draft, and not a second book.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → the round + (Add New Pool,#open-trader-pool-wizard). You should land on Profile & licence with title Untitled trader pool and a Draft chip. When you have finished reading, press Discard so this seed does not keep a leftover card.
Data. full_demo · seed 42 · Trader 1 · a clean seed has no drafts · last checked 2026-09-18.
2B.1 The trader’s problem
You need a named book that counterparties and the regulator can recognise: who you are, which wires you may use, what you may do, who is accountable, how charges land, and what you promise buyers. Typing that into a one-shot wizard fails the first time a licence date or a policy reference is still in the post.
The workspace lets you pause. Each section autosaves. You return from
the amber Trader pool drafts rail on
/org/trader-pools until the six core sections pass.
2B.2 How you get here
You must already sit in a trader seat — an organisation accredited to trade. If it is not, Trader Pools shows an amber notice instead of the create button: “The Organization has not been accredited to trade either by Eskom or by any municipality which supports wheeling.” Fix V2 §2 first.
| You want to | Click path | What opens |
|---|---|---|
| Start a new pool | Trader Pools → Add New
(#open-trader-pool-wizard) |
A new draft at
/org/trader-pools/onboarding/<case id>, title
Untitled trader pool, chip Draft,
data-mode="draft" |
| Resume a draft | Trader Pools → amber Trader pool drafts
(#trader-pool-onboarding-drafts) → the named card
(#resume-trader-pool-onboarding-<id>) |
The same draft, last section you were on |
| Change a live pool | Trader Pools → pool card → drawer Edit
(#trader-pool-edit-<id>) |
The same URL, prefilled, chip Editing
(#trader-pool-onboarding-edit-badge),
data-mode="edit" |
The page heading is Trader pool onboarding on a
draft and Edit trader pool on a live pool. The eyebrow
is Draft trader pool or Registered trader
pool. ← Trader Pools returns to
/org/trader-pools without discarding.
A foreign or unknown case id never opens. You bounce to the directory with “That onboarding draft is unavailable for this organization.”
2B.3 Words on this workspace
| Word on the screen | Plain meaning |
|---|---|
| Draft trader pool | Still a licence file, not a live book. |
| Editing | You reopened a live pool. Apply changes writes that pool; autosave keeps a draft. |
| Pool checklist | Seven sections. You may jump in any order. |
| Explanations | A right-hand list of plain-language notes. Click a choice to fill that input. |
| Check & mark complete | Saves this section and tells you what is still missing. It does not jump ahead. |
| Review readiness | Lists every section badge. Create trader pool appears only when the six core sections pass. |
| NERSA | National Energy Regulator of South Africa. Licenses trading unless you claim a Schedule 2 exemption. |
| SAWEM | South African Wholesale Electricity Market. Registration lives in standing data, not on this form. |
| SAPP | Southern African Power Pool. Needed only if this book may cross a national border. |
| Nomination | A month-ahead volume plan. This pool has no meter, so a capable book settles by nomination rather than meter reads. |
| MW / MWh | Megawatt is power (how hard you aim to contract). Megawatt-hour is energy (how much you aim to buy in a year). 1 MWh = 1,000 kWh. |
| Use-of-System | Network charges for using the wires. |
| Imbalance | The gap when this book is long or short against what it nominated or contracted. |
| IPP | Independent power producer — a generator you may buy from. |
| BRP / MPID | Balance Responsible Party and its market participant id. Kept on the organisation, not typed here. |
The six core sections that must pass before create are Profile & licence, Network & roles, Activities & limits, Operations & data, Commercial & risk, and Customer protections. Market standing data never blocks create. A ready draft usually reads 6 of 7.
Discard deletes the draft and never creates a pool. Edit of a live pool has no Discard. A new draft can only be created as Active.
2B.4 How to read the checklist badges
| Badge | What it means |
|---|---|
| Not started | No answers yet. |
| In progress | Some answers, required fields still blank. |
| Needs evidence | Profile, Operations or Protections has some answers but is not complete. |
| Complete | Every required field for that section is filled. |
| Optional | Market standing data with no form — the usual state. |
The progress line reads N of 7 sections complete. Beside it the save state says Draft created — no answers saved yet, Draft saved just now, or Last saved {day} at {time}.
The readiness tile is amber while core sections are missing (Draft is safely stored · N core sections still need information). It turns green when create is allowed (Ready to create pool · Core registration controls are complete). In edit mode it always says Draft changes are pending.
Check & mark complete confirms a complete section or shows inline missing-field feedback. Required fields have a star; required licence fields appear when that licence posture is selected. Draft saved does not mean section complete. Review readiness is the same reading in one place. Next: {section} beside it moves to the next section; on the last one, Market standing data, it reads Review readiness.
The section header counts the core sections on their own — Core section 2 of 6, and Optional section 1 of 1 on Market standing data — and stays pinned at the top while you scroll a long section. On a window narrower than 1280 px the checklist sits above the form as a compact two-column grid; picking a section there scrolls the form into view.
2B.5 Explanations drawer
Explanations
(#trader-pool-onboarding-explanations) opens a right-hand
list for this section
(#trader-pool-onboarding-explanations-drawer). Think of it
as the card catalogue for the form: find the word, click a choice if you
want it written in, close the drawer, keep working.
The header is branded green. The title is
Explanations. The eyebrow repeats the section name.
Close with the header X
(#trader-pool-onboarding-explanations-close), press
Explanations again, or press Escape. The arrow beside
Explanations points left while the drawer is open.
On a window 1280 px or wider the page makes room and the drawer sits
beside the form, so the form stays usable; the checklist shrinks to an
icon rail (#trader-pool-onboarding-section-rail), one icon
per section with its name on hover. Narrower, the drawer would cover the
form, so it opens over a dimmed backdrop
(#trader-pool-onboarding-explanations-backdrop), which also
closes it. Its intro says which you have — You can keep filling the
form while this panel is open. or Close the panel to return to
the form.
Most fields here have no ⓘ on the label. Compulsory
inputs still show the red *. Topics with choices (status,
licence posture, visibility, network rights, roles, activities,
treatments, protections) fill the matching input when you click them.
Topics without choices (name, emails, document references) are notes
only — you still type those.
The drawer stays open when you jump sections, and the topics change to match. NERSA licence topics appear only after you pick NERSA trading licence required. Cross-border topics appear only after Permitted.
2B.6 Create or edit — the chrome
- Open Trader Pools. Confirm you may trade (the + is present).
- Press Add New to start a draft, or open a card and press Edit to reopen a live pool.
- Work the Pool checklist. Jump with the checklist, or press Next: {section} at the foot of each section. Each change autosaves. Use Explanations when a word is unfamiliar.
- Press Check & mark complete on a section when you think it is done. Inline feedback lists what is missing and focuses the first missing field.
- Keep draft & exit
(
#trader-pool-onboarding-save-exit) returns you to/org/trader-poolswithout creating or updating the pool. Draft answers stay on the amber rail. Edit answers stay on the edit case so you can reopen them from Pool details. The confirmation explicitly says the live pool is unchanged. - Review readiness on a new draft, or Review
& apply changes on an edit,
(
#trader-pool-onboarding-review) opens the modal. Every section badge is listed, with repair links for missing information. Tab stays inside the review; Escape closes it and returns focus to the review button. - On a draft, Create trader pool
(
#trader-pool-onboarding-create-pool) is shown only when nothing core is missing. On success the case is ACTIVATED, the live pool is written, and you return with {name} was created successfully. - On edit, the same button reads Apply changes to live pool. It writes the answers onto the existing pool and returns with {name} was updated successfully. It does not create a second book.
- Discard
(
#trader-pool-onboarding-discard) exists only on a draft. It asks first, then deletes the case and never creates a pool. Edit has no Discard — you cannot throw the live pool away from here.
Locked on edit
(#trader-pool-onboarding-roles-locked): Eligible
supply roles, Eligible demand roles, and
Nomination capability. They are set at creation and
stay as registered. The notice on Network says so. Save leaves those
three alone even if the form is tampered with.
Dropdowns on this workspace are listed A–Z by label (Active before Suspended; Private before Public; Eskom and municipality before Eskom only).
2B.7 Profile & licence
Section hint on screen: “Pool identity, licence or exemption evidence and effective dates.”
Who this shop is, and whether it may trade under a full NERSA licence or a Schedule 2 exemption. An amber Licence evidence note is always shown: Eskom virtual wheeling still wants the evidence reference.
Defaults on a new draft: Schedule 2 exemption / registration applies, Active, Public.
| Field | Required to create? | What it means |
|---|---|---|
| Pool name | Yes | Everyday name. Becomes the directory card and the Strategy header. Placeholder: e.g. Cape Commercial Energy Pool. A brand-new draft shows Untitled trader pool until you type one. |
| Initial status | Yes — and it must be Active | Whether this pool is allowed to trade when you create it. Active — authorised and operational. Suspended — temporarily restricted; a new draft cannot be created in this state (initial status must be Active). Expired and Revoked are not on this select — those states come later from the directory. Click-to-fill in Explanations. |
| Trading licence posture | Yes | Schedule 2 exemption / registration applies — no NERSA number is required; keep the exemption evidence reference. NERSA trading licence required — shows number, issue date and expiry. Click-to-fill. |
| Counterparty-directory visibility | Yes | Public — eligible counterparties can find this pool. Private — only your organisation sees it. Click-to-fill. |
| Licence / exemption evidence reference | Yes | A document id, controlled URL or repository name. Store a reference, not the file. Eskom asks for this on virtual wheeling. |
| Pool effective date | No | The day this pool’s mandate starts, if later than licence issue. Leave blank if it starts when you create the pool. |
| NERSA licence number | If licence required | The identifier on the trading-licence certificate. Hidden while Schedule 2 is on. |
| Licence issue date | If licence required | The day NERSA issued the licence. |
| Licence expiry date | If licence required | The day that licence ends. |
Empty Pool name or missing evidence keeps Profile at Needs evidence. Picking Suspended keeps create blocked even if every other field is filled.
2B.8 Network & roles
Section hint: “Access mandate, trading roles and cross-border authority.”
Which wires this book may use, which generator and buyer shapes it may take, and whether it may cross a national border. This is the pool’s mandate, not a site connection.
Cards you are not accredited for do not appear. A trader with only Eskom accreditation sees Eskom only. Both accreditations unlock Eskom and municipality. The default is the first of Eskom · Municipality · Both that you hold.
Defaults on a new draft: cross-border Not permitted, supply Flexible, demand Trader sales, nomination Nomination capable.
| Field | Required to create? | What it means |
|---|---|---|
| Network access rights | Yes | Eskom only — national Transmission / Distribution. Municipality only — municipal distributors. Eskom and municipality — hybrid. Click-to-fill; hidden options stay hidden. |
| Cross-border trading | Yes | Not permitted — the book stays inside South Africa. Permitted — you may import or export; two more fields then become required. Click-to-fill. |
| Import / export licence reference | If Permitted | Document id for the cross-border authority. Shown on a blue panel only when Permitted. |
| SAPP portfolio name | If Permitted | The Southern African Power Pool book this pool is registered under. |
| Eligible supply roles | At least one supply or demand role | Which generator or trader supply shapes this book may take members from. Solar — daytime photovoltaic. Wind — variable day and night. Firm — dispatchable or firmed capacity, including a BESS (Battery Energy Storage System). Flexible — nomination-capable supply. Multi-select cards. Click a card or an Explanations choice to add or remove. Locked on edit. |
| Eligible demand roles | Same rule | Which buyer shapes this book may serve. An off-taker joins only when one of its strategy demand classes intersects this list. Industrial — factories and continuous process. Commercial — daytime-biased retail. Municipal — municipal bulk. Trader sales — sales into another trader’s book. Locked on edit. |
| Nomination capability | Yes | Nomination capable — this meterless pool may submit a nomination as supply. Not nomination capable — it cannot. Locked on edit. Click-to-fill on a draft. |
A plant you later add must share at least one supply class with this list. That matching is taught with generator-site classes in V2 §4.2.
Careful. Cross-border Permitted without both references flashes Still needed: import/export licence, SAPP portfolio.
2B.9 Activities & limits
Section hint: “Permitted scope, restrictions and compliance controls.”
What the licence allows, and what it forbids. Defaults: Buy energy, Sell energy, Wheel energy ticked; restrictions empty.
| Field | Required to create? | What it means |
|---|---|---|
| Permitted activities | At least one | Operational scope under the mandate. Buy energy — contract with generators or permitted sellers. Sell energy — on-sell or allocate to customers. Wheel energy — arrange wheeling, nominations and settlement. Aggregate generators — combine more than one generator portfolio. Portfolio balance — manage aggregate mismatch. Market participation — interact with market or balancing mechanisms. Forecasting — submit generation and load forecasts. Settlement — calculate invoices, credits and imbalances. Click-to-fill. |
| Licence restrictions | No | Hard limits in the licence or mandate (red-ringed cards). No generation — cannot act as a generator. No distribution grid holding — cannot hold grid assets. No unregistered IPPs — only authorised generators. No unregistered off-takers — only approved customers. Capacity limits enforced — observe contracted limits. No market speculation — stay inside the mandate. No unilateral tariff changes — follow agreed pricing. Optional. Click-to-fill. |
| Compliance and market-conduct policy reference | Yes | A policy id or controlled document URL for how this book behaves in the market. Placeholder: Policy ID or controlled document URL. |
2B.10 Operations & data
Section hint: “Accountable contacts, secure interfaces and reconciliation.”
Who runs the book day to day, and whether the secure link that carries nominations, meter data and settlement files is ready. A blue Operational accountability note is always shown: SAWEM wants that link; NERSA’s draft bilateral rules want a monthly energy and money reconciliation path.
Default: Secure data-interface readiness is Not assessed. Create will not accept that default — the interface must be Ready.
| Field | Required to create? | What it means |
|---|---|---|
| Operational contact name | Yes | The person accountable for forecasts, interfaces and incidents. |
| Operational notice email | Yes | Where operating notices for this pool should be sent. |
| Settlement and reconciliation email | Yes | Where monthly energy and financial reconciliation notices should be sent. |
| Secure data-interface readiness | Yes — and it must be Ready | Not assessed — nobody has reviewed the link. Planned — designed, not built. Testing — under test. Ready — the link can carry operating data. Remediation required — the check failed. Create flashes data interface must be Ready for any other pick. Click-to-fill. |
| Monthly reconciliation procedure | Yes | A procedure id or controlled URL for how this book compares energy and money each month. |
| Data / interface failure procedure | Yes | What to do when the secure link drops or a file fails. A reference, not the runbook file. |
| Cybersecurity controls reference | Yes | The control-set or policy id that protects this book’s operating interfaces. |
2B.11 Commercial & risk
Section hint: “Procurement targets, wheeling charges and balancing exposure.”
How you aim to buy, how network charges reach customers, and who carries imbalance. The megawatt targets are planning figures. They do not create a deal.
Defaults: wheeling Full pass-through, balancing Trader-borne.
| Field | Required to create? | What it means |
|---|---|---|
| Procurement target (MW) | No | How many megawatts this book aims to contract. Step 0.001; minimum 0. |
| Annual procurement target (MWh) | No | How many megawatt-hours this book aims to buy in a year. Optional. |
| Wheeling charge treatment | At least one | How Use-of-System / wheeling charges reach customers. Full pass-through — charges flow at source cost. Blended — charges sit inside a blended energy price or service fee. Partial pass-through — some charges pass through; others are absorbed or capped. Multi-select. Click-to-fill. |
| Balancing cost treatment | Yes | Who carries mismatch. Trader-borne — this book carries it and charges a spread or fee. IPP-borne — the generator carries shortfall or curtailment. Off-taker-borne — the buyer carries it. Shared — split under an agreed rule. Pass-through — charges and credits follow a published formula. Market-indexed — priced from an external index. Single select, A–Z. Click-to-fill. |
| Commercial dispute-resolution policy | Yes | Procedure id for invoice, tariff or allocation disputes on this book. Placeholder: Procedure ID or controlled document URL. |
Where this is taught. How settlement applies wheeling and imbalance: V8 §7.
2B.12 Customer protections
Section hint: “Safeguards, complaints, consent and dispute procedures.”
What this pool promises the buyers it serves. Defaults already ticked: Price caps, No unilateral price changes, Billing transparency, Balancing-cost protection, Dispute resolution. You may add or remove cards; at least one must remain.
| Field | Required to create? | What it means |
|---|---|---|
| Off-taker protection measures | At least one | Contractual safeguards. Price caps / Price floors — maximum or minimum customer price. Fixed-price windows — locks a price for a defined period. Transparent indexation — names sources and fallbacks. No unilateral price changes — an agreed change process. Billing transparency — calculation lines and evidence. Supply continuity — fallback when wheeled energy is unavailable. Curtailment protection — who carries a network cut. Balancing-cost protection — limits mismatch for the buyer. Forecasting support — data and cooperation. Dispute resolution — escalation path. Error correction — recalculation windows. Independent verification — independent checks. Realtime data access — operational visibility. Data integrity — validated settlement data. Audit trails — regulatory and financial evidence. Click-to-fill. |
| Customer complaints procedure | Yes | Procedure id or controlled URL for how a buyer raises a complaint. |
| Customer consent register | Yes | Register id for the consents this book holds — data use, allocation and billing authority. A reference, not the signed file. |
2B.13 Market standing data
Section hint: “SAWEM Party, agreements, accounts and credit cover remain authoritative.”
This section is a placeholder handoff, not a form. There are no inputs and no Check & mark complete; as the last section it ends with Review readiness. Market Participant identity, MPID, Market Participation and Balancing Agreements, settlement accounts and credit-cover providers belong to the organisation-level Market registration. This pool links to those records instead of copying them.
The card heading is Keep SAWEM standing data
authoritative. Open Market registration goes
to /org/brp/registry.
You can still create the pool and trade on a physical or virtual PPA without SAWEM registration. The pool is then not yet a market participant. The badge stays Optional.
Where this is taught. Trading-unit registration: V9 §3.9B. What a Trading Unit is: V9 §3.3.
2B.14 What “done” looks like
- Review readiness lists every badge. Missing core titles appear as a comma-separated list (Profile & licence, Operations & data).
- Create trader pool is shown only when nothing core is missing. Create on an incomplete draft stays hidden; the modal title is More evidence is needed.
- On success the draft is ACTIVATED, the live pool is written with the answers (and any onboarding-evidence references), and you return to the directory with {name} was created successfully.
- Done on this seat is: a quiet card with the name you typed, status Active, and no amber draft row for that id. Strategy still needs a first Performance click (§2.3 · §3).
Keep draft & exit on a draft leaves an amber
rail Trader pool drafts
(#trader-pool-onboarding-drafts) above the pool cards. A
clean Trader 1 seed has no drafts until you press
+.
| You see | It means |
|---|---|
| Untitled trader pool | Brand-new draft. Type Pool name. |
| Still needed: … | Required answers still blank, or a rule failed (Active, Ready, at least one role). |
| Review without Create trader pool | A core section is incomplete. |
| That onboarding draft is unavailable… | Wrong organisation or unknown id. |
| Market section with no inputs | Built that way — not an unfinished screen. |
| Edit on a live card | Same workspace, Editing chip, pool already filled. Apply changes to live pool writes that pool. Supply roles, demand roles and nomination stay locked. |
| No Discard | You are editing a live pool. |
| Amber Trader pool drafts missing | No open drafts — the usual clean seed. |
Where this is taught. The directory that receives the new card: §2. Opening the book: §3. Wiring members: §5. Generator plants you may later buy from: V2 §4. Off-taker shops you may later sell to: V5 §2.3.
3. Getting in — open the book behind a trader pool
Your commercial portfolio can look healthy in the directory while still having no forecast, allocation or risk view. Strategy gives each trader pool a book: the system record that turns its contracts into a plan you can inspect and act on.
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-07-18 against the full_demo manifest.
3.1 Pool, book and seat
A Trader Pool is the commercial grouping you manage: its generators, off-takers, prices, rules and coverage targets. A Trader Book is created for that pool when you first open Strategy. It owns its runs, allocations, simulations, nominations, battery schedules, snapshots and limits.
The seat determines the question you ask. A trader seat balances supply against demand; an off-taker seat starts with savings; an IPP seat starts with revenue and unsold energy. They use the same engine but are entered from their own directories. §12 maps those other seats without changing the trader workflow taught here.
| You are looking at | What it contains | Your first question |
|---|---|---|
| Trader pool | Commercial members and contracts | Do my buys cover my sales? |
| Strategy book | Executions and decisions for one pool | Is this portfolio healthy today? |
| Market seat | BRP registration, where enabled | Are bids and imbalance controlled? |
You never create the book in a separate setup wizard. Opening a pool workspace creates it if needed. Select Performance to inspect its forecast. That first visit can legitimately have no snapshot yet: it means no forecast has been run, not that the book is broken.
3.2 Open Strategy for the right pool
Start at Wheeling → Trader Pools
(/org/trader-pools). Select the pool name to open
Operations, then select Performance, Allocation, Commercial or
Dashboard. The pool workspace uses
/org/trader-pools/pools/:id/:section.
Check the pool name in the header: every number belongs to that pool. Unknown or foreign pool IDs return you to the directory.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Performance. You should see the same pool name and the latest forecast’s delivery window and generation time.
The demo also contains T1 Industrial Pool. Open it in a second browser tab only if you are comparing portfolios; do not infer a cross-pool total from either book’s KPI cards.
3.3 Read the directory before entering
The table directory and its dated financial verdict are taught in §2. It ranks material financial issues before setup tasks. Empty pools show Not assessed and dashes; an Active status is not a health verdict.
The optional portfolio summary shows the five metrics below. Pool rows always show forecast margin and spill when assessed. A forecast target date describes the model date; the generation timestamp describes when the record was created.
The five portfolio stat cards
Each top card answers one triage question about the whole organisation's trader books. The same labels appear as columns on every pool row — read the card for the portfolio glance, then the matching cell to find which pool is driving it. Full definitions and hour-level proof live in Performance and in the run detail (§4.1, §8).
Coverage — "Can we serve the load we sold?"
What it is. The share of demand that the book actually delivered under the latest forecast run.
Coverage = delivered energy ÷ demanded energy
Plain reading. Of every 100 kWh your offtakers wanted in the snapshot month, how many did wheeled supply cover? The gap is shortfall (see below) — often filled at expensive grid top-up for firm buyers.
Example. Demand = 100 MWh, delivered = 82 MWh → Coverage = 82%.
Demand |████████████████████| 100 MWh
Delivered|████████████████░░░░| 82 MWh → Coverage 82%
shortfall 18 MWh
Directory alert. Rose when Coverage < 50% — the book is failing to cover most of its sold demand; open that pool's Strategy before anything else.
Margin (fcst) — "What does the expected plan earn?"
What it is. The Rand result of the deterministic snapshot forecast: revenue from sales less the buy cost, wheeling and other forecast costs the engine priced on the allocation lines. The source label identifies the run-period or 30-day equivalent margin; the value is money, not a percentage.
Plain reading. If generation and demand land near the median forecast, does the book make or lose money over the snapshot month? Positive is the plan earning; negative means the expected shape already loses before you consider adverse weather.
Example. Sold energy earns R 1.20 M; buy + wheeling
+ spill sinks cost R 0.95 M → Margin (fcst) ≈ R 250K
(directory cards may show compact R 250K /
R 1M forms).
Revenue (sell) +████████████████ R 1.20 M
Costs (buy+whl+…) −████████████░░░░ R 0.95 M
─────────────────
Margin (fcst) ███ R 0.25 M
Directory alert. Rose when Margin < R 0 — the expected plan is already underwater; open Overview, then the run's allocation / spill / shortfall tabs to see which hours destroy value.
Margin@Risk (MaR) — "How much of that margin vanishes if generation is weak?"
What it is. The share of expected (P50) margin that disappears when the engine re-runs the same book on the P90 adverse generation case (firm obligations still priced at replacement cost).
Margin@Risk = (P50 margin − P90 margin) ÷ P50 margin
Plain reading. P50 is "what we usually earn"; P90 is "what we still earn when supply is conservatively low." MaR is the fraction of expected margin at risk if the adverse world shows up — not a second margin amount. A book with the same P50 margin but wind-heavy supply often has a higher MaR than a solar-heavy book, because wind's P50→P90 degradation is steeper (§6.4).
Example. P50 margin = R 1 000 000, P90 margin = R 720 000:
MaR = (1 000 000 − 720 000) ÷ 1 000 000 = 28%
P50 margin |████████████████████| R 1.00 M
P90 margin |██████████████░░░░░░| R 0.72 M
←──── MaR 28% ────→ margin destroyed in the adverse case
Directory alert. Rose when MaR > 20% — more than a fifth of expected margin is sensitive to weak generation; do not "fix" it only by chasing a higher P50 — the P90 gap has to improve too (§4.2).
Spill — "How much bought supply has no buyer?"
What it is. The share of total supply in the snapshot that was unsold in its hour — energy you procured (or generated under contract) that nobody took.
Spill = unsold supply ÷ total supply
Plain reading. Midday solar with no matching industrial load, or night wind with no offtake, shows up here. You often still paid for that energy (especially take-or-pay), so spill is usually sunk cost unless a spill value / recovery price softens it (§1.4).
Example. Total supply = 120 MWh, unsold = 9 MWh → Spill = 7.5%.
Supply |████████████████████| 120 MWh
Sold |██████████████████░░| 111 MWh
spill 9 MWh → 7.5%
Directory alert. Rose when Spill > 20% — a large slice of supply is orphaned; typical next move is daytime offtake on the Simulation workbench (§9), not more supply.
Shortfall — "How much demand still needs cover?"
What it is. The share of total demand that went unmet by wheeled supply in the snapshot — the mirror image of Coverage's gap.
Shortfall = unmet demand ÷ total demand
Plain reading. Evening firm load after solar drops off, or a book that simply does not have enough contracted supply, shows up here. Firm offtakers then take grid top-up at their Eskom (or replacement) rate — usually your most expensive energy and a direct hit to margin.
Example. Total demand = 100 MWh, unmet = 18 MWh → Shortfall = 18% (and Coverage would be 82% on the same numbers).
Demand |████████████████████| 100 MWh
Covered |████████████████░░░░| 82 MWh
shortfall 18 MWh → 18%
Directory alert. Rose when Shortfall > 20% — a large slice of sold demand is uncovered; add supply, reshape demand or firm cover — the opposite physical fix from high spill (§4.2).
Other signals on each pool row
| Signal on the Trader Pools row | Where it sits | Meaning | What you do next |
|---|---|---|---|
| Pool name | Left column, bold | The commercial book you will open | Confirm this is the portfolio you intend to operate |
Status badge (ACTIVE, SUSPENDED, …) |
Under the pool name | Registration / trading status of the pool itself — not a Strategy health colour | Prefer an ACTIVE pool; investigate before operating a
suspended one |
| Public / private dot | Small green check or red × on the pool icon | Whether the pool is listed as public | Orientation only; does not change Strategy maths |
| The five KPIs above | Centre columns (rose when alert) | Latest Strategy snapshot for this pool | Rose → open Strategy and diagnose; normal → open only if you need evidence |
— in a KPI cell |
Same columns | No snapshot written yet | Open Strategy, check membership, then Run Forecast Now |
| Physical / Virtual circles | Two columns before Actions | Count of physical vs virtual PPAs on the pool | Sanity-check contract shape before entering |
| Scale icon | Actions column (tooltip Strategy) | Enters the Strategy book for that row | Click when you have chosen the pool |
Hover any action icon if its meaning is unfamiliar; Strategy is always the scale icon with the "Strategy" tooltip.
Careful. A directory KPI is only as recent as its latest snapshot. If you have just added a contract or changed a rule, open Strategy and use Run Forecast Now before treating the number as a decision. Spill and shortfall can both look "amber-sized" for opposite reasons — read which card (or column) is stressed before you act.
3.4 The shared Strategy shell
Every trader-book route keeps the same context so you do not lose your place while moving from a problem to its evidence:
- ← Trader Pools returns to
/org/trader-pools; - the header repeats the pool name and “Strategy”;
- the tabs are Performance,
Allocation, Commercial and
Dashboard (
#strategy-nav). Allocation stays the lit top tab on Rules, Forecast and Outcomes — those views are not extra room tabs. Allocation opens on Rules. Forecast still lives at…/strategy/book?mode=forecastfrom the thread strip, a run link, or the old/allocationsforward. Each Book view carries the same thread strip, so the wiring, the engine’s plan and the settled month read as one story (§5, §6, §6A).
These are routes within the selected pool, not global worklists:
| Tab · mode | Route suffix | Use it when |
|---|---|---|
| Overview | /strategy |
You need the 30-second health check |
| Book (default) | /book → /pools |
Opens Rules — the cascade board. Top tab stays
Allocation (#strategy-tab-book) |
| Book · Rules | /pools (#book-stage-rules) |
You must change portfolio structure — the cascade board, with what the latest forecast did to each pool |
| Book · Outcomes | /book?mode=outcomes
(#book-stage-outcomes) |
You need the settled month: procured against sold, the money, the chains (§6A, §6B) |
| Book · Forecast | /book?mode=forecast
(#book-stage-forecast) |
You need a reproducible forward engine execution: the run
picker, tiles, flow, margin, caps, the battery fold; Open the
run ledger › sits at /allocations/<run id>
(§8) |
| Book · Battery dispatch | /bess |
The battery’s full day view, still under Allocation. Open it from Forecast’s Open full dispatch ›, not from a fifth top tab (§11.11) |
| Desk | /simulations |
You need to sell what the book is long or buy what it is short — position, candidates, basket, strategy board, commit (§9) |
| Desk → Commit · Nominations | /nominations |
You must prepare next month’s position or read a past plan — reached
from the Desk’s Commit step (plan rows and Open the nominations
workbench ›) or from Overview Open Nominations
workbench (§4.5, §9.9, §10).
?from= sends ‹ Back to that door. |
| Dashboard | /dashboard |
You want the long view: the pool’s story since it began — performance, leaks, trading web, health, outlook, moves (§12) |
| Desk · Counterparty exposure | /exposure → forwards to /simulations |
You need the per-counterparty table (§9.10) |
The old Nominations and Exposure
tabs are now the Desk’s Commit step and its exposure section
(/exposure forwards; /nominations keeps its
URL). The old Pools, Runs,
Chains and BESS tabs forward into the
Book: /allocations → Forecast, /chains →
Outcomes, /bess stays as the battery’s full dispatch page
under the Book tab.
Careful. Forecast and Outcomes are the two directions of time in one room. They are not extra tabs on
#strategy-nav— Allocation stays the top tab. Forecast (…/strategy/book?mode=forecast) is the strategy engine’s forward ledger for one run. The thread strip at the top of each Book view says which stage you are reading.
3.5 Read badges before acting
Badges here are the small labelled tags on Strategy screens — not the directory KPI values in §3.3. There are two kinds; read both before you treat a number as actionable.
Run and scenario badges
These appear mainly in Allocation’s Forecast run picker (§6) and on a run's detail header (§8). Each run row shows its scenario (what inputs the engine used) and its status (whether the execution finished, failed, or was replaced). They tell you whether a value is a plan, a declaration, a settled result or a safe what-if — read them before comparing two numbers.
| Badge | Meaning | Decision consequence |
|---|---|---|
FORECAST |
Rolling P50 plan | Use for the expected book position |
NOMINATED |
Submitted nomination rows | Compare with what you declared |
ACTUAL |
Settled meter data | Use only when available for outcome review |
SIMULATION |
Isolated what-if | Never mistake it for live exposure |
PENDING / RUNNING |
Engine has not finished | Wait; do not treat partial rows as a result |
COMPLETE |
Immutable execution succeeded | Safe to drill into and compare |
FAILED |
Execution ended with an error | Previous current result remains intact |
SUPERSEDED |
Newer run replaced it for its scenario and period | Keep it as history, not the current plan |
Severity badges
These appear on the Performance KPI cards (§4.2) and on the Dashboard (§12). They use the same language everywhere:
| Badge | Colour | Means |
|---|---|---|
| ok | Green | Within every configured limit |
| warn | Amber | A warning threshold is crossed |
| breach | Red | A hard limit is crossed |
If no limit exists, the metric remains ok; green therefore means "within configured limits," not "commercially perfect."
"Read badges before acting" means: check what kind of run you are looking at, and whether a card is warn or breach, before you act on the number.
3.6 A first five-minute tour
- Open T1 Renewables Pool and confirm the header.
- Read the Overview cards; if there is no snapshot, select Run Forecast Now.
- Open Book · Rules and check that supply and demand members look commercially plausible before changing anything; read the outcome badge on each card.
- Open Book · Forecast; the run picker opens on the
newest
FORECASTP50run — this is the evidence behind the Overview. - Return to Overview, then use Dashboard only if amber or red needs an hour-by-hour explanation.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Strategy → Runs. You should see a newest-first index where a current completed forecast is not labelledSUPERSEDED.
The next chapter uses the Overview as your daily opening move. When a card points to structural work, go to §5; when it points to a commercial opportunity, go to §9.
4. Overview — run the book
Route: /org/trader-pools/:id/strategy ·
Tab: Overview
You buy energy from many sellers and sell it to many buyers. Every morning you need one answer for this trader pool: is the book earning, where does the energy go, what can still go wrong, and what should you trade next? Overview is that page. It does not sign a deal. It reads the latest risk snapshot — a sealed forecast result — and turns it into cards you can scan in about a minute.
Think of a merchant’s shop window. The window does not restock the shelves. It shows today’s takings, what is still on the shelf, and the one job to do first. That window is Performance. The storeroom where you wire shelves and baskets is Allocation. The counter where you try a buy or a sell is Commercial. The lifetime accounts are Dashboard.
Where this is taught. How the directory lists every pool: §2. How you create or edit a pool’s licence file: §2B. How you open Strategy for one pool: §3. How you wire members and rules: §5.
How to read the whole page, then what to do
Read top to bottom. Do not start in the middle.
- Confirm the chip in the top bar names the pool you meant
(
{pool name} · Strategy). Overview is one book. A healthy neighbour says nothing about this one. - Read the first card — the big sentence. That is the period result in one line: the book earns or loses, and often why (spill that never sold, or demand left unmet).
- Glance at the three tiles under that sentence (Margin@Risk, VaR 95, spill / resale). Then the four Structural position bars beside it. Colour first: rose is a problem, amber is a warning, brand green is inside the tick.
- Check Concentration. One supplier or one buyer taking most of the book is a different risk from a bad hour.
- Read Where the energy goes left to right: supply pools → demand pools. Thick green ribbons are good trade. Thick rose ribbons lose money. Amber leaving to Spill · bought, unsold is energy you paid for with no buyer. Rose arriving from Shortfall · unmet demand is load you sold and did not cover.
- Trust rank 1 on Next best actions, then verify it on the screen the link opens. The list is a first move, not a signed order.
- Open Long or short, hour by hour only when you need the clock: which SAST hours are matched (green), long / spill (amber), or short / shortfall (rose). Switch Typical day and Tomorrow (P50 supply) to see whether tomorrow’s weather repeats the shape.
- Use Pool health to name the shelf or basket. Then Where the margin is made and lost for the month × hour, and Forecast said, book settled for whether the plan has been honest.
Good on this page: a headline that earns,
spill and shortfall inside their ticks, green ribbons, an empty or quiet
action list, and Pool health chips that read ok.
Bad: a headline that loses because N% of what it
buys never sells, rose gauges, a fat amber spill outlet, rank 1
telling you to sell the spill or cover the shortfall, and
breach chips on Solar or Industrial.
Where you go next — only exits that exist on this screen:
| Exit | Where it is | What it is for |
|---|---|---|
| Allocation | Tab | Wire pools, see the forecast, read settled outcomes |
| Commercial | Tab (/strategy/simulations) |
Try a buy or a sell before it is real |
| Dashboard | Tab | Limits and the long view |
| ← Trader Pools | Back link | The directory — not a pool switcher |
| Action links | Inside Next best actions | Simulations, Nominations, Pools, Allocations, BESS, or Dashboard — only when that action fires |
| Open Simulation Workbench | Footer of the actions card | Always there; same Desk |
| Open Nominations workbench | Footer of the actions card
(#overview-open-nominations) |
Always there — past and next plans, not only when a leak ranks |
| Plant now chips | Under the Long or short legend (#trader-plant-chips),
only if a supplier is live |
Opens Your plant live on this Overview |
| Run Forecast Now | #overview-run-forecast |
Seal a new snapshot (§4.10) |
| Explanations | #overview-explanations-open |
How to Read the View, then the A–Z words used on this page |
There is no Nominations tab in Performance.
Nominations keeps its own URL. Reach it from Open Nominations
workbench at the foot of Next best actions
(#overview-open-nominations), from a ranked
Re-optimise → Nominations card when that leak fires, or
from Desk · Commit. The workbench’s ‹ Back to Overview
(#nominations-back) returns here when you arrived with
?from=overview.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Overview (or the scale-icon Strategy chip). You should see the subtitle Run the book — position, flow, risk, and the next trade., the intro What the book earns, where its energy goes, what could go wrong, and what to trade next., Explanations beside Run Forecast Now, then the nine cards below.
Data. full_demo · seed 42 · T1 Renewables Pool · last checked 2026-09-18 against
StrategyOverviewLive. A seeded book that is long with almost no offtake headlines The book loses R 12.2 m this period because 96% of what it buys never sells. Snapshot Rand on a given machine moves with the latest forecast; the labels and rules below are the product.
The page title is Strategy · Overview. While a forecast runs, a full-screen overlay says Running forecast… and Stay on this page until the run finishes. Tabs and the back link are not clickable. Success flash: Forecast updated. Failure: Forecast run failed. or Forecast run crashed.
If there is no snapshot yet, the nine cards are hidden. You see a dashed empty panel:
No snapshot yet — run a forecast to populate coverage, margin and risk.
Under that empty panel the page still lists Supply
and Demand pools by name and member count
(N member(s)), or No supply pools. /
No demand pools. Those columns are a roster, not
health. Press Run Forecast Now
(#overview-run-forecast). The button tooltip: Rerun
full forecast: base P50 run plus P90 adverse stress run.
Words for this screen (no foreknowledge)
| Word | Plain meaning |
|---|---|
| Allocation | This pool’s strategy file: pools, runs, snapshots and limits. Created the first time you open Strategy |
| Snapshot | The sealed forecast result Overview reads. No snapshot → empty cards |
| P50 | The expected case — about half the time generation meets or beats it |
| P90 | The conservative generation case you are still 90% confident of getting. Always ≤ P50 for renewables |
| P05 / P95 | Edges of the sampled margin fan (worse / better), not generation grades |
| Margin | Sales minus buys minus forecast costs, in Rand |
| Margin@Risk | Share of P50 margin lost in the P90 adverse case |
| VaR 95 | Value at Risk at 95% — a tail gap on a one-day or one-month horizon |
| Coverage | Delivered energy ÷ demanded energy |
| Spill | Unsold supply ÷ total supply — bought or generated, no buyer that hour |
| Shortfall | Unmet demand ÷ total demand |
| Take-or-pay used | Share of minimum-take energy you actually used |
| HHI | Herfindahl-Hirschman Index — 1.0 means one supplier or one buyer takes everything |
| kWh / MWh / GWh | Energy units. 1,000 kWh = 1 MWh; 1,000 MWh = 1 GWh. Large books switch unit automatically |
| c/kWh | Cents per kilowatt-hour |
| SAST | South African Standard Time (UTC+2). Clock hours are SAST |
| Typical day | Every hour in the run, averaged by SAST clock hour, then divided by the number of distinct days |
| Long | Supply above demand that hour — spill, amber |
| Short | Demand above supply that hour — shortfall, rose |
| Matched | The overlap of supply and demand — green |
4.0 The book as a marketplace — pools in plain language
Before the cards, you need the two sides Overview assumes. A pool is a named group of members on one side only.
| Side | Plain meaning | Typical members |
|---|---|---|
| Supply | Energy you can place into the book | Generator sites, buy-side PPAs, trader blocks selling into you |
| Demand | Energy the book must serve | Off-taker sites, sell-side PPAs, trader blocks buying from you |
You do not put factories and solar farms in the same pool. You group solar with solar when they share a job (cheap daytime energy), and factories with factories when they share a service (industrial load that should be covered first).
Where this is taught. Creating pools, priorities, limits and members is §5. This section is only the picture Overview’s flow map and Pool health table assume. The hour-by-hour matching diagrams sit with that chart (§4.4).
Four commercial moves. The engine does not invent deals. It only allocates energy inside the deals you already seated.
| Move | Seat it as… | Do this when… |
|---|---|---|
| Supply sells into your demand | A source in a supply pool and a sink in a demand pool | You own both legs and want the engine to match them each hour |
| You buy from an IPP | Generator site or IPP PPA → supply | You need a known shape (solar midday, wind overnight, firm block) |
| You buy from another trader | Counterparty block → supply | You need volume or firmness faster than building your own IPP book |
| You sell to an offtaker or trader | Site, sell-side PPA, or trader-sales block → demand | You have surplus to place, or a firm sale to honour |
Layman’s rule. Fill demand in your head first, then buy supply that matches the shape — unless you are deliberately long renewables and hunting offtake. IPP buys own shape and green attributes. Trader buys fill gaps. Offsell to offtakers is the core placement. Offsell to traders is often firm — protect it with Firm supply.
4.1 The position card — what the book earns
On screen: the left card in the first row
(#overview-position). There is no folded
All five KPIs row and no
#overview-kpi-cards. Coverage, spill and shortfall now live
on Structural position (§4.2). Margin, Margin@Risk
and the spill money live here.
This is the shop-window price. One sentence, a fan if a Monte-Carlo risk run exists, then three tiles.
The headline
The heading (#overview-headline) is chosen in this order
from the latest snapshot (MARGIN_R, SPILL_PCT,
SHORTFALL_PCT):
| When | Headline you see |
|---|---|
| No margin figure | No margin figure in the latest snapshot |
| Margin < 0 and spill > 50% | The book loses {Rand} this period because {N%} of what it buys never sells |
| Margin < 0 and shortfall > 20% | The book loses {Rand} this period while {N%} of demand goes unmet |
| Margin < 0, otherwise | The book loses {Rand} this period |
| Spill > 20% | The book earns {Rand} but spills {N%} of its supply |
| Shortfall > 20% | The book earns {Rand} but leaves {N%} of demand unmet |
| Otherwise | The book earns {Rand} this period |
Rand is compact: R 412 k, R 12.2 m,
−R 12.2 m. On T1 Renewables Pool after the seed forecast,
expect the loses … because 96% … never sells line.
Good is earns with no “but spills” / “but leaves unmet”. Bad is loses because — you paid for energy that found no buyer.
The lede and the fan
The grey line under the headline:
- with a fan: P50 margin with the P05–P95 fan from the risk distribution; the dashed tick is break-even.
- without: P50 margin from the latest forecast run; run a risk distribution to see the fan.
The fan (#overview-margin-fan) is a horizontal bar:
| Mark | Meaning |
|---|---|
| P05 | Worse edge of sampled margin (left label) |
| P50 | Expected margin (centre, bold) |
| P95 | Better edge (right label) |
| break-even | Dashed tick at R 0, only when the fan crosses zero |
Green stroke when P50 ≥ 0; rose when P50 < 0. No Monte-Carlo
distribution → #overview-no-fan: No margin distribution
yet — the fan appears after a Monte-Carlo risk run. The three tiles
still show.
The three tiles
| Tile label | Number | How to read it |
|---|---|---|
| Margin@Risk · P90 adverse | MARGIN_AT_RISK_PCT, or — |
Share of expected margin that disappears if renewables under-deliver. Rose when the figure is above 25% |
| VaR 95 · one day or one month | From the latest risk distribution, or — / VaR 95 · no distribution | Tail gap at 95%. Prefers a one-month horizon when both exist |
| Margin if the spill sold at {c} c | Implied resale at the book’s average sell price | Only when there is spill and a sell price. Otherwise Spilled this period shows the spilled energy (or — if the run has no lines) |
Margin@Risk = (P50 margin − P90 margin) ÷ P50 margin × 100.
Example: P50 = R 412,000; P90 = R 298,000 → 27.7%. A
fat expected margin that melts in the P90 case is a risk problem, not a
success.
4.2 Structural position
On screen: the middle card in the first row
(#overview-gauges). Eyebrow: Structural
position.
Four bars, always in this order. There are no gauges for firm backing, price exposure, or escalation on this card — those numbers can still raise a next-best action (§4.5).
| Id | Label | Metric | Default tick if you set no limit |
|---|---|---|---|
#overview-gauge-top-utilisation-pct |
Take-or-pay used | TOP_UTILISATION_PCT |
target 80% (bad when below) |
#overview-gauge-coverage-pct |
Coverage | COVERAGE_PCT |
band 90–100, or the average of demand-pool coverage targets (bad when below) |
#overview-gauge-spill-pct |
Spill | SPILL_PCT |
max 5% (bad when above) |
#overview-gauge-shortfall-pct |
Shortfall | SHORTFALL_PCT |
max 5% (bad when above) |
Each row is: label · bar · value. The bar fills left
to right. A black tick marks the limit (labelled limit N%,
target N%, or the default words above). Missing value →
— and a grey bar (tone: none).
Colours on the bar
| Tone | Colour | When |
|---|---|---|
ok |
Brand green | Inside the tick |
warn |
Amber | Close to the tick (above ~80% of an “above” limit, or below ~110% of a “below” limit) |
bad |
Rose | Past the tick |
none |
Slate | No number |
Green means the metric is inside your warning threshold — not that the commercial outcome is automatically good. An amber Spill at 7.5% and an amber Shortfall at 7.5% are opposite jobs: one asks you to place midday supply, the other asks you to add supply or reshape sales.
Note. The Trader Pools directory paints rose at fixed triage cuts (§3.3). Inside the book, these bars use your risk limits (§12.6). Trust Overview for operating decisions on the open book.
Take-or-pay used (ToP utilisation): you agreed to pay for a minimum volume even if you do not take it. Low utilisation means you are paying for energy you then spill. The default “good” side is at or above 80%.
Coverage = delivered ÷ demanded. Spill = unsold supply ÷ total supply. Shortfall = unmet demand ÷ total demand. Coverage and shortfall are two views of the same gap: 82% coverage is 18% shortfall on the same numbers.
4.3 Concentration
On screen: the right card in the first row
(#overview-concentration). Eyebrow:
Concentration.
How much of the book sits with one supplier or one buyer. A healthy margin with one counterparty is still a single-point risk.
Supply HHI and Demand HHI are two
meters. The number is the HHI from the
snapshot (SUPPLY_HHI, DEMAND_HHI), shown to
two decimals, or —. The bar behind the needle is green
→ amber → rose; the needle sits at HHI × 100% (1.00 is the far right).
The note on the right names the largest pool share from this run
(Solar 72%) or the hint 1.0 = one supplier / 1.0 =
one buyer.
Counterparty exposure lists up to three
counterparties from counterparty_breakdown, largest first,
each with compact Rand and a share bar (first bar violet, the rest
slate). Empty copy: No counterparty exposure in the latest
snapshot.
Good is a mid-to-low HHI and a list that is not one name. Bad is 1.00 — one shelf or one basket is the whole book.
4.4 Where the energy goes
On screen: the wide card in the second row
(#overview-flow). Title: Where the energy
goes.
This is a flow map (a Sankey): shelves on the left, baskets on the right, ribbons between them. The intro on the card:
Supply pools on the left, demand pools on the right, ribbons sized by MWh allocated in the snapshot run and coloured by margin. Energy that finds no buyer leaves as spill; unmet demand leaves as shortfall.
Read it in this order
Find left and right. Left nodes are supply pools (Solar, Wind, Flexible, Firm — coloured by type). Right nodes are demand pools (Industrial, Commercial, Municipal, Trader Sales — slate). If two pools share a name, the map adds
(supply)or(demand).Read ribbon thickness. Thickness is MWh allocated in the snapshot run (
kWh sent÷ 1,000). A fat ribbon is a big path; a hairline is a small one.Read ribbon colour against the legend on the card:
Legend swatch Meaning Positive-margin flow Green — sold above what it cost Negative-margin flow Rose — bought dearer than it sold Spill (bought, unsold) Amber — paid-for energy with no buyer Shortfall Rose outline — unmet demand Hover a ribbon (when the chart has loaded). The label is compact Rand and margin in c/kWh, or bought, never sold / unmet.
Find the two outlets. Spill · bought, unsold sits as an extra node: supply ribbons that leave the book unused. Shortfall · unmet demand feeds into demand pools that were not fully served.
Read the footer totals (only when there are ribbons): Supply {energy} · Demand {energy}; if spill > 0, bold amber Spill {energy} ({N%}) · {Rand}; if shortfall > 0, bold rose Shortfall {energy} ({N%}).
Empty copy (#overview-flow-empty): No allocation
lines in the latest run yet — the flow map fills in after a forecast
with seated members.
Good is mostly green ribbons, thin or missing spill and shortfall outlets. Bad is a fat amber river into Spill — that is the same story as a loses because N% never sells headline.
4.4.1 How the sides interact each hour
For each forecast hour the engine roughly does this:
- Gather available energy in ACTIVE supply members (after caps, nominations, forecasts).
- Gather requirements in ACTIVE demand members.
- Serve firm demand from firm-capable supply first.
- Walk remaining open demand in pool priority, drawing from the supply merit stack.
- Leftover supply is spill; leftover demand is shortfall.
The flow map is those lines summed for the whole snapshot window. Hour-level proof lives in run detail (§8). Priorities and defaults are §5.1.
4.4.2 Worked example A — midday: sell renewables into offtake
Provenance. Illustrative hour, same conventions as full_demo trader books (c/kWh, MWh). Network losses ignored so the matching arithmetic stays visible.
Situation. 12:00 SAST. Solar has IPP energy. Industrial has factory load. Flexible holds a small trader-in block.
| Side | Pool | Member | Available / need | Buy or sell |
|---|---|---|---|---|
| Supply | Solar | IPP-A | 6 MWh | buy 65 c/kWh |
| Supply | Solar | IPP-B | 4 MWh | buy 70 c/kWh |
| Supply | Flexible | Trader-in | 2 MWh | buy 80 c/kWh |
| Demand | Industrial | Factory C | 8 MWh need | sell 120 c/kWh |
| Demand | Commercial | Mall D | 3 MWh need | sell 115 c/kWh |
Matching (open demand, no firm this hour)
- Industrial takes 6 MWh from IPP-A and 2 MWh from IPP-B.
- Commercial takes IPP-B’s remaining 2 MWh and 1 MWh from the trader-in block.
- Flexible still holds 1 MWh → spill.
Conservation. Supply offered
6 + 4 + 2 = 12 MWh. Demand served 8 + 3 = 11
MWh. Spill 12 − 11 = 1 MWh ✓.
On the flow map you would see a thick Solar → Industrial ribbon, a thinner Solar → Commercial ribbon, a thin Flexible → Commercial ribbon, and an amber Flexible → Spill · bought, unsold outlet.
4.4.3 Worked example B — evening: firm offtake and trader offsell
Provenance. Same illustrative book, 19:00 SAST.
Situation. Solar is dark. You still owe a firm evening sale to another trader. Industrial is still running.
| Side | Pool | Member | Available / need | Notes |
|---|---|---|---|---|
| Supply | Firm | Dispatchable block | 4 MWh | reserved for firm |
| Supply | Wind | Wind PPA | 3 MWh | open merit |
| Demand | Trader Sales | Trader-out block | 3 MWh firm | must be served |
| Demand | Industrial | Factory C | 5 MWh open | after firm |
Matching
- Firm first: Trader Sales takes 3
MWh from Firm. Remainder
4 − 3 = 1MWh. - Open: Industrial takes 3 MWh Wind + 1 MWh Firm remainder = 4 MWh served.
- Industrial still needs 1 MWh → shortfall.
Conservation. Supply 4 + 3 = 7 MWh.
Demand need 3 + 5 = 8 MWh. Served 3 + 4 = 7
MWh; shortfall 1; spill 0 ✓.
On the flow map: Firm → Trader Sales, Wind → Industrial, a thin Firm → Industrial remainder, and a rose Shortfall · unmet demand → Industrial inlet. Buying more solar would not fix 19:00.
4.5 Next best actions · ranked by rand at stake
On screen: the card beside the flow map
(#overview-actions). Title: Next best actions ·
ranked by rand at stake. A pill shows {N}
open.
The panel converts common symptoms into a first move, sorted by Rand at stake (highest first). Rank 1 has an amber surround; the rest are white. Each card has a rank disc, a title, a why, an impact pill, and a deep link.
Empty copy (#overview-actions-empty): Nothing
pressing — coverage, spill and assignment all look healthy.
The footer links are always there: Open Simulation
Workbench → /strategy/simulations (the
Commercial tab) and Open Nominations
workbench (#overview-open-nominations) →
/strategy/nominations?from=overview. The workbench then
offers ‹ Back to Overview.
| Condition (what the engine checks) | Typical title | Link label → URL |
|---|---|---|
| Spill > 5% | Sell the spill: {energy} has no buyer (or Supply is spilling {N%} — add daytime offtake…) | Find offtake → Simulations /simulations |
| Shortfall > 5% | Cover the shortfall: {energy} of demand unmet (or Demand shortfall {N%} — add supply or firm cover) | Find supply → Simulations |
| Take-or-pay used < 80% | Stop paying for take-or-pay energy you spill | Re-optimise → Nominations /nominations |
| Any allocation leg with negative margin | Cut the loss-making {source} → {target} leg | See the leg → Allocations /allocations |
| Firm backing < 1.0× | Firm sales exceed firm capacity ({N}×) | Review firm pool → Pools /pools |
| Indexed volume above the price-exposure limit (default 25%) | Hedge the {N%} indexed volume | Set limits → Dashboard /dashboard |
| Active contracts not in any pool | {N} active contract(s) not in any pool | Assign → Pools |
| Battery ≥ 1.2 cycles/day | Battery at {n} cycles/day — near the warranty cap | Open BESS /bess (§11.11) |
| Nomination tolerance breached in > 10% of hours | Nominations breach tolerance in {N%} of hours | Re-optimise → Nominations |
Impact pills show compact Rand when the engine can price the stake (≈ R 12.2 m), otherwise a plain tag (hygiene, deadline, warranty, structural breach).
An action labelled “add daytime offtake” is a shape hypothesis. Open the Desk, inspect the fit, and test terms before you create a proposal (§9).
4.6 Long or short, hour by hour
On screen: the full-width card
(#overview-clock). Title: Long or short, hour by
hour.
This is not a separate “Next Best Actions Long or Short” card. Long and short are the clock. The actions card is §4.5.
The intro on the card:
Net position on a typical day of the run: matched energy in green, supply above demand is long (spill, amber), demand above supply is short (shortfall, rose). The solid line is demand; the dashed line is tomorrow’s P50 supply from the suppliers’ weather forecasts.
The period toggle
#overview-clock-period is two buttons, not a URL:
| Button | What it plots |
|---|---|
| Typical day ({from} – {to} · {N} days) | The run’s hours averaged by SAST clock hour, then divided by the number of distinct days. Default |
| Tomorrow (P50 supply) | Same demand line; stacks rebuilt from tomorrow’s weather P50 across up to three seated supply generators |
Tomorrow is disabled, at half opacity, with tooltip No supplier weather forecast for tomorrow yet until that extra load arrives. While it loads you may see loading supplier forecast….
How to read Typical day
- Daylight / Night wash. The legend
(
#overview-clock-day-night-legend) marks Daylight (06:30–17:30) (sun, amber wash) and Night (moon, grey wash). Hours are SAST. - Three stacks, bottom to top in the legend:
Matched (green
#059669), Long (spill) (amber#f59e0b), Short (shortfall) (rose#e11d48). - Solid slate line = Demand (allocated delivered + shortfall that hour, typical-day average).
- Dashed slate line = P50 supply (tomorrow) when weather exists — overlaid on Typical day so you can compare today’s shape with tomorrow’s expected supply. It does not replace the stacks until you press Tomorrow.
- Plant now (
#trader-plant-chips) sits under that legend, above the chart. Each chip names the IPP site and the last sample time. Press it and Your plant live opens as a scrollable modal on this Overview (#overview-plant-live-modal) — it does not send you to/org/generator-sites/…/strategy/plant. Use it to check the live reading against the P50 tomorrow line. Absent when no seated supplier has a live feed; that is normal. - Clip strip (
#overview-clip-strip) under the chart: 24 cells, 0h → 23h. Caption: Clip strip · amber = long, the bid desk would clamp · rose = short. Hover a cell:{hh} · long {energy} · short {energy} per typical day. Darker amber means a fatter long hour (the top third of the day’s long peak). Slate means matched with no leftover.
Good on Typical day: a green matched band that follows the demand line, thin amber only at solar noon if you are slightly long, little or no rose. Bad: a tall amber plateau (you bought a shape nobody takes) or a rose evening block (you sold evenings you cannot cover).
How to read Tomorrow (P50 supply)
Press Tomorrow (P50 supply). The stacks are rebuilt as:
- Matched = min(tomorrow P50 supply, today’s typical demand)
- Long = supply above that demand
- Short = demand above that supply
The demand line stays. The dashed P50 line is not drawn again (it is the stack). Use this to ask: if tomorrow’s weather is the P50 we already have, do I still spill at noon or go short at 19:00?
If the button stays disabled, you have no supplier weather yet — stay on Typical day.
4.7 Pool health
On screen: the wide card in the last row
(#overview-pool-health). Title: Pool
health. Intro: Each pool against its own targets: coverage
band, spill and shortfall caps, and its share of the margin.
This is a table, not the old locator “pool cards”.
Two section rows — SUPPLY then DEMAND
— then one data row per pool (#overview-pool-{id}). Empty
section: No supply pools. / No demand pools.
Every table header
| Header | What it shows |
|---|---|
| Pool | Type icon, name, then a grey line:
{N} member(s) and, on a firm supply pool,
· firm |
| MWh | Energy in the snapshot for that pool (auto kWh / MWh / GWh), or — if none |
| Coverage vs band | Demand only. A bar: green wash is the pool’s coverage band; the dark fill is where coverage sits. Supply rows show — |
| Spill / short | Supply: {N%} spill. Demand: {N%} short (or
0% short / —). Rose when supply spill
> 20% or demand short > 5% |
| Margin | Compact Rand, right-aligned. Green if positive, rose if negative |
| (last column, no title) | Status chip: ok · warn ·
breach · idle |
How to read a supply row
MWh is allocated sent + spill for that pool. Coverage vs band is blank — supply has no coverage target. Spill / short is the spill share of that pool’s own energy. Chips:
| Chip | When |
|---|---|
idle |
No energy in the snapshot |
breach |
Spill % above this pool’s max spill cap |
warn |
Spill % above 20% (even if under the cap) |
ok |
Otherwise |
High Solar spill usually means missing daytime demand, not “too much solar forever”.
How to read a demand row
MWh is delivered + unmet. Coverage vs band compares snapshot coverage to the pool’s min–max band (or target ± 10 points, or 90–100). The green wash is the band; the fill is the value (capped at 100% on the bar). Spill / short is the unmet share.
| Chip | When |
|---|---|
idle |
No coverage figure |
breach |
Shortfall % above this pool’s max shortfall cap |
warn |
Coverage below the band minimum |
ok |
Otherwise |
Industrial below its band and Trader Sales at 100% are different jobs. Firm shortfall is rarely acceptable.
The row is a locator, not an editor. Change members and rules on Book · Rules (§5); return here after a new forecast.
| Side | Pool | MWh in | Placed / served | Spill / short |
|---|---|---|---|---|
| Supply | Solar | 10 | 10 | 0 |
| Supply | Flexible | 2 | 1 | 1 spill |
| Demand | Industrial | 8 need | 8 | 0 |
| Demand | Commercial | 3 need | 3 | 0 |
| Conservation | 12 offered | 11 served | 1 spill ✓ | |
Supply offered equals served plus spill. Demand need equals served plus shortfall. The flow map and Pool health are two views of the same lines.
4.8 Where the margin is made and lost
On screen: the upper right card in the last row
(#overview-heatmap). Title: Where the margin is
made and lost. Intro: Month × hour margin from the run’s
allocation lines. Green earns, red loses.
A heatmap (#overview-margin-heatmap): columns
are months in the run (labels like Oct. '25),
rows are SAST clock hours (0h …
23h). Each cell is the sum of margin_r for
that month-hour. The colour scale is centred on zero: green earns, red
loses, the ends are equal in size so a big win and a big loss are
comparable.
Empty copy: No priced lines in the latest run yet.
How to read it. Find the red cells first — those hours lose money. A red evening column every month is a shape problem (firm sales after solar). A red summer-noon column with a green winter-noon is a seasonal spill story. Then open Book · Forecast or Allocations when you need the lines behind a cell. This card does not edit prices.
4.9 Forecast said, book settled
On screen: under the heatmap
(#overview-drift). Title: Forecast said, book
settled. Intro on the card:
P50 margin at forecast time against the settled trader book, last 6 months. The gap is forecast error you are paying for.
A weather forecast says it will rain. The wet pavement — or the dry one — is what actually happened. This card is that pair, for money.
Forecast P50 is the plan: what the latest P50 (expected-case) risk snapshot said this book would
earn that month. Settled book is the receipt: what settlement actually wrote on the
trader statement — or, if no buy and sell legs have settled yet, that
month’s ACTUAL snapshot.
The chart (#overview-drift-chart) plots both on one pair
of axes for the last six calendar months, including
this month.
This card does not sign a deal. It does not re-run the forecast. It only asks: has the plan been honest?
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Overview, then scroll under Where the margin is made and lost. You should see#overview-drift, then either Loading settled months…, the two-line chart, or the empty copy below.
Data. full_demo · seed 42 · T1 Renewables Pool · last checked 2026-09-18 against
StrategyOverviewLive. Snapshot Rand moves with the latest forecast. The two teaching charts below use the same month labels and compact Rand the card prints. A seeded book that is long may show a large gap, or No month has both a forecast and a settled statement yet. The labels and rules are the product.
Where this is taught. The month’s buy and sell legs behind Settled book: §6A. How a snapshot is sealed: §4.10. The IPP card Forecast said, settlement did is a different screen — last month’s buyer carve, not this book’s margin (V4 §8.1.8).
Words on this card
| Word | Plain meaning |
|---|---|
| Forecast P50 | The green line. Expected-case monthly margin from the latest
FORECAST snapshot in that month
(MARGIN_R) |
| Settled book | The sky-blue line. Net margin on the consolidated trader statement
when buy and sell legs exist; otherwise that month’s ACTUAL
snapshot |
| Gap | Settled minus forecast, in Rand. The verdict averages this over months that have both numbers |
| R | South African Rand. The Y axis. Up is more profit (or a smaller loss). Below R 0 is a loss |
| Last 6 months | Six month ticks on X, oldest on the left, this month on the right.
Labels look like Apr. '26 |
The gap is error, not a bill on its own. Settled below forecast means you planned on money you did not get. Settled above forecast means you earned more than the plan — still a miss, but a happy one.
How to read the chart
Find the legend under the plot. Two names: Forecast P50 and Settled book.
Read the colours (Overview uses the shared line palette). Forecast P50 is first — brand green
#059669. Settled book is second — sky#0ea5e9.Read left to right. Each tick is one calendar month. Hover a month to see both Rand figures.
Ignore one line alone. A falling settled line is only a problem relative to the forecast. Two lines that fall together mean the plan saw the drop.
Look at the gap. Do the lines travel together, or does one wander off? Does the space grow as you walk toward this month?
Read the verdict under the chart, once extras have loaded:
Verdict When Settled margin runs {Rand} below forecast on average over {N} month(s). Average gap is negative — the plan was optimistic Settled margin runs {Rand} above forecast on average over {N} month(s). Average gap is positive — the plan was pessimistic No month has both a forecast and a settled statement yet. Lines may exist, but no month has a pair, so there is no average
A missing dot in one series is normal. That month has a forecast or a settlement, not both. The verdict ignores it.
Loading (page just connected): Loading settled
months… — the chart is a slow extra. Wait. Empty
(#overview-no-drift): No forecast snapshots or settled
statements in the last 6 months yet. Press Run Forecast
Now, or wait until a month has settled.
A good chart — the forecast was honest
A good chart is not “the book earned a lot.” It is “the plan and the receipt stay close.” Small gaps that flip sign (a little above, a little below) are weather noise. The gap does not grow.
Good — lines travel together
Why it is good: the sky receipt hugs the green plan. Gaps flip sign. Nothing grows. Verdict would read about R 3 k below — noise, not a lie.
Bad — one-way miss, growing gap
Why it is bad: the green plan stays high. The sky receipt falls, crosses R 0, and keeps dropping. The miss is one-way. The gap grows. You are paying for optimism.
| Month | Forecast P50 | Settled book | Gap |
|---|---|---|---|
| Apr. ’26 | R 380 k | R 365 k | − R 15 k |
| May. ’26 | R 400 k | R 412 k |
|
| Jun. ’26 | R 390 k | R 378 k | − R 12 k |
| Jul. ’26 | R 410 k | R 405 k | − R 5 k |
| Aug. ’26 | R 420 k | R 428 k |
|
| Sep. ’26 | R 400 k | R 394 k | − R 6 k |
| Average gap (the verdict) | − R 3 k ✓ | ||
Six small misses that change sign. The plan was honest. Trust the P50 headline for the next look-ahead — then still read spill and shortfall on the other cards.
| Month | Forecast P50 | Settled book | Gap |
|---|---|---|---|
| Apr. ’26 | R 410 k | R 80 k | − R 330 k |
| May. ’26 | R 420 k | R 40 k | − R 380 k |
| Jun. ’26 | R 400 k | − R 20 k | − R 420 k |
| Jul. ’26 | R 430 k | − R 80 k | − R 510 k |
| Aug. ’26 | R 450 k | − R 150 k | − R 600 k |
| Sep. ’26 | R 440 k | − R 200 k | − R 640 k |
| Average gap (the verdict) | − R 480 k | ||
Every month settled below the plan, and the hole got bigger. That is the sentence Settled margin runs R 480 k below forecast on average over 6 month(s). Do not treat the green line as cash.
Why the good one is good. The weather report was close to the pavement. A May beat and an April miss cancel. You can use the headline on §4.1 as a planning number.
Why the bad one is bad. The report kept promising rain. The pavement stayed dry — then the book crossed R 0 and kept losing. A common cause on a long trader book: the forecast still prices offtake you have not seated, so P50 margin stays fat while the ledger records spill. T1 Renewables Pool’s loses because N% never sells headline is that story in one sentence. This chart is the six-month proof.
What to do next
| What you see | Do this | Do not |
|---|---|---|
| Good — lines track, verdict a few thousand either way | Keep using the P50 headline. Read spill and shortfall as usual. No extra trade from this card | Do not skip the other eight cards. An honest forecast can still describe a book that spills |
| Bad — settled below, month after month, gap growing | Open Book · Outcomes for a settled month (§6A). Check Book · Rules if the forecast prices energy that never settles. Fix members, then §4.10 | Do not add sales that need the “air” megawatt-hours on the green line. Do not treat the headline as cash in the bank |
| Settled above — happy miss | Find the extra offtake or cheaper buy before you scale the book on luck. The plan was still wrong | Do not assume next month will beat the plan again |
| Empty / no paired months | Run a forecast. Wait for a month to settle. Come back | Do not invent a verdict from one line |
Book · Outcomes draws a cousin of this chart for the same six months. Dashboard keeps the long view (§12).
4.10 What happens when you run (or re-run) the forecast
Run Forecast Now
(#overview-run-forecast) is the on-demand twin of the
nightly strategy cycle for this book. It asks the engine:
Given everything seated on this book today — members, prices, caps, rules, forecast shapes, network losses, and the battery if you have one — what does the next year look like in the expected case, and how much of that margin melts away if renewables under-deliver?
The answer is frozen as a risk snapshot. Overview, Dashboard, and the directory chips all read that snapshot. No snapshot → the empty panel in the chapter open. A successful press replaces today’s snapshot for this book.
Same cycle, two triggers. Nightly (about 02:30 SAST, every active book) and Run Forecast Now (this book, now) both call the Margin-at-Risk pass: P50 base + P90 adverse + snapshot. The nightly rhythm is V3 §18.3.
The Book · Rules amber banner Forecast is behind this board is taught in §5.6. A simulation in Commercial is not a forecast re-run (§9).
4.10.1 When you should press it — and when you should not
| Situation | Press Run Forecast Now? | Why |
|---|---|---|
| First open / empty Overview | Yes | Cards cannot light without a snapshot |
| Pools shows Forecast is behind this board | Yes | The last seal describes the old book |
| You changed members, priorities, caps, rules, limits, or BESS | Yes | The snapshot is stale |
| You only opened Dashboard to browse | No | Reading does not change inputs |
| You are mid-edit with half-built members | Wait | You would freeze a half-built book |
| Nightly finished an hour ago and nothing changed | Optional | Harmless, usually unnecessary |
4.10.2 The pass in seven steps
No conveyor-belt diagram — the order is the list.
- Window. Today → a rolling 12-month half-open
window. Example: press on 23 Jul 2026 →
[2026-07-23, 2027-07-23). Each hour is its own match (§4.4.1). - Inputs. Freeze active pools and members, prices and caps, forecast grade, network edges, battery, period. Fingerprint: inputs hash. Same hash → same lines.
- P50 pass. Allocate every hour (firm first, then
open priority; tag
SPILL/SHORTFALL; optional battery pass). Store aFORECAST/ P50 run. This becomes the current forecast position. - P90 pass. Same period; every
renewable member swaps to P90. Tagged
SIMULATION/ P90 so it never becomes “the” current forecast. - Margin-at-Risk.
MaR (R) = P50 margin − P90 margin;MaR (%) = MaR (R) ÷ P50 margin × 100. That percentage is the Margin@Risk · P90 adverse tile. - Snapshot. One dated row: portfolio metrics, per-pool breakdown, breaches against active limits.
- Screens. Overview reloads the nine cards. Dashboard
reads the same snapshot. The previous equivalent
FORECASTrun is marked superseded only after this press completes.
While the overlay is up, keep treating the previous snapshot as the decision record. Only Forecast updated. means steps 1–7 finished.
4.10.3 P50 and P90 in plain language
Renewable forecasts are graded by exceedance:
| Grade | Plain reading | For generation |
|---|---|---|
| P50 | In a typical year you expect about this much | The median / expected case |
| P90 | You are 90% confident of getting at least this much | Always ≤ P50 — the conservative case |
| P10 | You only get this much or more in a lucky 10% of years | Optimistic (rarely used on this button) |
Common mix-up. “P90” is not “ninety percent — a lot.” It is the low case you are still confident of clearing. P90 ≤ P50 ≤ P10 for generation.
Toy plant: declared P50 = 43,800 MWh/yr, solar-like P90/P50 = 0.94 → P90 ≈ 41,172 MWh/yr. On a book, the adverse pass shrinks every renewable hourly shape, then re-matches the whole marketplace. Firm supply is not shrunk the same way.
Snapshot the Overview actually shows
Illustrative trader book on 1 Aug 2026 (rounded whole Rand):
MARGIN_R = 412 000 ← from P50 run
MARGIN_AT_RISK_PCT = 27.7 ← (412k − 298k) ÷ 412k × 100
COVERAGE_PCT = 82.0
SPILL_PCT = 9.3
SHORTFALL_PCT = 1.8
pool_breakdown[Industrial].COVERAGE_PCT = 75.0
breaches = [ MARGIN_AT_RISK_PCT warn if limit warn=25 ]
On T1 Renewables Pool after the seed, expect the opposite commercial shape: a loses R 12.2 m headline and spill near 96% — same cards, different numbers.
4.10.4 Re-run vs first run
| Object | First successful press | Second press the same day | If the press fails |
|---|---|---|---|
P50 FORECAST run |
Created; becomes current | New current; prior superseded | Prior current unchanged |
P90 SIMULATION run |
Created for MaR only | New adverse companion | Prior left alone |
| Risk snapshot for today | Created | Replaced | Prior snapshot still shown |
| Simulations / nominations | Untouched | Untouched | Untouched |
Press twice with no book changes: new run ids, same inputs hash and KPI values. Press after seating a priced PPA: hash, Margin and often MaR move.
4.10.5 Operator checklist
- Finish the structural change on Book · Rules, the battery or limits.
- Press Run Forecast Now here or on the Pools banner.
- Stay on the page while the overlay is up.
- When Forecast updated. appears, read the headline and rose gauges first, then rank 1.
Follow the lines. Allocation mechanics: §7. Runs list: §6. Dashboard: §12.
4.11 Explanations and other chrome
Explanations
(#overview-explanations-open) opens a right-hand drawer
(#overview-explanations-drawer). Eyebrow: Trader
Overview. Title: Explanations. Above the terms
sits How to Read the View
(#overview-how-to-read) — collapsed until you press
#overview-how-to-read-toggle. It is the short in-product
reading order: position, structural position, concentration, energy
flow, actions, hour-by-hour, pool health, margin heatmap, forecast
versus settled. Intro: Abbreviations and terms used on the
trader-pool Overview, in alphabetic order. Close with the X
(#overview-explanations-drawer-close), the backdrop, or
Escape. The list is A–Z from BESS (Battery Energy Storage
System) through VaR 95 (Value at Risk). It
does not include SAWEM — that word is not on this
Overview (it lives on the Bid Desk).
Plant now chips (#trader-plant-chips)
sit under the Long or short legend, above the chart — not above the
intro. They appear only when a seated supplier has a live telemetry
feed. Each chip shows the IPP site name and last sample
time. Press the chip: Your plant live opens as a
scrollable modal (#overview-plant-live-modal, branded
header, site name as the title). Close with the X
(#overview-plant-live-close), the backdrop, or Escape. You
stay in Performance. Absent on a book with no live feeds — that is
normal, not an error.
Busy overlay (#strategy-busy-overlay):
Running forecast… / Stay on this page until the run
finishes.
This is the morning pattern: Overview detects, Book / Desk / Dashboard change, a fresh snapshot confirms. Keep the two-sided picture from §4.0 when Pool health points at Solar spill versus Industrial shortfall — those are opposite shelves.
Where this is taught next. Book has its own Explanations drawer with a different How to Read for Rules, Forecast and Outcomes (§5.8, §6.8, §6A.4).
5. Book · Rules — how the book is wired
Route: …/strategy/book opens here
(…/strategy/pools) · Tab: Book
(#strategy-tab-book stays active) · Mode:
Rules (#book-stage-rules on the thread strip; Outcomes and
Forecast are the other stages, not extra #strategy-nav
tabs.)
What it is for. Pools are how you tell the engine what your book is. A pool is a named group of members on one side — supply (sources) or demand (sinks) — with a stated purpose, a priority, and side-specific limits. The engine only sees ACTIVE pools; a PPA that isn't a member of any pool doesn't exist as far as allocation is concerned.
Where the marketplace picture is taught. Why supply and demand pools exist, when you buy from an IPP vs another trader, and when you offsell to an offtaker vs a trader — with midday and evening worked examples — is §4.0; the hour diagrams sit with the Overview flow map (§4.4). This chapter is the build and edit screen: create pools, seat members, set priorities and rules.
Why pools at all, instead of just a list of contracts? Because allocation decisions are made between groups: solar as a class serves daytime load first; firm supply as a class is reserved for firm obligations; spill from renewables is routed to the flexible pool for tactical use. Pools carry those group-level policies (priorities, spill destinations, coverage targets, rules) so you never have to encode strategy contract by contract.
The Book’s thread, and what this mode adds to the board
Allocation on the strategy row opens
Rules. The top underline (#strategy-nav)
stays Operations · Performance · Allocation · Commercial · Dashboard —
Allocation stays lit. Rules,
Forecast and Outcomes switch on the
thread strip under that bar, not as extra room
tabs.
Every Book view still opens with the same thread strip: three stages — Rules · how the book is wired → Forecast · what the engine will do → Outcomes · what actually settled — each with a verdict pill (on the demo: 4 caps breached → September P50 · −R 12.2 m · spill 95.8 % → August · −R 381 k · not balanced). Clicking a stage opens that view. Under it the issues rail ranks everything wrong in the book — caps breached, a month that does not balance, a nominated run still running, a failed run, coverage outside its band, draft pools with no members — and each item points at the mode that fixes it.
Then the mode’s headline, written from the numbers: “The cascade sells into 4 demand pools in priority order — and supply outweighs what they can take 24 to 1. Whatever Solar, Wind, Flexible and Firm bring past 4 % will spill.”
The board itself is two columns with a wiring gutter between them. SUPPLY pools sit left in merit order, DEMAND pools right in priority order. Three things are new on the cards:
- an outcome badge at the foot of each card — the pool’s cap or band as a bar with the limit tick, filled with what the latest forecast actually did to it: green inside the cap or band, amber outside the band, red when a cap is broken. The wiring problem appears on the card you edit;
- wires in the gutter (
#book-wires) — coloured joiners from a supply card to a demand card. The colour is the supply shelf (Solar amber, Wind light blue, and so on). The word on the curve is the rule (shape match,price ≥ 12.5 c, …). A dashed red curve is leftover supply the latest forecast could not sell. The full reading guide is §5.7.
There is no three-card “next moves” strip under the
board. Reorder supply on the left column; coverage bands live on the
demand-card badges; spill and shortfall are on the issues
rail. When the latest forecast leaves more than 20 % of supply
unsold, a single line (#book-offtake-cta) offers
Find offtake → Desk — the same Desk door Overview
already ranks under Next best actions.
Everything else on this board — creating pools, seating members, rules, book rates, the unassigned-contracts strip and the amber Forecast is behind this board banner — is unchanged and taught below.
Above the board:
- Book rates — book-wide default spill value and shortfall top-up (c/kWh). Member assign prefills from these when set; blank member fields inherit them at run time (§5.3).
- Forecast is behind this board (amber banner) — appears when members, rules, priorities / caps, book rates, or an ACTIVE → ARCHIVED pool change the book after the last sealed forecast. [Run Forecast Now] on the banner runs the same cycle as Overview (§4.10, §5.6); the banner clears when that seal succeeds.
5.1 Creating pools — and what the defaults mean
[Seed default pools] (only shown while you have none) creates the standard Phase-1 set of eight pools. These are not arbitrary — their priorities and limits encode a sensible starting strategy:
Supply side (priority = order the allocator prefers them, lower first):
Pool Priority Max spill Purpose ☀ Solar 10 15% Cheap daytime energy; spill-tolerant. ☁ Wind 20 12% Night coverage and shape diversity. 🎚 Flexible 30 20% Nomination-based and tactical; receives the spill from Solar and Wind. 🔒 Firm 40 5% Dispatchable/firm blocks reserved for firm obligations. Cheapest-and-least-firm first, most-expensive-and-most-precious last: the allocator drains solar before it touches your firm block, and the firm block is held back for the customers who contractually must be served.
Demand side (priority = order in which demand pools get access to supply):
Pool Priority Coverage target (min–max) Max shortfall Firm 🔧 Industrial 10 75% (70–90) 5% — 🏬 Commercial 20 55% (50–60) 10% — 🏛 Municipal 30 65% (60–70) 10% — 💵 Trader Sales 40 100% (100–100) 0% ✓ Note the deliberate asymmetry: Trader Sales has the last priority number but is firm — and firm demand is served first, out of turn, from FIRM supply (§7.1). The priority ordering only governs the open (non-firm) demand queue.
How supply priority is applied. For every hour, the engine builds a supply merit stack from energy that is actually available in that hour. Lower numbers go first. The ordering is:
- supply-pool priority;
- buy price, cheapest first, for members in the same pool;
- member priority within that pool; and
- member ID as a final deterministic tie-break.
FIRM-pool supply is treated specially: it is offered to firm demand before the open merit stack is walked. Any FIRM supply left after firm obligations have been met becomes the last source available to open demand. Capacity caps, nominations and the hour's forecast are applied before the stack is built, so priority never creates energy that is not available.
How demand is matched and prioritised. The engine first separates firm demand from open demand. It serves all firm demand first, ordered by demand-pool priority and then member priority. It then serves open demand in the same lower-number-first order. Each demand tier draws from the eligible supply stack until its requirement is met or supply is exhausted. Demand members with the same pool and member priority share the available supply pro rata, using their allocation weights, rather than the first member taking everything. Coverage targets and maximum-shortfall settings are monitoring and risk thresholds; they do not override this hourly service order.
Worked example — one hour, ignoring network losses for clarity.
Available supply is Solar A 6 MWh at 65 c/kWh in the priority-10 Solar pool, Solar B 4 MWh at 70 c/kWh in the same pool, Wind 5 MWh at priority 20, and Firm 4 MWh at priority 40. Demand is Trader Sales 3 MWh firm at priority 40, Industrial 8 MWh at priority 10, Commercial 5 MWh at priority 20, and Municipal 5 MWh at priority 30.
- Trader Sales is firm, so it takes 3 MWh from the Firm pool first, leaving 1 MWh of Firm supply.
- Industrial is the first open-demand pool. It takes Solar A's 6 MWh and 2 MWh from Solar B.
- Commercial is next. It takes Solar B's remaining 2 MWh and 3 MWh from Wind.
- Municipal is last. It takes Wind's remaining 2 MWh and the final 1 MWh of Firm supply. It is left with a 2 MWh shortfall.
The result is auditable: firm demand was protected first, open demand followed its priority queue, and each demand drew from the highest-priority (lowest-numbered) eligible supply before more precious Firm energy was released. Within Solar, the cheaper Solar A energy cleared before Solar B.
- [+ New pool] opens a viewport-fitting modal (sticky header and footer; the middle scrolls). Fill every required field, then Save pool. The tables below list every field on that form: what it means, a concrete sample, and why you enter it. Choosing an archetype Type can prefill several limits — §5.1.4.
New pool — fields always on the form
| Field | What it represents | Sample input | Why you enter it |
|---|---|---|---|
| Name | The human label on the pool card, board, and run detail | Rooftop Solar West |
So operators can tell this shelf/basket apart from others of the same type |
| Side | Whether the pool is a supply source stack or a demand sink | Supply |
Chooses which Type list and which limit fields appear; the engine never mixes sides |
| Type | The commercial archetype (or Custom) for this pool | Solar (supply) or Industrial (demand) |
Drives default member class, type suggestions for limits, and how the board icons the card |
| Purpose | Free-text statement of what this pool is for | Cheap daytime PV; spill-tolerant daytime shelf |
Governance: activation refuses an empty purpose — every ACTIVE pool must say why it exists |
| Default priority | Integer order for this pool in the hour's walk (1–100). Lower runs first | 10 |
Puts this pool ahead of or behind siblings (seeded Solar is 10; a
late tactical pool often stays at 100) |
| Match policy | How strictly members must match Accepted member classes | Strict |
Strict = only fitting classes are offered;
Approved override = you may seat a mismatch on purpose and
keep the rule for audit |
| Accepted member classes | Which strategy classes may join this pool (checkboxes) | Tick Solar only |
Stops a wind PPA or industrial offtaker landing on the wrong shelf; under Strict, the add-member search hides incompatible subjects |
The priority strip under Default priority lists
other pools on the same side so you can pick a number that slots
correctly (e.g. between Solar 10 and Wind
20).
New pool — supply-only fields
Shown when Side = Supply.
| Field | What it represents | Sample input | Why you enter it |
|---|---|---|---|
| Max spill % | Largest share of this pool's supply that may remain unsold before risk tooling should flag it | 15 (Solar archetype) |
Sets your spill tolerance for Dashboard / Overview alerts — it does not cap generation; every unsold MWh is still recorded as spill |
| Spill destination pool | Optional other supply pool that receives routed spill for tracking | Flexible Pool |
Makes unsold Solar/Wind energy visible where you might nominate, sell, or charge a battery — routing alone does not create revenue |
Sample story. Solar produces 100 MWh; 82 MWh are allocated → spill = 18%. With Max spill 15%, the book flags a breach. If Spill destination = Flexible, those 18 MWh appear on Flexible for follow-up while still unsold.
New pool — demand-only fields
Shown when Side = Demand.
| Field | What it represents | Sample input | Why you enter it |
|---|---|---|---|
| Coverage target % | Operating aim: delivered energy ÷ demanded energy for this pool | 75 (Industrial archetype) |
The headline "did we cover this basket?" target in Performance pool cards and risk snapshots |
| Coverage min % | Lower edge of the acceptable coverage band | 70 |
Below this → under-coverage risk (you are leaving too much load uncovered) |
| Coverage max % | Upper edge of the acceptable coverage band | 90 |
Above this → over-procurement risk (you are covering more heavily than policy allows) |
| Max shortfall % | Largest share of demand that may remain unmet before a flag | 5 (Industrial) or 10 (Commercial) |
Separate shortfall tolerance from the coverage band — unmet MWh can breach shortfall even when coverage looks "close" |
| Firm | Toggle: treat this demand as a firm obligation | Unticked for Industrial; ticked for Trader Sales | Firm demand is served from FIRM supply before open demand; firm shortfalls price at the member's grid top-up (§7.2) |
Sample story. Industrial demand 100 MWh, delivered 65 MWh → coverage 65% (below min 70%) and shortfall 35% (above max shortfall 5%) — both risk conditions fire. These percentages are measurement and alert settings; they do not change the allocator's hourly priority walk.
Required to activate later. After save the pool is
DRAFT. Activation still needs purpose, at least one member, and the side's key limit (Max spill % on supply, Coverage target % on demand) — see the card actions in §5.2.
Type suggestions on New pool
When you create a pool by hand, you do not have to invent the risk numbers. Choosing a known Type on + New pool prefills the same archetype limits that Seed default pools uses (the tables at the top of this section). A green hint under Type summarises what was filled.
| Side | Type examples | Fields that are suggested |
|---|---|---|
| Supply | Solar, Wind, Flexible, Firm | Max spill %, purpose, default priority |
| Demand | Industrial, Commercial, Municipal, Trader Sales | Coverage target / min / max %, Max shortfall %, purpose, default priority (and Firm on Trader Sales) |
| Either | Custom | Nothing — leave limits blank until you set a policy |
Worked example — New Solar pool. Side = Supply, Type = Solar → the form fills Max spill 15%, priority 10, and purpose "Cheap daytime energy; spill-tolerant." The hint reads roughly: Suggested for Solar: max spill 15%, priority 10. Editable — change any value to override.
Worked example — New Industrial pool. Side = Demand, Type = Industrial → Coverage target 75%, band 70–90%, max shortfall 5%, priority 10.
Override rules (so suggestions stay helpful, not sticky)
- Suggestions run only on New pool, never when you Edit an existing pool (your saved limits stay put).
- Edit any suggested field and that value is yours — changing Type later will not overwrite a field you already customised.
- If you leave a field on the previous type's suggestion (or still
blank / priority still
100), switching Type replaces it with the new archetype. - Custom clears the green hint and does not invent numbers; keep or clear prior values yourself.
Use Seed default pools when you want all eight archetypes at once. Use + New pool + Type suggestions when you only need one more shelf or basket (for example a second Solar-shaped CUSTOM is still blank — pick Solar if you want Solar's spill tolerance).
How to set the supply-side spill fields.
Max spill % is the largest share of a supply pool's energy that may remain unsold before the dashboard flags it. It is a risk tolerance, not a cap on generation: the engine still records every unsold MWh as spill.
Spill destination pool is the pool where that spill is routed for tracking and tactical follow-up. It does not make the energy sold or create revenue; it gives the operator a clear place to see energy that could be nominated, sold, or used to charge a battery.
Example — Solar Pool. A solar pool produces 100 MWh in a period and the engine allocates 82 MWh. Its spill is
(100 − 82) ÷ 100 = 18%. If Max spill % is 15%, the 18% result breaches the pool's tolerance. If its spill destination is Flexible Pool, the 18 MWh is shown there for follow-up; it is still unsold energy until an actual commercial or battery action uses it.
How to set the demand-side coverage and shortfall fields.
Coverage target % is the operating aim for the share of demand that the book should deliver. Coverage min % and Coverage max % form the acceptable band around that aim: below the minimum is under-coverage risk; above the maximum signals over-procurement risk. Max shortfall % is a separate limit on unmet demand. These are dashboard and risk thresholds; they do not change the engine's hourly priority walk.
Example — Industrial Pool. Set a coverage target of 80%, an acceptable band of 70–90%, and a maximum shortfall of 30%. For 100 MWh of demand:
- 78 MWh delivered means 78% coverage and 22% shortfall. Coverage is inside the band and shortfall is inside its limit, although the operating target was missed.
- 65 MWh delivered means 65% coverage and 35% shortfall. Coverage is below the minimum and shortfall exceeds its limit, so both risk conditions are flagged.
- 94 MWh delivered means 94% coverage. It is above the maximum, signalling that the pool is being covered more heavily than its commercial policy allows.
Choose the target, band and shortfall limit together so they express one coherent commercial policy for the pool.
5.2 The pool card
Each card shows the pool's type icon, status badge
(DRAFT / ACTIVE / ARCHIVED),
purpose, side-specific figures (supply: spill ≤ X%; demand:
target X% and a 🔒 firm badge), member count and its
member list (each with its priority and a remove ×). Every member line
starts with the organisation that owns that site or
trader block, then the site or pool name, as
Organisation · Site (the same pattern as Deal Room
counterparties). A contract-only member (saved with
physical_ppa_id) still resolves to that counterparty
organisation and site or pool. Card actions:
The operational summary also shows the pool's
priority. Lower numbers are called first in the
allocation stack; 100 is last. The Member
compatibility panel shows the accepted member-class chips (for
example, Solar, Firm or Industrial) and the
match policy configured in the pool form (§5.1):
Strict means a member must share at least one accepted
class to be offered or added; Approved override permits
an intentional exception while retaining the configured classes as the
pool's commercial rule. Use the panel to check the admission rule before
adding a member (§5.3).
Reorder members from the card. The member list is grouped into priority tiers, with the lowest priority shown first. Within a shared priority tier, members are shown by ascending pro-rata weight; members with a blank weight (which use contracted volume) follow the explicit weights. This makes the allocation order and every pro-rata group visible without opening another screen.
Click Edit order beside a member to change its Priority or Pro-rata weight. Save the change and the card immediately moves the member into the appropriate priority tier and re-sorts that tier by weight. Priority controls which tier is considered first and cannot exceed 100; pro-rata weight controls the split only among members in the same priority tier, must be greater than zero, and cannot exceed 10. Leave the weight blank to use the member's contracted volume instead.
- + member — assign an unassigned executed PPA to this pool (§5.3); greyed out until one exists
- Rules — manage allocation rules (§5.4)
- Edit — reopen the pool modal
- Activate (DRAFT and ARCHIVED pools,
#activate-pool-{id}) — the engine only allocates ACTIVE pools. On a DRAFT card you also have Archive — go live, or retire the shelf without ever putting it in a run. Press Activate on a draft to bring it into the book, or on an archived card to put that shelf back into runs. You do not create a second pool of the same type: an archived Solar still occupies Solar on Select a type. Activation is validated against three requirements: a non-empty purpose, at least one member, and the side's limit set (max spill % for supply, coverage target % for demand). If something is missing you get the exact reason as a flash, e.g. "Cannot activate: coverage_target_pct must be set". Success flash: Pool activated. The point of the gate: a pool without a target can't be measured, and a pool that can't be measured shouldn't be in your book. Activating (or any other structural edit that changes the board fingerprint) marks Overview / Dashboard stale until you re-run the forecast (§5.6). - Archive (DRAFT and ACTIVE pools,
#archive-pool-{id}) — retires the pool from future runs. On a draft this is how you put the card away without activating it first. Past runs keep their lines (immutability, §1.3) so history is unaffected. The card stays on the board with an ARCHIVED badge. Press Activate on that card when you want it in the book again. Archiving is a structural change: the amber Forecast is behind this board banner returns until you press Run Forecast Now.
5.3 Adding members
On the trader Pools board, a member is an unassigned executed physical PPA (SIGNED or ACTIVE) that you assign to a pool. Prospect generator sites, offtaker sites and trader blocks are not addable from + member here — conclude the contract first, then assign it.
+ member is enabled only when the trader has at least one unassigned executed PPA (the same set that feeds the unassigned-contracts strip in §5.5). If none exist, the button is greyed out with "No unassigned contracts — conclude a PPA first".
Click + member on the target pool. The modal ranks
those unassigned contracts for that pool: side must
match, the counterpart must pass the pool's Strict
class compatibility, and only matches with a suitability score
above 50% are listed. Score chips use amber (fair,
>50–75), light green (good, >75–90) and green (strong, >90).
Select a row to open the configuration drawer (priority, pro-rata, caps,
spill / top-up); save creates a membership with
physical_ppa_id only.
If every unassigned contract scores 50% or below for this pool, the list is empty — use the strip's type suggestion, or open + member on a better-matching pool type. The strip's [Accept suggestion] / [Choose pool…] path remains the one-click / pick-pool onboarding for the same contracts.
| Path | What it is for | What gets saved |
|---|---|---|
| + member on a pool card | Ranked assign-to-this-pool for unassigned executed PPAs scoring >50% | Membership with
physical_ppa_id |
| Unassigned strip | Type suggestion and one-click / choose-pool onboarding (§5.5) | Same — membership with
physical_ppa_id |
Per-member fields, and why they exist:
- Label — optional override on the add-member form.
The Rules card prefers organisation · site or pool name
when those are known (see §5.2);
otherwise it falls back to this label or to
PPA {agreement ref}. - Priority — merit order within the pool, lower first. Between two solar PPAs, the cheaper/preferred one should carry the lower number.
- Pro-rata weight — when two members share the same priority, demand is split between them proportionally. If you leave it blank the weight defaults to the member's contracted volume, which is the settlement convention — so same-priority members share load the same way the settlement allocator would.
- MW cap — hard hourly ceiling for this member (also capped by the PPA's contracted capacity, whichever is lower).
- Nominated — marks a supply membership whose volumes come from submitted nominations rather than a forecast shape (typically a flexible / trader-fill contract). The engine then reads nomination rows for each hour, and ticking it enrols the member in the Nominations workbench (§10). The contract-assign + member drawer on trader Pools does not offer this toggle today — nominated flexible members in the demo are seeded; edit membership order / future config covers day-to-day changes.
- Spill value (c/kWh) — supply pools only: what a spilled kWh is still worth to you (a recovery or resale price). The trader book carries a Book rates default (Pools header); assigning a contract prefills from that book default when set, otherwise from the PPA's spill credit / price. Leaving the member field blank inherits the book default at run time (then zero if the book has none) — spilled energy is only a pure loss when both are unset. An explicit member value stays an override when book rates change. This same number is what charging a battery from spill "costs" (§11.2).
- Eskom top-up / Shortfall top-up (c/kWh) — demand pools only: what it costs to cover this member when your book falls short (grid / replacement energy). On the member form the field is labelled Shortfall top-up. Prefill prefers the book's shortfall top-up default (Book rates on Pools); otherwise the contract shortfall penalty / energy price. Blank inherits the book default at run time. Used to price firm shortfalls (§7.2), the nomination optimiser's cost of under-nominating (§10.2), and the battery's value when it backs a firm shortfall (§11.2).
Worked example — priority, then pro-rata. In one hour, the pool has 10 MW of demand to serve. The engine walks priority tiers in ascending order; it does not pro-rate across different priorities.
Member Priority Pro-rata weight MW cap Allocated MW Solar PPA A (lowest-cost) 10 — 3.00 3.00 — served first, up to its cap Solar PPA B 20 1 4.00 1.75 Solar PPA C 20 3 6.00 5.25 Solar PPA D 30 — 2.00 0.00 — no demand remains PPA A takes 3.00 MW first, leaving 7.00 MW for the priority-20 tier. PPA B and C then split that remainder in the ratio
1 : 3:7.00 × 1 ÷ (1 + 3) = 1.75 MWand7.00 × 3 ÷ (1 + 3) = 5.25 MW. Their caps do not bind, so the split stands. PPA D is considered only after the priority-20 tier; by then the 10 MW requirement is met. If B and C had blank weights, the engine would use their contracted volumes instead — for example, 2 MW and 6 MW would produce the same 1:3 split.
Members can be removed from the card's member list (trash control, with confirm). Removal destroys the membership and returns the executed PPA to the Unassigned contracts strip (§5.5) so you can place it on another pool. Historical allocation lines keep their kWh and prices; membership tags on those lines are cleared so the contract is free to reassign. Removing a member (or changing its priority / weight / caps) also raises the forecast-needed banner (§5.6).
5.4 Rules
Per pool, an ordered rule list that steers how the allocator serves it. Rules refine the default merit order — you only need them where the default (priority + price) doesn't express your contract or strategy.
Opening Rules. Click Rules on a pool card. The modal lists existing rules (reorder ▲/▼, enable/disable, delete) and a side-filtered picker: only rule types valid for that pool's side appear, and types already on the pool are omitted until you delete them. Each available type is a card with its name and a short description (the same intent as the table below). Pick a card, fill parameters when needed, then add.
Supply-side picker: PRIORITY,
PRO_RATA, MW_CAP, NOMINATION,
SHAPE_MATCH.
Demand-side picker: PRIORITY,
PRO_RATA, MW_CAP,
PRICE_OPTIMISE.
(PRICE_OPTIMISE is demand-only in the picker;
NOMINATION and SHAPE_MATCH are supply-only.) A
supply Shape match that names a Target
pool is drawn as a coloured joiner in the gutter — the click
path is §5.7.2; how to
read the colours is §5.7.
| Rule type | Parameters | What it does, and when to use it |
|---|---|---|
PRIORITY |
a priority number | Overrides the pool's default priority for allocation, without editing the pool. Use for temporary re-ranking — e.g. a month-long commitment that should jump the queue. |
PRO_RATA |
basis: contracted volume or weights | Controls how same-priority members share energy. Contracted (default) splits by PPA volume — the settlement-compatible choice. Weights uses the per-member pro-rata weights you set — for deliberate overrides. The split is a weighted "water-fill": a member who needs less than its share hands the surplus back to the others. |
MW_CAP |
the MW cap | Hard ceiling on the whole pool (or edge) per hour, on top of any per-member caps. Use to model a connection or offtake limit that individual contracts don't capture. |
PRICE_OPTIMISE |
minimum margin (c/kWh) | Skips any allocation whose margin (sell − buy − wheeling) would fall below the floor, letting that demand fall to the grid backstop instead. Firm demand always overrides the floor — a firm obligation is served even at negative margin, because failing to serve costs more. Use on demand pools where you'd rather not serve than serve at a loss. |
SHAPE_MATCH |
TOU periods (peak/standard/off-peak multi-select) + Target pool Dedic | ates a supply pool to a demand pool for specific TOU periods — the contractual "wind-backed night-shift energy" pattern (green claims, dedicated blocks). Target pool is labelled optional; leave it at Any and the rule stays on the card only. Name a demand pool and the gutter draws a joiner (§5.7.2). Note: in Phase 1 the ordinary merit order already does coarse shape matching by price; strict enforcement of this rule lands with a later milestone, so treat it as declared intent for now. |
NOMINATION |
none | Serve this pool's nominated members at
exactly their nominated volume: the engine allocates
min(nominated, available). Under-delivery vs nomination
shows up as shortfall; over-availability shows up as spill. |
5.4.1 Worked rule set — three hours, all six rule types
The following compact book shows how the rules combine. Network losses are ignored so the MWh remain easy to follow. Across the relevant pool Rules modals, the active rows are:
| Owner / precedence | Rule | Scope and parameters |
|---|---|---|
| Municipal / 10 | PRIORITY |
Municipal demand pool:
priority = 5 |
| Wind / 10 | SHAPE_MATCH |
Wind → Industrial:
tou_periods = [offpeak] |
| Municipal / 20 | MW_CAP |
Municipal demand pool:
mw = 8 |
| Flexible / 10 | NOMINATION |
Flexible supply pool; quantities come from submitted nominations |
| Municipal / 30 | PRO_RATA |
Municipal pool:
basis = weights |
| Commercial / 10 | PRICE_OPTIMISE |
Commercial demand pool:
min_margin_ckwh = 5 |
5.4.2 Example 1 — priority, pro-rata and a pool cap
At 12:00, Solar has 10 MWh. Municipal normally
follows Industrial (default priorities 30 and 10), but its
PRIORITY 5 rule moves it to the front for this run.
Municipal contains two members: Water Works needs 4 MWh at weight 1;
Clinic District needs 8 MWh at weight 3. The Municipal pool's
MW_CAP 8 rule limits the pool before the tier is
shared.
| Step | Calculation | Result |
|---|---|---|
PRIORITY |
Municipal effective priority 5 < Industrial 10 | Municipal is considered first |
MW_CAP |
min(12 demand, 8 pool cap) |
Municipal may receive at most 8 MWh |
PRO_RATA |
8 × 1 ÷ 4 = 2;
8 × 3 ÷ 4 = 6 |
Water 2 MWh; Clinic 6 MWh |
| Continue walk | 10 − 8 = 2 |
2 MWh remains for Industrial |
The run therefore records 8 MWh on the Municipal edge, split 2/6, plus 2 MWh to Industrial. Municipal has 4 MWh of unmet demand and Industrial has 6 MWh unmet. If Water Works needed only 1 MWh, weighted water-fill would give it 1 MWh and hand its unused share to Clinic District, subject to Clinic's own requirement.
5.4.3 Example 2 — shape dedication and margin protection
At 23:00, Wind has 10 MWh available at 75 c/kWh and
wheeling is 15 c/kWh. Industrial's night shift needs 6 MWh and pays 110
c/kWh; Commercial needs 5 MWh and pays 85 c/kWh. The off-peak
SHAPE_MATCH declares Wind → Industrial as the dedicated
pairing, so the first 6 MWh goes to the night shift. The remaining 4 MWh
reaches the Commercial edge, where PRICE_OPTIMISE tests the
margin:
Commercial margin = 85 − 75 − 15 = −5 c/kWh
−5 < required +5 c/kWh → skip the allocation
Commercial therefore takes 0 MWh from Wind and falls
to its grid backstop; the unused 4 MWh Wind remains
available for another eligible buyer or becomes spill. If Commercial
were firm, the margin floor would not block it: firm service overrides
PRICE_OPTIMISE.
Current-phase note. The
SHAPE_MATCHrow stores and exposes the off-peak dedication as auditable intent. Where strict shape enforcement is not enabled in the deployed engine milestone, ordinary merit order still decides the physical allocation; the other calculations in this example remain the rule's intended enforced outcome.
5.4.4 Example 3 — nomination is a ceiling, not a promise
At 19:00, the Flexible member has a submitted nomination of 7.5 MWh, actual available supply of 9.0 MWh, and matched demand of 8.5 MWh:
allocated = min(9.0 available, 7.5 nominated) = 7.5 MWh
The run allocates 7.5 MWh, records 1.5 MWh spill from availability above the nomination, and records 1.0 MWh shortfall against the 8.5 MWh demand. On a poor evening with only 6.0 MWh available, the same rule allocates 6.0 MWh: nomination limits upside but never manufactures energy.
Rules are applied in precedence order — use the ▲/▼ buttons to reorder, the Enable/Disable toggle to switch one off without deleting it (it greys to half opacity), and 🗑 to delete. New rules append at the bottom. Every run line records which rules produced it (the Rules column in run detail, §8.5), so you can verify a rule is actually biting. Adding, removing, reordering or toggling a rule marks the forecast stale until you re-run (§5.6).
5.5 Unassigned contracts (the onboarding strip)
An amber strip below the board lists every executed PPA of yours that is not in any pool. Each row shows a Supply or Demand side badge (buyer vs seller leg for your trader), plus a type suggestion ("wind IPP, as-generated → Wind pool"):
- [Accept suggestion] — one click creates the membership in the suggested pool. You get "Contract assigned to ." — or, if you haven't created a matching pool yet, "No pool yet — create one first."
- [Choose pool…] — opens the member modal with the contract fixed and ranks same-side pools by suitability %. Score chips: red / disabled at 50% or below; amber >50–75; light green >75–90; green >90. Select an eligible pool, configure priority / caps, then save.
The strip disappears when everything is assigned, and every newly executed contract reappears here until you place it. Removing a member from a pool (§5.3) puts that contract back on the strip. Treat it as a to-do list, not information: an unassigned contract is real money the engine cannot see, so your margin and coverage numbers are wrong until the strip is empty.
5.6 When the Pools board asks you to re-run the forecast
Overview and Dashboard read a sealed risk snapshot. That seal stores a fingerprint of the book's structure (pools, memberships, rules, book rates, pool status). When the live Pools board no longer matches the most recently sealed forecast, an amber banner appears at the top of Pools:
Forecast is behind this board — Members or rules changed since the last run. Overview and Dashboard still show the previous book — run a forecast to refresh them.
[Run Forecast Now] on the banner (and the same control in Performance) starts the Margin-at-Risk pass described in §4.10. While it runs:
- a full-screen spinner overlays the strategy area ("Running forecast…" / "Stay on this page until the run finishes.");
- strategy tabs and the Trader Pools back link are not navigable;
- the button shows a spinning icon and stays disabled.
When the seal succeeds, the flash "Forecast refreshed." appears, the overlay clears, and the amber banner disappears — Overview / Dashboard now match this board.
The banner returns when you:
- add, remove, or re-order / reconfigure a member;
- add, remove, reorder, or toggle a rule;
- change book rates or other fingerprint fields on pools / memberships;
- archive an ACTIVE pool (or otherwise change pool status in a way the fingerprint tracks).
It does not stay up merely because an older or future-dated snapshot row exists without a fingerprint — the board compares against the most recently sealed FORECAST.
5.7 The coloured joiners between Supply and Demand
The two-column board is a pair of warehouse aisles:
Supply shelves on the left (sources, in merit order),
Demand baskets on the right (buyers, in priority
order). Between them sits a narrow strip of coloured
joiners — the wiring
gutter (#book-wires inside
#book-cascade-board). Think of jumper cables between
shelves. The colour of the cable tells you which supply
shelf it left. The tag on the cable tells you the rule
that named that destination. A dashed red cable is not
a rule: it is leftover energy the latest forecast could not sell — spill.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Strategy → Allocation → Rules. URL:/org/trader-pools/01a0ab54-e46b-7dde-b45f-73d119213c75/strategy/pools. Widen the window past the phone breakpoint — the gutter is hidden on a stacked (mobile) board (hiddenuntilmd). You should see at least one solid coloured curve with a short label, and — once a forecast has spilled — a dashed redrest → spill · N %.
What a solid joiner is. The engine only draws a
solid curve when a supply pool has an active
allocation rule that names a living demand pool
(target_pool_id set, and that demand card is not
ARCHIVED). One curve per such rule. The arrow-head points
at the demand card. The curves are pictures, not buttons: they are
aria-hidden SVG. You do not draw them by dragging between
cards. You add a Shape match rule on the
supply card and name a Target pool —
the click path is §5.7.2.
Colour is the supply type, not the rule. This is the
usual misread. On T1 an amber curve labelled shape match looks
as if amber means shape-match, and a light-blue curve labelled
price ≥ 12.5 c looks as if blue means price. Those
colours belong to Solar (#f59e0b amber)
and Wind (#0ea5e9 light blue). Put the
same shape-match rule on Wind and the curve stays light blue; the word
still says shape match.
| Supply type | Colour on the joiner | Hex (as drawn) |
|---|---|---|
| Solar | amber / gold | #f59e0b |
| Wind | light blue | #0ea5e9 |
| Flexible | violet | #8b5cf6 |
| Firm | dark slate | #334155 |
| Hydro | teal | #0891b2 |
| Biomass | olive | #65a30d |
| Grid | grey | #94a3b8 |
| Custom | taupe | #a8a29e |
Demand cards themselves use a near-black slate
(#1e293b); they do not paint the joiners. Archived supply
shelves are omitted from the gutter, so their rules do not draw.
The word on the curve is the rule. The label is a
short gloss of rule_type (and its parameters):
| Label you see | Rule on the supply card |
|---|---|
shape match |
SHAPE_MATCH — pin this shelf
to that basket for chosen TOU
(time of use) periods or clock hours |
price ≥ N c |
PRICE_OPTIMISE with floor
N c/kWh — skip a non-firm sale whose margin would fall
below N |
price optimise |
PRICE_OPTIMISE with no floor
stored |
cap N MW |
MW_CAP — never send more than
N MW along this edge |
nomination |
NOMINATION — serve nominated
members at min(nominated, available) |
priority |
PRIORITY — temporary
re-rank |
pro rata |
PRO_RATA — split an
equal-priority tier |
Rules without a destination demand pool stay on the
card’s Rules modal only. They do not appear in the gutter. Pool-wide
PRIORITY / PRO_RATA / MW_CAP /
NOMINATION on a demand card likewise stay on that card.
The dashed red joiner is leftover supply. When a
forecast allocation run exists
and some of that run’s supply was unsold, the gutter adds a dashed rose
(#e11d48) curve along the bottom, labelled
rest → spill · N %. N is the unsold share of total supply
in that run, whole percent. No forecast, or a forecast with zero spill,
means no dashed curve. The dashed line does not point at a demand card:
spill has no buyer yet. When that leftover is more than 20 % of supply,
Find offtake → Desk (#book-offtake-cta)
sits under the board — not a trio of coaching cards.
Empty and hidden states.
- No solid joiners. No supply rule names a non-archived demand pool. Create one with the steps in §5.7.2, or un-archive the destination.
- No dashed red. Nothing has run, or the latest forecast sold everything.
- No gutter at all on a phone.
#book-wiresishiddenbelow themdbreakpoint so the columns can stack. Rotate or widen to see the joiners. - Headline above the board still talks. Even with no curves, the Rules headline still describes the cascade (how many supply shelves, how many demand baskets, whether supply outweighs demand). The joiners are the picture of named edges; the headline is the picture of volume.
5.7.2 How to create a solid joiner
A solid joiner is not a separate object. It is the picture of one fact: this supply shelf has a Shape match rule that names that demand basket. You create the fact on the supply card. The gutter then draws the cable.
You cannot paint a joiner from the Demand column.
Demand Rules never offers SHAPE_MATCH, and
the demand picker has no Target pool field. The dashed
red spill curve is also not something you add: it appears only after a
forecast leaves unsold supply (§5.6).
Before you start. You need at least one
Supply pool and one Demand pool,
neither ARCHIVED. You are on Book · Rules
(…/strategy/pools). Widen the window so the gutter is
visible (it is hidden on a phone).
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Strategy → Allocation → Rules. Pick a supply card whose Add a rule grid still shows SHAPE_MATCH — on T1 that is usually not Solar, because Solar already carries a shape-match. Flexible or Firm is the typical free shelf. You will point it at Industrial (or any named demand card).
- On the Supply card that should own the cable, click
Rules. The branded modal
#rule-list-modalopens (Ruleseyebrow, the pool name as the title, X at#rule-list-modal-close). Existing rules sit in an ordered list (#pool-rules-list). - Under Add a rule (
#available-rules), click the SHAPE_MATCH card (#available-rule-SHAPE_MATCH). The card explains that this type pins the shelf to a buyer for chosen hours. The form heading becomes Configure Shape match. (If the grid is missing and you see All applicable rules are already on this pool at#no-available-rules, this shelf already has every supply type, including Shape match. Delete thatSHAPE_MATCHrow first, or pick a different supply card.) - TOU periods is a multi-select: Peak, Standard, Off-peak. These are TOU (time of use) windows on the South African tariff clock — pick the hours this dedication should apply. You can select more than one.
- Target pool (edge, optional) is the field that creates the joiner. The prompt is Any. Any means the rule applies to the whole shelf and no curve is drawn. Open the list and choose a demand pool by name (Industrial, Commercial, Municipal, Trader Sales, …). That name is the basket the cable will point at.
- Click Add rule. A new row appears in the list: type
SHAPE_MATCH, a short parameter summary (the TOU periods you picked), and the usual ▲ / ▼ / Disable / trash controls. There is no extra flash — the list updating is the save. - Close the modal (X, Escape, or click outside). On a desktop-width
board a solid curve now runs from that supply card to
the demand card you named. Its colour is the supply
type (Flexible is violet, Firm is dark slate, Wind is light blue, Solar
is amber). The word on the curve is
shape match.
If nothing appears. Check four things, in order: you
named a Target pool rather than leaving Any; that
demand card is not ARCHIVED; you are looking at a wide
window (#book-wires is hidden on a stacked phone layout);
you added SHAPE_MATCH on a supply card,
not a demand card.
What the other supply types do.
PRIORITY, PRO_RATA, MW_CAP and
NOMINATION on the same picker have no Target pool field.
Saving them does not draw a joiner.
PRICE_OPTIMISE is demand-only in the picker, so you cannot
start a price ≥ N c cable yourself; the T1 Wind price joiner is
demo seed (§5.7.1).
After you save. Adding a rule is a structural
change. The amber Forecast is behind this board banner
returns until you press Run Forecast Now (§5.6).
The dashed red rest → spill · N % only refreshes after that
run.
How to take a joiner away. Open
Rules on the same supply card. Trash the
SHAPE_MATCH row. Closing the modal removes the curve.
Disable greys the row in the list but does
not hide the gutter curve today — delete the rule (or
archive the destination pool) when you want the cable gone.
T1 on the demo — reading the amber, the blue, and the dashed red
Data. full_demo · seed 42 · T1 Renewables Pool (
01a0ab54-e46b-7dde-b45f-73d119213c75) · Book · Rules.
On that seeded book the demo places a SHAPE_MATCH on
Solar aimed at a demand basket, and a
PRICE_OPTIMISE (floor 12.5 c/kWh) on
Wind aimed at a demand basket. After a forecast that
cannot sell everything, the gutter therefore typically shows:
| What you see | How to read it |
|---|---|
Solid amber curve,
shape match |
Solar (amber) is dedicated to that demand basket for the rule’s TOU / hours |
| Solid light blue curve, `price ≥ | 12.5 c` Wind (light blue) will not sell into that basket below a 12.5 c/kWh margin |
Dashed red
rest → spill · N % |
The latest forecast left N % of supply unsold — not a rule, a leftover |
The Rules picker on a supply card does not offer
PRICE_OPTIMISE (that type is demand-only when you add a
rule yourself). The T1 seed can still store a price-floor rule on Wind
with a named buyer, and the gutter will draw it. Treat that as demo
wiring you can delete; your own books only get a price joiner from a
supply shelf if a rule with a target actually sits there.
Extra shelves (for example a Custom Approved Override pool) can sit in the cascade without adding a curve, as long as they have no destination rule.
What “done” looks like. You can point at each solid curve and name the supply card, the rule, and the demand card. You do not treat amber as a synonym for shape match. You know the dashed red is unsold forecast energy, and you know a phone-width window will hide the whole gutter.
5.8 Explanations — How to Read Rules
Explanations (#book-explanations-open)
sits on the Rules toolbar next to Run Forecast Now. It
opens a right-hand drawer (#book-explanations-drawer) — the
same chrome as Overview Explanations (§4.11): green header, X
top-right, backdrop, Escape.
Eyebrow: Book · Rules. Title:
Explanations. Above the terms sits How to Read
the View (#book-how-to-read) — collapsed until you
press #book-how-to-read-toggle. It is the short in-product
reading order for this mode: thread strip, issues rail,
headline, Supply · Demand, outcome badges, wiring gutter, book rates,
unassigned contracts.
The A–Z list is only the words on the Rules board (ACTIVE through Wiring gutter). It does not include Forecast tiles such as Margin@Risk, or Outcomes warehouse words. Open Forecast or Outcomes and the same control teaches that mode instead.
Close with the X (#book-explanations-drawer-close), the
backdrop, or Escape.
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-07-18 against the full_demo manifest.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Strategy → Pools. You should see supply and demand structure before assigning or changing a member.
6. Book · Forecast — what the engine will do
You need an answer you can reproduce, not an editable dashboard number. A run is one immutable execution of the allocation engine for a scenario, grade and calendar month. Runs preserve the plan you had when you made a decision, while the index makes the current result easy to distinguish from its history.
Route:
/org/trader-pools/:id/strategy/book?mode=forecast ·
Tab: Book · Mode: Forecast (the old
/allocations route forwards here). Forecast is
not a #strategy-nav tab —
Allocation stays lit. Open it from the thread strip
(#book-stage-forecast), a run link, or this URL.
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-07-18 against the full_demo manifest.
6.1 The run picker, and what the mode shows
The Forecast mode reads one run at a time. The
run picker under the headline is a month input and one
chip per run of that month — Forecast P50,
Adverse P90, Nominated,
Actual — each with its status pill, a Simulations
×n count with any failures, Run backcast when the
month is past and has a Forecast but no Actual, and New
run. Pick a chip and everything below re-reads for that run;
the URL carries &run=<id> so a link reproduces
the view. Under the picker, Open the run ledger › drills to the
run detail page (§8).
The mode then reads top to bottom. The table is a map. Each block is taught in full from §6.9.
| Block | What it says |
|---|---|
| Headline | One sentence from the run’s KPIs, in the Overview’s voice: “September P50: every demand hour is covered, but 96.4 % of supply finds no buyer and the month loses R 13.1 m.” |
| Five tiles | Margin (with the grade, contracted ratio, Margin@Risk), Coverage (with shortfall), Spill (with its rand cost at the spill value), Effective price (with realised R/MWh and supply HHI), and the Battery (or take-or-pay utilisation when the book has none) |
| Where the supply goes | Each supply pool’s energy split into what the cascade sold to each demand pool and what it spilled — the demand pools in the same order and colours as the Rules board |
| Where the margin is made and lost | By time of use and by source pool, with the spill line; a sentence says whether the loss is a price problem or a wiring-and-demand problem |
| Long or short, hour by hour | The Overview’s clock per pool: supply stacked against the demand line on a typical day of the run |
| Pool caps, this run | The Rules board’s outcome badges as a table: result, cap or band, and ok · outside · breach |
| Battery dispatch (fold) | Only for books with an active battery: arbitrage margin, cycles a day, spill absorbed, firm hours backed, market arbitrage, and Open full dispatch › to the battery page (§11) |
| The run’s line ledger (fold) | The link to every line of the run, one SAST day at a time (§8) |
| Find offtake | A single line (#book-forecast-offtake-cta) under the
ledger, only when this run spills more than 20 % of supply. Find
offtake → Desk opens Simulations. Nominations and Outcomes stay
on the thread strip — they are not extra cards. |
| Cover shortfall | Same pattern (#book-forecast-cover-cta) when unmet
demand is above 5 %. Cover shortfall → Desk. |
There is no three-card “next moves” strip under Forecast. The thread strip already opens Nominations and Outcomes. Spill and shortfall that are this large get one Desk door each, the same way Rules offers Find offtake → Desk when leftover supply is above 20 % (§5).
The table below is what each run carries, and how to read it; on the picker the scenario is the chip, the period is the month input, the grade and status are the chip’s label and pill, and the four KPIs are the tiles.
| Column | What it records | How to use it |
|---|---|---|
| Scenario | Input family used by the engine (FORECAST,
NOMINATED, SIMULATION,
ACTUAL) |
Compare like with like. A simulation is a what-if, not the operating plan; a nominated run is the position you declared, not the forecast you hoped for. |
| Period | Whole calendar month the engine solved hour by hour | Confirm the month before comparing KPIs — August margin cannot justify a September nomination. |
| Grade | Forecast exceedance assumption on supply: P50 (expected / median) or P90 (adverse — output you are 90% confident of meeting or exceeding). Defaults to P50. | Treat P50 as the base plan and P90 as the stress view. Run both for the same scenario and period when you need Margin@Risk: the gap between their margins is the exposure if renewables under-deliver. Do not mix a P50 margin with P90 line items. A newer COMPLETE run supersedes only the same scenario and grade for that period, so the P50 and P90 currents can coexist. |
| Status | Execution state (PENDING → RUNNING →
COMPLETE, or FAILED) |
Read KPIs only from COMPLETE. RUNNING /
PENDING are in flight; FAILED changed nothing
— keep using the previous completed current. |
| Coverage | Share of demand met by allocated supply over the month
(allocated ÷ demand) |
Use as the first triage signal. Low coverage means hours where the stack could not serve load — open the run and inspect Shortfall hours before changing pools or nominations. Rising coverage toward target is progress; a high average can still hide evening gaps if solar-heavy. |
| Margin | Net rand outcome of every allocation, spill and shortfall line for the month | The commercial headline. Compare only within the same scenario and grade. A healthy P50 margin that collapses under P90 is a shape or firmness problem, not a price typo — drill into margin-by-TOU and spill/shortfall tabs before re-contracting. |
| Spill | Share of supply left unsold (spill ÷ supply) |
High spill means you paid for energy nobody took (painful under take-or-pay). Check whether the shape misses demand, a cap is binding, or you are simply long — then prefer reshaping or BESS absorption over celebrating low shortfall alone. |
| Shortfall | Share of demand left unmet by the stack
(shortfall ÷ demand) |
Firm shortfall is usually your most expensive energy (grid top-up). Prefer fixing shortfall hours over chasing a slightly higher margin that leaves evening gaps. On the detail page, the Shortfall tab names the members and hours. |
| Superseded | Newer equivalent COMPLETE result exists for the same scenario, grade and period | Keep for audit history at reduced opacity; do not treat it as the current plan. |
The current forecast is the newest non-superseded
COMPLETE run for that scenario, grade and period. A
nominated run has its own current row; it does not replace your forecast
simply because it was created later.
6.2 Row actions — Open and Run backcast
Two actions sit beside the run picker. They are not decoration: the picker is a triage list; these actions are how you prove a number or close the loop against meters.
Open →
Why it is there. KPI columns answer “how did the month look?” They cannot answer “which hour, which member, which rule?” The engine’s proof lives on the run detail page (§8). Open the run ledger › — under the picker and in the ledger fold — is the drill-through from the picker into that audit floor.
What it does. Navigates to
/org/trader-pools/:id/strategy/allocations/<run id>
for that immutable run — not “the latest for the
month”, and not a live recalculation. You see:
- scenario, grade, status, period and the inputs hash (reproducibility fingerprint);
- a day-by-day stacked chart of supply vs demand;
- tabs for allocation / spill / shortfall / margin (and BESS when the run dispatched a battery);
- every line the engine wrote, with prices and applied rules.
Use Open → whenever a Coverage, Margin, Spill or Shortfall figure surprises you, when you need evidence for a dispute or nomination decision, or when you want to compare a superseded row with its successor side by side (open each in turn). Superseded and failed rows remain openable so history stays auditable.
Run backcast
Why it is there. Forecast and nominated runs plan with shapes and declarations. After the month settles, you need a parallel Actual run built from measured meter energy so you can score forecast accuracy, nomination mismatch and dashboard panels that wait on settled actuals. Actual is intentionally not a choice in the New run modal — meters must exist first. Run backcast appears in the picker for a past month that has a Forecast but no Actual yet.
What it does. On a row that qualifies, Run backcast:
- Takes that row’s calendar month.
- Re-runs the allocation engine with scenario
ACTUAL(settled meter inputs instead of forecast shapes). - On success, adds a
COMPLETEActual row for the same period and refreshes forecast / nomination accuracy signals that depend on settled actuals. - If no member has settled meter rows for the month, nothing is written — you get a clear flash that settled data is not available yet.
When the control appears. Only on a
Forecast row that is COMPLETE, and only
while that period does not already have a
non-superseded COMPLETE Actual. Nominated, Simulation and
Actual rows do not show it; a forecast that already has its Actual for
the month does not show it either (re-backcast is a deliberate later
action once a newer Actual supersedes, or via ops schedules).
How to read the result. Filter to Actual
(settled) or leave All and find the new
ACTUAL row. Open → that Actual: the green
Forecast vs settled actual panel (§8.2) shows Margin / Coverage
/ Spill / Shortfall Δ tiles, the month shape overlay (Forecast line vs
Actual line), the same delivery period notice, and any
Proxied members. That panel is the commercial
forecast-error story; the day chart and tabs underneath then explain the
hours.
Worked example — June 2026 backcast on T1 Renewables Pool
Data. full_demo · seed 42 · stage S07 (strategy historical runs) · T1 Renewables Pool · period June 2026 · grades P50. The Forecast and Actual KPI maps below are the sealed gallery pair for that month; shortfall hour lines are the seeded first-weekday slice on each run.
1. Starting point on the Runs index. You already have a completed Forecast for June. Meters for the month have settled, so Run backcast is visible on that row. After it completes, the index shows two current (non-superseded) companions for the same period:
| Lane | Scenario | Grade | Status | What the engine consumed |
|---|---|---|---|---|
| Plan | FORECAST | P50 | COMPLETE | Forecast shapes / profiles |
| Settled | ACTUAL | P50 | COMPLETE | Measured meter energy |
2. Month roll-up — the numbers on each row. Coverage and residual shares are derived from the run KPI map with the same ratios the Runs header tooltips describe. Read them as snapshot dumps — the same card format as §4.10 · Snapshot the Overview actually shows.
How the Runs KPIs are derived
Coverage = allocated_mwh ÷ total_demand_mwh
Spill % = spill_mwh ÷ total_supply_mwh
Shortfall % = shortfall_mwh ÷ total_demand_mwh
Forecast snapshot (June 2026 · P50)
MARGIN_R = 331 500
MARGIN_R_PER_MWH = 263
COVERAGE_PCT = 81.3 ← 1 113 ÷ 1 369
SPILL_PCT = 3.6 ← 44 ÷ 1 217
SHORTFALL_PCT = 4.4 ← 60 ÷ 1 369
TOTAL_SUPPLY_MWH = 1 217
TOTAL_DEMAND_MWH = 1 369
ALLOCATED_MWH = 1 113
SPILL_MWH = 44
SHORTFALL_MWH = 60
Actual snapshot (June 2026 · settled)
MARGIN_R = 353 000
MARGIN_R_PER_MWH = 266
COVERAGE_PCT = 81.1 ← 1 126 ÷ 1 388
SPILL_PCT = 3.9 ← 48 ÷ 1 234
SHORTFALL_PCT = 4.7 ← 65 ÷ 1 388
TOTAL_SUPPLY_MWH = 1 234
TOTAL_DEMAND_MWH = 1 388
ALLOCATED_MWH = 1 126
SPILL_MWH = 48
SHORTFALL_MWH = 65
Δ snapshot (Actual − Forecast)
MARGIN_R = + 21 500 ← commercial headline improved
MARGIN_R_PER_MWH = + 3
COVERAGE_PCT = − 0.2 % ← demand (+19) slightly outran allocation (+13)
SPILL_PCT = + 0.3 %
SHORTFALL_PCT = + 0.3 %
TOTAL_SUPPLY_MWH = + 17 ← resource beat the P50 shape
TOTAL_DEMAND_MWH = + 19 ← load ran above the profile
ALLOCATED_MWH = + 13
SPILL_MWH = + 4
SHORTFALL_MWH = + 5
Conservation check (must hold before you trust the delta)
Forecast demand side : allocated + shortfall = 1 113 + 60 = 1 173
Forecast supply side : allocated + spill = 1 113 + 44 = 1 157
Actual demand side : allocated + shortfall = 1 126 + 65 = 1 191
Actual supply side : allocated + spill = 1 126 + 48 = 1 174
The residual gap to total demand / total supply is network loss and pool-level routing — open the run to see it on the lines.
Pattern to expect on your own page: one Forecast row and one Actual row for the same period; Δ is Actual minus Forecast. A healthier margin with slightly worse spill/shortfall means prices and mix helped more than volume residuals hurt — confirm on the detail tabs before changing contracts.
Supply disposition (MWh)
Read it: both months are mostly allocated energy; the thin top band is spill. Actual is only slightly taller — the +17 MWh supply shows up as +13 allocated and +4 spill.
Margin (R)
Read it: the commercial bar rises even though coverage slipped 0.2 %. Open both runs before assuming the book is “fine” — residual hours may still need firming.
3. Prove the residual on one hour (Open → → Shortfall tab). The seeded first weekday (1 Jun 2026) carries a shortfall line every hour. Three anchors show how Actual diverges from Forecast on the same clock:
| Hour (SAST) | Forecast shortfall | Actual shortfall | Δ kWh | Plain reading |
|---|---|---|---|---|
| 00:00 | 1,197 kWh | 1,244 kWh | +47 | Overnight unmet demand ran ~4% hotter |
| 12:00 | 1,569 kWh | 1,674 kWh | +105 | Midday gap widened — load and/or solar miss vs plan |
| 18:00 | 1,755 kWh | 1,899 kWh | +144 | Evening peak is where shortfall hurts most |
Shortfall hour deltas (seeded first weekday)
00:00 gap growth = 1 244 − 1 197 = + 47 kWh
12:00 gap growth = 1 674 − 1 569 = + 105 kWh
18:00 gap growth = 1 899 − 1 755 = + 144 kWh
Month SHORTFALL_MWH Δ = 65 − 60 = + 5 MWh (= 5 000 kWh)
The evening hours dominate the month’s +5 MWh shortfall delta — that is why a nearly flat coverage % can still hide a procurement problem. On the Actual detail page, filter the Shortfall tab to 18:00 and note which demand membership owns the line; that membership is the candidate for firmer supply or a nomination change next month.
4. What you do next.
- Keep the Forecast row as the plan you made; keep the Actual row as what meters proved.
- If margin Δ is positive but shortfall Δ is also positive (as here), fix evening firmness before celebrating the rand outcome.
- If you needed the opposite story (Actual weaker on margin), open Margin by TOU on both runs and find which period inverted.
- Nomination Performance and forecast-error panels that were “awaiting settled actuals” can now light up for June — the backcast is their input.
Note. A scheduled monthly backcast also runs after settlement reconciliation (see the operations catalogue). Run backcast on the index is the on-demand control when you need the Actual lane before the calendar job, or for a month you have just finished settling.
6.3 Choose the scenario deliberately
New run opens the modal. The scenario chooses inputs, not a cosmetic label.
| Scenario | Inputs | Use it when |
|---|---|---|
FORECAST |
Supply forecast shapes and demand profiles | You need the operating plan |
NOMINATED |
Submitted nomination rows | You need the position you declared |
SIMULATION |
Hypothetical inputs | You are testing an isolated case |
ACTUAL |
Settled meter data, when available | You are reviewing realised performance — created via Run backcast (§6.2), not from New run |
Use the Simulation Workbench for commercial candidates instead of manually creating a simulation run. It creates the required baseline and variant pair, keeps the candidate out of your live pool, and presents the deltas together.
6.4 Set period and grade
Inside New run, the Month picker covers a complete calendar month, hour by hour. Choose the month you intend to decide about; a high margin in August cannot justify a September nomination. Forecast grade chooses the supply confidence view (P50 expected or P90 adverse).
| Technology / source | P50 → P90 ratio | What the adverse case assumes |
|---|---|---|
| Solar | 0.94 | 6% below the P50 shape |
| Hybrid | 0.92 | 8% below P50 |
| Hydro | 0.90 | 10% below P50 |
| Wind | 0.86 | 14% below P50 |
| BESS | 1.00 | Dispatch is not reduced by a generation ratio |
For a solar P50 interval of 10.00 MWh, the derived P90 is
10.00 × 0.94 = 9.40 MWh. For a wind interval of 10.00 MWh
it is 10.00 × 0.86 = 8.60 MWh. That larger wind gap is why
two books with the same P50 margin can carry materially different
Margin@Risk.
Careful. P90 is an adverse planning view, not a guarantee that every interval will produce exactly 90% of P50. Use the pair to understand sensitivity, then inspect the allocation hours that cause the difference.
6.5 Worked New run — forecast August
Suppose you have adjusted a member in T1 Renewables Pool and need evidence now rather than at the next nightly cycle.
| Input | Selection |
|---|---|
| Pool | T1 Renewables Pool |
| Scenario | FORECAST |
| Month | August 2026 |
| Grade | P50 (expected) |
| Purpose | Confirm the revised expected operating plan |
- Open Book · Forecast and select New run in the run picker.
- Choose
FORECAST, choose August 2026 and retainP50 (expected). - Start the run. Its chip appears as
pending, thenrunning. - When it becomes
COMPLETE, select Open → and confirm the pool, period and grade on the detail page. - Repeat with
P90 (adverse)only if you need the risk pair; compare the two run-level margins rather than mixing their line items. - When meters for that month have settled, return to the Forecast row and select Run backcast to create the Actual companion; open the Actual for the Forecast-vs-settled panel (§8.2).
If the book has an active battery, its dispatch is included automatically using the two-pass method in §7.3. The completed detail page consequently includes the BESS evidence tab.
6.6 Understand superseding before you rerun
A successful newer run replaces the current row only within the same scenario, grade and period. The older row remains readable at reduced opacity so you can show what changed and when. Open → still works on superseded rows.
A failed run changes nothing: the previous completed current run remains current.
This is an audit feature. It prevents a manual rerun from rewriting yesterday’s decision evidence, while still ensuring one unambiguous current result.
6.7 Follow along — inspect, run, verify
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Runs. You should see newest-first rows with scenario, grade, status, KPI columns and, on the right, Open → (every row) and Run backcast on completed Forecast rows that do not yet have an Actual.
Filter to Forecast. Select Open → on the newest
completed non-superseded row and skim the day chart and Shortfall tab,
then return to the index. Create a P50 run for a month you are testing
via New run. Wait for COMPLETE before
comparing it with the prior row. If a completed Forecast shows
Run backcast, use it only when you know meters for that
month have settled — otherwise expect the “no settled meter data” flash.
If a new run fails, read the error and keep using the previous completed
result; no cleanup is required.
Runs answer “what did the engine decide?” The next chapter explains how the engine reaches those allocation decisions; §8 shows how to prove a particular result after you select Open →.
6.8 Explanations — How to Read Forecast
Explanations (#book-explanations-open)
sits to the right of the Forecast headline. Same drawer shell as §5.8. Eyebrow: Book ·
Forecast.
How to Read the View is a different fold from Rules: this mode is one sealed run, not the wiring diagram. The reading order is thread strip, headline, run picker, five tiles, where the supply goes, where the margin is made and lost, long or short hour by hour, pool caps, battery fold, then Find offtake (only when this run spills more than 20 % of supply) or Cover shortfall (only when unmet demand is above 5 %).
The A–Z list is the words on Forecast (Actual through Where the supply goes). Wiring gutter is not here — that word lives on Rules. Warehouse rule is not here — that word lives on Outcomes.
The in-product drawer is a one-screen reminder. The rest of this chapter walks the same blocks with the T1 September numbers.
6.9 How to read Forecast, block by block
A dashboard number you can edit is a wish. Forecast is a sealed run — one pass of the engine for one scenario, one grade and one calendar month. You cannot type a new margin onto the tiles. You pick another run, or you start a new one.
This mode does not change the wiring. That is Book · Rules. It does not settle meters. That is Book · Outcomes. It answers: if this book ran for this month at this grade, where would the energy go and what would the money do?
Think of a bakery that already bought the day’s flour. Forecast is the bake sheet for one oven setting: how much bread sold, how much dough was leftover, and whether the till ended up or down. The recipe is Rules. The till tape after the shop closed is Outcomes.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Allocation → Forecast on the thread strip (#book-stage-forecast). Deep link:/org/trader-pools/01a0ab54-e46b-7dde-b45f-73d119213c75/strategy/book?mode=forecast&month=2026-09&run=01a0b951-b50d-76c2-bfd8-840b7e. You should see the eyebrow Book · Forecast, a headline that names September P50, five tiles, then the two-by-two of charts and tables.
Data. full_demo · seed 42 · T1 Renewables Pool · run
01a0b951-b50d-76c2-bfd8-840b7ecc12cd· scenarioFORECAST· gradeP50· period 1 Sep 2026 → 1 Oct 2026 · statusCOMPLETE· not superseded. Numbers below are that run’s KPI map and allocation lines, last read 2026-09-19. Compact Rand follows the product (R 13.1 m,R 786 k). Energy labels follow the product too (35.7 GWh,979 MWh).
On screen, top to bottom
| Order | Block | DOM id |
|---|---|---|
| Shell | Heading Book — Forecast. Subtitle: How the book is wired, what the engine will do with it, and what actually settled — one thread across three views. Busy overlay: Running the book…. First paint: Loading the book…. | #org-page-heading,
#trader-book[data-mode=forecast] |
| 1 | Thread strip, then the issues rail | #book-thread, #book-stage-forecast,
#book-issues |
| 2 | Eyebrow Book · Forecast, headline, lede, Explanations | #book-forecast-headline,
#book-explanations-open |
| 3 | Run picker, then the meta line with Open the run ledger › | #book-run-picker,
[data-role=run-meta] |
| 4 | Five tiles | #book-forecast-tiles |
| 5–8 | Where the supply goes · Where the margin is made and lost · Long or short, hour by hour · Pool caps, this run | #book-flow, #book-margin,
#book-day, #book-caps |
| 9 | Battery dispatch (fold) — only when the run stored battery KPIs | #book-battery |
| 10 | The run’s line ledger (fold) | #book-ledger-fold |
| 11 | Find offtake → Desk and/or Cover shortfall → Desk | #book-forecast-offtake-cta,
#book-forecast-cover-cta |
There is no #book-moves strip on
Forecast. Nominations and Outcomes stay on the thread strip. The three
ranked cards live on Outcomes only (§6A.14).
What “looks good” vs “looks bad” on this whole page. Good: coverage high, spill inside its cap, margin positive, caps read ok, no Find-offtake line. Bad — and this is T1 September — every demand hour is covered and almost all supply spills and the month loses tens of millions. Covered customers are not the same as a healthy book.
6.10 Thread strip, issues rail and headline
The problem. You can open Forecast from three doors (the strip, a run link, this URL) and lose the rest of the Book. The strip is how you stay on the same tab.
Thread strip (#book-thread). Three
stages, left to right:
| Stage | Eyebrow | Id | What the body shows |
|---|---|---|---|
| Rules | Rules · how the book is wired | #book-stage-rules |
Live pool and member counts. Pill: cap verdict (4 caps breached on the demo). |
| Forecast | Forecast · what the engine will do | #book-stage-forecast |
Month, grade and compact margin. Pill prefers spill when spill > 20 %, else shortfall when shortfall > 5 %, else coverage. No run yet: No forecast run yet and pill run one. |
| Outcomes | Outcomes · what actually settled | #book-stage-outcomes |
Last settled month and net. Pill balanced / not balanced. Nothing settled: Nothing settled yet. |
Forecast is ringed (data-on=true) on this mode. A
negative margin prints rose; a positive one prints brand green. Clicking
a stage navigates; it does not rerun the engine.
On this T1 September run the Forecast stage reads September P50 and −R 13.1 m, with pill spill 96.4 %. The note under it is 100 % covered · 96.4 % of supply unsold.
Where the strip is taught. The three-stage Book thread — §5. This section only names what Forecast lights and what the pill prefers.
Issues rail (#book-issues). Ranked
cards under the strip, each with a colour dot (rose = bad, amber = warn,
slate = info), a title, a body, and a door (Rules › /
Forecast › / Outcomes ›). On T1
September the first card is Spill at 96.4 % of supply.
The body lists the supply pools that broke their cap (Solar, Wind,
Flexible, Firm) and ends Whatever the rules cannot sell, the
forecast spills at the spill
value. Next, Coverage outside its band on 2 demand
pools — Commercial and Municipal sit at 100 % against narrower
bands; the body adds Over-covered is over-bought. There is no
shortfall card: unmet demand is 0 %.
Headline (#book-forecast-headline). One
sentence from the run’s KPIs. The recipe, in order:
- Empty KPI map: {Month} {Grade}: the run has no figures yet ({status}).
- Spill > 50 % and margin negative (T1 September): {Month} {Grade}: every demand hour is covered, but {spill} % of supply finds no buyer and the month loses {abs margin}.
- Shortfall > 20 %: unmet-demand sentence.
- Margin negative (without that huge spill): loses / coverage / spill.
- Spill > 20 % with a profit: earns but spills.
- Otherwise: earns at coverage and spill.
T1 September hits rule 2:
September P50: every demand hour is covered, but 96.4 % of supply finds no buyer and the month loses R 13.1 m.
Lede (the grey line under the headline). Always: The engine’s month, one run at a time. Pick the run at the top; everything below re-reads. The same pool colours as the Rules board, so the bar that spills here is the card that breaches there.
Explanations sits to the right of that pair (§6.8).
6.11 The run picker and the doors around it
The problem. A month can hold a Forecast, an Adverse
P90, a Nominated plan, several simulations and — once meters settle — an
Actual. Mixing them on one canvas would lie. The run picker
(#book-run-picker) makes you choose.
Month input. type=month,
aria-label="Run month". Changing it patches
?month=YYYY-MM and reloads the chips. September cannot
explain August.
Chips. At most four, in this order, and only when that slot has a run:
| Chip label | Who it is | Id |
|---|---|---|
| Forecast P50 (or Forecast P90 if that is the current forecast slot) | Newest complete non-P90 FORECAST in the month |
#run-row-{id} |
| Adverse P90 | Complete FORECAST or SIMULATION with grade
P90 |
#run-row-{id} |
| Nominated | A NOMINATED run |
#run-row-{id} |
| Actual | A complete ACTUAL |
#run-row-{id} |
Each chip carries data-role="run-chip",
data-scenario and data-status, plus a status
pill: complete (green), pending /
running (amber), failed (rose). The
selected chip is ringed. Clicking it patches &run={id}
so a shared URL reproduces the view.
September 2026 on T1 also shows a dashed Simulations ×n count (nine simulation rows in this dataset, including hypothetical candidates) and an amber n failed pill when any run failed. The count is not a chip — it does not re-read the tiles.
This URL pins a run. The walkthrough uses
…&month=2026-09&run=01a0b951-b50d-76c2-bfd8-840b7e.
That is the full-month P50 (01 Sep 2026 → 01 Oct 2026). The
picker’s Forecast P50 slot can point at a
different complete September forecast if a later one exists.
Confirm the meta line under the picker before you quote a tile.
Meta line (data-role="run-meta"):
Run 01 Sep 2026 → 01 Oct 2026 · FORECAST · COMPLETE Open the run ledger ›
The link is
/org/trader-pools/{id}/strategy/allocations/{run id} — the
same door as §6.2
Open and §8.
New run (#book-new-run). Opens the
branded modal #book-new-run-modal (header
#book-new-run-header, title
#book-new-run-modal-title, close
#book-new-run-close or Escape or the backdrop
#book-new-run-modal-backdrop). Fields: Scenario
(FORECAST / NOMINATED /
SIMULATION), Month, Forecast grade
(P50 (expected) / P90 (adverse)). Helper:
Actual (settled) runs are not started here; they are rebuilt from
measured energy once meters settle. Run starts the
worker; the button reads Running… while it is in
flight. Scenario, period and grade are taught in §6.3–§6.5.
Run backcast (#book-run-backcast)
appears only when the picker month is before today’s month, a
Forecast exists, and no Actual exists yet. September 2026 on a 19 Sep
2026 clock is the current month — the button is hidden. How
backcast works: §6.2.
6.12 The five tiles
The problem. A month of hourly lines is too long to
scan. The five tiles (#book-forecast-tiles, each
data-role="forecast-tile" with data-key) are
the roll-up. Rose numbers are the leak. Green numbers are the ones that
held.
They sit in one row from md up (two columns on a phone).
Each tile is a label, a big value, and a note. They do not click
through.
On this T1 September P50 run:
data-key |
Label | Value (tone) | Note |
|---|---|---|---|
margin |
Margin · P50 | −R 13.1 m (rose) | 4 % contracted ratio · MaR 0 % |
coverage |
Coverage | 100 % (green) | 0 % shortfall · 2 demand pools |
spill |
Spill | 96.4 % (rose) | of supply unsold · −R 16.5 m at the spill value |
price |
Effective price | 157 c (slate) | realised R 57 / MWh · HHI supply 0.41 |
battery |
Battery | R 0 (green) | 0.00 cycles/day · absorbs 0.0 % of spill |
Tones: margin is rose when the month loses, green when it earns;
coverage is amber under 70 %, else green; spill is rose over 20 %, else
green; effective price is always slate; the battery tile is always
green. The fifth tile is Take-or-pay
(data-key=top) only when the run has no
bess_arbitrage_margin_r key — see §6.17.
Margin · P50
Why it exists. This is the commercial headline: every allocation, spill and shortfall line of the month, netted.
The label carries the run’s grade so you do not mix a P50 margin with
a P90 one. The value is compact Rand (R 13.1 m = about R
13,065,000). Full figure on the run: −R 13,064,676.
The note has two words:
- Contracted
ratio — sold supply ÷ all supply. Here 3.6
%, printed as 4 %. Same story as 96.4 % spill:
3.6 + 96.4 = 100. - Margin@Risk
(MaR) — share of P50 margin lost in the P90 case. This run
did not store
mar_pct, so the tile prints MaR 0 %. That is a missing pair, not “no risk”. September’s Adverse P90 chip (when present) is a separate simulation; do not treat MaR 0 % as a clean bill.
Looks good: a green value, contracted ratio near the share you meant to sell, MaR filled from a real P90 companion. Looks bad: a rose tens-of-millions loss while coverage is 100 % — you paid for energy nobody took.
Coverage
Why it exists. Did the buyers get served? Coverage is allocated ÷ demand. Shortfall is the leftover demand (Shortfall %).
T1 September: 100 % coverage, 0 % shortfall, 2 demand pools with energy in the run (Commercial and Municipal). Industrial and Trader Sales sat idle — they do not count here.
Tone turns amber under 70 %. 100 % is green. That is not the same as a healthy book: you can cover two small baskets and still drown in spill.
Looks good: high coverage and shortfall inside the demand cards’ bands. Looks bad: a green 100 % that hides a missing buyer class, or a high average that still leaves evening gaps (open §6.15 before you celebrate).
Spill
Why it exists. How much flour never became a loaf? Spill is unsold supply ÷ all supply (Spill %).
T1 September: 96.4 % of 59,600 MWh supply was leftover — 57,437 MWh. The note prices that leftover at the book’s spill value: −R 16.5 m. That is the spill lines’ margin (buy price minus the dump price), not the month’s net. The month’s net is the Margin tile; spill is the leak inside it.
Tone is rose over 20 % — the same threshold that shows Find offtake (§6.19).
Looks good: spill inside each supply card’s cap (15 % Solar, 12 % Wind, 20 % Flexible, 5 % Firm — §5.1). Looks bad: 96.4 %. You cannot nominate your way out of a book that bought ~24 times the demand it can serve.
Effective price
Why it exists. Two prices live on one tile because “what did we earn?” has two honest answers.
- The big number is effective price in c/kWh on sold energy only. T1: 157 c — about R 1,570 / MWh on the 2,163 MWh that found a buyer.
- The note’s realised
R/MWh divides the same sold margin by all
generation, unsold hours at zero. T1: R 57 / MWh.
Check:
1,570 × 3.6 % ≈ 57. The gap is the spill. - HHI supply is concentration of supply members (0 = many equal sources, 1 = one source). T1: 0.41 — a few members do most of the volume, not a monopoly.
The tile is slate on purpose: a high cents figure on a thin sold slice can look healthy while the month loses R 13.1 m.
Looks good: realised and effective sit close (little unsold energy) and HHI is not a single-member spike. Looks bad: 157 c next to R 57 / MWh.
Battery — or Take-or-pay
T1’s book seats Rosslyn BESS — 5 MW / 20 MWh on Firm. The run stored battery KPIs, so the fifth tile is Battery, not Take-or-pay. The value R 0 and the note 0.00 cycles/day · absorbs 0.0 % of spill mean the battery was present and did not work this month — it did not soak the 57 GWh leftover.
ToP utilisation for this run is 2.5 % (almost none of the Firm take-or-pay volume earned). That figure is not on a Forecast tile while the battery key exists. When a book has no battery KPIs, the fifth tile reads Take-or-pay and that utilisation is the value.
Looks good (battery): a positive arbitrage value and a real cycles/day number. Looks bad: R 0 beside 96.4 % spill — the battery did not save the bake.
6.13 Where the supply goes
The problem. The Spill tile says how much leftover you have. It does not say which shelf leftover it, or which basket bought the slice that sold.
On screen: #book-flow. Title:
Where the supply goes. Intro on the card:
Each supply pool’s energy for the run, split into what the cascade sold to the demand pools and what it spilled. The demand pools are the same cards, in the same order, as on the Rules board.
This is a server-drawn SVG (no hover, no separate legend). Colours are the legend: they match the Rules cards.
| Side | Colour | Who |
|---|---|---|
| Supply · Solar | amber #f59e0b |
Solar Pool |
| Supply · Wind | sky #0ea5e9 |
Wind Pool |
| Supply · Flexible | violet #8b5cf6 |
Flexible Pool |
| Supply · Firm | slate #334155 |
Firm Pool |
| Demand bars | ink #1e293b |
Commercial, then Municipal (priority order) |
| Spill outlet | amber #d97706 at half opacity |
Leftover |
How to read it, left to right.
- Left stack. One bar per supply pool that moved
energy, tallest first. The label is
{name} {energy}. - Ribbons. A coloured band from a supply bar to Sold is that pool’s allocated energy. An amber wash from the same bar to Spill is that pool’s leftover.
- Right stack. Demand bars in Rules priority order (not by size). T1 only draws Commercial and Municipal — Industrial and Trader Sales had no demand in the run.
- Right labels. Sold {energy} · {sold %} %. Under it, in rose: Spill {energy} · {spill %} % and {rand} at the spill value. A Shortfall {energy} line appears only when unmet demand is above zero — T1 has none.
Empty copy, when the run has no allocation lines: No allocation lines in this run.
Where the Overview cousin is taught. Overview §4.4 is a ribbon map of the snapshot run, coloured by margin, with hover. This Forecast chart is the picked run, coloured by pool type, with no hover. Same marketplace, different job.
Worked reading — T1 September P50
Conservation first. The chart must add up before you argue a ribbon.
Supply (alloc + spill) = 59,600 MWh
Sold (allocated) = 2,163 MWh → 3.6 % → label “Sold 2.2 GWh · 3.6 %”
Spill = 57,437 MWh → 96.4 % → label “Spill 57.4 GWh · 96.4 %”
Shortfall = 0 MWh
Demand (sold + shortfall) = 2,163 MWh
Sold + spill = 59,600 MWh = supply ✓
Left stack, tallest first:
| Supply pool | Energy on the bar | Sold | Spill | Spill share |
|---|---|---|---|---|
| Wind Pool | 35.7 GWh | 629 MWh | 35.1 GWh | 98.2 % |
| Solar Pool | 17.8 GWh | 1,424 MWh | 16.4 GWh | 92.0 % |
| Firm Pool | 4.3 GWh | 110 MWh | 4.2 GWh | 97.5 % |
| Flexible Pool | 1.8 GWh | 0 | 1.8 GWh | 100 % |
Flexible has no sold ribbon — the whole bar washes into Spill. Approved Override Supply is ACTIVE on Rules and sent nothing this run, so it is absent.
Where the 2.2 GWh actually landed (the five allocation legs):
| From | To | Energy | Sold-leg margin |
|---|---|---|---|
| Solar Pool | Commercial Pool | 760 MWh | +R 1.2 m |
| Solar Pool | Municipal Pool | 665 MWh | +R 1.4 m |
| Wind Pool | Municipal Pool | 520 MWh | +R 650 k |
| Firm Pool | Commercial Pool | 110 MWh | +R 94 k |
| Wind Pool | Commercial Pool | 109 MWh | +R 136 k |
Demand bars, Rules order: Commercial 979 MWh, Municipal 1.2 GWh. No shortfall notch.
Looks good: fat coloured ribbons into Sold, a thin amber spill outlet, every live demand bar present. Looks bad: a left stack that is almost entirely amber wash — T1.
Where to go next. A fat leftover from one shelf: open that card on Rules and the joiners in the wiring gutter. Need a buyer for the leftover: Find offtake → Desk (§9). Need the hour: §6.15 then the ledger (§6.18).
6.14 Where the margin is made and lost
The problem. The Margin tile is one number. You still need to know whether you lost money on prices (sold energy was cheap) or on leftover dough (sold energy was fine; unsold energy sank the month).
On screen: #book-margin. Title:
Where the margin is made and lost. Intro:
By time of use and by source pool. Sold energy earns; spilled energy loses buy price minus the spill value.
Two small tables, then one verdict sentence.
By TOU (data-role="margin-tou"). Rows
in clock order: Peak, Standard,
Off-peak, then Battery / untimed when
a line has no TOU. Positive margins print green with a leading
+; negative ones print rose with −. Empty
body: No margin breakdown in this run.
By source (data-role="margin-source").
One row per supply pool that sold, with the pool colour chip,
the name, and the word sold. Sorted richest sold-margin
first. A final Spill · all pools row
(data-role="margin-spill") is the amber chip and the
leftover’s rand. Flexible does not appear on T1 — it sold nothing.
The verdict under the tables (margin_note):
| When | Sentence |
|---|---|
| Month loses, spill loses, every sold source is ≥ 0 | Sold energy makes money in every hour. The loss is entirely the energy that never sells — a wiring and demand problem, not a price problem. |
| Month loses, but some sold source is also negative | The book loses money on what it sells as well as on what it spills; check the buy prices against the sell side. |
| Month earns, spill still loses | Sold energy carries the book; spill is the leak. |
| Otherwise | Margin is positive across the board. |
T1 September is the first sentence. Remember: the product says “every hour” while the test is every source pool’s sold margin. The TOU table is allowed to be red — it includes spill.
Where the Overview cousin is taught. Overview §4.8 is a month × hour heatmap of the snapshot. This card is two tables for the picked run.
Worked reading — T1 September P50
By TOU (these rows include spill):
| By TOU | Margin |
|---|---|
| Peak | −R 2.1 m |
| Standard | −R 5.1 m |
| Off-peak | −R 5.9 m |
| Battery / untimed | +R 12 k |
Off-peak is the worst clock band because that is when the book is longest and the leftover is cheapest to dump. The +R 12 k is BESS reserve lines, not a dispatch profit.
By source (sold legs only) plus the spill row:
| By source | Margin |
|---|---|
| Solar Pool · sold | +R 2.5 m |
| Wind Pool · sold | +R 786 k |
| Firm Pool · sold | +R 94 k |
| Spill · all pools | −R 16.5 m |
Sold sources = 2.5 m + 786 k + 94 k ≈ +R 3.4 m
Spill = −R 16.5 m
BESS reserve (untimed)= +R 12 k
Month (Margin tile) = −R 13.1 m
3.4 m − 16.5 m + 0.012 m ≈ −13.1 m ✓
Looks good: green TOU rows, green source rows, a small or missing spill row. Looks bad: green sold rows and a spill row that is five times larger — a wiring-and-demand problem. Rewire or sell offtake; do not first cut the sell price.
Where to go next. Price problem → member buy/sell on Rules. Wiring-and-demand problem → gutter and Find offtake. Hour proof → §8 Margin tab.
6.15 Long or short, hour by hour
The problem. A month total can hide a noon glut and an evening gap. You need the shape of a typical day.
On screen: #book-day. Title:
Long or short, hour by hour. Intro:
A typical day of the run: supply stacked by pool against the demand line. Above the line is long (spill), below it short (shortfall). The Overview’s clock, now per pool.
A typical day is every line of the run grouped by SAST clock hour (the stored UTC hour + 2), then divided by the number of days in the period. This run is 1 Sep → 1 Oct, so each point is the month’s that-hour total ÷ 30.
How to read the SVG (no hover, no clip strip, no Tomorrow toggle — those belong to Overview §4.6):
- X axis. 0h … 23h SAST, labelled every four hours
(
0h,4h,8h,12h,16h,20h). - Y axis. Energy. Ticks use the same compact units as
the flow chart (
kWh/MWh/GWh). On T1 the noon stack is about 136 MWh, so the axis is in MWh. - Stacked areas. One band per supply pool, coloured like Rules. The engine draws the smallest shelf at the bottom and the largest on top: Flexible, Firm, Solar, then Wind.
- Solid ink line = demand that hour (allocated delivered + shortfall). The word demand sits at 23h.
- Long vs short. Stack above the line = long (you will spill). Line above the stack = short (you will buy top-up).
Empty copy: No hourly lines in this run.
Worked reading — T1 September, three clock hours
Every hour is long. Demand is a thin ink thread under a tall stack.
| SAST | Typical-day supply | Typical-day demand | Long (spill) | Plain reading |
|---|---|---|---|---|
| 00:00 | 50 MWh | 2.2 MWh | 48 MWh | Night wind and firm still dwarf the two live baskets |
| 12:00 | 136 MWh | 3.8 MWh | 132 MWh | Solar noon is the tallest leftover of the day |
| 18:00 | 88 MWh | 3.0 MWh | 85 MWh | Evening is still long — there is no shortfall notch |
Looks good: the stack follows the demand line; a little amber only at solar noon if you are slightly long; a rose evening only if you sold firm hours you cannot cover. Looks bad: a stack that never touches the line — T1. You are not “a bit long at noon”; you are long for 24 hours.
Where to go next. Noon leftover → sell daytime offtake on Desk, or stop seating more solar until the gutter has a buyer. An evening short (not present here) → firm shelf or Cover shortfall. Hour proof → the ledger.
6.16 Pool caps, this run
The problem. Rules shows a badge on each card. Forecast repeats those badges as a table for this run, so you can quote them next to the tiles.
On screen: #book-caps. Title:
Pool caps, this run. Intro: The Rules board’s
outcome badges, as a table.
Columns: Pool, Result, Cap / band, and a pill.
| Pill | Tone | Meaning |
|---|---|---|
| ok | green | Inside the spill cap or the coverage band |
| outside | amber | Coverage below the min or above the max |
| breach | rose | Spill above the cap, or shortfall above the demand card’s max shortfall |
| — | slate | No reading |
A supply row is {colour chip}{name} spill. Result is the
run’s spill %. Cap / band prints ≤ {cap} %. A demand row is
{chip}{name} coverage. Result is coverage %. Cap / band
prints {min}–{max} % when both ends exist.
Only ACTIVE pools that actually took part
(active?) appear. Drafts, archives, and live pools with no
energy in the run are omitted. Empty table: No pool took part in
this run.
Worked reading — T1 September P50
| Pool | Result | Cap / band | Pill |
|---|---|---|---|
| Solar Pool spill | 92 % | ≤ 15 % | breach |
| Wind Pool spill | 98 % | ≤ 12 % | breach |
| Flexible Pool spill | 100 % | ≤ 20 % | breach |
| Firm Pool spill | 98 % | ≤ 5 % | breach |
| Commercial Pool coverage | 100 % | 50–60 % | outside |
| Municipal Pool coverage | 100 % | 60–70 % | outside |
(97.5 % Firm spill rounds to 98 % on the table.) Industrial and Trader Sales have bands on Rules and no demand in this run, so they are absent. The four breach rows are the same four names on the issues rail. The two outside rows are the over-covered baskets: every hour was served, which is more cover than those cards asked for.
Looks good: every pill ok. Looks bad: a column of breach plus outside — you both dumped most of the flour and over-fed the two baskets that showed up.
Where to go next. Press Rules › on the issues card, or open the named pool on the board. Do not edit a cap to hide a 96 % spill; seat a buyer or take less supply.
6.17 Battery dispatch
The problem. A battery can soak leftover noon energy and give it back in the evening. You need to see whether this run used it.
When the fold exists. #book-battery
renders only when the run’s KPI map has
bess_arbitrage_margin_r — even if the value is zero. It is
a <details> that opens by default. Summary:
Battery dispatch · {member label} · from this run shown only for books with an active battery
T1’s member label is Rosslyn BESS — 5 MW / 20 MWh.
Five mini tiles (data-role="battery-tile"):
| Label | T1 value | Note on T1 |
|---|---|---|
| Arbitrage margin | R 0 | for the run |
| Cycles | 0.00 / day | degradation priced |
| Spill absorbed | 0.0 % | of the book’s spill |
| Firm hours backed | 0 % | discharges into arbitrage, not firm shortfall (amber) |
| Market arbitrage | — | day-ahead spread (no bess_market_arbitrage_r
on this run) |
Under the tiles: The dispatched day, the hourly schedule, the
rejected-pairs trust device and the asset settings live on the full
dispatch page. Open full dispatch › goes to
/org/trader-pools/{id}/strategy/bess. The link does
not carry ?run= — the destination page
loads the book’s latest complete Forecast that already has battery
intervals (§11.11).
Where this is taught. This section is the Forecast fold — five tiles and a door. The full
/strategy/besspage (header, which run it opens, facts, chart, moves, hour table, empty states) is §11.11. How the engine decides charge, hold and discharge is §11.2.
When the fold is absent. A book with no battery KPIs
does not render #book-battery. The fifth tile then becomes
Take-or-pay. That is honest: there is nothing to
fold.
T1’s honest empty-ish state. The fold is
there. The battery did not dispatch. One
BESS_CHARGE line (2.3 MWh) and +R 12 k of
BESS_RESERVE sit on the run; they do not move the arbitrage
tile off R 0 and they do not absorb the 57 GWh spill.
Looks good: cycles above zero, spill absorbed above zero, or firm hours backed above zero. Looks bad: a named BESS and a row of zeros next to a 96 % spill tile.
6.18 The run’s line ledger
The problem. Charts argue. Lines prove.
On screen: #book-ledger-fold — a dashed
fold, closed until you open it. Summary:
The run’s line ledger · Allocations · Spill · Shortfall · Margin · Audit one SAST day at a time
The body: Every allocation, spill and shortfall line of this run
with its provenance, priced hour by hour. Then Open the run
ledger › — the same allocations URL as the meta line under the
picker. The destination heading has ← Pool · Forecast
(#allocation-back-to-forecast) back to this Forecast for
the same pool, month, and run.
This fold does not inline the day table. It is a door.
Where this is taught. The destination
/org/trader-pools/:id/strategy/allocations/:run_id— header, ← Pool · Forecast, day picker, every tab, empty states, and the T1 September walk — is §8. Start at §8.6 for the click path.
Use it when a tile surprises you, when you need a line for a dispute, or when you want to compare this run with a superseded companion.
6.19 Find offtake, Cover shortfall, and empty states
The problem. After you have read the leak you still need one obvious next click. Forecast does not invent a third “moves” gallery.
Find offtake
(#book-forecast-offtake-cta) is a single line under the
ledger, only when this run’s spill is above 20 %:
Spill has no buyer in this run. Find offtake → Desk
The link (#book-forecast-offtake-desk) opens Simulations
(/strategy/simulations) — §9. T1
September is 96.4 %, so the line is present.
Cover shortfall
(#book-forecast-cover-cta) is the twin, only when unmet
demand is above 5 %:
Demand is served at the top-up price. Cover shortfall → Desk
T1 September is 0 % shortfall, so the line is absent. Both lines can appear together on a book that is long in one hour and short in another.
Nominations and Outcomes are not repeated here. They stay on the thread strip.
Empty and partial states you will actually see
| State | What the page does |
|---|---|
| No complete forecast yet | Headline: No forecast run yet. Run one to see what the engine would do with this wiring. Tiles, charts and tables do not render. Picker still offers New run. |
| Run in flight | Status pill pending / running. Headline may say the run has no figures yet. Read KPIs only from complete. |
| Failed run | Rose failed pill. The previous complete current is unchanged (§6.6). |
| Run with no allocation lines | Flow: No allocation lines in this run. Day: No hourly lines in this run. |
| No TOU breakdown | No margin breakdown in this run. |
| No pool took part | Caps: No pool took part in this run. |
| No battery KPIs | No #book-battery. Fifth tile is
Take-or-pay. |
| Battery KPIs all zero | Fold is present; tiles read R 0 / 0.00 / 0.0 % — T1. |
| Spill ≤ 20 % | No Find-offtake line. |
| Shortfall ≤ 5 % | No Cover-shortfall line — T1. |
| Current calendar month | No Run backcast. |
What to do next on T1 September
- Believe the headline: the customers who showed up were served; the month still loses R 13.1 m on leftover supply.
- Open Rules and sit a buyer on the gutter, or press Find offtake → Desk and price a sell-side candidate.
- Do not start from the 157 c effective price — that is the thin sold slice.
- When you need a line, open the run ledger. When the month has settled, read Outcomes — Forecast will not rewrite itself into a warehouse.
6A. Book · Outcomes — what actually settled
Route:
/org/trader-pools/:id/strategy/book?mode=outcomes&month=YYYY-MM
· Tab: Book (#strategy-tab-book) ·
Mode: Outcomes (#book-stage-outcomes on
the thread strip; BookLive). The old
…/book?month= link and the old …/chains route
open here.
A trader buys from several sources and sells to several sinks in the same month. Forecast (§6) answers “what would the engine do?” Outcomes answers “what actually cleared?” — every buy leg and sell leg on which this pool sat, the warehouse rule that you cannot have sold more than you procured, the chains that make the month up, and how far the forecast missed the ledger.
Think of Book as a warehouse stocktake. Forecast is the bake sheet you wrote before the month. Outcomes is the till tape after the shop closed: who delivered flour, who left with bread, and whether you sold more loaves than you ever took in.
6A.1 The trader’s problem
Opening one PPA’s settlement detail shows one leg. Your commercial
question is the book: who gave me energy, who did I give it to,
does Σ sell ≤ Σ procured still hold, and did the plan I ran
a month ago look anything like this?
6A.2 What you see
The table is a map. Each block is taught in full from §6A.5.
| Region | Job |
|---|---|
| Thread strip · issues rail | The same strip as the other modes; Outcomes is the lit stage. On T1 today that pill is September · −R 469 k · not balanced — not the older August · −R 381 k figure |
| Headline | One sentence from the ledger. Pick August and you get a buy-only month. Pick September and you get the 7.2 GWh paper sale |
| Month picker | The last six months as chips, each with balanced · not balanced · nothing settled; a month input and arrows for anything older |
| Procured against sold | Two bars: what came in from suppliers, what went out to buyers, with the honest ceiling marked and any sold energy that has nothing behind it in red. Under it the book check |
| The month’s money | Bought (buy legs), network borne, sold (sell legs), gross and net margin — own seat only — with a note comparing the forecast’s P50 for the month against the settled net |
| Procured (buy legs) · Sold (sell legs) | Counterparty + kWh for every period where this pool is the buyer-trader or the seller-trader, with Σ totals |
| Chains | The month’s chains with balance badges, an Unbalanced only filter, and one chain opened to its rail and volume bridge (§6B) |
| Forecast said, book settled | P50 margin at forecast time against the settled net margin, last six months, with a verdict sentence. A snapshot on a twelve-month run is scaled to one month before it is compared |
| Three moves | Cover or cancel the uncovered sale, reconcile forecast to ledger, read the six-month story on the Dashboard. Outcomes keeps this strip. Forecast dropped it |
Data is assembled by Statement.TraderBook.build/3 and
ChainExplorer — the same projections statements use. No
settlement maths is redone; line amounts and period totals are read off
the ledger.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Allocation → Outcomes. Deep link:/org/trader-pools/01a0ab54-e46b-7dde-b45f-73d119213c75/strategy/book?mode=outcomes&month=2026-09. You should see the thread strip, the headline, the two bars and the book check, the money ledger, the buy/sell panels, the chains and the three move cards.
6A.3 How to read it
- Read the badge before you argue a month commercially. A red badge means a sell leg has no supply behind it — a paper commitment, or supply legs missing from settlement.
- Buy legs are “who gave me what”; sell legs are “who I gave it to”.
- The upper bar is the most that can honestly be sold. Sold energy past it is the red segment, and the same energy shows as uncovered out-legs in the book check.
- Net margin is your seat’s P&L (sell revenue − buy cost − network you bore). Counterparty prices never appear.
- The drift panel is the reconciliation: if the forecast prices thirty times the supply that settles, fix the wiring on the Rules board before trusting the forecast money.
6A.4 Explanations — How to Read Outcomes
Explanations (#book-explanations-open)
sits to the right of the Outcomes headline. Same drawer shell as §5.8. Eyebrow: Book ·
Outcomes.
How to Read the View is the warehouse order: thread strip, headline, month picker, procured against sold, the month’s money, buy legs · sell legs, chains, forecast said versus book settled.
The A–Z list is the words on Outcomes (Balanced through Warehouse rule). It does not repeat the Rules gutter or the Forecast flow chart.
The walk below is that same order, with every control and the T1 numbers.
6A.5 How to read Outcomes, block by block
A dashboard number you can edit is a wish. Outcomes is a warehouse stocktake for one settled month. You cannot type a new net onto the money card. You pick another month, or you open a chain and prove a leg.
This mode does not change the wiring. That is Book · Rules. It does not run the engine. That is Book · Forecast. It answers: who gave me energy, who did I give it to, and did I sell more than I bought?
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Allocation → Outcomes on the thread strip (#book-stage-outcomes). Deep link:/org/trader-pools/01a0ab54-e46b-7dde-b45f-73d119213c75/strategy/book?mode=outcomes&month=2026-09. You should see the eyebrow Book · Outcomes, a headline that names September’s 7.2 GWh sale, then the conservation chart beside the money card.
Data. full_demo · seed 42 · T1 Renewables Pool (
01a0ab54-e46b-7dde-b45f-73d119213c75) · last read 2026-09-19 fromTraderBook.build/3andsettlement_periodsonwb_wheeling_dev. Compact Rand follows the product (−R 469 k,R 12.9 m). Energy labels follow the product too (460 MWh,7.2 GWh). The live Outcomes URL was not opened in a browser this pass — Phoenix was up; the login door blocked automation. The numbers are the same projections the page renders.
On screen, top to bottom
| Order | Block | DOM id |
|---|---|---|
| Shell | Heading Book — Outcomes. Subtitle: How the book is wired, what the engine will do with it, and what actually settled — one thread across three views. First paint: Loading the book…. | #org-page-heading,
#trader-book[data-mode=outcomes] |
| 1 | Thread strip, then the issues rail | #book-thread, #book-stage-outcomes,
#book-issues |
| 2 | Eyebrow Book · Outcomes, headline, lede, Explanations | #book-outcomes, #book-outcomes-headline,
#book-explanations-open |
| 3 | Month arrows, month input, six chips, recomputed stamp | #book-month-picker,
[data-role=chains-computed-at] |
| 4–5 | Procured against sold · The month’s money | #book-conservation, #book-money |
| 6–7 | Procured (buy legs) · Sold (sell legs) | #trader-book-buy, #trader-book-sell |
| 8 | Chains list and the opened chain | #trader-chains, #chains-list,
#chains-detail |
| 9 | Forecast said, book settled | #book-drift |
| 10 | Three next-move cards | #book-moves |
#book-moves is Outcomes-only. Forecast
has no three-card strip (§6.9). Rules has none
either. Nominations stay off this page — they are not a
#strategy-nav tab. The three ranked cards stay here so a
broken warehouse has an obvious next click.
What “looks good” vs “looks bad” on this whole page. Good: green Σ sell ≤ procured, chains balanced, forecast and settled net sit close, the issues rail is quiet on this month. Bad — and this is T1 September — the lower bar runs 15.7× past the upper one, three sell legs sit outside any linear chain, and the month loses R 469 k on a 7.2 GWh paper sale.
6A.6 Route, Book tab, thread strip and issues rail
The problem. You can open Outcomes from four doors and lose the rest of the Book. The strip is how you stay on the same tab.
#strategy-nav. Overview ·
Allocation · Desk · Dashboard.
Allocation is lit
(#strategy-tab-book.tab-active). Outcomes is
not a fourth room tab. There is no
#strategy-tab-book-outcomes and no
#book-mode-switch on this page. Book stays the tab; the
thread strip switches the mode.
How you get here.
| Door | What it does |
|---|---|
Thread strip Outcomes
(#book-stage-outcomes) |
Opens …/book?mode=outcomes with no month — the LiveView
then defaults to last calendar month (August on a 19 Sep 2026
clock) |
This URL with &month=YYYY-MM |
Pins the warehouse to that month. A shared link reproduces the view |
Old …/book?month=YYYY-MM (no mode) |
Still Outcomes. The month query is enough |
Old …/chains?month=&chain= |
Forwards into Outcomes with the same month and chain |
The default month and the strip’s month are not the
same clock. The page without ?month= lands on today minus
one month. The strip names the last month that has any received or
supplied energy, walking back at most six months from today. On
T1 that last month is September, even if you then pick
August in the chips.
Thread strip (#book-thread). Three
stages, left to right:
| Stage | Eyebrow | Id | What the body shows |
|---|---|---|---|
| Rules | Rules · how the book is wired | #book-stage-rules |
Live pool and member counts. Pill: cap verdict. |
| Forecast | Forecast · what the engine will do | #book-stage-forecast |
Month, grade and compact margin. |
| Outcomes | Outcomes · what actually settled | #book-stage-outcomes |
Last month with settlement energy, compact net, pill balanced / not balanced. Nothing settled: Nothing settled yet. |
Outcomes is ringed (data-on=true) on this mode. A
negative net prints rose; a positive one prints brand green. Clicking a
stage navigates; it does not re-settle a period.
On T1, 19 Sep 2026, the Outcomes stage reads September · −R 469 k with pill not balanced. The note under it is 7.2 GWh sold against 460 MWh bought · 3 sell legs with no supply behind them.
That is not the older August · −R 381 k · not balanced line. August is a different warehouse: 186 MWh bought, nothing sold, the warehouse rule holds, net −R 196 k. Do not paste an Overview figure onto this strip. Confirm the month word and the pill before you quote the net.
Where the strip is taught. The three-stage Book thread — §5. This section only names what Outcomes lights and which month it prefers.
Issues rail (#book-issues). Ranked
cards under the strip, each with a colour dot (rose = bad, amber = warn,
slate = info), a title, a body, and a door (Rules › /
Forecast › / Outcomes ›). The
September-unbalanced card is the Outcomes one:
September book does not balance 7.2 GWh sold against 460 MWh bought. 3 out-legs uncovered. Outcomes ›
T1 also carries the Forecast/Rules cards the other modes already taught: spill around 96 % of supply, coverage outside its band on Commercial and Municipal, and a draft pool with no members. Those doors open Rules or Forecast. They do not change the warehouse.
When no month in the last six has energy, the rail adds Nothing has settled yet and points at Outcomes.
6A.7 Headline, lede and Explanations
The problem. The charts are true and still easy to argue past. The headline is the one sentence the ledger wants you to believe first.
Eyebrow. Small brand-green caps: Book · Outcomes. Same pattern as Forecast’s Book · Forecast.
Headline (#book-outcomes-headline). One
sentence from the month’s statement and book check. The recipe, in order:
- No statement at all: {Month Year} has no settled legs yet.
- Statement exists, but both sides are zero: {Month} settled nothing: no buy leg and no sell leg reached FINAL.
- Book check is not balanced (T1 September): {Month} settled {bought} bought and {sold} sold — the book does not balance: {N} sell leg(s) have no supply behind them, and the month lost (or made) {abs net}.
- Something bought, nothing sold (T1 August): {Month} settled {bought} bought and nothing sold — the book carried {abs net} of supply cost with no revenue against it.
- Otherwise: bought, sold, balanced, and a net loss or margin.
T1 September hits rule 3:
September settled 460 MWh bought and 7.2 GWh sold — the book does not balance: 3 sell legs have no supply behind them, and the month lost R 469 k.
T1 August hits rule 4:
August settled 186 MWh bought and nothing sold — the book carried R 196 k of supply cost with no revenue against it.
T1 June hits rule 2 (a statement with empty legs):
June settled nothing: no buy leg and no sell leg reached FINAL.
Lede (the grey line under the headline). Always: What the ledger says happened, one settled month at a time. The statement first, the chains that make it up underneath, and the forecast that predicted it beside it. A month that does not conserve energy is flagged before any money is read.
Explanations (#book-explanations-open)
sits to the right of that pair. The drawer, the How to Read fold, and
the A–Z list are §6A.4. Eyebrow inside
the drawer: Book · Outcomes. Close with
#book-explanations-drawer-close, the backdrop, or Escape.
The walk you are reading is the How to Read order written out.
Outcomes does not open the Forecast New
run modal. There is no #book-new-run on this
mode.
6A.8 The month picker
The problem. A book has several closed months. Mixing them on one canvas would lie. The picker makes you choose.
Arrows. Ghost chevrons
(phx-click="shift_month", by="-1" /
by="1"). Each click patches ?month= one
calendar month and clears any selected chain.
Month input. type=month,
aria-label="Settlement month",
phx-change="select_month". Changing it patches
?month=YYYY-MM. September cannot explain August.
Chips (#book-month-picker). The last
six calendar months from today, newest first, each a patch
link:
…/book?mode=outcomes&month=YYYY-MM
| Chip | What it carries |
|---|---|
| Label | Mon YYYY — Sep 2026, Aug 2026, … |
| Selected | Dark ring (selected?) |
| Settled and balanced | Green pill balanced |
| Settled and not balanced | Rose pill not balanced |
| No received or supplied energy | Slate pill nothing settled |
A month is settled on a chip when the book check sees received kWh or supplied kWh above zero. Status FINAL is not required. T1 September is still DRAFT on every September period — the chip still reads not balanced, because the energy is there.
On a 19 Sep 2026 clock the six chips are Sep, Aug, Jul, Jun, May, Apr:
| Chip | T1 pill |
|---|---|
| Sep 2026 | not balanced (460 MWh in, 7.2 GWh out) |
| Aug 2026 | balanced (186 MWh in, nothing out) |
| Jul 2026 | balanced (187 MWh in, nothing out) |
| Jun 2026 | nothing settled |
| May 2026 | nothing settled |
| Apr 2026 | nothing settled |
Recomputed stamp
([data-role=chains-computed-at]). When the chain index has
a clock: recomputed {dd Mon HH:MM}. Honest “as of now”, not an
issued report. Empty when the index has no timestamp.
The URL also keeps &chain= and
&unbalanced=1 when those filters are on. Changing the
month drops the chain. Toggling the filter keeps the month.
6A.9 Procured against sold — the conservation chart
The problem. Two tables of counterparties do not show, at a glance, whether you sold more than you bought. The chart is the warehouse door.
Card (#book-conservation). Title
Procured against sold. Helper: Energy conservation
for the month. In-legs are what the book received from its suppliers;
out-legs what it delivered to buyers. Sold cannot exceed bought unless a
sell leg is a paper commitment with no chain behind it.
How to read the SVG (role="img",
Procured against sold energy):
- Bought · in — the upper green bar. Length is procured kWh (delivered on buy legs).
The number to the right is the compact label (
186 MWh,460 MWh). - Sold · out — the lower demand-coloured bar. Length is sold kWh (supply on sell legs), clipped to what was bought.
- Red tail — only when sold > procured. It starts at the bought ceiling and runs to the sold tip. The label adds · {energy} with nothing behind it.
- Dashed vertical — drops from the bought tip. Caption: what was bought · the most that can honestly be sold.
- Sentence under the bars. Over: A balanced month has the lower bar no longer than the upper one. This month is {ratio}× over. Inside: Sold energy sits inside what was bought. Empty: Nothing sold this month.
T1 August — nothing sold, so no red tail:
Bought · in → 186 MWh Sold · out → 0 kWh Sentence: Nothing sold this month. (the sold bar is empty; the ceiling still marks 186 MWh.)
T1 September — the picture you open the page to see:
Bought · in → 460 MWh Sold · out → 7.2 GWh · 6.7 GWh with nothing behind it Sentence: A balanced month has the lower bar no longer than the upper one. This month is 15.7× over.
7.2 GWh is 7,200,000 kWh on one OffTaker A period. 460 MWh is 459,740 kWh delivered on the IPP3 buy legs. 7,200,000 ÷ 459,740 ≈ 15.7. The red tail is the paper sale.
Book check ([data-role=book-check]),
under the SVG:
Book check · {fan-out · }{N} in-legs · {N} out-legs · {N} uncovered
| Word | Plain meaning |
|---|---|
| In-legs | Buy periods this month — this pool is the buyer-trader |
| Out-legs | Sell periods this month — this pool is the seller-trader |
| Uncovered | Uncovered out-legs — sells that sit on no linear chain |
| fan-out · | Prefix when uncovered > 0. The book sold to a sink the chain walk did not keep (fan-out) |
Badge
([data-role=book-balance-badge]) |
Green Σ sell ≤ procured or rose Sold more than procured |
August: 2 in-legs · 0 out-legs · 0 uncovered and green Σ sell ≤ procured.
September: 5 in-legs · 4 out-legs · 3 uncovered and rose Sold more than procured. The chain walk keeps one next hop; the other three September sells never join a linear path. Book still owns them. That is why the statement and the chain list can disagree on count — §6B.8.
Empty card. When there is no statement, the two-column grid is replaced by a dashed panel: No settled statement for {Month Year}. June on T1 still has a statement (empty legs), so you get the chart at zero rather than this dashed empty. The dashed empty is the “Ash could not build a statement” state.
6A.10 The month’s money
The problem. Energy conservation is not a P&L. You can pass the warehouse test and still lose money — or fail it and still invoice a sliver.
Card (#book-money). Title The
month’s money. Helper: From what was bought to what was
kept, own seat only.
Five rows ([data-role=money-row], data-key
on each). Costs print with a minus; revenue with a plus. Gross and net
are extrabold. The net cell is [data-role=net-margin].
| Key | Label | What it sums | T1 August | T1 September |
|---|---|---|---|---|
buy |
Bought · {N} buy leg(s) | Your trader_buyer energy lines, as a
cost. Note: energy at PPA prices |
−R 158 k (2 buy legs) | −R 391 k (5 buy legs) |
network |
Network borne | Your buy-side wheeling, transmission, distribution and ancillary. Note: wheeling, use-of-system and losses on the buy side | −R 37 k | −R 92 k |
sell |
Sold · {N} sell leg(s) | Your trader_seller energy lines. Note:
only covered legs invoice |
R 0 (no sell legs) | +R 14 k (4 sell legs) |
gross |
Gross margin | Sell − buy, before network | −R 158 k | −R 377 k |
net |
Net margin | Gross − network. Note: after network | −R 196 k | −R 469 k |
Exact cents behind the compact labels, August: buy 15,841,730 · network 3,727,466 · sell 0 · net −19,569,196. September: buy 39,077,875 · network 9,194,793 · sell 1,384,933 · net −46,887,735.
Imbalance, curtailment credits, trader-margin lines and levies sit on the ledger. They do not appear on this card. The card is the seat’s energy-and-network story, not a restatement of every category.
Forecast note under the list, when the drift series has a P50 for a month: The forecast for {Month} said {P50} at P50; the ledger settled {net}. See the drift panel. On T1 September that is The forecast for September said −R 12.9 m at P50; the ledger settled −R 469 k. The plan priced leftover supply the warehouse never bought.
Counterparty prices never appear. You see your cost, your network, your revenue.
6A.11 Procured (buy legs) and Sold (sell legs)
The problem. The bars collapse counterparties. You still need the names.
Two tables, side by side from lg up.
Procured (buy legs) (#trader-book-buy).
Columns Source and kWh. One row per
buy period ([data-role=buy-leg]). Footer Σ
buy ([data-role=procured-kwh]) when the list is
not empty. Empty body: No settled buy legs this month.
kWh is a whole number, no compact MWh label — 186373,
not 186 MWh. The compact label lives on the conservation
chart.
T1 August
| Source | kWh |
|---|---|
| IPP1 Sandton Solar | 0 |
| IPP3 Midrand Hybrid | 186373 |
| Σ buy | 186373 |
T1 September
| Source | kWh |
|---|---|
| IPP1 Sandton Solar | 0 |
| IPP3 Midrand Hybrid | 228335 |
| IPP3 Midrand Hybrid | 0 |
| IPP3 Midrand Hybrid | 0 |
| IPP3 Midrand Hybrid | 231405 |
| Σ buy | 459740 |
IPP1’s DEMO-SUPPLY period is a live buy PPA that delivered nothing. It still counts as an in-leg. IPP3 is the thread-cast generator (IPP3 Midrand Hybrid). Several September rows share one agreement because settlement stored more than one period start in the month.
Sold (sell legs) (#trader-book-sell).
Columns Sink and kWh. Rows
[data-role=sell-leg]. Footer Σ sell
([data-role=sold-kwh]). Empty body: No settled sell
legs this month — that is August.
T1 September
| Sink | kWh |
|---|---|
| OffTaker A Rosebank Mall | 0 |
| OffTaker A Rosebank Mall | 0 |
| OffTaker A Rosebank Mall | 0 |
| OffTaker A Rosebank Mall | 7200000 |
| Σ sell | 7200000 |
OffTaker A Rosebank Mall is the thread-cast sink. 7,200,000 kWh on one period is the paper sale the red tail is made of. Delivered on that same period is only 16,293 kWh — the table shows supply kWh on sell legs, not delivered. That is deliberate: the warehouse asks what you committed, not what the customer took.
There is no sort, no filter, and no row click on these tables. To study a path, use Chains.
6A.12 Chains — pick a path
The problem. The statement is the whole warehouse. A break usually lives on one route. Chains is the map of those routes.
Where this is taught. Every card on an opened chain — rail, volume bridge, money, legs, book-check strip — is §6B. This section is the Outcomes chrome around that detail: the list, the filter, the click, and what T1 shows.
Layout (#trader-chains). List on the
left (#chains-list, four columns from xl).
Detail on the right (#chains-detail, eight columns) when a
chain is selected. When none is selected: a dashed panel, Select a
chain to study the volume bridge and margin.
List header. Chains · {total}
([data-role=chains-verdict]). When unbalanced > 0, a
rose pill {N} unbalanced
([data-role=chains-unbalanced-count]).
Unbalanced only
(#chains-unbalanced-toggle). Ghost border when off; rose
btn-error when on. Click patches
&unbalanced=1 (or drops it). The list then hides
balanced paths. The URL is shareable.
Empty list (#chains-empty). No
chains for this month — or No chains for this month (unbalanced
filter on) when the toggle hid everything. August on T1 is the
first form: buy-only months have no linear IPP → you → sink path of two
or more legs. Turn the filter on in June and you get the second form
(the LiveView test asserts that copy).
A row. Button
#chain-row-{head_period_id},
data-role="chain-row",
data-balanced="true|false". Body:
- Path label — Generator → You → Off-taker (T1 September: IPP3 Midrand Hybrid → You → OffTaker A Rosebank Mall)
- {N} legs
- Badge
[data-role=chain-balance-badge]: green balanced or rose BREAK
Click patches &chain={head_period_id}. The selected
row is lightly highlighted. A deep link may pass any leg’s
period id; the screen still opens the whole chain.
What opens on the right (#chains-detail
→ <.chain_detail>):
| Block | Id | What you do with it |
|---|---|---|
| Lifecycle mismatch | #chains-lifecycle-mismatch |
Amber, only when one leg is FINAL and another is still DRAFT / PRELIMINARY. September on T1 is all DRAFT, so this card usually stays down. Do not compare a future re-run to an immutable close |
| Investigation order | #chains-investigation |
Numbered checklist when the chain is broken. Red steps are the ones that look relevant. It does not press buttons for you |
| The rail | #chains-rail |
Left-to-right hops with kWh, a status chip, and Σ=0 / Σ≠0 |
| Volume bridge | #chains-bridge |
First-leg supply, minus loss / spill / banked, equals expected delivery, versus last-leg delivered. Unexplained must be ~0 ✓. A red residual is the named volume break |
| Money | #chains-money |
sell − buy − network borne = margin. Your
margin is your seat. Chain margin appears only when it
differs |
| Legs | #chains-legs |
One hop per row. Period and Ledger open the contract rooms. hidden replaces the links on a silhouette hop |
| Book check strip | #chains-book-check |
The month’s warehouse (received ≥ supplied),
plus an amber fan-out notice when sells sit outside any chain.
Book → (#chains-to-book) patches Outcomes
for the same month — you are already there |
T1 September should open the IPP3 → You → OffTaker A path. Expect a BREAK or a loud unexplained residual: the sell supply is 7.2 GWh and the buy delivered is hundreds of megawatt-hours. That is the same 15.7× the conservation chart already shouted.
August has no chain to click. The dashed Select a chain… panel stays up.
6A.13 Forecast said, book settled
The problem. A plan that prices energy the ledger never saw will keep sending you to Desk. The drift panel is the six-month argument.
Card (#book-drift). Title
Forecast said, book settled. Helper: P50 margin at
forecast time against the settled net margin, last six months. The gap
is forecast error you are paying for. This is the trader cousin of
IPP Allocation’s Forecast vs
settled card — same idea, different ids and a book-level net rather
than a buyer carve.
How to read the SVG (Forecast margin against settled margin by month):
- X axis — six month ticks (
Mar…Sepwhen September is selected), ending on the picker month. - Y axis — compact Rand, including below zero.
- Dashed grey line — forecast P50
(
forecast_r). A twelve-month snapshot is scaled to one month (margin × 30 / dayswhen the run is longer than 45 days) before it is plotted. - Solid green line + dots — settled net
(
settled_r), only for months that have procured or sold energy. - Legend (top right): dashed · forecast P50 solid · settled net.
Verdict ([data-role=drift-verdict]). No
pair: No month has both a forecast snapshot and a settled statement
yet. Otherwise: The forecast misses the ledger by about
{average absolute gap} a month across {N} month(s). Fix the wiring
before trusting the forecast money.
T1 September has a forecast snapshot around −R 12.9 m (the same order as the Forecast headline’s −R 13.1 m / −R 12.2 m) and a settled net of −R 469 k. The gap is about R 12.5 m. The plan assumed leftover supply would keep losing money at forecast scale; the ledger only bought 460 MWh and then booked a 7.2 GWh paper sale. Neither number is the one you want — and they are not the same number.
Empty SVG. When no month in the window has a snapshot or a statement: No forecast snapshots or settled statements in the last six months yet.
Pick August and the window is March–August. September’s snapshot drops off the right. July and August then have settled nets (about −R 196 k each) and usually no matching P50 snapshot — the verdict falls back to No month has both… until a snapshot lands in that window.
6A.14 The three moves — Outcomes only
The problem. After you have read the warehouse you still need one obvious next click. Forecast solved that with a single Desk line. Outcomes keeps a three-card strip.
#book-moves. Three columns from
lg. Each card is [data-role=book-move] with
data-key. The first card has the brand border. Open
› is the door. The worth figure sits on the right.
This strip does not render on Forecast or Rules. Do not look for it under the Forecast ledger. Do not remove it from Outcomes to “match” Forecast.
| Key | Title | Body (product copy) | Worth | Open › goes to |
|---|---|---|---|---|
cover_sale |
Cover or cancel the uncovered sale | {sold} sold on paper against {bought} bought. Either supply legs are missing from settlement or a sell leg should not be active. | The month’s compact net. Note: the month’s net | Same Outcomes month
(…/book?mode=outcomes&month=YYYY-MM) so you can open a
BREAK chain |
reconcile |
Reconcile forecast to ledger | Check which supply members have settlement periods; the Rules board shows the ones that never settle. | — · wiring | Book · Rules
(…/strategy/pools) |
dashboard |
Read the six-month story | The Dashboard carries these months forward: margin, spill, and who the counterparties were. | — · history | Dashboard (…/strategy/dashboard,
#strategy-tab-dashboard) |
cover_sale is omitted when the book
check is missing or the month is balanced. August on T1 therefore shows
two cards (Reconcile, Dashboard) in the three-column
grid. September shows all three. The first September card is the
cover-or-cancel one, worth R 469 k.
There is no fourth card for Nominations. Nominations is not a strategy-nav tab. The thread strip already sits above the page.
6A.15 Empty states, refusals and what this page is not
The problem. A quiet page is easy to misread as “the book is fine.” These are the empty and partial states the LiveView actually paints.
| State | What the page does |
|---|---|
| No statement for the month | Dashed panel: No settled statement for {Month Year}. No conservation chart, no money card, no buy/sell tables. Chains and drift still render |
| Statement with zero legs | Headline rule 2. Bars at zero. Nothing sold this month. Buy/sell tables show their empty copy. T1 June |
| Buy-only month | Green warehouse badge. Sell table: No settled sell legs this month. Chains empty. Two move cards. T1 August / July |
| Unbalanced month | Rose badge, red tail, three move cards. T1 September |
| No chains | #chains-empty: No chains for this month |
| Unbalanced filter hides every row | #chains-empty: No chains for this month (unbalanced
filter on) |
| No chain selected | Dashed Select a chain to study the volume bridge and margin. |
| No drift points | No forecast snapshots or settled statements in the last six months yet. |
| DRAFT periods | Still in the statement. Chips can read balanced / not balanced before anyone presses FINAL. September on T1 is this state — do not treat it as a closed warehouse |
| REVERSED periods | Dropped. A reversed re-run is not a trade |
| Nothing in the last six months | Thread: Nothing settled yet. Issues rail: Nothing has settled yet |
What Outcomes does not do
- It does not re-price or re-settle a PPA.
- It does not run the engine. There is no New run here.
- It does not show another party’s confidential retail price.
- It does not persist an issued chain report. The recomputed stamp is “as of this open.”
- It is not Market Operator file reconciliation (V9).
- It is not the Forecast
#book-movesstrip, because Forecast has none.
What to do next on T1
- Believe the strip: the last month with energy is September, −R 469 k, not balanced. Do not quote August · −R 381 k from an older Overview pass.
- Pick August when you want a clean FINAL buy-only month (186 MWh, −R 196 k, warehouse holds).
- Pick September when you want the 7.2 GWh paper sale. Read the red tail, then open the BREAK chain, then press Cover or cancel the uncovered sale.
- If Forecast still prices −R 12.9 m against a −R 469 k ledger, open Reconcile forecast to ledger and fix members on Rules before you trust the plan.
Where this is taught next. End-to-end path health on the same pool — §6B Chains. Per-contract settlement detail — V8 §12. The forward view — §6. Chain / trader P&L concepts — V8 §10.
6B. Settled Chains — end-to-end path health
Route:
…/trader-pools/<id>/strategy/book?mode=outcomes&month=YYYY-MM&chain=<period_id>
· Tab: Book · Mode: Outcomes, the
chains section (the old /chains route forwards here with
its month and chain)
The statement at the top of Outcomes (§6A) answers one warehouse question for the whole month: did I sell more than I bought? The Chains section under it answers a different question: for each path from a generator, through me (and maybe another trader), to an off-taker — does the energy story and the money story still make sense?
Think of Book as your warehouse stocktake. Chains is walking each delivery route on the map and checking that what left the plant can explain what arrived at the customer, after the losses and spill the deal allows — and that your margin on that route is the one you expect.
6B.1 The trader’s problem (in plain words)
You often have two (or more) PPAs that are each fine on their own:
- Leg A — you buy from an IPP.
- Leg B — you sell to an off-taker (or to another trader).
Opening either contract’s settlement page only shows that one deal. Nothing on that page proves the two legs still form one coherent trip. Energy can “leak” between them (more left the plant than can be explained by delivery + loss + spill), or one leg’s books can fail the sum-to-zero test while the other looks clean.
Chains finds those linked legs for the month, lays the path out, and lets you study a break without rebuilding a spreadsheet.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Org → Trader pools → T1 strategy → Allocation → Outcomes; the chains sit under the statement. Pick a month that has settled legs (e.g. July 2026 on full_demo). You should see the verdict strip, a chain list, and — after selecting a row — the rail, volume bridge, money, legs table and book check.
6B.2 How Chains differs from Book and from Runs
| Room | Question it answers |
|---|---|
Book · Forecast
(…/book?mode=forecast) |
What would the forward strategy engine do? |
Book · Outcomes — the statement
(…/book?mode=outcomes) |
For the whole month, did Σ sell ≤ Σ procured? |
Book · Outcomes — the chains
(…&chain=) |
For each linear path, does volume + ledger still hold? |
Chains only discovers linear paths (IPP → trader → … → off-taker). If you sell to two sinks from one buy, the engine may show one chain and leave the other sell for Book — that is called out in the book-check strip (§6B.8).
Deep theory (balanced meaning, investigation order, lifecycle mismatch) lives in V8 §10 and the screen walk in V8 §10.6. This chapter is the trader Strategy-tab guide: every card and every field.
6B.3 Page chrome (above the cards)
| Control | What it is | What it means |
|---|---|---|
| Title | Chains — {Month Year} |
Which calendar month you are reconciling |
| Subtitle | Pool name · “linear paths IPP → trader → … → off-taker · as recomputed now” | Reminds you these results are calculated when you open/change the month — not a saved audit file |
| ‹ › and month input | Step or pick YYYY-MM |
Changes ?month= and reloads chains |
| Unbalanced only | Toggle (turns red when on) | Hides healthy chains so you only hunt breaks |
The strategy shell tabs are Overview · Allocation · Simulations · Nominations · Dashboard · Exposure — same pool context as everywhere else in Strategy; the chains are a section of the Book's Outcomes mode, not a tab of their own.
6B.4 Verdict strip (month health)
White card under the title. Read it before you pick a chain.
| Field | Plain meaning |
|---|---|
| N chains | How many end-to-end paths the system found for your pool this month |
| N balanced | Paths that pass both checks: every leg’s ledger sums to R 0.00, and first-leg supply is at least last-leg delivered |
| N unbalanced | Paths that fail one or both checks (shown in red when > 0) |
| recomputed {date time} | When this page last ran the numbers — honest “as of now”, not an issued report |
If total is 0, the empty list explains: no multi-leg chains for that month (or the unbalanced filter hid everything).
6B.5 Chain list (left / master)
| Field on each row | Plain meaning |
|---|---|
| Path label | Who → who → who (e.g. generator name → You → off-taker). “You” is this trader pool |
| N legs | How many PPA settlement periods sit on that path (usually 2) |
| balanced / BREAK badge | Green = path OK; red BREAK = investigate this row |
Click a row to select it (?chain= becomes that chain’s
head period id). The selected row is lightly highlighted. Deep links
from a period detail page may pass any leg’s period id; the
screen still opens the whole chain.
When nothing is selected (empty month), the right side says: Select a chain to study the volume bridge and margin.
6B.6 Detail column — cards in reading order
Once a chain is selected, read top to bottom: warnings → picture of the path → volumes → money → per-leg table → warehouse cross-check.
Lifecycle mismatch (amber, only when needed)
Shows when one leg is FINAL and another is still DRAFT / PRELIMINARY (or similar). Plain meaning: do not treat those two closes as the same kind of truth. Fix or understand status first (V8 §10.5).
Investigation order (when the chain is broken or mismatched)
Numbered checklist (volume before money). Steps that look relevant to this break can highlight in red. It does not run actions for you — it is the order to work through.
The rail
A left-to-right cartoon of the path:
| Piece | Data | Plain meaning |
|---|---|---|
| Start node | Party label | Who energy enters from (often the IPP; may say You if you are the seller on a later hop) |
| Edge | ── {kWh} ──▶ |
Energy on that hop (delivered kWh for the leg) |
| Status chip | DRAFT / FINAL / … | How hard that leg’s settlement is |
| Σ=0 / Σ≠0 | Tick or red fail | Does that leg’s own ledger sum to zero? |
| Next node | Party label | Who receives that hop (You, off-taker name, or italic silhouette if you are not a party to that hop) |
Silhouette / italic nodes mean: you may see the kWh for the bridge, but not that stranger’s money — same privacy idea as statements.
Volume bridge
This is the study table: can supply explain delivery?
| Row | Plain meaning |
|---|---|
| First-leg supply | kWh that entered the chain at the first PPA (plant / source supply) |
| − permitted loss (x%) | Network loss allowed along the chain (factor shown when known) |
| − contract spill | Surplus the deal treats as spill, not delivery |
| − banked | Energy parked in banking adjustments instead of delivered now |
| = expected delivery | What should remain after those deductions |
| Last-leg delivered | What the final buyer actually received |
| Unexplained | Expected minus delivered. 0 ✓ (within 1 kWh) means the bridge closes. A non-zero red number is the named volume break — nothing is quietly swept under the carpet (g-unexplained-kwh) |
Money
| Row | Plain meaning |
|---|---|
| Formula line | Always: sell − buy − network borne = margin |
| Buy cost | What you paid on buy legs (shown as a cost) |
| Sell revenue | What you earned on sell legs |
| Network borne (you) | Network / UoS-style charges on your seat |
| {agreement} connection | Per-leg network amount (evidence only — not a “no double-count ✓” verdict) |
| Your margin | Your seats only on this chain — the number you care about commercially |
| Chain margin (optional) | All trader seats on the path; shown when it differs (e.g. trader–trader hop). Never treat chain margin as your P&L on a multi-trader path |
Legs table
One row per hop, in chain order:
| Column | Plain meaning |
|---|---|
| # | Order on the path (1 = head) |
| Leg | From → to labels |
| Agreement | PPA agreement reference (monospace) |
| Status | Settlement status chip |
| Supply | That period’s supply kWh |
| Delivered | That period’s delivered kWh |
| Σ ledger | Sum of line items on that period; ✓ if zero, ✗ if not — names a broken leg |
| Period / Ledger | Drill into existing contract rooms (only on legs you are party to) |
| hidden | Shown instead of links when the leg is a silhouette for your seat |
Book check strip
| Field | Plain meaning |
|---|---|
| received … ≥/< supplied … ✓/✗ | Your whole-month warehouse check (same spirit as Book): energy you took in vs energy you pushed out |
| Fan-out notice (amber, when needed) | “N sell leg(s) are not part of any linear chain — book view covers them.” Linear discovery missed a fork; open Book |
| Book → | Jump to §6A for the same month |
6B.7 How to use the screen when something is red
- Read the verdict — how many breaks this month?
- Turn on Unbalanced only if the list is long.
- Open a BREAK row.
- If Lifecycle mismatch shows, stop comparing FINAL to draft numbers.
- Read the rail — which hop shows Σ≠0?
- Read Unexplained on the bridge — that quantity is the volume story.
- Only then trust Your margin on the money card.
- Use Period / Ledger links to prove a single leg in the full settlement UI (V8 §12).
- Confirm Book check still agrees with the warehouse.
6B.8 Book check strip and fan-out
Chains never pretends to list every commercial relationship you have. It lists linear discovered paths. Book still owns fan-in / fan-out aggregates. When the strip warns that sell legs sit outside any chain, that is expected for some books — not a silent failure of Book.
6B.9 What this screen does not do
- It does not re-price or re-settle a PPA.
- It does not persist an “issued” chain report (Phase 1 recomputes on open; the monthly runner only logs unbalanced chains).
- It does not show another party’s confidential retail price.
- It is not Market Operator file reconciliation (V9).
Where this is taught next. Mechanism and worked bridge numbers — V8 §10. Screen blocks in settlement vocabulary — V8 §10.6. Warehouse aggregate — §6A.
7. How the engine allocates (what a run actually does)
Before reading a run detail, it helps to know the walk the engine performs for every hour of the period. It is deterministic — same inputs, same result, always — and it has two hardwired stages followed by the configurable merit order:
7.1 The allocation walk
Build the hour's supply stack. Every active supply member contributes its forecast (or nominated) kWh for this hour, capped by MW caps. The stack is merit-ordered: pool priority first (Solar 10 before Wind 20 before Flexible 30 before Firm 40 in the seeded book), then cheapest buy price first within a pool, then member priority.
Serve firm demand first — hardwired. Demand pools flagged firm are served before anything else, and they draw on FIRM-pool supply first, then whatever else remains. This is not a rule you can reorder or delete; it is the invariant that your contractual must-serve obligations are always covered before discretionary sales. It is also why the seeded Firm supply pool sits last in the open merit order — it is being held in reserve for exactly this step.
Serve open demand in priority order. Remaining demand pools are walked by priority (Industrial 10, Commercial 20, Municipal 30…). Each pool drains the supply stack in merit order; members at the same priority share pro-rata (§5.4). Pool rules (
MW_CAP,PRICE_OPTIMISE,NOMINATION…) apply as each edge is drained.Whatever supply is left is spill; whatever demand is left is shortfall. Spill is routed to the pool's spill destination and valued at the member's spill value (zero if unset) — for take-or-pay supply that margin is negative: you paid for energy with no buyer. Shortfall on firm demand is priced as a grid top-up: buy at the member's shortfall top-up c/kWh, sell at the contract rate — usually a locked-in loss that the engine makes visible rather than hiding.
7.2 How each flow is priced
Every allocation line prices its energy the way settlement would:
- Buy price = contract base c/kWh × the hour's TOU multiplier × the compounded escalation factor (from the PPA's start date and escalation mechanism), clamped to the contract's floor/cap. The line stores every one of those components separately, so any price can be traced.
- Sell price — from the sell contract the same way; for trader-margin sales, sell = buy + fixed margin, or buy × (1 + margin %), per the trader terms.
- Wheeling — the per-edge network charge, on delivered energy.
- Losses —
kwh_delivered = kwh_sent × DLF. You pay the buy price on sent energy and earn the sell price on delivered energy, so the loss factor quietly eats into the margin of every line — exactly as it does at settlement. - Margin (R) = revenue − energy cost − wheeling, per line; every KPI on every screen is a sum of these.
The scenarios below use one-hour slices so every quantity can be followed from the allocation decision to the line price. Together they cover the five line kinds you will meet most often: normal allocation, firm shortfall, spill, battery charge and battery discharge. Each scenario opens with a one-sentence plain reading; the maths underneath is unchanged. After the fourth scenario, §7.2.5 puts all four on one simple picture.
7.2.1 Scenario 1 — midday solar with network losses
In plain words. You buy cheap midday solar, lose a little on the wires, sell what arrives to a factory for more — and keep the difference as profit.
A Solar-pool PPA is first in merit order at 12:00. It buys at 65 c/kWh; the Industrial-pool factory pays 120 c/kWh; wheeling is 15 c/kWh; and the edge DLF is 0.966. The factory needs at least the available solar quantity, so the whole 16,710 kWh is sent.
The important detail is that revenue and wheeling use
delivered kWh, while the PPA cost uses
sent kWh. The run therefore records
kwh_sent = 16710, kwh_delivered = 16141.86,
buy = 65, sell = 120,
wheeling = 15 and margin = R 6087.45. The
568.14 kWh network loss is not a separate spill line; its cost is
already visible in the lower delivered quantity and effective buy price
of 65 ÷ 0.966 = 67.29 c/kWh.
7.2.2 Scenario 2 — partial firm cover and grid top-up
In plain words. A must-serve buyer needs more than your reserved firm supply. You still cover them — the gap comes from expensive shortfall top-up — so the customer is served but the hour can lose money.
At 19:00 a firm buyer needs 5,000 kWh, but the reserved Firm-pool block has only 3,000 kWh. The contracted block costs 140 c/kWh, sells at 160 c/kWh and wheels at 8 c/kWh with DLF 1.0. Because the destination is firm, the remaining 2,000 kWh becomes a priced grid top-up at the member's 225 c/kWh shortfall top-up rate.
The run writes two lines: an ALLOCATION line for the
3,000 kWh contracted flow, and a SHORTFALL line for 2,000
kWh with buy = 225 and sell = 160. A non-firm
demand shortfall has no automatic replacement purchase and therefore
records zero realised margin rather than this top-up loss. This
distinction is why the firm flag and the shortfall top-up rate must be
correct.
7.2.3 Scenario 3 — a profitable sale with loss-making spill
In plain words. You sell some of the night wind at a profit, but the rest has no buyer. You still paid for that leftover energy, so the hour loses money overall.
At 02:00 a take-or-pay Wind member produces 8,000 kWh at 82 c/kWh. Open demand can take only 5,000 kWh at 125 c/kWh; wheeling is 12 c/kWh and DLF is 1.0. The remaining 3,000 kWh has a spill value of only 10 c/kWh.
The first 5,000 kWh creates a normal ALLOCATION line.
The remainder creates a SPILL line with no destination and
no wheeling: recovery of R300 less the R2,460 energy cost gives
−R2,160. This is why a positive allocation margin does
not guarantee a profitable hour. It also explains why spill limits, ToP
utilisation (§12.3) and a useful battery
charge outlet matter.
7.2.4 Scenario 4 — the book holds a battery
In plain words. Soak up free leftover midday solar into the battery, then use it in the evening instead of buying expensive top-up — move free waste into expensive need.
This book has an active 4 MW / 10 MWh battery at its minimum SoC, 90% round-trip efficiency, 8 c/kWh degradation cost and a 20 c/kWh minimum spread. Pass A finds 4,000 kWh of zero-valued solar spill at 12:00 and a firm shortfall worth an avoided 220 c/kWh at 19:00. The dispatcher tests:
spread = 220 − 0 ÷ 0.90 − 8 = 212 c/kWh ≥ 20 —
dispatch.
The charge produces a BESS_CHARGE line with
buy = 0 (the foregone spill value) and zero margin;
charging only positions the battery. The absorbed 4,000 kWh is removed
from the original spill quantity. The evening
BESS_DISCHARGE line uses a stored marginal cost of
charge cost ÷ η_rt + degradation = 8 c/kWh, a discharge
value of 220 c/kWh and margin R7,632. If the same energy had been bought
from surplus PPA supply at 60 c/kWh rather than zero-valued spill,
stored cost would be 60 ÷ 0.90 + 8 = 74.67 c/kWh and the
3,600 kWh discharge margin would fall to approximately
R5,232.
This is the pricing view of the book-level two-pass. The next section explains how Pass A, dispatch and merge produce these battery lines over the whole month; the BESS screen then shows the same movements as an SoC schedule.
7.2.5 Four scenarios at a glance
Strip away the c/kWh arithmetic and the four stories are one simple loop: match supply to demand → price what matched → name what was left over → (optional) move leftovers in time with a battery.
1 · Sold cleanly — ALLOCATION
Buy cheap → lose a little on the wires → sell higher
Result = profit on the matched energy
2 · Must serve, not enough — SHORTFALL
Firm buyer needs more than reserved supply
Result = customer still served · hour may lose money on top-up
3 · Bought, nobody took it — SPILL
Part sold at a profit · leftover still paid for
Result = good sale can sit inside a losing hour
4 · Move waste to need — BESS
Charge free midday leftover → discharge into evening firm gap
Result = avoid expensive top-up · earn the spread
| If you see… | Plain meaning | Line kind |
|---|---|---|
| Energy matched buyer ↔︎ seller | A normal wheeled sale | ALLOCATION |
| Firm buyer still hungry after the stack | Grid (or replacement) filled the gap | SHORTFALL |
| Supply left with no buyer | You paid for energy nobody took | SPILL |
| Battery soaking midday / helping evening | Waste moved to need across hours | BESS_CHARGE / BESS_DISCHARGE |
| Line kind | Quantity shown | Buy / value provenance | Margin treatment |
|---|---|---|---|
ALLOCATION |
Sent and delivered kWh | Source contract buy; destination contract sell; edge wheeling | Delivered revenue − sent energy cost − delivered wheeling |
SHORTFALL |
Unserved demand kWh | Firm: shortfall top-up buy and contract sell | Firm replacement loss/profit; non-firm records zero realised margin |
SPILL |
Unallocated sent kWh | Source buy versus configured spill recovery | Recovery − sunk supply cost; no wheeling |
BESS_CHARGE |
Battery input kWh | Foregone spill value, surplus-PPA cost or allowed grid cost | Zero on charge; economics are realised on discharge |
BESS_DISCHARGE |
Battery output kWh | Stored marginal cost versus avoided top-up or sale value | Output × (discharge value − stored marginal cost) |
7.3 When the book holds a battery — the two-pass
In plain words. First measure the book without the battery — where energy is wasted and where buyers are short. Then ask the battery to move that waste into those shortages. Then write the schedule into the run as charge and discharge lines.
A battery's value is time: charge when energy is
cheap or leftover, discharge when it is expensive or missing. That
decision is only honest if the engine already knows what the
rest of the book would do alone. So when the book has an active
BessAsset (§11.3),
each run becomes a two-pass (three steps: discover →
schedule → merge). Without a battery, the engine still takes the single
walk in §7.1 — nothing
changes.
A · Pass A — value discovery
Run the full month as if no battery existed
Output = hour-by-hour spill and shortfall “price tags”
Purpose = show the battery what it can trade against
B · Dispatch — the schedule
Day by day, pick charge→discharge pairs that clear the spread rule
Output = SoC walk + every move (and every held pair)
Purpose = turn opportunity into a physical plan
C · Merge — write it into the run
Add BESS_CHARGE / BESS_DISCHARGE lines; shrink absorbed spill
Output = final run lines + dispatch intervals (the battery fold in Book · Forecast, and the dispatch page)
Purpose = one auditable result the KPIs can sum
Why the battery is left out of Pass A
If the battery sat in the ordinary merit stack, it would compete for the same kWh it is later asked to absorb — circular and unstable. Pass A therefore allocates with the battery excluded. What remains is the book's raw shape:
- Spill hours — leftover supply and what that leftover was still worth (often 0 when spill is zero-rated).
- Shortfall / unmet hours — firm gaps priced at avoided shortfall top-up, or open demand priced at the sale you would otherwise have made.
Those two vectors are the charge-cost and discharge-value ladders the dispatcher reads (§11.2). Pass A does not invent battery economics; it only paints the opportunity surface.
What dispatch does with that surface
For each calendar day in the run period the dispatcher:
- Builds candidate charge hours (cheapest sources first: spill → surplus PPA → grid if allowed) and discharge hours (highest outlets first: firm shortfall → peak sale → standard sale).
- Tests charge→discharge pairs with the spread rule — only pairs that clear efficiency, degradation and your minimum spread are taken, highest spread first.
- Respects physics: power limits, SoC floor/cap, round-trip losses, and the daily cycle cap.
- Rolls end-of-day SoC into the next morning so a month is one continuous battery story, not 30 isolated days.
Pairs that look profitable but fall under the minimum are held and later listed on the rejected-pairs strip — the audit of what the battery declined. Deep arithmetic and a full weekday walk live in §11.2; here the point is only that dispatch consumes Pass A, it does not re-allocate the book from scratch.
What merge changes on the line list
Merge is bookkeeping with consequences:
| After merge… | What changes |
|---|---|
New BESS_CHARGE lines |
Energy into the battery; margin 0 (positioning only); buy = charge cost (often 0 from free spill) |
New BESS_DISCHARGE lines |
Energy out; buy = stored marginal cost; sell = discharge value (e.g. avoided top-up); margin = realised arbitrage |
Existing SPILL lines |
Quantity reduced by whatever the battery absorbed — stored energy is no longer counted as waste |
Pass-A SHORTFALL lines |
Left as the discovery record; the economic cover appears on
BESS_DISCHARGE, not by rewriting the shortfall row |
| Dispatch intervals | Every active hour persisted for the run's battery fold and the BESS screen (§11.4) |
Ordinary ALLOCATION lines from Pass A stay; the battery
does not rewrite sales that already matched. It adds
storage movement, subtracts absorbed spill, and
realises the shortfall-avoidance value on the discharge line.
Worked example — one day through all three beats
Same numbers as §7.2.4: 4 MW / 10 MWh battery, η_rt 90%, degradation 8 c/kWh, min spread 20 c/kWh, starting at the SoC floor.
Pass A finds (battery absent):
| Hour | Kind | Quantity | Price tag the battery sees |
|---|---|---|---|
| 12:00 | SPILL |
4,000 kWh solar leftover | foregone value 0 c/kWh (free charge) |
| 19:00 | SHORTFALL |
firm gap | avoided top-up 220 c/kWh (valuable discharge) |
Dispatch decides:
spread = 220 − 0 ÷ 0.90 − 8 = 212 ≥ 20 → take the pair.
Charge 4,000 kWh at 12:00 (≈ 3,600 kWh recoverable after round-trip);
discharge 3,600 kWh at 19:00 into the firm gap.
Merge writes:
| Line | Sent / moved | Buy | Sell | Margin |
|---|---|---|---|---|
BESS_CHARGE @ 12:00 |
4,000 kWh in | 0 c/kWh | — | R 0 (positions only) |
BESS_DISCHARGE @ 19:00 |
3,600 kWh out | 8 c/kWh stored | 220 c/kWh | R 7,632 |
SPILL @ 12:00 |
reduced by 4,000 kWh | — | — | that leftover is no longer waste |
Pass-A SHORTFALL @ 19:00 |
still on the books as discovery | — | — | cover value sits on the discharge line |
That is the whole two-pass story for one day. Over a month the same
loop repeats, with SoC carrying from day to day. The run detail's
BESS tab shows that run's frozen schedule (§8.4). The /strategy/bess page walks
the latest Forecast that already has intervals (§11.11); the chart-reading guide
stays in §11.4.
Properties worth knowing
- A battery-free book is completely untouched — same lines, same KPIs, same inputs hash as a world without Phase 2. The two-pass only engages when an active battery is a pool member.
- The battery's configuration is part of the run's inputs hash — change minimum spread, cycle cap, efficiency or degradation and the next run provably ran with different inputs.
- Saving asset config never rewrites an old run — immutability still holds; you must re-run to see new dispatch (§1.3).
- Hypothetical / what-if paths can skip dispatch — ephemeral workbench runs may allocate without persisting BESS intervals; production forecast and nomination runs that see an active battery take the full two-pass.
Where the dispatcher is taught. Spread rule, charge/discharge ladders, SoC walk and rejected pairs: §11. This section only explains how that schedule is produced inside a run.
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-07-18 against the full_demo manifest.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Run a forecast for T1 Renewables Pool, then open run detail → BESS (or Strategy → BESS) to see Pass-A opportunities turned into charge/discharge intervals for that run.
8. Run detail — the engine made visible
The trader’s problem. A Forecast tile can say the month loses R 13.1 m. That number is a sum. You need the floor where every kilowatt-hour that made the sum is written: who supplied whom, in which SAST hour, at which buy / sell / wheeling price, under which rule.
Route:
/org/trader-pools/:trader_pool_id/strategy/allocations/:run_id
· Tab: Book (#strategy-tab-book stays lit
on #strategy-nav). This is not a fifth top tab. The page
subtitle is Run detail — hourly allocations, spill, shortfall and
margin.
How you arrive. From Book · Forecast, Open
the run ledger › under the run picker or inside
#book-ledger-fold (§6.18). Overview does not open this
URL; it sends you to Forecast first (§4). The click path is §8.6.
← Pool · Forecast
(#allocation-back-to-forecast) returns to Forecast for this
pool, this run’s month, and this run id. Clicking
Allocation on the nav bar does not do that —
it opens Rules.
What it is for. This is the run ledger — the audit floor. Every KPI anywhere in the module is a sum over the lines shown here; when a number surprises you, this screen is where you find out why — down to the hour, the member pair, the price components and the rules that fired. On an Actual run that has a paired Forecast, the green Forecast vs settled actual panel (§8.2) sits above the day chart so you score the plan before you dive into a single day. How the engine decides a line is §7; this chapter only teaches the page that shows those lines.
8.1 Header
Above the badges, ← Pool · Forecast
(#allocation-back-to-forecast) opens Book · Forecast for
this trader pool, the run’s month, and this run — you do not need the
browser Back button. The href is
…/strategy/book?mode=forecast&month=YYYY-MM&run=<run id>
(month is the first day of the run period as YYYY-MM).
Scenario + status badges, the run period, and the inputs
hash — the reproducibility fingerprint (inputs hash, §1.3). It
covers the book, scenario, period, every pool and member with all their
pricing terms and caps, the forecast versions, the network edges — and
the battery parameters when one is present. Change any of those and the
hash changes; two runs with the same hash produce identical results. The
short hash (#run-hash-short) toggles the full value
(#run-hash-full) on click (#run-hash-toggle);
the clipboard icon (#copy-run-inputs-hash)
copies the full hash in one action (tooltip: Copy full inputs
hash). A superseded run shows an amber banner (“This run is
superseded by a newer run for the same period.”); a failed run
shows the error in red (§8.7). An
ACTUAL run also shows the Settled chip.
The header period prints period_start through the last
calendar day of the window (period_end minus one day), for
example 01 Sep 2026 – 30 Sep 2026. The Audit tab prints
the raw period_start → period_end
(2026-09-01 → 2026-10-01).
8.2 Forecast vs settled actual
In plain words. After meters settle and you run a backcast (§6.2), open the Actual run. A green panel asks one question: how did reality differ from the forecast we used for the same month?
This panel appears only on a complete Actual run
that still has a matching current Forecast for the same delivery
period (same period_start /
period_end, non-superseded, complete). Forecast-only and
Nominated runs do not show it — there is nothing settled to score
against. If the Forecast for that month was superseded and never
replaced, the panel is absent until a current Forecast pair exists
again.
Same delivery period (top-right notice)
The small label same delivery period is not
decoration. It confirms the engine paired this Actual with a Forecast
whose calendar window is identical — June with June, not June with May.
Without that guarantee the Δ tiles would mix different months and look
like "forecast error" when they are really period mismatch. If you ever
doubt the pair, check both rows on the Runs index: same month label, one
FORECAST, one ACTUAL.
The four Δ tiles — what each number means
Each tile is Actual KPI minus Forecast KPI for the
whole month. A leading + means Actual was higher; a minus
means Actual was lower. Units are R for margin and
% for the three ratio deltas (the change in each
percentage KPI — e.g. 81.3% → 81.1% shows as −0.2
%).
Margin Δ (R)
Actual margin_r − Forecast margin_r
+ means the settled month earned more Rand than the plan expected
− means the plan overstated commercial outcome
Use it as the commercial headline: did meters leave you richer or poorer than the operating forecast?
Coverage Δ (%)
Actual coverage_pct − Forecast coverage_pct
+ means a larger share of demand was met by allocated supply
− means a smaller share was met (more relative gap)
Coverage is allocated ÷ demand. Both numerator and
denominator can move when meters arrive, so a tiny Coverage Δ can hide
big volume moves — always read it with Spill and Shortfall.
Spill Δ (%)
Actual spill_pct − Forecast spill_pct
+ means a larger share of supply went unsold
− means less relative waste than the plan
Spill is spill ÷ supply. Higher Actual spill often means
generation beat the shape or demand under-ran — the overlay
chart and Spill tab say which hours.
Shortfall Δ (%)
Actual shortfall_pct − Forecast shortfall_pct
+ means a larger share of demand was left unmet by the stack
− means the book covered relatively more of load
Shortfall is shortfall ÷ demand. Firm hours with higher
Actual shortfall are the expensive top-up story; open the Shortfall tab
after you spot the shape on the charts.
How to read a mixed signal. The June 2026 T1 gallery pair (§6.2) is the pattern to expect: Margin Δ +R 21,500 while Coverage Δ −0.2 %, Spill Δ +0.3 %, Shortfall Δ +0.3 %. Plain reading: the month made more money even though residual shares were slightly worse — prices and mix helped more than volume residuals hurt. The tiles give that verdict in four numbers; the charts and tabs prove it.
The overlay chart — why it exists
Under the tiles sits a two-line chart: Forecast vs Actual, hour-of-day 00h–23h on the x-axis. A chart legend at the top of the panel names the colours before you read the picture:
Gold line — Forecast (planned allocated energy).
Sky line — Actual (settled allocated energy).
Green band — hours where Actual sits above Forecast: more wheeled kWh settled than the plan expected that hour.
Red band — hours where Actual sits below Forecast: less wheeled kWh settled than planned that hour.
Each point is the month total of allocated (
ALLOCATION) sent kWh summed into that SAST hour across every day of the run. It is not one day and not a pool stack — it is the book's shape fingerprint for the period.The two lines answer: when we thought energy would wheel versus when meters say it did. Midday green means solar/load came in heavier than planned at noon; evening red means the plan overstated evening wheeled volume.
Why you need it. The Δ tiles are month scalars — they cannot show when the miss happened. Shape error (wrong hours) drives different actions from volume error (right shape, wrong scale): nominations, battery dispatch, and procurement all care about the hour.
| Forecast vs settled overlay (this panel) | Day stacked chart (§8.3) | |
|---|---|---|
| When you see it | Only on Actual runs with a paired Forecast | Every complete run |
| Time scope | Whole run period, rolled into 24 hour-of-day buckets | One selected SAST day (◀ day ▶) |
| What is plotted | Two totals: Forecast allocated sent kWh vs Actual | Supply pools stacked + demand line |
| Question it answers | Did the shape of wheeled energy match the plan? | In this day, who filled whom, and where did spill/shortfall sit? |
| Use it to | Score forecast accuracy; find systematic hour biases | Debug a day; open tabs for the lines behind the picture |
They are complementary, not duplicates. Read the overlay first for "was the month's shape honest?"; then page the day chart to "show me Tuesday 19:00 inside the Actual run."
Proxied members (amber line)
When the Actual engine cannot find settled meter rows for a member, it falls back to that member's forecast energy and marks the member proxied. Those membership ids are stored on the run KPIs and listed under the overlay in amber:
Proxied members: Solar · IPP-A, Industrial · Factory, …
In plain words. Some sites in this Actual still used plan shapes because meters were missing — treat those sites' "actual" as incomplete.
- If the list is empty, every active member had meter energy; the comparison is fully settled.
- If names appear, the month-level Δ and overlay still run, but those members pull the Actual toward the Forecast (they cannot create meter surprise). Prefer fixing meter coverage before you rewrite contracts off that backcast.
- A backcast that would proxy everyone does not create an Actual at all — you get the flash that settled data is not available (§6.2).
What to do with the panel
- Confirm same delivery period and that the Settled chip is on.
- Read the four Δ tiles for the commercial and residual verdict.
- Scan the overlay for hour bands where Actual peels away from Forecast.
- Note any Proxied members before trusting the miss.
- Use
◀ day ▶and the stacked chart below — plus Spill / Shortfall tabs — to turn a hour-of-day bias into concrete lines.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Strategy → Runs → filter Actual (settled) → June 2026 → Open →. You should see the green Forecast vs settled actual panel above the day chart, with Δ tiles matching the §6.2 snapshot arithmetic.
8.3 Day selector + chart
Runs cover a month; the screen shows one SAST day at
a time (◀ day ▶). On Actual runs this chart sits
under the Forecast-vs-settled overlay (§8.2) — different job: the
overlay scores month shape; this chart anatomises one day. The
stacked-area chart shows each supply pool's delivered kWh stacked per
hour, with the demand line overlaid — you can literally see the solar
hump fill the daytime load and the gap left in the evening. Reading it
takes three seconds: stack above the line = spill hours; line above the
stack = shortfall hours; the vertical order of the bands is the merit
order at work.
The examples below show how the chart represents each pricing scenario in §7.2. They are deliberately small slices of a day: the live chart shows the same relationship across all 24 SAST hours. Hover the relevant hour in the application to see the exact kWh and the allocation lines behind it.
- Midday solar with network losses
Read it: the solar band meets the demand line. The 568 kWh loss is already excluded because the chart stacks delivered kWh; inspect the Allocation row for sent kWh and DLF.
- Partial firm cover and grid top-up
Read it: the line clears the stack by 2,000 kWh. For
firm demand, that gap produces the priced SHORTFALL top-up
line; it is not another coloured supply band.
- Profitable sale with loss-making spill
Read it: the stack sits above the demand line. The
5,000 kWh below the line is the normal sale; the red cap is the 3,000
kWh SPILL line with its separate recovery value.
- Battery turns midday spill into evening cover
Read it: the dashed gold wedge is solar spill sent to
BESS_CHARGE; the purple band at 19:00 is
BESS_DISCHARGE covering the firm outlet. The fine gold line
is the SoC direction, not energy delivered.
8.4 Tabs
| Tab | What you see | What to use it for |
|---|---|---|
| Allocations | The tagged flows: SAST hour (sun/dark), source and destination as colour-coded pool · member badges (line-kind icon on Source), kWh sent and delivered, buy/sell/wheeling c/kWh, margin (R), rules, and a day total footer. Empty: *No allo | cations this day.* The "who supplied whom at what price" record. Check a specific contract is being drained in the order you intended; verify a rule fires (Rules column). |
| Spill | Supply hours nobody bought: Hr, source, unsold kWh, spill value, sunk cost, margin, and a day total footer. Empty: No spill this day. | Find when and from which member you're losing money on unsold energy — the shape you'd take to the workbench to sell (or feed to a battery). |
| Shortfall | Demand hours nobody supplied: Hr, destination, unserved kWh, firm Yes/No badge, top-up cost, margin, and a day total footer. Empty: No shortfall this day. | Find the hours you're buying from the grid at top-up rates — the shape you'd take to the workbench to buy against (or back with a battery). |
| Margin | Two side-by-side cards: Margin by TOU and Margin by source pool (each with Margin, Share %, and a Total footer). | Answer when the book earns or loses (TOU), and which supply pool earned the allocation margin — the two cuts answer different workbench questions. |
| Audit | Provenance card: inputs hash (with copy), scenario badge, grade, period, requested by, started, completed, duration, margin (R) and coverage. | The frozen identity of the run for governance and disputes — not a second KPI dashboard. |
| BESS | (only when the run dispatched a
battery) The same day view as /strategy/bess (§11.11): facts, dispatch chart
(§11.4), moves, hourly schedule
and rejected pairs — frozen t |
o this run's intervals.
Audit exactly what the battery did inside this specific run — the
schedule that produced this run's BESS_* lines. Use this
tab when the standalone page bound a different Forecast. |
Annotated samples. Every label in the views below has a red numbered marker. Match it to the red-arrow callout immediately beneath the sample; these are illustrative values, not a second run.
Allocations sample view
| Hr 1 | Source 2 | Dest 3 | Sent 4 | Delivered 5 | Buy 6 | Sell 7 | Whl 8 | Margin 9 | Rules 10 |
|---|---|---|---|---|---|---|---|---|---|
| ☀ 12 | ⇄ Solar · IPP-A | Industrial · Factory | 16,710 kWh | 16,142 kWh | 65.0c | 120.0c | 15.0c | R 6,088 | merit_order |
- 1Hr is the SAST settlement hour, with a sun or moon mark for daylight (06–17) vs dark (00–05 and 18–23).
- 2Source is the supplying pool and member as colour-coded badges; the small icon before the badges is the line kind (there is no separate Kind column).
- 3Dest is the receiving pool and member as colour-coded badges.
- 4Sent is injected energy; the buy cost is charged on it.
- 5Delivered is energy after DLF losses; sell and wheeling use it.
- 6Buy is the source or stored-energy cost in c/kWh.
- 7Sell is the destination contract or discharge value in c/kWh.
- 8Whl is the edge wheeling charge in c/kWh.
- 9Margin is the line’s realised Rand contribution.
- 10Rules records the allocation provenance. A Total footer sums Sent, Delivered and Margin; Buy / Sell / Whl show volume-weighted averages for the day.
Spill sample view
| Hr 1 | Source 2 | Unsold kWh 3 | Spill value 4 | Sunk cost 5 | Margin 6 |
|---|---|---|---|---|---|
| ☾ 02 | Wind · PPA-W | 3,000 | 10.0c | R 2,460 | −R 2,160 |
- 1Hr pinpoints when the supply could not be placed (SAST hour with the same sun/dark mark as Allocations).
- 2Source identifies the affected pool and member.
- 3Unsold kWh is the remaining sent energy after allocation.
- 4Spill value is the configured recovery price per kWh.
- 5Sunk cost is the source-energy cost already incurred.
- 6Margin is recovery less sunk cost; no wheeling applies.
Shortfall sample view
| Hr 1 | Destination 2 | Unserved kWh 3 | Firm 4 | Top-up 5 | Margin 6 |
|---|---|---|---|---|---|
| ☾ 19 | Firm · Evening Buyer | 2,000 | Yes | 225.0c | −R 1,300 |
- 1Hr is the SAST hour with sun/dark marking (same legend as Spill).
- 2Destination is the pool and member still needing energy, as colour-coded badges.
- 3Unserved kWh is the gap after normal allocations.
- 4Firm says whether the gap must be replaced.
- 5Top-up is the member’s Eskom replacement cost in c/kWh.
- 6Margin is realised only for a firm replacement; non-firm remains zero. A Total footer sums Unserved kWh and Margin; Top-up shows a volume-weighted average.
Margin sample view
The Margin tab is two cards, not one cross-tab. Each cuts realised Rand margin on a different axis so you can answer two questions without mixing them.
- Margin by TOU answers when money is made or lost — off-peak, standard, or peak. It includes every line kind (allocations, spill, shortfall, and curtailment when present), so evening top-up losses and unsold-energy write-downs appear in the period that caused them. Its Total matches the run’s headline margin.
- Margin by source pool answers which supply book earned the allocation margin. It groups allocation lines only by the supplying pool — spill and shortfall are left out of this card on purpose, because they are residual shapes you take to the workbench, not supply that cleared a buyer.
We keep the cuts separate because a single pool×TOU matrix hides the headline: most books earn the bulk of margin in standard hours off solar and lose money in peak on top-ups. The TOU card makes that time shape obvious; the source-pool card makes the portfolio shape obvious. Share % on each card is that row’s contribution to the card’s Total (100% in the footer when the total is non-zero).
Why the two Totals can differ. They are not required to match. TOU Total = sum of all line margins for the run. Source-pool Total = sum of allocation line margins only. Whenever spill, firm shortfall, or curtailment carries non-zero margin (common for spill: recovery less sunk cost), that Rand appears in the TOU card and not in the source-pool card. In the sample below the gap is spill (−R 2,160) plus firm shortfall (−R 940): TOU Total R 85,540 versus source-pool Total R 88,640. Equal totals only mean those residuals happened to contribute zero.
Margin by TOU
| TOU 1 | Margin 2 | Share 3 |
|---|---|---|
| standard | R 88,640 | 103.6% |
| peak | −R 940 | −1.1% |
| offpeak | −R 2,160 | −2.5% |
| Total 4 | R 85,540 | 100.0% |
Margin by source pool
| Source pool 5 | Margin 6 | Share 7 |
|---|---|---|
| Solar | R 86,240 | 97.3% |
| Firm | R 2,400 | 2.7% |
| Total 8 | R 88,640 | 100.0% |
-
1TOU is the tariff period bucket
(
offpeak,standard,peak). - 2Margin (left card) is realised Rand for that period across all line kinds.
- 3Share (left card) is that period’s percentage of the TOU Total — negative shares mean the period lost money against a positive total.
- 4Total (left card) is the run’s full headline margin (all line kinds). It can be lower than the source-pool Total when residuals lose money.
- 5Source pool is the supplying pool for allocation lines.
- 6Margin (right card) is realised Rand attributed to that supply pool’s allocations only.
- 7Share (right card) is that pool’s percentage of the source-pool Total.
- 8Total (right card) sums allocation margins by source pool. It excludes spill, shortfall and curtailment — so it need not equal callout 4. Here R 88,640 − R 85,540 = R 3,100 of residual margin sitting only in the TOU card.
Audit sample view
A two-column provenance card — the same fields as the Audit tab, in order. There is no Run ID row here (the URL already identifies the run); scenario is a colour badge, separate from grade; started and completed are separate rows with a derived duration between them; headline outcome is only Margin (R) and Coverage.
- Inputs hash 1
- 8b7f3c…a21d ⎘
- Scenario 2
- FORECAST
- Grade 3
- P50
- Period 4
- 2026-08-01 → 2026-08-31
- Requested by 5
- A. Ndlovu
- Started 6
- 2026-08-01 06:01:12Z
- Completed 7
- 2026-08-01 06:14:03Z
- Duration 8
- 12.9 min
- Margin (R) 9
- R 412,000
- Coverage 10
- 94.0%
- 1Inputs hash is the reproducibility fingerprint for book, terms, forecasts and network (§8.1). The clipboard control copies the full hash (tooltip: Copy full inputs hash) — same action as on the run header.
-
2Scenario is shown as the scenario badge
(
FORECAST,ACTUAL, or nominated) — not combined with grade. - 3Grade is the forecast grade used for the run (e.g. P50 / P90), or blank when not applicable.
-
4Period is the delivery window as
period_start → period_end. -
5Requested by records who initiated the run (or
—if unset). - 6Started is when execution began.
- 7Completed is when execution finished.
-
8Duration is derived from started → completed
(minutes, or
< 1 minwith seconds when under a minute). - 9Margin (R) is the run’s headline realised margin from KPIs.
- 10Coverage is the run’s coverage percentage from KPIs. Spill and shortfall are not repeated on this card — use those tabs or the run header KPIs.
BESS sample view · appears only after dispatch
Below the KPI strip and dispatch chart sits the schedule
table — one row per active hour for the selected day, with the
same sun/dark hour marks and row hover as Spill / Shortfall. Source uses
colour-coded badges (Spill, Contract,
Market). Every column except Hour carries an
i info tip (white tooltip) in the live UI; every column
is listed below.
| Hour 7 | Action 8 | kWh 9 | Source 10 | Outlet 11 | Forecast 12 | Cost 13 | Value 14 | Spread 15 | SoC 16 | Rationale 17 |
|---|---|---|---|---|---|---|---|---|---|---|
| ☀ 12 | charge | 4,000 | Spill | — | — | 0 | — | — | 3.80 | charge 4.0 MWh from spill @ 0c |
| ☾ 19 | discharge | 3,600 | — | firm | a1b2c3d4 · P50 | 17.0 | 210.0 | 193.0 | 0.40 | discharge 3.6 MWh @ 210c to firm |
Rejected pairs 18 · 13h → 21h · spread 16.1c < minimum · held
- 1Day margin — realised discharge margin for the selected day (Rand).
- 2Cycles/day — equivalent full cycles for the run: total discharged energy ÷ usable battery capacity ÷ days in the run period. One cycle means you discharged a volume equal to the usable capacity once. Compare it to the asset’s Max cycles/day (often 1.5) — the warranty ceiling the dispatcher will not exceed, even if more pairs look profitable (§11.1). Readings near that cap with pairs still held on the rejected-pairs strip argue for more capacity or less aggressive discharge, not for ignoring the warranty (§11.4, §12.6).
- 3Spill absorbed — share of spill converted into stored energy.
- 4Firm backing — share of output serving firm shortfall.
- 5End SoC — usable energy carried into the next day (MWh).
- 6Dispatch chart — charge bars below zero, discharge above, with SoC and price lines. Full reading guide: §11.4 · How to read the dispatch chart.
- 7Hour — SAST settlement hour with sun (06–17) or moon (00–05 and 18–23) mark; same legend as Spill.
-
8Action —
chargewhen energy enters the battery this hour,dischargewhen it leaves. - 9kWh — energy moved this hour (charge-in on charge rows, discharge-out on discharge rows).
-
10Source — where charge energy came from, as a
badge:
Spill(unsold book energy),Contract(contracted supply), orMarket(grid / market buy). Blank (—) on discharge rows. -
11Outlet — where discharge energy went:
contract,firm, ormarket. Blank (—) on charge rows. -
12Forecast — short price-forecast id and
confidence lane (e.g.
P50) when the hour used a market price forecast; otherwise—. - 13Cost — charge cost in c/kWh (0 for zero-rated spill). On discharge rows this is the stored marginal cost carried into the hour.
- 14Value — discharge value in c/kWh. Blank on charge rows (charging positions; it does not earn).
- 15Spread — value minus cost in c/kWh for the economics that cleared the min-spread rule (§11.2). Often blank on pure spill-charge rows.
- 16SoC — state of charge after the hour, in MWh (end-of-hour usable energy).
- 17Rationale — human-readable reason the dispatcher moved energy this hour (the audit sentence).
- 18Rejected pairs — charge→discharge pairs that looked profitable but were held because spread was below the configured minimum.
8.5 Reading a line
In plain words. Open a complete run → leave the Allocations tab selected (it is the default). Use
◀ day ▶until you see the day you care about. Each row in the table is one tagged energy flow for one SAST hour: who supplied whom, how much left the injector, how much arrived after losses, the three price legs in c/kWh, the Rand that flow contributed, and which engine rules produced it. If a KPI on the Runs index surprised you, this is the place that proves the number.
This section walks the Allocations table exactly as the screen shows it (§8.4 sample). Spill and Shortfall are separate tabs — they are not mixed into this table.
What you see before the columns
- Sun / dark legend above the table: sun hours are 06–17 SAST; dark hours are 00–05 and 18–23. The same marks appear in the Hr cells.
- Row hover highlights the whole row (pointer cursor) so you can track across the wide table.
- Total footer at the bottom of the day: sums for Sent, Delivered and Margin; Buy / Sell / Whl are volume-weighted averages for that day (not simple averages of the cell values).
Column by column — what each cell means
| Column on screen | What it is | How to read it |
|---|---|---|
| Hr | SAST hour of the flow (0–23), with a sun or moon icon | Same hour can have several rows (different source→dest pairs). Match the hour to the day chart above. |
| Source | Who supplied the energy | A small line-kind icon, then two colour badges:
pool (filled) then member (outline).
Tooltip titles say Pool · … and Member · ….
There is no separate Kind column — the icon is
the kind. |
| Dest | Who received the energy | Same badge pattern as Source (pool + member). Blank or
— only when the line kind has no destination (unusual on
this tab). |
| Sent | kWh injected / leaving the source | Buy cost is charged on this volume. Info tip: Injected Energy. |
| Delivered | kWh that arrived after network losses (DLF) | Always ≤ Sent when DLF < 1. Sell and wheeling are priced on this volume. Info tip: Injected energy less DLF. |
| Buy | Source (or stored) cost in c/kWh | What that kWh cost the book to use. On battery discharge rows this is the stored marginal cost, not the live grid price. |
| Sell | Destination contract (or discharge) value in c/kWh | What the book earns / avoids per delivered kWh. |
| Whl | Edge wheeling charge in c/kWh | Network use-of-system on the path from source to dest; charged on Delivered. |
| Margin | Realised contribution of this row in Rand | Not c/kWh — Rand for the whole flow. See the worked sum below. |
| Rules | Engine tags that produced the line | e.g. merit_order, firm_reservation,
bess_dispatch. Provenance for disputes — not a second
KPI. |
Worked example — one ordinary allocation row
Take the sample row from §8.4 (same numbers as the Allocations sample view):
| Hr | Source | Dest | Sent | Delivered | Buy | Sell | Whl | Margin | Rules |
|---|---|---|---|---|---|---|---|---|---|
| ☀ 12 | ⇄ Solar · IPP-A | Industrial · Factory | 16,710 kWh | 16,142 kWh | 65.0c | 120.0c | 15.0c | R 6,088 | merit_order |
Read it left to right:
- When. Hour 12 SAST (sun = daylight band).
- Who → whom. The Solar pool member IPP-A supplied the Industrial pool member Factory. The ⇄ icon marks a normal ALLOCATION (supply that cleared a buyer).
- How much. 16,710 kWh left the plant; 16,142 kWh arrived after DLF losses (~3.4% lost on the wire in this example).
- At what prices. Buy 65.0 c/kWh on what was sent; sell 120.0 c/kWh and wheeling 15.0 c/kWh on what was delivered.
- What it earned. Margin is calculated in Rand as:
Margin (R) — this row
revenue = Delivered × Sell = 16,142 × 120.0 = 1,937,040 c
cost = Sent × Buy = 16,710 × 65.0 = 1,086,150 c
wheeling = Delivered × Whl = 16,142 × 15.0 = 242,130 c
margin_c = revenue − cost − wheeling = 608,760 c
margin_R = margin_c ÷ 100 = R 6,087.60 ≈ R 6,088
Same pricing story as §7.2 — the Allocations tab makes that arithmetic visible per hour and per pair.
- Why this pair. Rules =
merit_ordermeans the engine placed this flow under ordinary cheapest-first / demand-stack logic. No firm reservation or battery rule intervened.
Line-kind icons on Source (there is no Kind column)
The small icon before the Source badges tells you what kind of line you are looking at:
| Icon meaning | Line kind | Typical Rules tag | What the money columns mean |
|---|---|---|---|
| Arrows (⇄) | ALLOCATION | merit_order, firm_reservation, … |
Normal wheeled sale: Buy = source cost, Sell = contract, Margin as above. |
| Battery full | BESS_CHARGE | bess_dispatch |
Energy into the battery. Buy = charge cost (often 0.0 from zero-rated spill). Margin is 0 — charging does not earn; it only positions energy for later. |
| Battery empty | BESS_DISCHARGE | bess_dispatch |
Energy out of the battery. Buy = stored marginal cost (charge cost ÷ round-trip efficiency + degradation — §11.2). Sell = discharge value. Margin = realised arbitrage. |
Spill, shortfall and curtailment lines live on their own tabs (or BESS schedule), not as Dest rows here. If you expected an unsold or unmet hour in Allocations and cannot find it, open Spill or Shortfall.
How this ties back to the headline KPIs
- Sum Margin over every Allocations (+ Spill / Shortfall / BESS) line for the whole run → run KPI margin_r.
- The day chart above the tabs is the same energy picture: stacked Source pools vs the demand line; this table is the audit of each stack slice.
- Change nothing on this screen — runs are immutable. To try a different book shape, use Simulations (§9) or change pools and Run Forecast Now.
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-07-18 against the full_demo manifest.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Book · Forecast → Open the run ledger › → Allocations tab → page to a sunny midday hour. You should see Source / Dest badges, Sent larger than Delivered when DLF applies, and a Margin you can recompute from Buy / Sell / Whl as above. For the Forecast-vs-Actual panel, open the matching Actual run instead (§8.2). The T1 September numbers on this destination page are §8.8.
8.6 How you get here
The problem. Forecast’s fold says Open the run ledger ›. You need to know which URL that is, that Allocation stays lit, and how you walk back without losing the run.
The address
/org/trader-pools/{trader_pool_id}/strategy/allocations/{run_id}
That {run_id} is the immutable allocation run you opened — not
"the latest forecast for the month". A shared URL always shows the same
lines. The old /strategy/allocations index (no run id)
forwards to Book · Forecast (§6).
T1 Renewables Pool, September 2026 P50:
/org/trader-pools/01a0ab54-e46b-7dde-b45f-73d119213c75/strategy/allocations/01a0b951-b50d-76c2-bfd8-840b7ecc12cd
#strategy-nav — Book
stays lit
The room tabs stay Operations · Performance · Allocation · Commercial
· Dashboard. This page mounts under Book
(#strategy-tab-book is active). There is no "Runs" tab any
more. Clicking Allocation on the bar opens
…/strategy/book — that is Rules, not
Forecast. That is why the page has its own return link.
Three doors in
| You start on | What you press | What opens |
|---|---|---|
| Book · Forecast, under the run picker | Open the run ledger › on the meta line
(data-role="run-meta") |
This run’s ledger |
Book · Forecast, #book-ledger-fold |
The same Open the run ledger › inside the dashed fold (§6.18) | The same URL |
| Overview | There is no ledger link. Open Book · Forecast first (§4), then use either door above. | Forecast, then this page |
A run that belongs to a live Scenario Lab cook also shows an amber
SIMULATED ribbon at the top
(#simulated-ribbon-{id}) — a door into Lab, not a second
ledger. Ordinary T1 Forecasts do not show it.
The walk back — ← Pool · Forecast
#allocation-back-to-forecast is already on the product.
Label: ← Pool · Forecast. Href:
/org/trader-pools/{id}/strategy/book?mode=forecast&month=YYYY-MM&run={run_id}
On T1 September P50 that is
…/book?mode=forecast&month=2026-09&run=01a0b951-b50d-76c2-bfd8-840b7ecc12cd.
The month is the first day of the run period as YYYY-MM.
You land on the same Forecast fold you left, with the same run still
selected. Browser Back also works; the link is the one you can
bookmark.
Careful. Allocation on
#strategy-navis Rules. ← Pool · Forecast is Forecast. They are not the same door.
8.7 Empty, failed, and incomplete runs
The problem. Not every run has a chart. You need to know when the floor is closed, when a day simply has no lines, and what the page does if the id is wrong.
The header (badges, period, hash, back link) always renders when the
run exists. The comparison panel, day picker, Day supply vs
demand chart (#run-day-chart) and the tabs render
only when status is COMPLETE.
| What you see | What it means | What to do |
|---|---|---|
| Amber banner This run is superseded by a newer run for the same period. | A newer complete run of the same scenario, grade and period exists. Lines here are history. | Read them for audit. Open the current Forecast chip if you want the operating plan. |
| Rose banner Run failed: plus the stored error | Status is FAILED. No chart, no tabs. |
Keep using the previous complete current (§6.6). |
| Header only — no day picker, no tabs | Status is PENDING or RUNNING. The worker
has not written lines yet. |
Wait; refresh. Read KPIs only from COMPLETE. |
| Flash Run not found. then Forecast | The run id is missing or belongs to another book. | Check the pool and the run chip. |
| Allocations: No allocations this day. | This SAST day has no ALLOCATION lines. Other days of
the same run may. |
Page ◀ / ▶. Open Spill — leftover often
lives there. |
| Spill: No spill this day. | Every sent kWh that day found a buyer. | Unusual on T1. Check neighbouring days. |
| Shortfall: No shortfall this day. | Every demand hour that day was served. | T1 September is this state on every day — coverage is 100 %. |
Margin cards with Total R 0.00 and Share
— |
The KPI maps are empty (or truly zero). | Confirm the run completed and has lines. |
| No BESS tab | The run persisted no battery intervals. | Honest. A book with a battery that never dispatched still hides the tab. |
A complete run with a battery that did persist intervals shows the BESS tab even when the Forecast fold’s arbitrage tile is R 0. That is T1 September — one charge line and reserve hours, taught on the battery page (§11.11).
8.8 Worked walk — T1 September P50
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-09-19 against the seeded T1 book (September P50
01a0b951-b50d-76c2-bfd8-840b7ecc12cd).Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Book · Forecast (?mode=forecast&month=2026-09&run=01a0b951-…) → Open the run ledger ›. You should land on…/strategy/allocations/01a0b951-b50d-76c2-bfd8-840b7ecc12cdwith Allocation lit and the day reading Tuesday 01 Sep 2026.
What the header says
| On screen | T1 September P50 |
|---|---|
| Back link | ← Pool · Forecast →
…/book?mode=forecast&month=2026-09&run=01a0b951-b50d-76c2-bfd8-840b7ecc12cd |
| Scenario | FORECAST |
| Status | COMPLETE (no Settled chip — that is Actual only) |
| Period | 01 Sep 2026 – 30 Sep 2026 |
| Inputs hash (short) | #7e4d7cf6 (#run-hash-toggle reveals the
rest) |
| Grade (Audit tab) | P50 |
| Requested by | — |
| Duration | under a minute (< 1 min (2 s)) |
| Headline KPIs (Audit) | Margin −R 13 064 676.47 · Coverage 100.0% |
Those KPIs are the same month you already read on Forecast: every demand hour covered, 96.4 % of supply unsold, the month loses R 13.1 m (§6.12). The ledger proves the sum.
The green Forecast vs settled actual panel is absent. This is a Forecast. Open a June Actual if you want the Δ tiles (§8.2, §6.2).
Tuesday 01 Sep 2026 — the first day
The picker starts on the first SAST day of the period. Caption on the
chart: Supply pools stacked by hour (MWh delivered), with the demand
line overlaid — stack above the line is spill; line above the stack is
shortfall. Id #run-day-chart.
On T1 the stack sits far above the demand line in every hour. That is the 96.4 % spill story drawn as a day, not as a tile.
Allocations — one night hour, then the day total
Default tab. Sun/dark legend: Sun hours 06–17 · Dark
hours 00–05 and 18–23. Cells are rounded whole kWh; prices drop
trailing zeros (85 not 85.0).
Hour 00 SAST (moon) opens the month with three
merit_order sales. Read the Wind → Municipal row left to
right:
| Hr | Source | Dest | Sent | Delivered | Buy | Sell | Whl | Margin | Rules |
|---|---|---|---|---|---|---|---|---|---|
| ☾ 00 | Wind Pool · Durban Coastal Wind · DEMO-SUPPLY-1247843 | Municipal Pool · OffTaker C Midrand DC | 1,668 | 1,668 | 85 | 210 | 0 | R 2 084.57 | merit_order |
revenue = 1,667.659 × 210.0 = 350,208.39 c
cost = 1,667.659 × 85.0 = 141,751.02 c
wheeling = 1,667.659 × 0.0 = 0.00 c
margin_R = (350,208.39 − 141,751.02) ÷ 100 = R 2,084.57
Sent equals Delivered on this row — no DLF bite. Buy 85 c/kWh is the wind contract; sell 210 c/kWh is what the municipal buyer pays. The same hour also sells Wind and Firm into Commercial Pool (275 kWh each). A member badge can print an em dash when the membership has no label or site name; the pool badge still names the book.
Day footer for 01 Sep 2026 (Allocations only):
| Sent | Delivered | Margin | |
|---|---|---|---|
| Total | 74,992 kWh | 74,992 kWh | R 117 646.12 |
Seventy-five allocation rows. Buy / Sell / Whl in the footer are volume-weighted averages for the day, not a simple mean of the cells.
Spill — why the month loses money
Same day, Spill tab. Empty copy would be No spill this day. T1 is the opposite: 111 leftover rows, 1,661,761 kWh unsold, day margin −R 414 635.79.
The largest hour-00 leftover:
| Hr | Source | Unsold kWh | Spill value | Sunk cost | Margin |
|---|---|---|---|---|---|
| ☾ 00 | Wind Pool · Durban Coastal Wind · DEMO-SUPPLY-1247843 | 38,581 | 40 | R 32 794.21 | −R 17 361.64 |
sunk = 38,581.429 × 85.0 ÷ 100 = R 32,794.21
recovery = 38,581.429 × 40.0 ÷ 100 = R 15,432.57
margin = recovery − sunk = −R 17,361.64
No wheeling on spill. That is the same wind that sold 1,668 kWh to Midrand in the same hour — the rest of the plant had no buyer.
Shortfall — the honest empty
No shortfall this day. The tab is not broken. Coverage is 100 % for the month; every demand hour was served. The leak is unsold supply, not unmet load. Find offtake → Desk on Forecast is the next click (§6.19).
Margin — two card totals that must not match
The Margin tab is the whole run, not the selected day.
Margin by TOU (every line kind, including spill):
| TOU | Margin | Share of −R 13.1 m |
|---|---|---|
| peak | −R 2 063 872.30 | 15.8% |
| offpeak | −R 5 868 384.13 | 44.9% |
| standard | −R 5 144 740.03 | 39.4% |
nil |
R 12 320.00 | −0.1% |
| Total | −R 13 064 676.47 | 100.0% |
The nil bucket is a real KPI key the engine stored —
hours that did not land in peak / standard / off-peak. It is small. Do
not ignore a named TOU because of it.
Margin by source pool (allocation lines only):
| Source pool | Margin |
|---|---|
| Solar Pool | R 2 516 592.66 |
| Wind Pool | R 786 497.62 |
| Firm Pool | R 93 552.23 |
| Total | R 3 396 642.51 |
The two Totals differ on purpose (§8.4).
Sold-leg allocation earns about +R 3.4 m. Spill
write-downs (and the tiny nil / reserve noise) pull the
headline to −R 13.1 m. Same conservation as Forecast’s
margin tables (§6.14).
BESS tab — present, not the home
The BESS tab is on this run because 29 dispatch
intervals were persisted (one BESS_CHARGE, twenty-eight
BESS_RESERVE). The Forecast battery fold still reads R 0
arbitrage (§6.17). Do not re-learn
charge, hold and spread here.
Where this is taught. The full
/strategy/besspage — which run it opens, facts, chart, moves, hour table — is §11.11. This tab is the same day view frozen to this run (#run-bess).
8.9 Screen ids
| What | Id or selector |
|---|---|
| Strategy tab bar | #strategy-nav |
| Book (stays lit) | #strategy-tab-book |
| Back to Forecast | #allocation-back-to-forecast |
| Inputs hash toggle | #run-hash-toggle · #run-hash-short ·
#run-hash-full |
| Copy hash (header) | #copy-run-inputs-hash |
| Forecast vs Actual overlay | #forecast-actual-overlay (Actual + paired Forecast
only) |
| Day chart | #run-day-chart |
| Day pager | button[phx-click="shift_day"][phx-value-by="-1"] /
"1" |
| Tab buttons | button[phx-click="select_tab"][phx-value-tab="allocations\|spill\|shortfall\|margin\|audit\|bess"] |
| Copy hash (Audit) | #copy-audit-inputs-hash |
| BESS day view | #run-bess |
| Simulated ribbon | #simulated-ribbon-{sim_run_id} (Lab cooks only) |
| Forecast fold (door, not this page) | #book-ledger-fold |
Tables themselves have no wrapper ids. Assert on the empty copy, the
column info tips (data-tip="Injected Energy", The
allocation provenance), and title="Pool · …" /
title="Member · …" on the badges.
8.10 What this page is not
- It does not change the book. Runs are immutable. To try a different shape, use the Desk (§9) or change pools and Run Forecast Now.
- It does not teach the allocation walk. Cheapest-first, firm first, spill and shortfall pricing live in §7.
- It does not replace Forecast. Tiles, flow, typical day and Find offtake stay on Book · Forecast (§6).
- It does not replace the battery page. When the BESS tab is present, read it as this run’s frozen schedule, then go to §11.11 for the standalone screen.
9. The Desk — sell the long, buy the short (what if I signed this?)
Open Trader Pools → pool → Commercial. The
Delivery month field selects a calendar month and
follows you between pool tasks. The visible window explains why its
position can differ from Performance’s latest snapshot run. Candidate
simulations use this calendar period and remain indicative. The
workspace route is
/org/trader-pools/pools/:id/commercial?month=YYYY-MM; older
simulation routes still work. View pool contracts
carries the pool and month through Deals, contract tabs and the return
to Commercial.
Route:
/org/trader-pools/:id/strategy/simulations ·
Tab: Desk (was Simulations; the
Nominations and Exposure tabs are now steps and
sections of this page — §9.9, §9.10)
This chapter is written for someone who has never run a portfolio what-if before. No jargon assumed. By the end you should know what the book needs (its sell need and its buy need, each priced against doing nothing), who to sell to and buy from, how to try one contract in the deal panel beside the candidate list or several at once in the basket, what the Strategy board shows about the co-ordination between buy legs and sell legs, and how to commit — proposals and nominations — without touching live contracts, forecasts or nominations until you say so.
The Desk is the trader’s twin of the IPP Sales Desk (§14) and the off-taker Procurement Desk (§13), two-sided: a trader both sells and buys, and the two needs are read together.
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-07-18 against the full_demo manifest.
Not this screen. The Scenario Lab / market-month harness (§16, §17) scripts the whole market. This Desk tab answers only: "what if this book signed this one contract?"
In plain English — why simulations exist
Imagine your energy book is a wardrobe that already has clothes in it. A salesperson offers a new jacket at a great price. The price tag cannot tell you whether the jacket fits with the trousers and shirts you already own. A bargain solar PPA can raise margin while worsening spill (you generate more than anyone can take at midday). An evening buyer can be worth more than a cheaper daytime buyer if your surplus sits after sunset.
A simulation is a safe fitting room for a contract.
You keep the wardrobe as it is (baseline). Then you pretend the new jacket is already hanging there (variant) and ask the same measuring tools you already trust — margin, spill, shortfall, coverage — whether the outfit got better or worse. Nothing leaves the fitting room until you deliberately Build Proposal.
| Everyday idea | On this screen |
|---|---|
| Wardrobe today | Your trader book / pools as they stand |
| Trying on a jacket | Injecting one hypothetical buy or sell member |
| Measuring tape | Engine KPIs (margin, spill, shortfall, coverage) |
| "Looks better" | Green deltas that all tell one story |
| Leaving with the jacket | Build Proposal → normal negotiation |
| Leaving empty-handed | Leave status COMPLETE / later DISCARDED —
book unchanged |
Why you run simulations (desired outcomes)
- See portfolio fit before negotiation — cheap is not the same as useful.
- Compare like-for-like — baseline and variant use
the same
SIMULATIONscenario and period, so deltas are apples-to-apples. - Defend a commercial decision — fit score + KPI deltas travel into the proposal message so the story is evidence, not memory.
- Fail safely — bad ideas stay in the Past simulations log; membership, forecasts and nominations never move.
What never happens during a simulation
- No pool membership is saved.
- No forecast is superseded.
- No nomination plan is written.
- No contract is executed (promotion only opens a proposal).
How the screen is laid out
The page is one flow, top to bottom, and a step rail
(#desk-rail) at the top lights the step you are on.
Everything else is either always visible or slides in from an edge so
you never lose the position strip.
| Region | What it shows | Ids to look for |
|---|---|---|
| Step rail | Position → Candidates → Basket → Strategy board → Commit; the lit step follows what you have done (a selected candidate lights Candidates, a leg in the basket lights Basket, a simulated basket lights Strategy board) | #desk-rail |
| Headline | One sentence from the numbers: how long the book is, how short, what spill earns today and on SAWEM, and which side the desk says to work first | #desk-headline |
| Position strip | The Book net position chart (surplus above zero, gap below) with a Sell need card and a Buy need card either side. Each card names its kWh, its share, its heaviest window, and its Option 0 — what happens if you sign nothing. A dashed The desk says box gives the verdict | #workbench-book-position, #desk-sell-need,
#desk-buy-need |
| Candidates | The Sell / Buy tabs you know, each card now carrying a signal row: how much of the need the candidate would absorb (sell) or cover (buy), the routes open to it (physical PPA, Eskom VPPA, via trader, municipal wheeling), badges such as evening load or already a member, and a + Basket button | #sell-candidates-panel,
#buy-candidates-panel,
[data-role="candidate-signal"] |
| Deal panel (right of the list) | Click a candidate and the deal form opens beside the list — the same layout as IPP Sales and OffTaker Procurement, not a side drawer. Add to basket parks the leg so you can keep browsing. Clear Deal returns the dashed placeholder | #desk-deal-panel,
#selected-generation-deal-card /
#selected-offtake-deal-card, #simulation-form,
#simulate-btn, #deal-basket-toggle |
| Basket tray (bottom) | Every leg you have added, with its terms; Simulate basket runs all of them as one book | #desk-basket, #basket-simulate,
#basket-clear |
| Strategy board | For a simulated basket: buy legs → pools → sell legs, the residual to SAWEM and the grid, KPIs before and after, and exposure per counterparty | #desk-strategy-board |
| Compare | Option 0 in row 0, then every strategy and every single simulated leg on one valuation basis, ranked by the mode you pick | #desk-compare, #desk-rank-mode |
| Counterparty exposure | The per-counterparty table from the latest risk snapshot against the limits in force — the old Exposure tab | #exposure-page, #exposure-table |
| Commit | Build a proposal per leg, open the Bid Desk for the SAWEM residual, and the nominated members’ plans with a link to the nominations workbench — the old Nominations tab | #desk-commit, #desk-open-nominations |
| Past simulations | The decision log, unchanged | #past-simulations |
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Commercial. In full_demo September the headline reads the book is long 39.0 GWh and short nothing; the Sell need card values Option 0 at SAWEM P50 ≈ 85 c after the imbalance haircut — above the ~78 c the energy cost — and the Buy need card says do not buy for the book as it stands.
9.1 Start with the portfolio problem — the two needs and Option 0
The Desk starts where the IPP and off-taker desks start: with the need, priced against doing nothing.
- Sell need · long (
#desk-sell-need). The kWh the current forecast leaves unsold, its share of supply, the hours it is heaviest, what it cost to buy (landed c/kWh) and what it earns today as spill. Option 0 for the long side is the day-ahead market: bid the surplus at SAWEM’s P50 less a 5 % imbalance haircut. The card shows the Rand a month that yields and whether it beats or still loses against what the energy cost. No day-ahead record loaded → the card says so instead of inventing a price. - Buy need · short (
#desk-buy-need). The kWh no supply pool covers, its share of demand, the unmet window. Option 0 for the short side is the grid: top up at the book’s top-up price (default 210 c) — the card shows the Rand a month that costs. - The desk says. Under each card, one verdict. Long and short nothing → sell first, buy only what a sale needs; short and long nothing → buy first; both → sell the long, buy the short, and let the Strategy board show whether one counterparty can do both. A buy for a book that spills already is called out as a leg that only makes sense paired with a sale.
Everything below the strip is ranked against these two cards.
Choose the missing shape before you choose the counterparty. The chart at the top and the candidate list underneath are two views of the same question.
Book net position — one chart for both sides
The fold always shows Book net position (24h) from a
single FORECAST allocate:
| Side of the zero line | Colour | Meaning | Which tab cares |
|---|---|---|---|
| Above | Rose — Surplus (unsold) | Generation still without a buyer (spill) | Sell |
| Below | Sky — Gap (shortfall) | Demand still unmet | Buy |
| Dashed | Slate — Contracted | Total allocated volume (context only) | Both |
Sell emphasises the surplus lobe; Buy emphasises the gap lobe. You never lose sight of the other side — that is the point of a combined book view.
Read it: tall pink at midday → look for daytime buyers. Tall blue only in the evening → a pure solar purchase will not finish the job. Empty dashed placeholder means no book position yet — run a forecast in Performance first.
Sell tab — "Who can buy my surplus?"
When Sell is active:
- The chart emphasises Surplus (unsold) — the sales prospectus buyers are ranked against.
- The left list is Sell Candidates: Off-taker sites and Trader pools, ranked by surplus / unsold fit.
- Cards show name, connection / business / topology details, category
badge (
Off-takerorTrader), and a Fit score (0–100).
Buy tab — "Who can fill my gap?"
When Buy is active:
- The chart emphasises Gap (shortfall) — the procurement opportunity sellers are ranked against.
- The left list is Buy Candidates: Generator (IPP) sites and Trader pools, ranked by portfolio gap / load-profile fit.
- Cards show technology, capacity, connection, topology, category
badge (
IPPorTrader), and Fit.
Fit score — what the number means
The fit score (0–100) is computed from the latest book shape for the current month. The engine builds a 24-hour gap vector (shortfall) and a surplus vector (spill), then compares the candidate's daily profile with cosine similarity. Higher = the candidate's shape lines up better with the problem you are trying to solve. The list is ordered best first: a practical shortlist, not a guarantee of commercial value.
| Fit colour (on the card) | Rough meaning |
|---|---|
| Green (≥ 75) | Strong shape match — start here |
| Amber (50–74) | Partial match — check hours carefully |
| Rose (< 50) | Weak match — price alone will not save it |
Sell example (full_demo feel)
Your solar book spills hard from 10:00–15:00. A retail load that peaks 09:00–17:00 may score about 85. A flat 24/7 factory might score about 55 because it absorbs only part of the midday bump — nights still leave surplus stranded.
Buy example
Evenings show a thick grid band. A wind / evening-heavy IPP may score high; pure midday solar may score lower even if its tariff looks cheap — because it does not hit the hours you still buy from the grid.
Tip. Identify the problem from Overview (spill / shortfall / next-best-actions) before clicking the first card. The chart fold is there so you never forget which gap you are shopping for.
9.2 Enter terms you can defend — beside the candidate list
Clicking a candidate card fills the deal panel to
the right of the list (#desk-deal-panel) — the same
two-column layout as the IPP Sales Desk and the
off-taker Procurement Desk. The candidate list stays on
the left (#desk-candidates, lg:col-span-4);
the selected deal sits beside it (lg:col-span-8). There is
no side drawer: the form does not overlay the page.
The panel holds the same deal form as before, so the field-by-field
guide below still applies. Two extra strips sit with the form: the
header repeats the candidate’s signal row (absorbs/covers, routes,
badges), and Add to basket
(#deal-basket-toggle) parks the candidate with default
terms — or with the terms of its latest complete simulation — so you can
keep browsing and try several together (§9.8). Simulating in
the panel still runs one leg against the baseline; adding to the basket
does not run anything until you press Simulate basket.
Clear Deal (#clear-deal-btn) returns the
dashed No Candidate Selected placeholder.
Click a candidate. The right side leaves the dashed No Candidate Selected placeholder and opens the deal form that matches the tab — the same commercial forms used on the Procurement and Sales workbenches.
| Tab | Form title | Mirrors | Primary button |
|---|---|---|---|
| Buy | Selected Off-take Deal
(#selected-offtake-deal-card) |
Procurement | Simulate Purchase |
| Sell | Selected Generation Deal
(#selected-generation-deal-card) |
Sales | Simulate Sale |
Both forms show the candidate name, a Fit Score chip, Clear Deal, and (for trader-to-trader candidates) an amber refusal banner — VWA registration for traders is not modelled yet (decisions V2); runs stay indicative (NERSA Phase-1/2), not authority to execute.
Buy — Selected Off-take Deal fields
| Field | What you are pretending | Why it changes the result |
|---|---|---|
| Target Pool Supply Structure | Which supply pool receives the pretend purchase | Routing and pool rules (e.g. Flexible vs Wind) |
| Capacity (MW) | Contracted nameplate (default 5) | Caps energy the pretend member can deliver each hour |
| Tariff Price (c/kWh) | Energy off-take rate (default 95) | Buy cost / landed cost with DLF |
| Wheeling Cost (c/kWh) | Network / admin add-on (book default often 15) | Added on top of price ÷ DLF |
| Contract Term (Years) | Commercial horizon (default 10) | Stored on the simulation and any later proposal |
Hover the ⓘ next to the form title for the same field explanations in-app.
Sell — Selected Generation Deal fields
| Field | What you are pretending | Why it changes the result |
|---|---|---|
| Target Pool Demand Structure | Which demand pool receives the pretend sale | Where the buyer sits in the book |
| Capacity (MW) | How much you pretend to sell (default 5) | Caps how much the pretend buyer can take each hour |
| Energy Price (c/kWh) | Sale tariff (defaults from book LCOE / base price) | Revenue side of the variant |
| Contract Term (Years) | Commercial horizon (default 10) | Stored on the simulation / proposal |
Sell has no wheeling field on this form — that matches SalesLive. Defaults are starting points for exploration; replace them with the conversation you actually expect to have.
After you press Simulate…
The engine builds two isolated cases under the
SIMULATION scenario:
- Baseline — the book as it stands (no new member).
- Variant — the same book with the hypothetical candidate and your typed terms injected only for this calculation.
The candidate is never persisted as a real pool member. When the run finishes, the Result — baseline vs simulated panel appears under the form (next section). Use Simulate again / Simulate Purchase / Simulate Sale to change terms and re-run; Clear Deal drops selection and result.
9.3 Compare baseline and variant
The deal panel’s baseline vs simulated result is one leg
against the book as it stands. The Compare table lower
on the page (#desk-compare) is where legs meet each other:
Option 0 in row 0, every strategy you have simulated this session, and
every single complete simulation, each with margin, spill, shortfall,
the largest counterparty’s share of revenue and margin-at-risk.
One valuation basis: every row’s residual spill is
valued at SAWEM (P50 × 0.95) rather than at the book’s spill value, so a
strategy that sells 3 % of the surplus is not flattered against the
market alternative. Pick Balanced · Margin · Spill · Security ·
Low risk (#desk-rank-mode) to re-rank;
Balanced penalises any counterparty above half of revenue.
The result panel is the heart of the workbench. It shows four deltas (variant minus baseline) with trend icons. Colour is directional: green always means better for the book, even when the number itself falls.
| Result | Plain meaning | Better direction |
|---|---|---|
| Δ Margin | Extra (or lost) Rand margin | Higher |
| Δ Spill | Change in unsold supply (percentage points) | Lower |
| Δ Shortfall | Change in unmet demand (percentage points) | Lower |
| Δ Coverage | Change in delivered / demand (percentage points) | Higher |
A coherent "yes"
+R 43,700 margin, −2.1 pp shortfall,
+2.1 pp coverage — same story three ways: the candidate
earns money and closes the gap.
A coherent "careful"
+R 43,700 margin with +4.0 pp spill —
cheap energy with nowhere useful to go. Do not promote on margin
alone.
How to read arrows
Green arrow next to −2.1 pp spill is
good. The sign is the arithmetic; the colour is the
judgement.
Read all four results together. Then either Build Proposal (see §9.6) or clear / pick another candidate.
9.4 Worked variant — test daytime offtake
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Simulations. You should see: Sell tab selected by default, Book net position chart (surplus emphasised), Sell Candidates, and Past simulations at the bottom.
Suppose Overview reports midday solar spill on T1 Renewables Pool. You want to know whether a daytime buyer earns its place before you phone anyone.
Starting facts (illustrative full_demo shape)
| Input | Baseline | Variant |
|---|---|---|
| Pool / book | T1 Renewables Pool | Same |
| Chart | Net position surplus tall 10:00–15:00 | Same chart (book unchanged) |
| Candidate | None | Daytime off-taker, Fit ≈ 85 |
| Capacity | Existing members only | +5 MW pretend sale |
| Energy price | Existing contracts | e.g. book LCOE / typed sale tariff |
| Scenario | SIMULATION |
SIMULATION |
Visual story — three outcomes for the same surplus
1 · Baseline (no new buyer)
Read it: generation is fine; the pink band is the sales problem. Fit scores rank buyers against this shape.
2 · Weak fit (flat 24/7 load)
Read it: nights soak some energy, midday still spills. Margin may rise a little; Δ Spill barely moves — do not promote on price alone.
3 · Strong fit (daytime offtake)
Read it: the variant should show lower spill, higher coverage, and margin that moves the same way — one story, four numbers.
Step-by-step on the data (what you type and what you look for)
- Stay on Sell. Confirm the net-position surplus lobe is tall at midday (if empty, run Forecast in Performance).
- Open the highest-fit Off-taker card (daytime shape). Note Fit ≈ 80–90.
- On Selected Generation Deal, set target demand pool, capacity (e.g. 5 MW), energy price you would actually quote, term (e.g. 10 years).
- Click Simulate Sale. Wait for Result — baseline vs simulated.
- Check the four deltas as one story:
| KPI | Example "good sell" reading | Why |
|---|---|---|
| Δ Margin | +R … (green up) |
Extra revenue from absorbing surplus |
| Δ Spill | − … pp (green) |
Midday unsold shrinks |
| Δ Shortfall | ~0 or slightly better | You were selling surplus, not covering demand |
| Δ Coverage | + … pp (green) |
More of generation found a buyer |
- If the four numbers disagree (margin up, spill up), try another candidate or terms — do not promote.
- If they agree, proceed to §9.6. Otherwise leave the row in Past simulations as evidence you tested the idea.
Buy-side twin (same method): switch to Buy (gap lobe emphasised), pick a high-fit IPP, fill Selected Off-take Deal (include wheeling), Simulate Purchase, require margin↑ / shortfall↓ / coverage↑ without a spill blow-out.
9.5 Finding the price where the deal stops working
A single Simulate answers "is this price helpful today?" The next question is harder: at what price does the deal stop helping? The system answers by re-running the same what-if at several energy prices and reading off where your saving (buyer bill improvement vs grid) or margin (seller) crosses zero — the break-even price. Nothing is written to the book; the sweep is analysis only.
Sellers use the same engine on the Sales workbench — see V4 §5.6.1 rather than re-learning it here.
Data. full_demo · seed 42 · stage S09 · numbers below are the engine's August 2026 offtaker what-if shape (0.5 MW AS_GENERATED against Megaflex), rounded for reading.
Starting facts
| Actor / input | Value |
|---|---|
| Buyer site | OffTaker C Midrand DC (demo offtaker book) |
| Seller plant | daytime solar candidate, 0.5 MW contracted |
| Energy price tried | 40 / 70 / 160 c/kWh (plus 15 c/kWh wheeling) |
| Period | Aug 2026 (one allocator month) |
| Metric watched | Δ saving (R) — buyer's bill improvement vs grid |
The arithmetic, stepped
At 40 c/kWh the variant saves about R17,670 for the month (cheap green displaces Megaflex).
At 70 c/kWh the same shape costs about R17,490 (all-in with wheeling now sits above avoided retail in too many hours).
Saving falls roughly linearly with price × deal volume. Zero lies between the two brackets:
break-even ≈ 40 + 30 × 17,670 / (17,670 + 17,490) ≈ 55 c/kWhClosed-form cross-check (same month):
70 + (−17,490) / allocated_MWh / 10 ≈ 55 c/kWh✓
(The/ 10converts R/MWh into c/kWh — a factor-of-ten slip here would miss by hundreds of cents.)
What you should take away
| Swept price | Δ saving (illustrative) | Reading |
|---|---|---|
| 40 c/kWh | +R17,670 | Comfortably worth doing |
| ≈55 c/kWh | ≈ R0 | Break-even — above this, walk away |
| 70 c/kWh | −R17,490 | Paying to take the energy |
| 160 c/kWh | deeply negative | Far past the useful range |
On your own book the absolute Rands differ; the pattern does not: three prices, one zero-crossing, a break-even you can defend on a call. Capacity has a twin question — how much MW before more stops helping? — answered by the same engine's capacity knee (over-contract exposure starts biting past the knee). Advisors and proposal studios surface both; this chapter is the plain-language home for the price side.
9.6 Build a proposal from a simulation
Build Proposal turns an accepted what-if into a private draft — it does not send anything to the counterparty. The simulation's fit score and KPI deltas stay on the proposal message as evidence; advisor suggestions land in your private negotiating brief. Price and capacity sweeps run in the background while the draft builds, so advice is waiting when you reach the pricing stage.
The draft's instrument follows the simulation's target
pool: a virtual pool (VIRTUAL /
VIRTUAL_BUYERS) produces a virtual
proposal; a contracted / buyers pool produces a
physical one. Promotion is refused —
not silently converted — when that instrument is not available for the
pair (for example a virtual promote against an incomplete VWA). The Grid
backstop pool still cannot be promoted.
The plain-language home for what the button does on each seat:
- Off-taker Workbench → V3 §13.2
- IPP Sales Workbench → V4 §6
- Compose / send → V7 §3.4 (offtaker buyer) · V7 §3.4a (IPP seller) · V7 §3.4e (trader buyer)
- Why a
DRAFTis invisible until you send → V7 §3.1
| You are doing | Counterparty | Proposal type | Where you land |
|---|---|---|---|
| Buying | Generator site (IPP) | TRADER_IPP |
Trader Buy studio (…/simulations/proposals/:id/buy) —
V7
§3.4e |
| Selling | Off-taker site | OFFTAKER_TRADER |
Trader Sell studio (…/simulations/proposals/:id/sell) —
V7
§3.4f |
| Either | Another trader | TRADER_TRADER |
Refused on the workbench — VWA registration for traders is not modelled yet (decisions V2) |
After Build Proposal on a supported physical sell path you land in the Trader Sell Proposal Studio — net-position evidence, price card, trader seller terms, and readiness-gated Send to buyer (V7 §3.4f). On a supported physical buy path you land in the Trader Buy Proposal Studio — evidence, contract type, trader buyer terms, and readiness-gated Send to seller (V7 §3.4e). A private negotiating brief and suggestions are already attached. Nothing reaches the counterparty until you send.
Selecting another trader shows an amber banner: Trader-to-trader physical/virtual is not confirmable until VWA registration is modelled — see decisions V2. Simulations stay indicative (NERSA Phase-1/2). Build Proposal repeats that copy in the flash and never invents a draft — you stay on Simulations.
9.7 Use the decision log — and walk the whole screen
Past simulations table
The bottom table (#past-simulations) is your
decision log. It does not pretend a discarded idea was
a live book position; it answers "why did we not sign?" months
later.
| Column | What you see | Why |
|---|---|---|
| Direction | Badge: Buy (badge-info +
shopping-cart) or Sell (badge-success +
banknotes) |
Instantly see which side of the book you tested |
| Status | Status badge: DRAFT / RUNNING (spins) /
COMPLETE / PROMOTED / DISCARDED /
FAILED |
Lifecycle of that what-if |
| Δ Margin | Signed Rand delta | Quick commercial headline; still re-open the full four-KPI story when deciding |
Element-by-element field guide (what to click, what it means)
Work top → bottom, left → right:
- Page chrome — Strategy shell, subtitle "Search counterparties, simulate a contract, compare KPIs, build a proposal." Confirms you are on the what-if workbench for this trader pool.
- Chart fold header — Book net position. Open / Close collapses the chart when you want more room for candidates.
- Net position chart — 24 SAST hours. Rose surplus above zero, sky gap below, dashed contracted reference. Active tab emphasises its side; footnote restates how to read it.
- Sell / Buy tab bar
(
#candidates-tab-bar) — banknotes = Sell, shopping-cart = Buy. Switching clears selection so forms cannot cross-wire. - Candidate groups — Off-takers + Traders (Sell) or Generators + Traders (Buy). Empty group = no eligible counterparties for that kind.
- Candidate card — click to select (sky ring), or
Tab to the counterparty’s name (a real button,
#…-candidate-{id}-select) and press Enter or Space. Fit score is the shape shortlist; details (technology, topology, monthly kWh with comma thousands, etc.) are context for the commercial call. - No Candidate Selected placeholder — dashed card until you pick someone; copy changes with the active tab.
- Deal form — Off-take (Buy) or Generation (Sell); ⓘ explains each term; V2-open refusal banner on trader-to-trader.
- Simulate Purchase / Simulate Sale — starts the baseline/variant pair; button shows Simulating… while the engine runs.
- Result panel — four deltas + Build
Proposal;
SIMULATIONscenario badge reminds you this never supersedes live forecasts. - Past simulations — badges for direction and status; Δ Margin for the archive.
Six-step click-through session (recommended rhythm)
- Open Overview; note whether the pain is spill (sell) or grid / shortfall (buy).
- Open Simulations; confirm net position and which lobe the active tab emphasises.
- Pick the highest-fit candidate on that tab; set terms you can defend on a call.
- Run the simulation; require the four deltas to tell one story.
- Build Proposal only for that story — or leave
COMPLETE/ discard later and try the next card. - After a real contract lands, assign it on Pools and re-forecast; do not expect the pretend member to appear by magic.
Follow along. Seat:
trader_1@webill.net· Path: T1 Renewables Pool → Strategy → Simulations. You should see Sell selected, Book net position (surplus emphasised), ranked Sell Candidates, deal form after click, result deltas after Simulate, and a Past simulations row with Direction and Status badges.
Start from the portfolio problem, not from the first candidate. Run detail (§8) is where you audit an engine result line-by-line; the proposal workflow lives in the Deals volume. The next chapter covers nominations — a different monthly commitment, not a contract what-if.
9.8 The basket and the Strategy board — several legs as one book
A single what-if answers “this one contract?”. A trader’s real question is “these two sales and that one purchase, together?” — because a purchase only pays when a sale needs its shape, and two sales compete for the same surplus.
- Fill the basket. From a candidate card’s +
Basket or the deal panel’s Add to basket. Each leg
lands in the tray at the bottom (
#desk-basket) with its side, terms and whether it has been simulated. Default terms are 5 MW at the book’s base price (sell) or 95 c plus the book’s wheeling rate (buy); a candidate with a complete simulation brings that simulation’s terms. - Simulate basket (
#basket-simulate). Every leg without a simulation gets one created; the engine then allocates the whole book with all legs injected at once, no run persisted. The result is named Strategy A, B, … and stays for the session. - Read the board (
#desk-strategy-board). Left: buy legs (new and existing) feeding the supply pools. Middle: the pools. Right: sell legs (new and existing) taking energy, each with the kWh it takes and its share of revenue. Between them the co-ordination lines: which purchase feeds which sale. Beneath: the residuals — what still spills to SAWEM and what is still topped up from the grid, in kWh and Rand. Then KPIs before → after (margin, spill, shortfall, coverage, contracted ratio, margin-at-risk) and exposure per counterparty with the concentration verdict. Several strategies sit as buttons above the board. - Compare (§9.3) ranks the strategies against Option 0 and the single legs.
Data. full_demo · seed 42 · T1 Renewables, September. Add OffTaker C Midrand DC (absorbs 3 %) and Simulate basket: the board shows one sell leg taking 1.2 GWh, 91.7 % of supply still spilling to SAWEM, and Compare ranks the strategy just under Option 0 — the desk’s point exactly: sell more, or sell at a better price than the market nets.
9.9 Commit — proposals, the Bid Desk and nominations
The last step (#desk-commit) turns a chosen strategy
into work:
- Proposals from the strategy. One row per leg with Build proposal › — the same promotion as §9.6, opening the trader sell or buy proposal studio with the simulation’s evidence attached. A leg that has not been simulated says so.
- SAWEM residual. What the strategy still leaves for the day-ahead market is bid month by month from the Bid Desk (V9); the row links there.
- Nominations · the nominated members. The book’s
recent nomination plans with their status and cost summary. Each plan
row (
#commit-plan-{id}) opens that month on the nominations workbench (?month=YYYY-MM&from=desk). Open the nominations workbench › (#desk-open-nominations) opens the same page for the current month. The workbench is titled Desk — Commit · Nominations and ‹ Back to the Desk (#nominations-back) returns here. §10 describes that workbench in full; nothing about how plans are proposed, overridden, approved or submitted has changed.
9.10 Counterparty exposure in Commercial
The per-counterparty table (#exposure-page,
#exposure-table) sits between Compare and Commit: every
counterparty on the latest risk snapshot with side, position MW,
exposure in Rand, the limit in force and an ok · warn · breach
status. It is the page that used to be the Exposure
tab; …/strategy/exposure forwards here and carries a
?date= if you had one. The strategy board’s own exposure
panel is the forward-looking twin — what the strategy would
make each counterparty’s share — so the two read together: today’s book
on the snapshot, tomorrow’s book on the board. The risk method behind
the snapshot is V3
§22.5.
10. Nominations — the workbench (how much should I commit?)
The trader’s problem. Flexible supply is bought by declaration. Before each delivery month you must tell the system — hour by hour — how much a flexible member will deliver. Guess too low and the shortfall is topped up from the grid. Guess too high and you still pay the physical PPA for energy nobody took. Those two mistakes do not cost the same. This page replaces an eyeball guess with a priced nomination plan you can explain, override, approve, and only then submit.
Open Trader Pools → pool name → Operations →
Nominations. Route:
/org/trader-pools/pools/:id/operations?panel=nominations&month=YYYY-MM.
Legacy nomination links still work. The month selector chooses the
delivery month; it does not change a plan’s generation date.
This chapter is written for someone who has never nominated flexible energy before. No jargon assumed. By the end you should know what a nomination is, why the market forces you to make one, how Webill turns that guess into a priced decision, and what to click on the live workbench — every card, tip, empty state and gate that is built now.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Operations → Nominations. You should see plans for the delivery month and the selected member’s templates.
Data. full_demo · seed 42 · T1 Renewables Pool · last read 2026-09-19 from
strategy_nomination_planson book01a0ab57-ea8b-76a0-8871-1aa65bef7922. Numbers below are that book’s live rows, not a hand-drawn example.
In plain English — the bakery problem
Imagine you run a bakery that must order flour the day before. Tomorrow’s customers are uncertain:
- Order too little → you turn customers away, or buy emergency flour at a punishing price.
- Order too much → leftover flour spoils (or sells for scrap).
Those two mistakes do not cost the same. Emergency flour is usually far more expensive than the scrap value of leftovers. So the smart order is not “the average of what I usually sell” — it is a bit higher than average, because running short hurts more than running long.
A nomination is that flour order, for electricity.
Flexible (as-generated / trader-fill) supply is bought by declaration: before each delivery month you must tell the system — hour by hour — how much your flexible member will deliver. Settlement then holds you to that declaration. Guess wrong and you pay, asymmetrically:
| Mistake | Everyday meaning | Money consequence |
|---|---|---|
| Nominate too little | You promised less than demand needed | The shortfall is topped up from the grid at the Eskom top-up rate — usually your most expensive energy, and for firm sales often a locked-in loss. |
| Nominate too much | You promised more than anyone took | You still pay the PPA buy price for energy that spills — recovered only at (at best) spill value. |
Today many traders still “eyeball” this number. The Nominations workbench replaces the eyeball with a priced, explainable plan: an optimiser proposes the MWh, shows you exactly why, lets you override any hour, and — only after you approve — submits the plan into settlement. Nothing reaches settlement without your explicit sign-off.
Too little (shy)
Read it: you under-promised. Demand still arrived; the tall amber band is emergency energy at top-up rates.
Too much (bold)
Read it: you over-promised. The pink band is energy you paid for that nobody needed — recovered only at spill value.
Sweet spot (workbench)
Read it: because top-up hurts more than spill, the workbench aims a little above the average residual — not at the cap, not at the mean.
What a nomination is used for
- Market / SO declaration — the formal “this is how much I will deliver” commitment for the month.
- Settlement input — after you
Submit, the plan expands into 20-minute nomination rows
that settlement (and every
NOMINATEDrun — §6.1) reads. - Book planning — even before submit, the PROPOSED plan is a priced forecast of mismatch cost, so you can see whether a contract’s tolerance band or your top-up rates are about to hurt you.
How you benefit
- Less guesswork — the number comes from your book’s residual demand and your real prices, not a gut feel.
- Explainable decisions — every hour stores the scenarios, costs and critical ratio that produced it (the rationale panel). Months later you can still defend the number.
- Measurable saving — the KPI strip shows vs P50: how much cheaper the optimiser is than “just nominate the average”.
- Human override, human gate — you can edit any hour while the plan is PROPOSED; only Approve → Submit commits. The monthly worker never submits for you.
How to get the best out of nominations
| Do this | Why it matters |
|---|---|
| Enrol the right members (§10.1) | No tick = no plan. No demand in the book = a correct zero nomination. |
| Keep pools and PPAs current before the 20th | The worker proposes from the book as it stands; stale memberships → stale plans. |
| Read the rationale on peak hours (especially evenings) | That is where asymmetry is largest and money is made or lost. |
| Override only when you know something the model doesn’t | Outages, one-off plant maintenance, known plant trips — not “round numbers”. |
| Watch the ⚠ tolerance chip | A high breach probability means renegotiate the band or accept the penalty before you lock the month. |
| Approve early, submit before the deadline | Two-step sign-off is deliberate; leaving it to the last hour invites mistakes. |
| After submit, run a Nominated scenario (§6.1) | See the declared position in the same charts you already trust. |
10.1 Prerequisites — enrolling a member
The workbench operates on nominated members: supply-pool memberships with the Nominated box ticked (§5.3). Two things matter:
- The member should carry a physical PPA — the buy price comes from the contract, and submission writes settlement rows against that PPA. A prospect member (site with no contract) can be optimised for planning, but cannot be submitted.
- Your book needs demand for the optimiser to measure — the residual it nominates against is your demand minus your non-nominated supply. An empty demand side means a zero residual and a zero nomination (correctly: there is nothing to serve).
If no member is enrolled, #nominations-empty says so:
No nominated members. Mark a Flexible-pool membership
nominated on the Pools screen, then re-optimise
here.
10.2 How the optimiser thinks — the newsvendor rule, step by step
The method is the classic newsvendor problem: a newspaper seller must decide this morning how many papers to buy before knowing how many customers will show up. Too few → missed sales; too many → worthless unsold stock. Demand is uncertain and each mistake costs differently — newsvendor is the mathematics of the best quantity under exactly that shape of uncertainty. Here, the “papers” are kWh and the “customers” are your residual demand.
For each nominated member and each hour template (weekday / Saturday / Sunday × hour 0–23) the optimiser walks five steps:
Step 1 — measures the residual demand. It runs your
book for the month without its nominated members. Whatever
demand goes unserved in that run is, by definition, the energy the
flexible member exists to supply — the residual
R, per template hour.
Step 2 — admits it doesn’t know the exact number.
The residual is a forecast, so the optimiser turns it into a small
scenario set: five values around the expected residual,
with probabilities. (Until settled-actuals history exists to derive your
book’s real forecast-error distribution, default error ratios are used,
and the plan records scenario_source: default_quantiles —
honest provenance, visible as the Default quantiles
badge.)
Step 3 — asks: how much does each mistake hurt?
You can be wrong in two opposite ways. They almost never cost the same:
| Mistake | Everyday picture | What you pay extra |
|---|---|---|
| Too little (short) | You under-promised; demand still arrived | You buy the missing energy from the grid at the expensive top-up rate — instead of from your cheaper PPA. |
| Too much (long) | You over-promised; nobody needed it | You still paid the PPA price for energy that spilled — and you only get back the cheap spill credit. |
So Step 3 just puts a Rand-per-kWh price on each kind of pain:
Step 3 — what does “wrong” cost?
Short pain (Cu) — each kWh you
under-nominated costs you the gap between grid top-up and your PPA buy
price.
Long pain (Co) — each kWh you
over-nominated costs you the gap between your PPA buy price and what
spill recovers.
Short pain Cu = grid top-up − PPA buy price
Long pain Co = PPA buy price − spill recovery
Where the numbers come from: top-up from the firm demand you would otherwise leave short; buy price from that member’s PPA for that hour; spill recovery from the membership’s spill value. You do not type these by hand — the workbench reads them from the book.
Worked feel: if grid top-up is 210c and your PPA is 95c, each short kWh hurts 115c. If spill only recovers 40c, each long kWh hurts 55c. Short hurts about twice as much as long — that fact drives Step 4.
Step 4 — aims a little toward the more expensive mistake.
If both mistakes cost the same, you would nominate the middle of the scenarios (the average). They do not cost the same. When short hurts more, you deliberately nominate a bit high — you accept a little more spill risk to avoid expensive grid top-up. When long hurts more, you would aim a bit low. That “tilt” is all Step 4 does.
Step 4 — how far to tilt?
Think of a scale from 0% to 100% of the residual scenarios (Step 2’s five bars). Step 4 picks a target coverage on that scale:
Aim point = short pain ÷ (short pain + long pain)
Example with the numbers above: 115 ÷ (115 + 55) = 0.676
→ aim to cover about 68% of the residual outcomes, not
50%. Then pick the smallest scenario bar that already
reaches that 68% — that MWh is the nomination (capped by the member’s MW
limit).
| If… | Aim point | What you nominate |
|---|---|---|
Short hurts more (Cu > Co) |
Above 50% | Above the average residual |
| Both hurt equally | 50% | Near the average |
Long hurts more (Co > Cu) |
Below 50% | Below the average residual |
In the screen this aim point is labelled q* (“critical quantile”). You do
not need the name — only the idea: tilt toward the mistake that
hurts more.
Step 5 — checks the bill before you commit.
Steps 1–4 suggested a nomination. Step 5 answers the only question that matters to a trader: “If I lock that number in, what do I expect to pay for being wrong — and is it better than the obvious alternatives?”
You still do not know which residual will actually happen. So the workbench does not pretend to. Instead it asks, for each possible residual from Step 2:
- If I nominated N MWh and reality was R MWh, was I short or long?
- Multiply the shortfall (or the spill) by the short pain or long pain from Step 3 — that is the mismatch cost for that one outcome.
- Weight that cost by how likely the outcome is (the % under each bar).
- Add those weighted costs up — that single Rand figure is the expected mismatch cost for nomination N: the bill you should plan for, on average, if this hour template repeats many times.
It then runs that check for three strategies side by side:
| Strategy | What you nominate | Everyday meaning |
|---|---|---|
| Aim for the average | The middle / expected residual | The “sensible guess” most people make by eye. |
| Workbench pick (Step 4) | The tilted number | Deliberately a bit high (or low) because mistakes are unequal. |
| Nominate the cap | The member’s full MW limit | “Just max it out so we never go short.” |
If the workbench pick is doing its job, its expected mismatch cost is the lowest of the three. That is the proof: not “trust the formula”, but “here is the cheaper bill versus two common guesses.”
Step 5 — what you are looking at
Mismatch cost — the extra Rand you pay when nomination and reality disagree (grid top-up when short, unpaid spill when long).
Expected — not a crystal ball. It means: average the mismatch cost across the five possible residuals, giving more weight to the more likely ones.
Why three strategies? So you can see the workbench beat both “guess the average” and “nominate everything” in Rand, not in jargon.
On the screen this lives in the rationale panel when you click an hour: scenarios, short/long pain, aim point, nomination, and the expected-cost comparison. Months later you can still open that panel and see why that hour said 6.19 MWh.
Worked feel — a clean evening hour. A flexible member buys at 95 c/kWh (cap 10 MW); the demand it serves tops up at 210 c/kWh; spilled energy recovers 40 c/kWh. Short pain is 115c, long pain is 55c, aim point is 68%. That picture is how the maths tilts. The T1 demo does not use those prices — its live weekday 19:00 is in §10.10.
The intuition to keep: because being short costs more, nominate above the average — but nowhere near the cap.
The tolerance guard. If the PPA carries an imbalance tolerance band (e.g. ±10%), the plan also reports the probability that the realised residual lands outside the band around the nomination — computed straight off the scenario set. That is the ⚠ tol figure. High % = warning: renegotiate the band or accept the penalty before you sign the month.
10.3 The plans roster
The nominated PPA identity lives in the page heading
(#org-page-heading) and the compact line
#nominations-ppa-identity under the crumb — member
· MW, not a top card. The workbench itself opens with a
Plans table (#nomination-plans /
#nomination-plans-table): a header strip, then one
selectable row per nominated member.
Roster header
Left to right:
- The heading Plans.
- The month selector
#nomination-month-nav— chevron left, a mono label such asSep 2026, chevron right. Bounds are the current delivery month ± 3 months. On 19 September 2026 that is June through December. A chevron disables (opacity, no click) when the next step would leave those bounds. Changing month patches the URL to?month=YYYY-MM&from=…and clears any open cell or cost modal. - The roster sentence
#nomination-roster-summary. It always starts with how many nominated members you have, then only the parts that apply: N to review (PROPOSED), N ready to submit (APPROVED), N submitted, N without a plan. T1 September reads 1 nominated member · 1 ready to submit. T1 October reads 1 nominated member · 1 to review. T1 August reads 1 nominated member · 1 submitted. - Re-optimise all
(
#nomination-reoptimise-all). The ⓘ sits on the left of the button (tooltip-left): Rebuilds every plan still PROPOSED for this month from a fresh residual run. APPROVED and SUBMITTED plans stay locked. After the click, a flash names the count — Re-optimised N plan(s). — or, if some were locked, Re-optimised N plan(s); M approved/submitted plan(s) left as is.
Each plan row
Each row is #nomination-plan-row-{membership_id} with
data-role=nomination-plan-row. The selected row washes
brand green (data-selected=true,
aria-pressed=true). Click a row to load that member’s
workbench below.
The Member column is the membership’s own label when
it has one. On T1 that is Nominated
PPPA-202609-867473777 — the same words as
#org-page-heading and
#nominations-ppa-identity. If the membership has no label,
the row falls back to PPA {agreement_ref}, then the
generator site name, then Nominated member. The identity line
also shows the MW cap when the membership has one.
A plan that exists shows:
| Column | Meaning |
|---|---|
| Status | PROPOSED (info / light-bulb), APPROVED (warning / check), SUBMITTED (success / paper-airplane). SUPERSEDED plans are filtered out, so you never pick a dead version. |
| Nominated | Month total — T1 312.4 MWh. |
| E[cost] | Month expected mismatch cost — T1 R 61,250. |
| ⚠ tol | Tolerance breach probability when a band applies. Amber under 25%, rose at 25% and above. — when there is no band. T1 September is ⚠ 22%; October is ⚠ 65%; August is ⚠ 35%. |
vs P50 is not on the table. That saving lives on the KPI strip (§10.4) once you open the plan.
A member with no plan for the selected month shows status — no
plan — and — in the numeric columns. The workbench below
then shows #nomination-no-plan: No plan yet for {label}
— press Re-optimise all to build one for {Month
YYYY}.
Which month? The selector defaults to the current calendar month. The monthly worker (§10.7) proposes next month on the 20th — step the chevron forward to see that review. Desk Commit rows also deep-link with
?month=YYYY-MM&from=desk.
10.4 The plan detail — header, KPIs, hour grid and rationale
Once a plan is selected, #nomination-plan-detail
(data-status=PROPOSED|APPROVED|SUBMITTED) fills the rest of
the page. There are no day-type tabs. Read it top to
bottom: header, KPI strip, hour grid, rationale.
Header — same words as the page heading
The workbench heading is the same member label as
#org-page-heading — on T1, Nominated
PPPA-202609-867473777. Beside it: the status badge, then a
scenario source badge (title Scenario uncertainty
provenance):
| Badge | Meaning |
|---|---|
| Default quantiles | Built-in error bands around the residual forecast (used until your book has enough settled history). |
| Measured | Drawn from real forecast-error history (n= sample size
when shown). T1 September and August show this. |
| Override | Someone forced custom scenario inputs for this template. |
| · vN (optional) | Version of the forecast-error profile — so two plans can be compared if the profile was updated. |
#nomination-plan-meta is the three-part provenance
line:
- Applies to
#nomination-plan-month— September 2026 (delivery month). - Generated
#nomination-plan-generated— a UTC stamp such as 16 Sep 2026 17:51 UTC. - Submitted — only after submit, in green: the submitted-at stamp plus — read-only.
Stepper and the three buttons
The lifecycle rail on the right is
#nomination-plan-steps
(aria-label="Plan lifecycle"). Three pills only:
Proposed → Approved → Submitted. The current step is
the solid green pill; earlier steps are done (check); later steps are
grey. DRAFT does not appear on this stepper — the
optimiser proposes in the same call, so a plan that reaches this page is
already PROPOSED or later. SUPERSEDED plans are filtered from the
roster.
Three actions sit under the stepper:
| Button | Id | When you see it | What it does |
|---|---|---|---|
| Costs (cog) | #nomination-open-costs |
Hidden once SUBMITTED | Opens the branded cost modal (§10.4 costs). Re-optimise from that modal only succeeds while the plan is still PROPOSED. |
| Approve plan | #nomination-approve |
Only on PROPOSED | Flash Plan approved. Status → APPROVED; the grid and override form lock. |
| Submit nominations | #nomination-submit |
Always, but disabled until APPROVED | Hover title while PROPOSED: Approve the plan first. While APPROVED: Expand the plan into 20-minute nomination rows for settlement. After submit: Already submitted. Flash: Submitted N 20-minute nomination rows. |
That two-step gate is the whole point of the page. Re-optimise cannot sneak past a plan you have already signed.
The KPI strip
#nomination-kpis is five tiles. Every label is an info
header whose tip opens above the tile
(placement={:top}, tooltip-top).
| Tile id | Label | Tip (exact) | T1 September |
|---|---|---|---|
#nomination-kpi-nominated |
Nominated | Plan’s total for the month. | 312.4 MWh · note month total across 72 hour templates |
#nomination-kpi-cost |
E[cost] | Month’s expected mismatch cost at the optimiser’s numbers. | R 61,250 · expected mismatch cost for the month |
#nomination-kpi-saving |
vs P50 | Saving against naively nominating the expected value. | R 21,050 saved (green) · 26% below nominating the average (P50) |
#nomination-kpi-tol |
⚠ tol | Tolerance-breach probability. | 22% (amber) · chance an hour lands outside the imbalance band. No band → — and no imbalance band on the contract |
#nomination-kpi-overrides |
Overrides | Hour templates where you replaced the optimiser’s N by hand. | 0 / 72 · no hand overrides — pure optimiser plan. A count turns the tile amber. T1 October is 1 / 72 (weekday 12:00). |
This is where vs P50 lives — not on the plans table.
The hour grid
#nomination-hour-grid is one table: a sticky header of
hours 00–23, then three rows at once — Weekday,
Saturday, Sunday. There is no tab to switch day type.
The title Nominated MWh by hour carries an info tip
that opens below the words
(placement={:bottom}, class tooltip-bottom).
That placement is deliberate — a top tip would cover the bars. The tip
says: Optimiser’s nomination per hour (N) for each day type. Bar
height = MWh vs this plan’s peak hour. Click a cell to read its
rationale below.
#nomination-heat-legend on the right of that title:
- A light emerald stub — Bar height = MWh vs the plan’s peak hour (scaled to the tallest hour on this whole plan, so weekday and Sunday are comparable).
- A dark emerald stub — Peak of the day (the tallest hour on that row).
- A brand-green dot — Overridden by hand.
- Sun 06–17 · Moon Dark 00–05, 18–23. Hour header cells wash amber in sun hours and slate at night.
Each day-type row (tr[data-day=weekday|saturday|sunday])
shows the day name, then {N} days · {MWh} MWh/day — the
calendar count for this delivery month times that row’s hourly sum. Each
cell is #nomination-cell-{day}-{hour} (for example
#nomination-cell-weekday-19). The number is the
effective MWh (your override if you typed one,
otherwise the optimiser’s N). The bar grows from the bottom of a 30 px
track. A hand override also draws a tick at the optimiser’s N and the
green dot in the corner. Hover title on a plain cell: N {MWh} MWh ·
E[cost] R …/h. On an override: Override {MWh} MWh · optimiser N
{MWh} MWh.
Click a cell to select it (aria-pressed=true, brand
ring). The rationale panel below updates. The page always keeps a cell
selected: on first load it picks the weekday peak hour
(or the overall peak if weekday is empty), so the rationale is never a
blank hole.
Rationale panel — field by field
#nomination-rationale-panel (data-day,
data-hour) is the optimiser showing its homework for
one hour template. Title: Rationale · Saturday
19:00 plus why the optimiser nominates what it does for this
hour. The scenario-source badge can differ per template
(n= when measured).
If that hour has no line, the panel says No optimiser line for {day} {hour} — nothing to explain.
Otherwise three columns:
Residual scenarios — lowest to highest
(#nomination-scenario-chart). Five bars, shortest residual
on the left. The figure under each bar is the
cumulative probability. Filled (darker) bars are
outcomes the nomination already covers; the horizontal line is
N; a second brand line appears when you have an
override (ovr). The chosen bar — the one that first
reaches q* — is marked q*. Hover a bar
(tooltip-top): X.XX MWh · p=0.yy · cumulative
0.zz. These are five possible residuals, not five
nominations.
Decision. #nomination-decision-mwh is
the effective MWh for this hour, then MWh this hour. If you
overrode, a brand line says Your override — the optimiser proposed
{N} MWh. #nomination-decision-reading is a
plain-English sentence built from Cu, Co and q* — it will say the
optimiser leans high (or low), which scenario it picked, whether a MW
cap trimmed it, and how many Rand per hour the tilt saves against
P50.
While the plan is PROPOSED,
#nomination-override-form sits under that reading. The
Override ⓘ opens above
(tooltip-top): Replaces the optimiser’s N for this hour
when the plan is submitted — only for PROPOSED plans. Clear it to return
to N. Type MWh in #nomination-override-input
(placeholder is the optimiser’s N), press Save override
(#nomination-save-override) → flash Override
saved. The KPI override count ticks up and the cell gets
data-overridden=true. Clear
(#nomination-clear-override, danger style) appears only
after a save → Override cleared.
On APPROVED or SUBMITTED the form is gone. The note reads Overrides are only possible while a plan is PROPOSED — this plan is approved and waiting to be submitted. (or this plan has been submitted.)
Numbers
(#nomination-rationale-numbers). Every label except
Saving is an info tip that opens
above:
| Label | Tip (exact) | T1 weekday 19:00 |
|---|---|---|
| Cu | Short pain: extra c/kWh when you under-nominate (grid top-up − PPA). | 125 c/kWh |
| Co | Long pain: extra c/kWh when you over-nominate (PPA − spill recovery). | 45 c/kWh |
| q* | Aim point: share of residual outcomes to cover — Cu ÷ (Cu + Co). | 0.68 |
| nominate | Chosen MWh for this hour — smallest scenario that already reaches q*, then capped. | 6.19 MWh |
| E[cost] | Expected mismatch cost per hour at this nomination. Lower is better. | R 1,013.00/h |
| P50-nom | Same expected cost if you had nominated the average (P50) residual instead. | R 1,332.00/h |
| Saving | (no tip) | R 319.00/h (green when the tilt is cheaper) |
| ⚠ tol | Plan-level probability that an hour lands outside the imbalance tolerance band. | 22% on the September plan, plus ⚠ 22% probability outside the imbalance tolerance band |
The five residual bars behind that 19:00 cell, lowest to highest: 4.46 · 5.45 · 6.19 · 7.06 · 8.11 MWh at probabilities 10% / 20% / 30% / 25% / 15%.
How to read one panel in ten seconds
- Bars — what residual might be.
- Cu vs Co — which mistake hurts more.
- q* — how far to tilt.
- nominate — the number.
- E[cost] vs P50-nom — is the tilt worth it in Rand?
- ⚠ line (if any) — tolerance trouble ahead?
This panel is the governance heart of the workbench: any nominated number, months later, can be decomposed back into the exact scenario set and costs that produced it.
Costs — changing the optimiser’s assumptions
Costs (#nomination-open-costs) opens
#nomination-cost-modal. The title Cost
parameters sits in the branded green
.wg-modal-header. X
(#nomination-cost-close,
aria-label="Close cost parameters") and Escape
(phx-window-keydown) and the backdrop all close it.
The lead copy: Values below are this plan’s current Top-up and Imbalance tolerance. Edit either field, then Re-optimise to rebuild the PROPOSED plan. Clear a field to fall back to the book / contract default.
When you can use it
- The button is hidden once the plan is SUBMITTED.
- Re-optimise only succeeds while the plan is still PROPOSED. An APPROVED plan can still open the modal, but submit answers with This plan is APPROVED — cost parameters can only be re-optimised while PROPOSED. Leave a field blank to keep the default. Only filled fields override.
What Re-optimise does
The footer note is on the form: Re-optimise supersedes this PROPOSED plan and builds a new one with your overrides stored on the new plan’s params. APPROVED and SUBMITTED plans stay locked. Cancel closes with no change. Success flash: Re-optimised with new cost parameters.
Two fields, each with a “Current plan:” line
(#cost-topup-current, #cost-tolerance-current)
that names the source — your override, member rate,
book default, fallback default, contract, or
no band on contract.
Top-up (c/kWh)
What it is. The grid replacement price you pay when you under-nominate — the expensive energy that covers residual demand the flexible member did not cover. In c/kWh. Placeholder Book default.
How it changes the maths. Short pain is
Cu = top-up − PPA buy price. Raise top-up → Cu rises → the
workbench nominates more (still capped). Lower top-up →
less upward tilt. Co does not move.
Why you would change it. A tariff hike the book has not priced yet; a book top-up that looks too high for this member; a what-if before you renegotiate the PPA. After Re-optimise, open a peak hour: Cu, q*, nominate, and E[cost] vs P50-nom should move together.
Imbalance tolerance (%)
What it is. The ±% band around the nomination inside which the PPA treats mismatch as acceptable. Placeholder Contract default. Current plan prints e.g. ±10% · contract or none · no band on contract.
How it changes the maths. Tolerance does not change Cu, Co, q*, or nominated MWh. It only recomputes ⚠ tol. The helper under the field says so: Does not change nominated MWh — only the ⚠ tol breach probability on the plan and rationale panel.
Why you would change it. Stress a tighter or looser band before renegotiation; surface a commercial band the contract row does not yet carry. After Re-optimise, nominate and E[cost] should stay put; only ⚠ tol moves. Change one field at a time when you are diagnosing.
Costs — decide in thirty seconds
- Still PROPOSED? If already APPROVED/SUBMITTED, costs will not rebuild the plan.
- Changing Top-up? You are changing short pain → expect nominate and E[cost] to move.
- Changing tolerance? You are only changing the ⚠ risk flag → nominate should stay put.
- Blank = keep the book default; filled = your assumption, stored on the new plan’s params.
- Re-optimise → re-open a peak hour rationale and confirm Cu / q* / ⚠ match the story you intended.
- Happy? Approve. Unhappy? Adjust again before sign-off — not after Submit.
10.5 Approve and submit — the sign-off gate
The on-screen stepper is the lifecycle you can act on:
The monthly worker may create PROPOSED plans; it never Approves or Submits. APPROVED and SUBMITTED plans stay locked. DRAFT never appears on this stepper.
Status path — who moves the plan
- Optimise → PROPOSED (the first status you see here).
- PROPOSED — you override / approve → APPROVED (optimiser cannot touch it after that).
- APPROVED — you submit → SUBMITTED (read-only; Costs disappears).
- From PROPOSED only: re-optimise is allowed; the old plan becomes SUPERSEDED and drops off the roster.
What submit actually does. Each hour template
expands into real settlement rows: for every matching calendar day of
the delivery month, each nominated hour becomes three 20-minute
rows of one third of the hour’s energy each — the grain
settlement works at. The rows carry the PPA, the SAST-correct interval
timestamps, TOU/season/day-type tags, and the plan’s identity as their
provenance
(submitted_by: strategy_nomination_plan:<id>). The
confirmation tells you the scale: Submitted 1,584 20-minute
nomination rows. From that moment the rows are visible to
settlement and consumed by every NOMINATED run (§6.1).
Example count. A plan nominating 8 evening hours on weekdays only, in a month with 22 weekdays: 22 days × 8 hours × 3 slots = 528 rows, each carrying kWh ÷ 3.
Re-submitting. If you re-optimise and submit again
for the same month (before the deadline, or as a post-deadline
revision), the previous month’s rows are replaced
wholesale — not patched — and the new rows are marked
revised instead of firm. Wholesale replacement
matters: a revised plan may nominate a different set of hours,
and patching would leave stale rows behind. The submitted plan shows its
timestamp on #nomination-plan-meta: Submitted 16 Sep
2026 17:51 UTC — read-only.
10.6 A complete worked session — click by click
Walk T1 once from Overview. September on the demo is already APPROVED, so you are looking at a locked grid; step to October to practise override → approve → submit on a PROPOSED plan.
1 · Arrive
From Overview press Open Nominations workbench
(#overview-open-nominations). URL keeps
?from=overview. Overview stays lit. Crumb reads
Overview · Nominations.
2 · Read the header and the table
The heading names Nominated PPPA-202609-867473777. The Plans table has one row: 312.4 MWh, R 61,250, ⚠ 22% in September. Press the row if it is not already selected.
3 · Inspect 19:00
On the hour grid click #nomination-cell-weekday-19. Rationale should show Cu 125 c/kWh, Co 45 c/kWh, q* 0.68, nominate 6.19 MWh, E[cost] R 1,013.00/h vs P50-nom R 1,332.00/h.
4 · Override (October)
Step to Oct 2026 (PROPOSED). Click weekday 19:00. In
#nomination-override-form type a value, Save
override → Override saved. Totals recompute; the
rationale still records the optimiser’s N. T1 already has one seeded
override at weekday 12:00 (6.25 vs 5.65).
5 · Approve
Press Approve plan. Status → APPROVED, the form disappears, Submit nominations enables. Re-optimise all will leave this plan locked.
6 · Submit
Press Submit nominations → confirmation with the 20-minute row count. Status → SUBMITTED, Costs disappears. Launch a Nominated run (§6.1) to see the declared position.
Checklist after submit
- Plan badge reads SUBMITTED and the grid is read-only.
- Confirmation flash named a non-zero row count (or you know why it was zero — usually no PPA on the member).
- A Nominated run for that month shows coverage shaped by your declarations, not a raw forecast shape.
- If you must revise before the deadline: re-optimise is blocked on APPROVED/SUBMITTED — create a deliberate new propose path only when your process allows wholesale replacement (§10.5).
10.7 The monthly rhythm — the worker proposes, you dispose
On the 20th of each month at 05:00 (configurable per deployment), a scheduled worker builds a PROPOSED plan for next month for every active nominated member — so when you arrive, the review is waiting rather than the modelling. The worker observes the same lock you do: a plan you have already approved or submitted for that month is skipped, never replaced.
Your only recurring job is the review loop:
Your monthly review loop
- 20th — worker proposes next month.
- You inspect peak hours + ⚠ tolerance.
- Override where you know better (rationale form, PROPOSED only).
- Approve → Submit (before the nomination deadline).
- Optional Nominated run to verify the declared book.
Do that comfortably ahead of the deadline and nomination stops being a last-minute scramble — it becomes a priced, auditable habit.
10.8 How you get here
Nominations is its own URL. Four doors write ?from= so
‹ Back (#nominations-back) returns to the
door you used. A missing or unknown from behaves as
desk.
| Door | Control | URL | Nav that stays lit | Back label |
|---|---|---|---|---|
| Overview footer | #overview-open-nominations · Open Nominations
workbench |
…/nominations?from=overview |
Overview | ‹ Back to Overview → /strategy |
| Overview ranked leak | Re-optimise → Nominations when take-or-pay is under-used or tolerance is breached (§4.5) | …/nominations?from=overview |
Overview | same |
| Desk · Commit row | #commit-plan-{id} |
…/nominations?month=YYYY-MM&from=desk |
Desk | ‹ Back to the Desk →
/strategy/simulations |
| Desk · Commit footer | #desk-open-nominations · Open the nominations
workbench › |
…/nominations?from=desk |
Desk | same |
| Dashboard | a Dashboard link that passes from=dashboard |
…/nominations?from=dashboard |
Dashboard | ‹ Back to Dashboard |
| Book | a Book link that passes from=book |
…/nominations?from=book |
Book | ‹ Back to Book |
Where the doors are taught. Overview actions: §4.5. Desk Commit: §9.9. Getting in: §3.
10.9 Page chrome
While plans load, Shell.page_loading shows Loading
nominations…. Then:
#strategy-nav— Overview / Book / Desk / Dashboard. The tab that matchesfrom=is active. There is still no Nominations tab.- Page heading — Desk — Commit · Nominations —
{member label} (
#org-page-heading) once a nominated member is selected. The compact line#nominations-ppa-identityunder the crumb repeats member · MW. There is no Nominated PPA card. #nominations-desk-crumb—{door} · Nominations. From Overview that is Overview · Nominations. From the Desk, Desk · Commit · Nominations. From Dashboard / Book, those names. The back link sits on the same line.#nominations-workbench— empty state, or plans table + detail + optional cost modal.
10.10 T1 on the demo
One nominated member, label Nominated
PPPA-202609-867473777, PPA PPPA-202609-867473777,
membership 01a0ab57-f6dd-70c0-bca0-8db95f74d53b.
| Month (selector) | Status you will see | MWh | E[cost] | vs P50 (KPI) | ⚠ tol | Overrides | Scenario badge |
|---|---|---|---|---|---|---|---|
| August 2026 | SUBMITTED (Costs hidden; meta shows Submitted … — read-only) | 312.4 | R 61,250 | R 21,050 saved | 35% | 0 / 72 | Measured |
| September 2026 (default) | APPROVED (Submit enabled; override form gone) | 312.4 | R 61,250 | R 21,050 saved | 22% | 0 / 72 | Measured |
| October 2026 | PROPOSED (Approve + override form live) | 312.4 | R 61,250 | R 21,050 saved | 65% | 1 / 72 (weekday 12:00, 6.25 vs 5.65) | see badge on the header |
| July 2026 | SUPERSEDED is filtered — the table row reads — no plan — | — | — | — | — | — | — |
| November 2026 | A seeded DRAFT can appear if you step this far; the live optimiser never leaves DRAFT on this page (it proposes in the same call). | — | — | — | — | — | — |
Weekday 19:00 on the August / September / October plans is the same line: 6.19 MWh, Cu 125 c/kWh, Co 45 c/kWh, q* 0.68, E[cost] R 1,013.00/h, P50-nom R 1,332.00/h, residual bars 4.46 / 5.45 / 6.19 / 7.06 / 8.11 MWh.
10.11 Empty states
| Id | When | Copy |
|---|---|---|
#nominations-empty |
No active nominated memberships in this book | No nominated members. Mark a Flexible-pool membership
nominated on the Pools screen, then re-optimise
here. |
#nomination-no-plan |
Members exist, but the selected row has no live plan for this month | No plan yet for {label} — press Re-optimise all to build one for {Month YYYY}. |
Hour cell — |
That day-type / hour has no optimiser line | Title No optimiser line; rationale No optimiser line for {day} {hour} — nothing to explain. |
| KPI — | vs P50 or ⚠ tol has nothing to show | Saving tile —; ⚠ tol — with no imbalance band on the contract. |
| Load failure | The async page load exits | Flash Could not load nominations. |
A plan with a PPA-less member can still be proposed and approved; submit writes 0 settlement rows (the flash still reports the count).
10.12 Screen ids
| What | Id or selector |
|---|---|
| Strategy tab bar | #strategy-nav |
Overview / Desk (lit from from=) |
#strategy-tab-overview ·
#strategy-tab-desk |
| Crumb + back | #nominations-desk-crumb ·
#nominations-back |
| PPA identity | #org-page-heading ·
#nominations-ppa-identity |
| Page body | #nominations-workbench |
| Empty / no plan | #nominations-empty ·
#nomination-no-plan |
| Plans table | #nomination-plans · #nomination-month-nav
· #nomination-roster-summary ·
#nomination-reoptimise-all ·
#nomination-plans-table ·
#nomination-plan-row-{membership_id} |
| Detail | #nomination-plan-detail ·
#nomination-plan-meta · #nomination-plan-month
· #nomination-plan-generated ·
#nomination-plan-steps |
| Actions | #nomination-open-costs ·
#nomination-approve · #nomination-submit |
| KPIs | #nomination-kpis ·
#nomination-kpi-nominated ·
#nomination-kpi-cost · #nomination-kpi-saving
· #nomination-kpi-tol ·
#nomination-kpi-overrides |
| Hour grid | #nomination-hour-grid ·
#nomination-heat-legend ·
#nomination-cell-{day}-{hour} |
| Rationale | #nomination-rationale-panel ·
#nomination-scenario-chart ·
#nomination-decision-mwh ·
#nomination-decision-reading ·
#nomination-override-form ·
#nomination-override-input ·
#nomination-save-override ·
#nomination-clear-override ·
#nomination-rationale-numbers |
| Cost modal | #nomination-cost-modal · .wg-modal-header
· #nomination-cost-form ·
#nomination-cost-close · #cost-topup-ckwh ·
#cost-tolerance-pct · #cost-topup-current ·
#cost-tolerance-current |
| Overview door | #overview-open-nominations |
| Desk doors | #commit-plan-{id} ·
#desk-open-nominations |
10.13 What this page is not
- It is not a fifth
#strategy-navtab. Overview or Desk stays lit so you can see which door you used. - It does not use day-type tabs or a separate ovr row. All three day types are on one grid; override lives in the rationale form.
- It does not put a Nominated PPA card at the top. Member · PPA · MW live in the page heading. vs P50 is on the KPI strip, not the plans table.
- It does not submit for you. The 20th worker only proposes.
- Peaker cover (naming a thermal member as top-up) is a membership setting on Pools, not a control on this workbench.
- Forecast, Outcomes and BESS keep their own chapters. This page does not steal those screens.
10.10 Reconcile before sign-off
The Nominated tile is the calendar-weighted total of the effective hourly quantities, including manual overrides. Multiply each day type’s daily total by the number of matching days in the delivery month, then add them. Submission expands those same templates into three 20-minute rows per hour in South African Standard Time (SAST).
If the saved summary differs by more than 0.001 MWh, the roster says needing reconciliation, uncertain cost and tolerance summaries show dashes, and a warning shows both quantities and the calendar counts. Approve plan and Submit nominations are disabled; the server also refuses either action, so the status and settlement rows remain unchanged. Re-optimise a proposed plan. An already approved inconsistent record needs a corrected replacement; the page does not silently rewrite its approval. New demo plans derive totals and costs from their templates. Older demo records can still show this warning. Manual quantity overrides refresh a proposed plan’s quantity summary; cost figures remain the optimiser’s baseline.
11. BESS — dispatch the battery
Open Trader Pools → pool → Operations → Battery
dispatch at
/org/trader-pools/pools/:id/operations?panel=battery.
Legacy /strategy/bess links enter this panel. The five
workspace tabs remain visible.
The Forecast fold (#book-battery) is a five-tile summary
of that run plus Open full dispatch ›. The
destination page is taught in §11.11. Books without an active
battery never see the fold or a populated page.
What it is for. A battery is the one member whose value is time itself: it buys hours and sells them back later. This screen gives it a real, deterministic dispatch: an hour-by-hour charge/discharge schedule computed against your book's actual spill and shortfall, priced with the same conventions as everything else, and — critically — explainable both ways: every hour it moved energy shows its economics, and every profitable-looking pair it declined shows why it held.
The classic pattern it monetises is the one most South African books have: midday solar spill (paid-for energy with no buyer) three hours before an evening peak / firm shortfall (energy bought from the grid at punitive rates). A dispatched battery converts the one into the other.
Without a battery
Read it: paid-for solar sits unused at noon; the evening demand line clears the stack — expensive grid top-up.
With dispatch
Read it: the dashed gold wedge soaks spill into the battery; the purple band returns it against the evening firm gap. Fine gold line = SoC.
11.1 The battery's physics, in five parameters
The asset-config modal (⚙, §11.4) captures the battery as the dispatcher sees it. The defaults are sensible for a grid-scale lithium unit:
| Parameter | Default | What it means |
|---|---|---|
| Usable capacity (MWh) | — | The energy window between the SoC bounds — how much the battery can hold. |
| Max charge / discharge (MW) | — | Power limits: how fast energy can go in or come out (per hour). |
| Round-trip efficiency η_rt (%) | 88 | Of every kWh cycled through, only 88% comes back. Losses are split evenly: one-way efficiency = √0.88 ≈ 0.938, so charging 5 000 kWh stores ≈ 4 690, and delivering 5 000 draws ≈ 5 330 from storage. |
| Min / max SoC (%) | 10 / 100 | The operating window — the dispatcher never drains below the floor or fills past the cap. |
| Initial SoC (%) | 10 | Where each planning period starts; within a run, each day starts where the previous day ended. |
| Max cycles/day | 1.5 | The warranty limit, in equivalent full cycles (energy discharged ÷ usable capacity). The dispatcher will not exceed it, however profitable the day looks. |
| Degradation cost (c/kWh) | 15 | Warranty amortisation per discharged kWh — cycling is never free, and this keeps the dispatcher honest about it. |
| Min spread (c/kWh) | 20 | The profitability threshold (§11.2). Below it, the battery holds rather than grinding out thin cycles. |
| Grid charging allowed | off | Whether the battery may charge from the grid. ⚠ Enabling it adds wheeling cost and dilutes the battery's green (REC) attributes — the modal warns you. |
11.2 How the dispatcher decides — the spread rule
This section is for someone who has never dispatched a battery. No trading jargon assumed. By the end you should know what the engine looks at, what "spread" means in Rand, why some hours charge and others discharge, what gets held back, and what to look at on the screen.
In plain English — the warehouse problem
Imagine you run a warehouse that can store goods overnight.
- In the morning you sometimes have leftover stock nobody bought — it is already paid for, sitting idle.
- In the evening customers arrive who will pay a high price (or you would otherwise buy emergency stock at a punishing rate).
The smart move is obvious: park the leftovers in the warehouse in the morning, sell them in the evening. That is what a battery does with electricity.
Two catches make it non-obvious:
- Storage is lossy. Put 100 units in; only about 88 come back out (round-trip efficiency from §11.1).
- Cycling wears the asset. Every discharge costs a little warranty money (degradation).
So the engine does not move energy just because "evening is expensive". It asks, for each possible morning→evening pair: after losses and wear, is the profit large enough? That profit gap is the spread. Below your min spread threshold, the battery holds — it stays idle on purpose.
Step 1 — what the engine already knows
Before the battery moves anything, an allocation run has already priced the book without it (Pass A — §7.3). For every hour of the day the engine therefore already knows:
| Input | Plain meaning | Why the battery cares |
|---|---|---|
| Spill | Paid-for energy with no buyer | Cheap (often free) charge fuel |
| Firm shortfall | A firm promise the book cannot cover | Highest-value place to discharge — avoids expensive grid top-up |
| Unmet sales | Demand that could still take energy | Next best discharge outlet (peak, then standard) |
| Prices | Contract buy, sell, wheeling, top-up | Turn every hour into cents per kWh |
Those four facts become two numbers per hour: a charge cost ("how expensive is energy going in?") and a discharge value ("how valuable is energy coming out?").
Step 2 — charge cost (what it costs to fill the battery)
The engine always charges from the cheapest available source first. Think of a shopping list sorted by price:
Charge cost ladder — cheapest first
- Spill — energy the book already paid for but nobody took. If spill is zero-rated, charge cost is 0 c/kWh (free fuel).
- Surplus PPA energy — leftover contracted supply. Cost = the contract buy price (e.g. 65 c/kWh).
- Grid off-peak — buying from the grid to charge. Only available if you ticked Grid charging allowed in §11.1. Usually the most expensive option, and it dilutes green attributes.
Step 3 — discharge value (what the energy is worth coming out)
Discharge goes to the highest-value outlet first — the place where each kWh saves or earns the most:
Discharge value ladder — highest outlet first
- Firm shortfall — cover a firm promise the book cannot meet. Value = the avoided Eskom top-up (e.g. 210 c/kWh). This is usually the best use of a kWh.
- Peak sale — sell into peak demand. Value = sell price − wheeling (e.g. 150 − 15 = 135 c/kWh).
- Standard sale — same idea in standard hours (e.g. 120 − 15 = 105 c/kWh).
Step 4 — what "spread" means in cents
Pick one charge hour and one later discharge hour. The spread is the profit per kWh delivered, after two taxes:
The spread rule — in four lines
- Spread = discharge value − (charge cost ÷ η_rt) − degradation.
- Dispatch only when spread ≥ min spread (default 20 c/kWh).
- Rank clearing pairs highest-spread first (best profit first).
- Everything else is held — and listed so you can see why (§11.4).
Plain-language unpacking of the two taxes:
- Efficiency tax (÷ η_rt). Round-trip efficiency 88% means: to deliver 1 kWh out, you must put roughly 1 ÷ 0.88 ≈ 1.14 kWh in. Free spill still costs 0 after this; paid energy gets more expensive.
- Degradation tax. Default 15 c/kWh of discharged energy — warranty wear, so cycling is never "free profit".
- Min spread. Even a positive spread can be too thin. Below the threshold the battery holds rather than grinding a cheap cycle.
Good pair — dispatch
Read it: free midday spill into a 210c firm gap. After the 15c wear tax, 195 c/kWh remains — well above the 20c floor.
Thin pair — held
Read it: paid charge into a weaker sale. Spread is positive (16.1) but below 20 — the engine refuses the cycle and lists it as held.
Step 5 — how charge vs discharge is chosen for the day
For each day the dispatcher roughly does this:
- Build candidate pairs — every sensible charge hour × later discharge hour, using the ladders above.
- Score each pair with the spread formula.
- Drop pairs below min spread (they become the rejected-pairs strip on screen).
- Take the best remaining pairs first, subject to physics: usable capacity, max MW in/out, SoC floor/cap, and max cycles/day (§11.1).
- Write the schedule — each hour is charge, discharge, or idle; SoC walks from morning start to evening end.
The classic South African shape from the chapter opener — midday spill in, evening firm gap out — is simply the highest-spread pairs winning that race.
Step 6 — what you should look at on the screen
When a day has been dispatched, read it in this order (§11.4 has the full map):
Trader checklist — one dispatched day
- KPI strip — day margin (Rand earned), cycles/day (warranty budget), spill absorbed, firm backing, end SoC.
- Dispatch chart — bars down = charge; bars up = discharge; SoC and price lines. Full reading guide: §11.4 · How to read the dispatch chart.
- Schedule table — hour-by-hour action, kWh, source, cost, value, spread, SoC after, and a plain-English rationale.
- Rejected-pairs strip — every pair the engine declined, with the arithmetic ("13h → 21h · spread 16.1 < min · held"). This is how you audit a "no" as easily as a "yes".
If charge energy is free spill, the rejected strip is often empty — free fuel clears almost any threshold. It fills up when charging starts costing real money.
Worked example — one August weekday. Battery: 5 MW / 20 MWh usable, η_rt 88%, SoC 10–100%, degradation 15 c/kWh, min spread 20 c/kWh, start SoC 2.0 MWh. Book that day: zero-rated solar spill of 6.7 MWh/h from 10:00–13:00; peak sales at 17:00–18:00 worth 135 c/kWh net; a firm shortfall at 19:00 whose avoided top-up is worth 210 c/kWh.
Four candidate pairs scored:
Pair value cost ÷ η_rt degr. spread ≥ 20? spill 10h → firm-short 19h 210 0 15 195.0 ✓ best spill 11h → peak 18h 135 0 15 120.0 ✓ spill 12h → peak 17h 135 0 15 120.0 ✓ solar @65 13h → standard 21h @105 105 73.9 15 16.1 ✗ held The last row is the discipline the spread rule buys: 16.1 c/kWh is positive but below the 20c threshold — the battery holds instead of wearing its warranty for thin margin. That is the pair you find in the rejected-pairs strip.
The SoC walk (schedule table):
Hour Action MWh SoC after 10:00 charge from spill 5.0 in 2.0 + 5.0 × 0.938 = 6.69 11:00 charge from spill 5.0 in 11.38 12:00 charge from spill 5.0 in 16.07 13:00 charge from spill 4.19 in (clipped) 20.00 — the cap 14–16 idle — 20.00 17:00 discharge to peak 5.0 out 20.00 − 5.0 ÷ 0.938 = 14.67 18:00 discharge to peak 5.0 out 9.34 19:00 discharge to firm 5.0 out 4.01 (20%) ✓ above the floor The battery charges 19.19 MWh to deliver 15 — the 13:00 top-up to the cap is free spill banked so SoC survives three full-power discharge hours. Cycles: 15 ÷ 20 = 0.75 of the 1.5/day cap ✓. Book spill that day drops from 26.8 to ~7.6 MWh.
The economics: peak sales 2 × 5 000 kWh × 1.20 = R 12 000; firm backing 5 000 × (2.10 − 0.15 − 0.15) = R 9 000 → ≈ R 21 000 for the day, against R 0 for the same battery sitting idle — and midday take-or-pay spill is partly recovered as the charge source.
11.3 Setting a battery up
- The site must be a battery. Only generator sites with technology BESS or HYBRID can carry dispatch parameters — the form rejects anything else.
- Configure the dispatch parameters. If your book has no configured battery, the BESS screen's empty state lists your organisation's eligible BESS/HYBRID sites, each with a [Configure dispatch] button → the asset-config modal (§11.1). One battery configuration per site.
- Make it a pool member. The dispatcher only sees batteries that are active members of an active supply pool — conventionally your 🔒 Firm pool (a battery is the classic firm-backing asset). Add the site as a member on the Pools screen (§5.3).
- [Re-run dispatch] — runs the current month; the two-pass (§7.3) engages and the day view populates.
To stop dispatching without losing the configuration, edit the asset and untick active — the member reverts to a plain flat firm block.
11.4 Reading the screen
The chart-reading guide lives here. The full
/strategy/bess walk — every control, id, empty state, and
the T1 demo — is §11.11.
The page is one day inside the battery’s month, under the Book. It opens with the Book’s thread strip (
#book-thread, Forecast stage lit), a breadcrumb Book · Forecast · Battery dispatch (#bess-crumb) naming the run this dispatch belongs to, and ‹ Back to the forecast (#bess-back-to-book). Then a headline written from the selected day, the five facts, the dispatch chart, the day as moves, the reserve verdict when one exists, and the hourly schedule folded beneath. The right rail holds the month heat-calendar, the asset card, and what the battery feeds in the Book.
The identical day view appears as the BESS tab
inside any run detail that dispatched a battery (§8.4) — there it shows that run’s frozen
schedule; /strategy/bess shows the latest Forecast that
already has intervals.
How to read the dispatch chart
This is the picture of one selected day: what went into the battery, what came out, how full it was hour by hour, and what each active hour cost or earned. You do not need trading jargon — only the words below.
Terms used on this chart
| Term | Plain meaning |
|---|---|
| Charge | Energy going into the battery this hour (filling it). |
| Discharge | Energy coming out of the battery this hour (emptying it into a use). |
| SoC (state of charge) | How much usable energy is stored at the end of the hour, in MWh. |
| Price (on the chart) | The cents-per-kWh figure for that hour's action: charge cost on charge hours, discharge value on discharge hours. Idle hours sit at zero. |
| SAST | South African Standard Time — every hour label on the chart is a SAST clock hour. |
Axes and units
The chart has three scales working together:
What each axis shows
- Bottom (X) — hours of the selected day, labelled
0h…23hin SAST. Each bar is one settlement hour. - Left (Y), unit MWh — energy. Charge and discharge bars are megawatt-hours moved in that hour. Because the interval is one hour, bar height in MWh also equals average power in MW for that hour — but the axis title on screen is MWh, not MW. The SoC line uses this same left axis (stored energy).
- Right (Y), unit c/kWh — money intensity. The dashed Price line (and, when present, the P25–P75 forecast ribbon) plot here. Split gridlines are hidden on the right axis so the energy picture stays primary.
Zero on the left axis is the mirror line: charge bars grow downward (negative), discharge bars grow upward (positive). That is deliberate — energy in and energy out are opposite directions on the same scale.
Legend — each series on the live chart
The legend under the plot lists these names exactly as the UI draws them. Series that have no data that day simply stay flat at zero (or hide their band).
Contract charge
Bars below zero in emerald (#059669). Energy
charged from non-market sources — typically
spill (paid-for energy with no buyer) or leftover
contract supply. On T1 this is the overnight fill, not
a midday solar wedge.
Market charge
Bars below zero in a separate amber tone. Energy bought from the market / grid to charge the battery. Only appears when Grid charging allowed is on (§11.1). Treat it as a warning colour in the story: real money went in, and green attributes may dilute.
Contract / firm Discharge
Bars above zero in amber (#f59e0b). Energy
discharged into the book's own outlets — covering a firm
shortfall, or selling into contracted / peak demand. This is
the "evening cover" stack on a classic day. T1’s October forecast
instead sells evenings to market (pink), so this series
often stays flat.
Market Discharge
Bars above zero in pink. Energy discharged into the market rather than the book's firm or contract outlets. Absent on many books; when present it means the battery earned by selling out rather than by covering your own shortfall.
SoC
A smooth purple line on the left (MWh) axis. End-of-hour stored energy. It should rise through charge windows, hold (flat) through idle hours, and fall through discharge windows. It must stay inside the asset's min/max SoC window (§11.1).
Price
A dashed slate line on the right (c/kWh) axis. On a charge hour it is the charge cost; on a discharge hour it is the discharge value. Hover the chart to read the exact number for that hour. Idle hours sit near zero — there was no priced action.
P25–P75 forecast
A soft purple ribbon on the right (c/kWh) axis. Shown only when the day used a market price forecast. It is the uncertainty band between the 25th and 75th percentile forecasts — the lane the dispatcher considered for market-aware hours. If you see no ribbon, that day had no forecast cells attached.
Reserve floor
A teal dashed band / floor on the left (MWh) axis. Shown only when the run held a reserve (see the Reserve band KPI and the Reserve availability card under the chart). It marks the raised SoC floor the battery must respect — energy kept back rather than fully discharged for arbitrage. The companion "Reserve base" series is the ordinary min-SoC floor; the legend highlights Reserve floor as the held level.
Note. "Spill absorbed" and "Firm backing" are KPI tiles, not legend series. The chart shows where energy moved; the schedule's Source / Outlet badges and those KPIs tell you why that movement mattered for spill and shortfall.
One day on the dispatch chart
Read it: left axis = MWh (bars + SoC); right axis = c/kWh (dashed Price). Midday bars below zero fill the battery; evening bars above empty it; SoC climbs then falls; Price is cheap at charge and valuable at discharge.
Step-by-step — reading one day
Use this order every time. It turns a busy plot into a five-minute audit.
Six steps — how to read the dispatch chart
- Orient on the day and the hours. Confirm the
day picker selection and the amber selected-day badge
on the chart header. Scan
0h→23h(SAST). Mentally mark midday (roughly 10h–14h) and evening peak (roughly 17h–20h) — that is where classic SA books move energy. - Find the charge windows. Look below the zero line for emerald Contract charge (and any amber Market charge) bars. Note which hours are tallest — those are the main fill hours. Idle hours have no bar.
- Find the discharge windows. Look above the zero line for amber Contract / firm Discharge (and any pink Market Discharge) bars. Check that discharge sits later than the charge you just found — time-shifting is the whole point.
- Trace the SoC trajectory. Follow the purple SoC line left → right. It should rise while charging, stay flat while idle, and fall while discharging. Ask: does it hit the cap too early (clipped charge)? Does it scrape the floor (or a teal Reserve floor) before evening is done? End-of-day SoC should match the End SoC KPI — that is tomorrow's start.
- Look for rejected opportunities and gaps. Hours with no bars between a charge block and a discharge block are idle by design, not missing data. Then drop to the rejected-pairs strip: every held pair ("13h → 21h · spread 16.1 < min") is a profitable-looking move the engine refused. Tall midday spill with an empty evening and a busy rejected strip often means the spread rule (or cycles/SoC limits) blocked cover — not that the chart failed to draw.
- Compare to the demand / spill story. Pair the
picture with the KPI strip and the Hourly schedule:
- Midday Contract charge + schedule Source = Spill → this is spill absorbed into storage (the Spill absorbed KPI).
- Evening Contract / firm Discharge + schedule Outlet = firm → this is shortfall covered / firm backing (the Firm backing KPI).
- Read the dashed Price line (or hover tooltips): charge hours should be cheap (often 0 c/kWh on zero-rated spill); discharge hours should be valuable (firm avoided top-up is often the tallest). If Price is high on a charge bar, you are looking at paid or market charge — check whether that still cleared min spread in the schedule's Spread column.
Tip. Hover any hour on the live chart for the axis tooltip (all series at that hour). Then open the matching row in Hourly schedule for Source, Outlet, Spread, and the plain-English Rationale — chart for shape, table for proof.
[⚙ Asset config] on the right-rail asset card re-opens the parameters modal (§11.1); saving prompts "Battery saved. Re-run dispatch to apply." — configuration changes never silently alter an existing run (immutability, §1.3); they take effect on the next run, whose inputs hash will show the change. The full modal walk is §11.11.
11.5 What it feeds
The dispatch flows into everything downstream automatically: the
run's BESS_CHARGE / BESS_DISCHARGE lines (§8.5) roll into the run KPIs, the nightly
snapshot picks up four battery metrics (arbitrage margin, cycles/day,
spill absorbed, firm backing — §12.7), the
dashboard's ⑥ BESS panel displays them, a cycles/day risk
limit (§12.6) turns warranty
discipline into an alert, and the Overview's next-best-actions (§4.5) prompt you when the battery runs
near its cap with profitable pairs still on the table — the data-driven
case for a bigger battery, which the Simulation workbench (§9) can
then price.
11.6 In the wholesale market, degradation cost travels as a price
Worth knowing before your battery enters SAWEM, because it changes where one of these parameters lives.
The market registry asks a storage unit four things (§7.4): its charging rating, its minimum stable charging point, its energy levels, and its cycle efficiency. It asks nothing about degradation. There is no field for cost per discharged kilowatt-hour, no field for maximum cycles per day, and no field for minimum spread — the Market Operator has never heard of them and could not act on them if it had.
So those three stay here, doing exactly what they do now: driving dispatch, gating pairs on the spread rule (§11.2), and feeding the cycles/day risk limit. They are not sent to the registry, and the registration payload is tested to exclude them.
The cost still reaches the market — as a price. A battery’s offer is a ladder of cost increments, and the deeper rungs, the ones only reached on a hard discharge, carry more degradation than the shallow ones. A shallow cycle offers cheaper than a deep one, which is what the physics says and what a market can actually act on.
Two things follow for how you read a market offer built from this book:
- The spread rule and the offer ladder are not the same
mechanism. Here, a pair below
min_spreadis simply not dispatched. In the market, the same reluctance shows up as a higher price on the deep rungs — the market may still clear it, and it pays for the privilege. - Get the ladder wrong and nothing looks wrong. Priced too low, the battery is dispatched more than it should be and earns revenue that does not cover the life it is spending. Priced too high it never clears and earns nothing. From outside, the battery just looks unlucky.
How much of a cycle counts as “shallow”, and whether the ladder reflects marginal or average life cost, are open commercial decisions rather than calculations. Building the offer is V9 §5’s territory; what a storage unit registers is V9 §3.7.
11.7 The market offer still carries a flat addend
§10.6 above described where degradation cost would travel. It now travels. When the desk builds a submission curve for a storage unit, the degradation cost is added to every discharge block’s cost increment before the curve goes to the market. It is no longer a parameter that stops at the book boundary.
Two things about that are worth stating plainly, because the second one is a limitation and not a feature.
The decision. Degradation reaching the market through the offer price is a decision, not something derived from the Market Code. The Code gives a storage unit no field for it, and it was never going to grow one — degradation is a commercial parameter and the registry holds physical ones. Pricing it into the offer is the only route left, and it is recorded as such rather than presented as the obvious reading.
The market-offer addend is a single constant. In the market curve, a shallow cycle and a deep one price identically. The same rand-per-megawatt-hour is added to the first discharge block and the last, which is precisely what §10.6 said should not happen. It is a placeholder that works and is honest about being one: the code asserts that market-curve limitation by name in a test. The book’s dispatcher now uses the owner’s depth curve when one is recorded; this does not change the wholesale offer builder.
Depth would need the increments to differ by block — the third block carrying more life cost per megawatt-hour than the first. Deciding by how much is a question for a battery engineer with your warranty curve, not for a reading of the Market Code, which is why it is still open.
What this means for you in the meantime: your battery’s offers into
SAWEM are cost-covering on average across a cycle and wrong at both ends
of one. If your commercial case turns on deep-cycle discipline, keep the
min_spread rule doing that work here in the book, where it
is depth-aware, rather than expecting the market offer to carry it.
11.8 Depth: the same kilowatt-hour costs more at the bottom of the battery
The owner can record a warranty cycle-life curve on Battery
contract. Load LFP default fills the editor
with the illustrative LFP default v1 table; it does not
save or apply it. The owner must also record the cycling-attributed pack
replacement cost and provenance, including residual-value treatment. A
battery without a table keeps its configured flat wear cost, normally 15
c/kWh. The trader sees the resulting Depth (%) and Wear (c/kWh) on each
dispatch interval.
The dispatcher divides effective capacity into ten equal
terminal-energy slices. Each slice costs the extra fraction of a pack
consumed at that depth, divided by the slice’s kWh. It only discharges a
slice when the outlet price less charging cost, efficiency losses and
that slice’s wear clears the minimum spread. A depth wear
hold means the next slice failed that test.
| Depth band | LFP default wear (c/kWh), 20 MWh and R25.2m pack |
|---|---|
| 0–10% | 5.65 |
| 10–20% | 11.49 |
| 20–30% | 15.67 |
| 30–40% | 19.04 |
| 40–50% | 22.27 |
| 50–60% | 25.09 |
| 60–70% | 28.06 |
| 70–80% | 30.23 |
| 80–90% | 33.41 |
| 90–100% | 34.09 |
On a shallow day delivering 8,000 kWh, the table charges R1,037.04 of wear, compared with R1,200 at flat 15 c. At an outlet worth 62 c with charging at 10 c and 88% round-trip efficiency, the eighth slice still clears a 20 c minimum spread; the ninth does not. The depth model stops at 16,000 kWh and books R3,150 of wear. A single fill of this battery, with its 10% storage floor, can physically deliver at most 16,885.50 kWh; an 18,000 kWh flat comparison would need another charging opportunity during the day. Wear is based on cumulative terminal discharge, not the instantaneous percentage of stored energy.
11.9 State of health
The owner records a dated capacity test rather than overwriting history. A 94% test makes a 20 MWh asset dispatch as 18.8 MWh from that date: its 10% floor becomes 1.88 MWh and its 1.5-cycle budget becomes 28.2 MWh. Power ratings stay unchanged. Before any test, dispatch uses nameplate capacity. Existing runs retain their applied health percentage in their daily audit.
Smaller slices also increase wear per kWh if the pack replacement cost is unchanged. At 94% health the ladder is divided by 0.94; on the 62 c example above the eighth slice now fails and the depth model stops at 70%, or 13,160 kWh. Health and pack cost are visible only to the owner. The trader’s two contract chips show cycles against the owner’s cap and measured round-trip efficiency, with No settled month yet before ACTUAL battery evidence exists.
11.10 The two plans of one day
Open Plans to compare the day-ahead and latest intraday schedules. The hand-over hour marks where the replacement schedule starts. Earlier hours are copied from the preceding plan; their energy and ending state of charge do not change. Without a replan, the screen says No re-plan today. The reserve-floor band marks the storage that a contracted upward service needs.
A weather refresh rebuilds the remaining plan before the IDM decision reads the position. A completed 2 MW, one-hour upward activation draws 2,000 terminal kWh and reduces stored energy by 2,132.007 kWh at 88% round-trip efficiency. The daily audit records that correction and its instruction reference. Replaying the same inputs creates no extra plan. Later replans carry the executed part of the earlier intraday plan and apply each activation once. A measured state of charge can replace the assumed hand-over value when telemetry is available.
For the noon example, 10,000 kWh charged before noon leaves 11,380.832 kWh in storage. If only 1,200 more kWh can charge, evening delivery falls from 13,000 to 9,856 kWh: a 3,144 kWh change. The state of charge immediately before noon is conserved; the ending value of the changed noon interval is expected to differ. The IDM decision uses the revised suffix while the DAM record and the day-ahead forecast remain available.
11.11 The
/strategy/bess page
The problem. The Forecast fold tells you whether this run used the battery. It does not show the day. You still need to see the tank fill and empty: which hours charged, which hours discharged, why a pair was held, and which settings the dispatcher obeyed.
Think of the battery as a water tank. Cheap leftover energy is water you pour in. Expensive evening hours are taps you open later. This page is the tank’s diary for one day — and a calendar of the other days in the same run.
Data. full_demo · seed 42 · T1 Renewables Pool (
01a0ab54-e46b-7dde-b45f-73d119213c75) · Rosslyn BESS (5 MW / 20 MWh) · last read 2026-09-19 from the seeded book.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Book → Forecast →#book-battery→ Open full dispatch ›, or open/org/trader-pools/01a0ab54-e46b-7dde-b45f-73d119213c75/strategy/bessdirectly. You should see Book lit on#strategy-nav, Forecast lit on#book-thread, and a headline for Sunday 13 September.
How you get there
There is no BESS door on #strategy-nav. The four tabs
stay Operations · Performance · Allocation · Commercial ·
Dashboard. While you are on this page,
Allocation (#strategy-tab-book) is the lit
tab.
Ways in:
| Door | What it does |
|---|---|
| Forecast fold Open full dispatch › | From #book-battery on Book · Forecast (§6.17). The href is
/strategy/bess with no ?run=
— the page picks its own run (below). |
| Direct URL | /org/trader-pools/:id/strategy/bess |
| Overview next-best action | Battery at {n} cycles/day — near the warranty cap →
Open BESS /bess (§4.5) |
| Run detail BESS tab | The same day view (BessView) frozen to
that run (§8.4). Use this when you need
a month that is not the latest Forecast. |
| Old BESS tab | /bess still opens this page under Book (§3.4) |
The Forecast fold stays the summary. Do not expect the hour table there.
Which run it opens
The page heading is Dispatch — {power} MW / {energy} MWh (T1: Dispatch — 5 MW / 20 MWh). The subtitle: The battery’s part of the forecast run: one dispatched day at a time, inside its month, under the Book.
On connect it shows Loading BESS dispatch…, then binds one run:
- Take the book’s latest complete, non-superseded
Forecast run (§6)
(
latest_allocation_runsorted by creation, not by calendar month). - If that Forecast already stored dispatch intervals, use it.
- If it stored none, walk other complete non-superseded runs and take the first that has intervals (older demos sometimes left battery evidence only on a Simulation).
T1’s latest Forecast with intervals is the September 2026 P50
(01a0b951-b50d-76c2-bfd8-840b7ecc12cd). The crumb chip
reads FORECAST P50 · 01 Sep 2026 → 01 Oct 2026 ·
complete. The run KPIs are all zero: arbitrage R
0, cycles 0.00 / day, spill absorbed 0
%, firm backing 0 %. That matches the Forecast
fold’s tiles (§6.17).
The page does not read ?run= or
?month= from the Forecast URL. If you had a different run
selected on Forecast, Open full dispatch › can still
land on this latest Forecast. To inspect another run’s battery, open
that run’s ledger and use the BESS tab.
T1 also has an October 2026 P50 Forecast
(01a0ab61-a371-729c-b79c-c36c7881b70f) that did
dispatch — about R 569,889 arbitrage over the run,
0.836 cycles a day, 1.3 % of spill
absorbed, still 0 % firm backing. It is older by
creation, so /strategy/bess does not open it. The worked days below use September for
what this page shows, and 29 October for a day that actually moved
energy.
Top of the page
Read downward.
#book-header /
#book-thread. The same three-stage strip as every
Book view: Rules → Forecast → Outcomes. Forecast is lit
(#book-stage-forecast). The Forecast pill is the book’s
spill or coverage word — not a battery pill. Click Forecast to leave
this page and return to the fold.
#bess-crumb. Book · Forecast ·
Battery dispatch — 5 MW / 20 MWh, then the run chip
(data-role="bess-run-chip") and the words the battery’s
part of this run.
#bess-back-to-book. ‹ Back to
the forecast returns to
/strategy/book?mode=forecast&run={id}&month={YYYY-MM}
when a run is bound, or to Forecast without a run if none is.
#bess-contract-chips. Two owner-facing
numbers the trader may see:
| Chip | Id | What it says |
|---|---|---|
| Cycles to date | #bess-cycles-chip |
Trailing-year cycles against the owner’s
BESS_CYCLES_PER_YEAR cap, or No settled month yet ·
owner’s cap {n / not recorded} |
| Measured RTE | #bess-rte-chip |
Measured round-trip efficiency after an Actual month, or No settled month yet |
T1 shows No settled month yet on both until Actual battery evidence exists. Health and pack cost stay on the owner’s Battery contract (V4 §20).
#bess-flat-model. A one-line note
Wear: flat {n}c/kWh (no cycle-life table). Hidden on T1 —
Rosslyn carries a cycle-life table, so wear varies with depth (§11.8).
#bess-plans. A closed
<details>: Plans · day-ahead and intraday.
With no intraday replan for the selected day,
#bess-no-replan reads No re-plan today.
When an Intraday run exists for that date,
#bess-plan-comparison shows the hand-over hour
(#bess-hand-over) and a 24-row table of day-ahead vs
intraday discharge (#bess-plan-hour-0 …
#bess-plan-hour-23). How the two plans relate is §11.10. On T1, 13 September
has no replan; 19 September can.
A simulated ribbon appears only when a Simulation owns the bound run. T1’s September Forecast does not show one.
The headline and the facts
#bess-headline is one sentence written
from the selected day’s moves and the run’s battery KPIs.
- A day with neither charge nor discharge: On {weekday date} the battery did nothing: no hour cleared the minimum spread.
- A day that moved energy: On {weekday date} the battery earned (or lost) R {n}: it charged {MWh} from {sources} and discharged {MWh} to {outlets} at up to {c} c. {cycles} cycles a day over the run, {spill %} of the book’s spill absorbed, {firm %} of firm hours backed.
T1 on Sunday 13 September charges 2.3 MWh from spill and discharges nothing, so the sentence reports earned R 0 and the run’s zeros. Later September days (14–19) take the did nothing wording.
Under the headline: One day of the battery’s month. The facts, the chart, the moves and the hours are one object; the day strip on the right is how you change it…
The facts (data-role="bess-facts") sit
above the chart. Each tile (data-role="bess-fact") has a
label, a short hint, the day number, a run ·
line for the whole Forecast, and a pointer to the chart or table that
proves it.
| Label | Hint | Day number | Run line | Pointer |
|---|---|---|---|---|
| Day margin | Realised discharge margin for selected day | Rand for this day | run · {R} · arbitrage over the run | → the moves below |
| Cycles/day | Discharged energy ÷ usable capacity ÷ days (vs warranty max cycles/day) | This day’s equivalent full cycles | run · {n} · a day over the run · cap {max} | → energy moved |
| Spill absorbed | Spill converted to stored energy | The run’s % (not re-cut per day) | of the book’s spill, over the run | → the teal charge bars |
| Firm backing | Output serving firm shortfall | The run’s % | When zero: discharges into the market, not Firm Pool shortfall | → the outlet column |
| End SoC | Energy carried into next day | Last interval’s SoC, MWh | min {floor} · max {cap} MWh | → the SoC line’s last point |
Three extra tiles appear only when the run stored them:
| Label | When | What it is |
|---|---|---|
| Market arbitrage | bess_market_arbitrage_r present |
Day-ahead spread against the P25–P75 forecast |
| Reserve band | bess_reserve_mwh present |
MWh held back for the reserve offer |
| Forecast slippage | bess_forecast_slippage_r present |
Realised against the price forecast |
T1 September shows the five standing tiles at R 0 / 0 / 0 % / 0 % / 4.0 MWh on the 13th (End SoC is the tank after the 2.3 MWh charge). Market arbitrage, reserve band and slippage stay hidden — the KPI map has no keys for them. Firm backing’s run line is the amber warning: this battery sold (or sat) rather than covering Firm Pool shortfall.
The dispatch chart on this page
The chart lives in a white card titled Dispatch
chart. Subtitle: Charge bars below zero, discharge above —
with SoC (MWh) and price (c/kWh) over the day. The moves under the chart
are the same hours, grouped. The amber selected-day badge is
#bess-chart-selected-badge. The plot itself is
#bess-dispatch (the shared .StrategyChart
hook).
How to read the axes, colours and legend is §11.4. Do not re-learn it here.
On T1 13 September you will see a small emerald Contract
charge bar at 0h and a flat night. No discharge
bars. The purple SoC line steps from the morning start up to 4.0
MWh and holds. That is an honest empty-ish day, not a broken
chart.
The day as moves
#bess-moves groups consecutive hours
that did the same thing. One row (data-role="bess-move",
data-kind, data-hours) per block.
| Kind | Left border | Title pattern | Money |
|---|---|---|---|
| Charge | Teal | Charge {MWh} MWh from {spill / the market / the grid / contract supply} | −R {charge cost} · bought · charge |
| Discharge | Sky | Discharge {MWh} MWh to {market / firm shortfall / contract demand} | +R {margin} (rose if negative) · margin · discharge |
| Held | Dashed grey | Held plus the rejected pair that starts in the block | R 0 · declined |
| Idle | Dashed grey | Idle or Held · full | R 0 · waiting |
A lone idle hour is dropped (the table still has it). Two or more idle hours become a row.
Under the rows: Rejected pairs — why the battery
held. Empty copy: None — every profitable charge→discharge
pair was dispatched. When pairs exist, each line is
{charge}h → {discharge}h · spread {c} · below minimum · held
(or held by marginal depth wear). Market-sourced holds show the
P25 − P75/η − degradation arithmetic.
T1 13 September: one charge move (Charge 2.3 MWh from spill at 40 c), then a held/idle evening whose schedule rationale is contracted reserve held. Day margin stays R 0 because nothing came back out.
If the selected day has no intervals, the section says No dispatch on this day.
When the run held a priced reserve,
#bess-reserve-verdict appears under the moves:
Reserve availability (MWh at the schedule boundary,
market alternative vs reserve offer, and why the floor was held or
released) plus the reserve card. T1 September does not render it —
bess_reserve_mwh is absent — even though some hour
rationales still say the reserve was held.
Hourly schedule
#bess-hourly-schedule is a dashed
<details>, closed until you open it. Summary:
Hourly schedule — Charge and discharge actions for
the selected day, hour by hour — the 24 rows behind the moves.
Badge: #bess-schedule-selected-badge.
The table is #bess-hourly-schedule-table. Above it, the
sun/moon legend: Sun hours 06–17 / Dark hours
00–05 and 18–23. Each hour cell carries a sun or moon.
| Column | Tip on the header | What you read |
|---|---|---|
| Hour | (no tip) | SAST hour with sun/moon |
| Depth (%) | Depth of discharge, percent | End-of-hour depth, or Not recorded |
| Wear (c/kWh) | Wear cost, cents per kilowatt hour | Slice wear, or Flat model |
| Action | charge when energy enters; discharge when it leaves | Emerald charge or orange discharge badge |
| kWh | Energy moved this hour | Charge-in or discharge-out, rounded |
| Source | Spill, Contract, or Market — blank on discharge | Amber Spill, cyan Contract, rose Market |
| Outlet | contract, firm, or market — blank on charge | Teal contract, violet firm, rose market |
| Forecast | Short price-forecast id and confidence lane | {first 8 of id} · {lane}, or — |
| Cost | Charge cost in c/kWh | The stored cost; — when idle |
| Value | Discharge value in c/kWh | Blank on charge rows |
| Spread | Value minus cost against the min-spread rule | Often blank on a pure charge |
| SoC | State of charge after the hour, MWh | End-of-hour usable energy |
| Rationale | Human-readable reason | e.g. charge 2.27 MWh from spill @ 40.0c |
Empty body: No dispatch this day. (13 columns.)
These rows are the persisted dispatch intervals — the audit
trail behind BESS_CHARGE / BESS_DISCHARGE
lines (§8.5).
The right rail
On a wide screen the rail is the right three columns. On a narrow screen it stacks under the day view.
#bess-day-picker. Card labelled
Dispatch period, with the run’s first–last interval
dates (T1: 13 Sep 2026 – 19 Sep 2026 — only days that
stored intervals, not the whole September month). Selected-day badge:
#bess-day-selected-badge. Month label with ‹
› (shift_calendar, disabled at the edges of the
interval set). Weekday chips Mon–Sun. Each date is
#bess-day-{YYYY-MM-DD}
(data-role="bess-day-tile"). Days without intervals are
greyed and disabled. A teal bar (data-role="bess-day-bar")
is that day’s margin, scaled to the month’s tallest day. Footer:
Each tile’s bar is that day’s margin; the month reads before you
click. Click a live tile to rebuild the headline, facts, chart,
moves and table for that date.
#bess-asset-card. The
asset — The numbers the dispatcher obeys. Each row is
data-role="bess-param":
| Label | Note | T1 Rosslyn |
|---|---|---|
| Power | max charge / discharge | 5 / 5 MW |
| Energy | usable · SoC 10–100 % | 20 MWh |
| Round trip | efficiency η | 88 % |
| Cycles | warranty cap a day | 1.5 |
| Degradation | priced into every spread | 15 c/kWh |
| Min spread | below this the engine holds | 20 c/kWh |
| Grid charging | market as a source | allowed |
⚙ Asset config opens the branded Edit
battery modal (green #wg-modal-header, close
#bess-config-close, Escape or Cancel). Fields match §11.1, each with
an info tip. Allow grid charging warns that grid charge
adds wheeling and dilutes green (REC) attributes. Submit is Save
& re-run. Success flash: Battery saved. Re-run dispatch
to apply. Failure: Could not save the battery
configuration.
Re-run dispatch runs the engine for the current calendar month (not the bound Forecast’s month) and flashes Dispatch re-run. Then the page reloads. Re-run never silently edits the old run (§1.3). The note under the buttons: Re-run recomputes this run’s battery pass; the Book’s Forecast stage re-reads.
From the empty-battery state the same modal is titled Configure battery and is reached from Configure dispatch on an eligible site.
#bess-feeds-card. What it feeds
in the Book.
| Row | T1 September |
|---|---|
| Firm Pool shortfall · member of the Firm pool | Amber pill 0% backed |
| Book spill · charged at the spill value | Teal pill 0% absorbed |
| Market arbitrage · day-ahead spread | Hidden unless the KPI exists |
Links: Rules · Firm Pool card › →
/strategy/pools, and Forecast · battery fold
› → the same Forecast URL as ‹ Back to the
forecast.
Empty states
| What you see | When | What to do |
|---|---|---|
| No battery configured. Dispatch modelling needs a BESS or HYBRID generator site with dispatch parameters. plus a list of eligible sites and Configure dispatch | The book has no active BessAsset member |
Configure, then add the site to a supply pool (§11.3) |
| No eligible BESS/HYBRID sites in this organisation yet. | Empty list inside that dashed box | Register a BESS or hybrid site first (V2) |
| No dispatched run yet — press Re-run dispatch. | A battery is seated but no complete run stored intervals | Press the button in the box |
| Loading BESS dispatch… | First paint / after save or re-run | Wait; a load failure flashes Could not load BESS dispatch. |
| No dispatch on this day. / No dispatch this day. | Selected date has no intervals, or only idle hours that the moves list dropped | Pick another day, or believe the hold |
| Headline the battery did nothing | Intervals exist but no charge or discharge cleared the spread rule | Read rejected pairs and the reserve rationale |
| Forecast fold present, this page all zeros | T1 September — the battery is seated and the run stored intervals, but it did not sell the stored kWh | Honest. The 2.3 MWh charge and the reserve hold are the whole story |
Books without battery KPIs never render #book-battery.
You can still type /strategy/bess; you will land on the
configure-empty state if no asset is seated.
T1 on the demo
Two days, two truths.
What /strategy/bess opens (13 September 2026,
latest Forecast). Rosslyn is a 5 MW / 20 MWh tank, 88 %
round-trip, 10–100 % SoC, 1.5 cycles/day, 15 c/kWh wear, 20 c/kWh min
spread, grid charging allowed, cycle-life table on. At
00:00 it charged 2,272.727 kWh from spill
at 40.0 c/kWh. SoC ended the hour at 4.012
MWh and stayed there. Hours 17–20 are stored as idle with
rationale contracted reserve held — the evening tap stayed
closed so a contracted reserve could keep the floor. Day margin
R 0. Cycles 0. The Forecast fold’s
Battery R 0 tile is the same story in five numbers.
A day that did dispatch (29 October 2026, October P50
Forecast — open that run’s BESS tab). Overnight it poured
18.0 MWh of spill into the tank at 40 c
(00h–03h, last hour clipped at the
18.8 MWh health-adjusted cap). Evening it sold
15.9 MWh to the market at 186
c (17h–20h). SoC walked 6.57 → 18.8 →
1.88 MWh. Wear rose with depth (11.0 → 35.4 c/kWh). Day margin about
R 23,174. The October run totals about R
569,889 arbitrage, 0.836 cycles a day,
1.3 % of a huge spill book absorbed, 0
% firm hours backed — it sold evenings rather than covering
Firm Pool shortfall.
Looks good: a charge block, a later discharge block, SoC that climbs then falls, day margin above zero, rejected pairs you can recite. Looks bad: a named BESS, a 96 % spill tile on Forecast, and this page’s facts still at R 0 — T1 September.
What to do next on T1 September
- Believe the page: the tank took 2.3 MWh and held it for reserve. It did not earn.
- Open the October run’s BESS tab if you need to see a charge→discharge day on this book.
- Do not raise min spread or re-run hoping September will suddenly absorb the 57 GWh spill — the battery is 20 MWh.
- When you want a buyer for the leftover solar, leave through Forecast · battery fold › and use Find offtake → Desk (§6.19).
Data. full_demo · seed 42 · stage S09 (settlement matrix) · last re-derived 2026-09-19 against the seeded T1 book (September P50
01a0b951-…; October P5001a0ab61-…for a dispatching day).Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: T1 Renewables Pool → Book → Forecast → Open full dispatch ›. You should see Book lit, Forecast lit on the thread strip, and Sunday 13 September with a 2.3 MWh spill charge and R 0 day margin.
12. Dashboard — the story of the pool
Route: …/strategy/dashboard ·
Tab: Dashboard
What it is for. Overview (§4) is today. The Book (§5, §6) is how the pool is wired and what this month did. The Desk (§9) is where you act. The Dashboard is the long view and the coach: how the pool has performed since it began, where the money leaked, who it traded with, how healthy it has been month by month, what the next twelve months look like, and the moves that would change them most. It is the trader’s twin of the off-taker (V5 §7) and IPP dashboards — six chapters, each a verdict sentence, one visual and a So what.
Of the ten numbered panels this page used to be, two survive as folds — forecast quality by member under Chapter 4 and the sampled distribution under Chapter 5. The rest were removed in 3.9.1 because the chapters, the Book or the Bid Desk already tell what they told; their sections below are kept as stubs so older links still land.
The six chapters
The verdict and the dial. The header writes one sentence from the numbers (“The book made R 1.3 m over 6 months but kept only 57 % of what it could have; R 1.0 m leaked, most of it grid top-up above sale price”) and shows the pool’s single score: kept of what the book could have made. Achievable is realised margin plus the avoidable losses in Chapter 2; the dial is realised ÷ achievable. Chips grade the months — settled (every leg FINAL), preliminary (a draft or preliminary leg), engine (an ACTUAL run, no settlement), forecast (the current month) — and a flagged month (a ledger or seed artefact, such as sales many times larger than purchases) is dimmed and excluded from every total. Read an earlier snapshot keeps the old Period card for audit; Edit limits opens the limits editor (§12.6).
| Chapter | The question | The visual | Folded underneath |
|---|---|---|---|
| 1 · Performance | Did the book make what the plan said, and what it could have? | Margin by month: settled bar, plan outline (that month’s FORECAST), achievable tick; the current month as a forecast band; one diary line per month | — |
| 2 · Where it leaked | Every Rand the book could have kept and did not, with an owner | The loss ledger: unsold energy below cost · market alternative not taken (the avoidable part, counted by the dial) · grid top-up above sale price · imbalance charges · nomination misses · take-or-pay not used · network carried (a cost, not a loss) · paired items that cancel (excluded). Rows stay visible at zero; each names its owner and links to the screen that fixes it | — |
| 3 · Who we traded with | Which counterparties actually moved energy, and which are only wired | The trading web: sources left, buyers right, the pool in the middle; solid lines are settled kWh, wide by volume; dashed lines are members that never settled a leg. Spill / SAWEM and the grid are counterparties too; a trader-to-trader leg is violet. A ranked table with cheapest, most reliable, ≥ 50 % of revenue, trader, modelled badges | — |
| 4 · Health over time | Was each vital inside its limit, month by month, and what changed when a colour did | The health strip: eight vitals (coverage, spill, shortfall, margin at risk, concentration, counterparty exposure, imbalance, nomination accuracy) × every month, coloured by the limit in force that month — your limit where one exists, a default threshold where none does — with an events row read from contract dates, limit effective dates, the snapshot’s structure digest changing and plan status | forecast quality by member (the ⑧ league) |
| 5 · Outlook | Where is the book heading | Twelve months at P50 with the P90 band, the first move dotted in; facts: margin at risk, VaR 95 / 99 at one day and one month, the position next month with its Option 0 | the sampled distribution — margin quantiles p05–p95 with its absent / stale notice (§22) |
| 6 · Next moves | What would change the next twelve months most | Up to three moves ranked by Rand a month — sell the unsold block, nominate (or drop) the trader-to-trader sale, add an evening shape, buy the short hours, tighten tolerance, run the back-cast — each opening the Desk, Nominations, the Book or the Bid Desk. Run the back-cast scores the last settled month in one click and lights the nomination rows | — |
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Dashboard. In full_demo the story runs February to September 2026: four engine months, two settled months (June, July: purchases from Sandton Solar and Midrand Hybrid, no sale settled), August flagged, September the forecast. The dial reads about 57 %; the web shows one supplier and no settled sale; the outlook says the year loses money at P50 because 95 % of supply has no buyer; move 1 is to sell the unsold block.
Data. The story reads settled legs with REVERSED re-runs dropped (the same rule as the Book’s check), the ACTUAL and FORECAST runs, the month-end snapshots, the hourly imbalance positions, the BRP panel, nomination plans, limits and memberships. When a month is back-cast, its nomination and forecast-quality scores now also land on that month’s ACTUAL snapshot, so the health strip can show them as a series.
The folded panels
Two folds remain — open one by clicking its dashed Folded · bar under the chapter. Forecast quality by member (Chapter 4) is the MAPE / bias league per member on the selected snapshot, worst contributor first. The sampled distribution (Chapter 5) is the margin fan — quantiles p05 to p95 from the stochastic sampler — with a stated absence when no distribution exists for the snapshot and a stale notice when it is from another date; the method is §22. The sections that follow describe the panels that were removed.
12.1 Top bar
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in the header — Read an earlier snapshot and Edit limits — see the six chapters. The heading and anchor are kept so older links still land here.
12.2 ① Portfolio Margin
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in Chapter 1 · Performance — see the six chapters. The heading and anchor are kept so older links still land here.
12.3 ② Risk
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in Chapter 5 · Outlook and Chapter 4 · Health over time — see the six chapters. The heading and anchor are kept so older links still land here.
12.4 ③ Coverage
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in Chapter 4 · Health over time (the coverage row) — see the six chapters. The heading and anchor are kept so older links still land here.
12.5 ④ Price
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in Chapter 1 · Performance (the landed and sale c/kWh on each month) — see the six chapters. The heading and anchor are kept so older links still land here.
12.6 ⑤ Operational Alerts + Edit limits
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in Chapter 4 · Health over time and the header’s Edit limits — see the six chapters. The heading and anchor are kept so older links still land here.
12.7 ⑥ BESS
Battery contract limits now include BESS_CYCLES_PER_YEAR
(above), BESS_RTE_MEASURED_PCT (below) and
BESS_AVAILABILITY_PCT (below). They are data-driven
warn/breach limits evaluated after ACTUAL battery evidence arrives. The
trader’s BESS page shows cycles against the owner’s cap and RTE; the
owner sees all three on Battery contract. See V4 §20 for the window
and evidence basis.
Where this is taught. The trader
/strategy/besspage — contract chips, day view, calendar — is §11.11.
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in the chapters above — see the six chapters. The heading and anchor are kept so older links still land here.
12.8 ⑦ Nomination Performance
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in the chapters above — see the six chapters. The heading and anchor are kept so older links still land here.
12.9 ⑧ Forecast Quality
Route cue: Dashboard → panel ⑧ Forecast Quality.
This panel answers one question: "After the month settled, how wrong was the forecast — as a portfolio error rate, as a signed over-/under-estimate, and which members dragged the book?" Panel ⑦ scores nominations you submitted (§12.8). Panel ⑧ scores the engine's forecast energy shapes against the same meters. Same Actual gate; different question.
Everything here comes from the selected risk
snapshot — and only when that snapshot's metrics already carry
a non-empty FORECAST_ACCURACY_BY_MEMBER map (merged in by
backcast after an Actual run). On Forecast — or before any member can be
scored — the panel shows the awaiting-actuals copy.
In plain English — every concept on this panel
Read this once; the rest of the section assumes these words.
| Word on / about the panel | Plain meaning |
|---|---|
| Forecast (energy) | What the engine expected each non-proxied member to generate or consume that hour, from the month's FORECAST run inputs |
| Actual (energy) | What meters observed for that member that hour — the settled truth the backcast uses |
| Backcast | Re-running allocate on settled volumes for the same delivery month (§6.2). Seals the Actual snapshot and merges forecast-quality metrics into it |
| MAPE | Mean Absolute Percentage Error — average hour-by-hour |forecast − actual| ÷ actual, as a percent. "How far off, ignoring whether high or low" |
| Bias | Signed error: (Σ forecast − Σ actual) ÷ Σ actual × 100. Positive = forecast was too high (over-estimated settled energy). Negative = forecast was too low |
| Portfolio MAPE / Bias | Book-wide scores: MAPE is volume-weighted across eligible members; bias uses the summed forecast and actual totals |
| Member row | One scored site / membership: its own MAPE, bias, and settled kWh |
| Settled kWh | Sum of that member's observed meter energy over hours used in the score |
| Proxied member | A membership whose energy is inferred, not metered — excluded from this scorecard (same provenance rule as nomination scoring) |
| Zero-actual hour | An hour where the meter read 0. Dropped from MAPE (dividing by zero is meaningless); still counted in bias totals when present |
| Awaiting settled actuals | Empty state when FORECAST_ACCURACY_BY_MEMBER is empty —
usually Forecast period, or Actual backcast has not yet scored a
matching FORECAST run |
When this panel lights up — the Actual gate
Panel ⑧ is gated on settled reality plus a scored forecast. It does not invent quality on a forward plan.
On a Forecast period (or unscored Actual)
What you see. Grey note: "Awaiting settled actuals — member forecast quality appears after an ACTUAL backcast."
Why. There is no member breakdown yet. The Forecast
run is live for panels ①–⑥; comparing it to meters waits for
backcast to pair that month's COMPLETE FORECAST run with ACTUAL inputs
and write FORECAST_MAPE_PCT /
FORECAST_BIAS_PCT /
FORECAST_ACCURACY_BY_MEMBER.
What to do. Keep using Forecast for morning triage.
Flip Period to an existing … · Actual
month (§12.1), or run backcast after meters
land (§6.2).
On an Actual period (after backcast scored the forecast)
What you see. Two tiles — Portfolio MAPE, Bias — plus a member table sorted by impact (MAPE × settled kWh, worst first).
How they get there. Backcast finds the matching COMPLETE FORECAST run for the same delivery window, builds forecast vs actual hourly energy per non-proxied member, scores MAPE/bias, and merges the results into the Actual risk snapshot.
Neighbours. ⑦ Nomination Performance shares this Actual unlock. ⑨ Market does not — market figures can already be live on Forecast when BRP registration is ACTIVE (§12.10).
| You want to… | Period select | Why |
|---|---|---|
| See whether June's forecast was noisy | Jun 2026 · Actual |
MAPE / bias need settled hours vs the June Forecast run |
| Plan July before meters | Jul 2026 · Forecast |
Panel ⑧ correctly says awaiting — use run detail / Simulations instead |
| Check "did backcast even score quality?" | Actual month still awaiting | No matching FORECAST run, no eligible members, or metrics not merged yet |
Careful. Panel ⑧ is not nomination accuracy. A perfect nomination scorecard with an ugly MAPE means declarations were good but the engine's prior shape was wrong — different fix (error profiles / membership / forecast inputs), not only re-optimise nominations.
Anatomy — every visual element on panel ⑧
| Piece on screen | What you see | What it means |
|---|---|---|
| Panel title | ⑧ Forecast Quality |
Report card for forecast energy vs settled meters |
| Tile grid | Two stat cards | Live when the member map is non-empty |
| Portfolio MAPE | Percentage, e.g. 9.3% |
Volume-weighted average member MAPE for the book |
| Bias | Signed percentage, e.g. +4.1% or
−12.5% |
Portfolio over-/under-estimate; leading + when ≥ 0 |
| Member table | Columns: Member · MAPE · Bias · Settled kWh | League table of who contributed error |
| Footer note | "Positive bias means the forecast over-estimated settled energy." | Reminder of the sign convention |
| Empty state | "Awaiting settled actuals …" | No members in FORECAST_ACCURACY_BY_MEMBER on the
selected snapshot |
Sort order. Rows are ordered by MAPE × settled kWh descending — not alphabetically. A medium MAPE on a huge plant ranks above a terrible MAPE on a tiny site, because that is where the book's error mass lives.
The two portfolio tiles — what each shows and why it matters
Portfolio MAPE · FORECAST_MAPE_PCT
What it is. For each eligible member, hour MAPE is the mean of |F − A| ÷ A over hours with actual > 0. Portfolio MAPE is the settled-volume-weighted mean of those member MAPEs:
member MAPE % = mean over hours ( |F − A| ÷ A ) × 100 (skip A = 0)
portfolio MAPE % = Σ (member MAPE × member settled kWh) ÷ Σ settled kWh
Rounded to one decimal on the tile.
Why it is here. One noise number for the book. High MAPE means the shapes you planned on were unreliable — nomination residual scenarios, MaR stories, and DAM positions all inherit that uncertainty (§10.2).
How to read it.
| Reading | Meaning | Typical next look |
|---|---|---|
| Low single digits | Forecast tracked meters well | Still check bias sign and the member league |
| ~10–20% | Material noise | Which members own the impact column; run Δ (§8.2) |
| ≫ 20% | Systematic shape failure | Membership / resource assumptions; refresh forecast-error profiles after enough Actuals |
| Low MAPE, ugly ⑦ | Forecast OK, nominations not | Nominations workbench — not a modelling fire drill |
Bias · FORECAST_BIAS_PCT
What it is. Signed portfolio error:
bias % = (Σ forecast − Σ actual) ÷ Σ actual × 100
Taken over the same members/hours used in the scorecard (forecast
summed only on hours that have an actual observation). Displayed with an
explicit + when non-negative.
Why it is here. MAPE is unsigned — 10% high and 10% low look the same. Bias tells you the direction: persistently positive means you planned as if more energy existed than meters delivered (optimistic supply / underestimated demand, depending on side); negative means the opposite.
How to read it (UI footer agrees).
| Reading | Meaning | Typical next look |
|---|---|---|
| Near 0% with moderate MAPE | Noisy but centred | Hour-shape noise; member table for outliers |
| Sustained + (over-estimate) | Forecast too high vs meters | Spill / shortfall story on Actual run; do not grow sales on that optimism |
| Sustained − (under-estimate) | Forecast too low vs meters | Missed cover or under-declared resource; check whether MaR used a timid P50 |
| Big |bias| with small MAPE | Almost impossible long-run — usually one-sided hours dominate | Member rows; which hours actually settled |
The member table — every column
| Column | Field | What it shows | How to use it |
|---|---|---|---|
| Member | label |
Display name of the scored membership (site / PPA label) | Identify who — open that member on Pools / run detail |
| MAPE | mape_pct |
That member's own mean absolute % error | Noise for this site alone |
| Bias | bias_pct |
That member's signed (F − A) ÷ A × 100 | Direction for this site; same + / − convention |
| Settled kWh | actual_kwh |
Sum of observed meter kWh in the score | Weight — large settled kWh × MAPE = why this row sorted high |
Who appears. Non-proxied members that have at least one eligible actual hour (actual > 0 for MAPE). Members with no meter overlap against the forecast are omitted — they do not pad the table with zeros.
Worked sort. MAPE 10% on 500 kWh (impact 5 000) ranks above MAPE 12% on 100 kWh (impact 1 200). The UI test fixture uses exactly that pattern: Tshwane Solar before Small Wind.
How forecast vs actual relate (schematic)
Think of one member-hour as two bars: what the forecast claimed vs what the meter showed. Absolute gap feeds MAPE; the sign of the gap feeds bias.
Notice. The same 20% absolute miss can be +bias or −bias. Portfolio MAPE treats them alike; the Bias tile and the Bias column do not.
Worked example — three solar hours, then a two-member book
Same arithmetic the engine uses (WB.Strategy.Accuracy).
Numbers match the unit tests so you can re-check by hand.
One member — three hours (seeded solar check)
| Hour | Forecast (F) | Actual (A) | |F−A|÷A |
|---|---|---|---|
| h11 | 16.40 | 14.76 | 11.1% |
| h12 | 16.71 | 16.71 | 0.0% |
| h13 | 15.20 | 12.16 | 25.0% |
MAPE = mean(11.1%, 0%, 25%) = 12.0%.
Bias = (16.40+16.71+15.20 − 14.76−16.71−12.16) ÷ (14.76+16.71+12.16) × 100 ≈ +10.7% (forecast over-estimated).
Two members — portfolio weights
| Member | Settled kWh | Member MAPE | Contribution |
|---|---|---|---|
| Small solar | 100 | 10% | 1 000 |
| Large wind | 300 | 20% | 6 000 |
Portfolio MAPE = (1 000 + 6 000) ÷ 400 = 17.5%.
If Small forecast 110 vs 100 and Large forecast 240 vs 300: portfolio bias = (110+240 − 100−300) ÷ 400 × 100 = −12.5% (book under-estimated overall because the large wind miss dominates).
1 · Hour MAPE crumbs → 12%
Look for: tall absolute misses, not the sign. Learn: mean of the three crumbs is 12%. Act: if live months stay here, open the member league before blaming nominations.
2 · Bias stack → +10.7%
Look for: whether Σ F sits above or below Σ A. Learn: positive bias means the forecast over-stated settled energy. Act: do not add sales that need that "air" energy.
3 · League sort by impact
Look for: top row = biggest MAPE × kWh product. Learn: fix the heavy plant first. Act: open that member's Actual vs Forecast Δ on run detail.
Zero-actual hours (edge case)
Hour with A = 0 is skipped for MAPE (no division by zero) but still participates in bias when you sum forecast and actual totals. A forecast of 100 against a true zero meter hour does not inflate MAPE; it does push bias positive if that hour is in the actual map as an explicit zero.
How to read Forecast Quality — a deliberate order
- Confirm the Period card shows
… · Actualfor the month you care about (§12.1). Awaiting on Forecast is expected. - If awaiting on Actual, confirm a COMPLETE FORECAST run exists for that same delivery window and that backcast has run (§6.2).
- Read Portfolio MAPE — noise size for the book.
- Read Bias — direction. Remember: positive = over-estimated.
- Walk the member table top-down — first row is usually where to spend investigation time.
- Pair with ⑦ Nomination Performance — same meters, different decision (submitted nominations vs engine shapes).
- Pair with run-detail Δ (§8.2) when you need hour evidence, not only the league.
- Act forward — refresh error profiles / membership / next Forecast; you cannot rewrite last month's sealed snapshot by staring at the tiles.
What you can learn — and how to act
| What the panel shows | What it usually means | What to do next |
|---|---|---|
| Awaiting on Forecast | Gate working as designed | Flip to Actual, or wait for backcast |
| Awaiting on Actual | No scored members / no paired FORECAST run | Run backcast; confirm Forecast COMPLETE for that month |
| Low MAPE, bias ≈ 0 | Shapes held | Protect the process; watch ⑦ separately |
| Low MAPE, bias persistently + | Quietly optimistic | Do not grow offtake on that optimism; check spill on Actual |
| Low MAPE, bias persistently − | Quietly pessimistic | Coverage / shortfall may have been worse in plan than in meters |
| High MAPE, one member on top | Local resource / meter / seating fault | Fix that membership first |
| High MAPE, many members | Systemic forecast process | Error profiles, weather/resource inputs, proxy exclusions |
| Ugly ⑧, quiet ⑦ | Forecast wrong, nominations still hit | Modelling fix; nominations may be compensating by luck |
| Quiet ⑧, ugly ⑦ | Shapes OK, declarations not | Nominations re-optimise / submit discipline (§12.8) |
| Rising MAPE month over month | Residuals drifting | Overview next-best-actions; stop treating P50 as certain |
Why this panel exists (desired outcomes)
- Score the forecast itself, not only the nominations layered on top of it.
- Separate noise (MAPE) from direction (bias) so "wrong" has a verb.
- Name the members so triage starts at the top of the impact league, not in a spreadsheet hunt.
- Stay honest about the Actual gate — quality appears only after meters and backcast, like settlement.
- Feed the next loop — high MAPE refreshes residual / error-profile thinking for nominations and MaR; it does not rewrite history.
Follow along. Seat:
trader_1@webill.net(passwordsupersecret). Path: Trader Pools → T1 Renewables Pool → Strategy → Dashboard. Pick an… · Actualmonth. Panel ⑧ Forecast Quality should leave awaiting and show Portfolio MAPE, Bias, and the member table (worst impact first). Flip to Forecast and confirm the awaiting copy returns. Compare with ⑦ on the same Actual — they unlock together but answer different questions.
Capacity-normalised skill and diversification
Forecast Quality shows capacity-normalised MAE alongside the existing MAPE and bias. It reads weekly issued-forecast skill evidence; no scorecard means the necessary observations have not landed. The diversification tile compares the book’s generation error standard deviation with the capacity-weighted sum of its members’ standard deviations over their common observed hours.
For capacities 10,000 and 6,000 kW, member deviations 6% and 8% give a weighted 6.75%. A measured book deviation of 4.2% gives a factor 0.622. Perfectly correlated errors give 1.0. No observations or zero denominator are unavailable. The versioned six-month book profile supplies the sampler’s thin-cell fallback; its version and the fallback hours travel with the sampled path set. These metrics do not introduce a new bid gate.
12.10 ⑨ Market (BRP)
Retired panel (3.9.1). This panel was removed from the Dashboard when the page became the story of the pool; what it showed now lives in the chapters above — see the six chapters. The heading and anchor are kept so older links still land here.
Capture and the plan-to-actual bridge
The Market panel distinguishes acceptance from DAM capture. Cannibalisation measures how far generation hours fall below the average price; the limit warns above the configured threshold. Capture is a historical benchmark with source and date, rather than a forecast.
The Performance bridge follows seven steps: volume, average market price, generation shape, imbalance, contract terms, leaked energy, and unexplained items. A positive step helped the month; a negative step hurt it. The residual stays visible at zero.
The plan of record is the latest completed monthly forecast in force at SAST month start. A subsequently superseded run can still be that plan. If none existed, a later monthly forecast is labelled plan chosen after the month began · low confidence. Missing plan prices or settled delivery refuse a bridge. Where a bridge exists, the Performance plan bar uses the same plan cents.
