← Manual home

V11 · Market Operator

The market from the Market Operator’s chair — DAM and IDM, then the /mo console room by room.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

1. The market in one picture

The participant volume (V9) teaches what a Balance Responsible Party does with a bid after it leaves the book. This volume is the other chair: the Market Operator. You accept declarations, run the auction, publish one price for the country, write the chalkboard, and later raise the invoice. You do not write a participant’s prices. You do not throw a switch.

Think of SAWEM as a produce market that opens the day before.

Farmers (generators) write sealed notes: “I can sell this many crates, and I will not go below this price.” Buyers (loads) write sealed notes: “I will take this many crates if the price is at most this.” You open every note, fill demand from cheapest supply upward, and announce one crate price for that hour. Every accepted crate trades at that price — not at the number on the farmer’s note. The note only got them into the market.

That auction is the Day-Ahead Market (DAM). It runs once, the day before delivery. Its price is the System Marginal Price (SMP) — one number per hour for the whole country, not one number per zone.

The next morning the weather changes. A solar farm that promised 75 crates can now only deliver 20. The market does not reopen the whole auction. It runs five smaller Intra-Day Market (IDM) auctions that only move the hours still left. The original crate price (the SMP) stays. The intraday auction has its own price, used only for the megawatt-hours that actually moved.

%%{init: {"themeVariables": {"fontSize": "18px"}, "flowchart": {"nodeSpacing": 36, "rankSpacing": 40, "padding": 16}}}%%
flowchart LR
  subgraph yesterday ["Yesterday (D−1)"]
    A["BRPs submit DAM bids<br/>by 10:00"] --> B["MO clears<br/>and publishes by 14:00"]
    B --> C["One SMP per hour<br/>+ two schedules"]
  end
  subgraph today ["Trading Day D"]
    C --> D["Five IDM auctions<br/>revise remaining hours"]
    D --> E["Meters and instructions"]
  end
  subgraph later ["After delivery"]
    E --> F["Indicative statement"]
    F --> G["Initial statement<br/>+ invoice"]
    G --> H["Money moves"]
  end

Three facts that stop most confusion:

  1. The DAM price is not per zone. Zones belong to the System Operator. They limit how much can actually flow. They do not set a local energy price. See §6.6.
  2. Clearing is not paying. You publish schedules and prices at 14:00 on D−1. The cash leaves bank accounts weeks later, on the Settlement Calendar. See §8.
  3. The IDM does not rewrite the DAM bid. It re-uses the day-ahead price curve and changes volume for hours that have not yet started. See §9.

1.1 How to read this volume

If you have twenty minutes, read this chapter, §3, and §11. That is the story: one auction yesterday, five smaller auctions as the day unfolds, money that is calculated immediately and paid later.

If you are answering a participant who says “why was I charged this?”, start at §7 and §8, then walk the same hour in §11.

The current /mo console — panels, queues, Bidding tabs — is §12–§26. Chapter 12 is the map; Market Desk and Bidding share §13; each later chapter is one sidebar room.

Where this is taught. The BRP primer is V9 §1. The System Operator seat is V12. The authority for the numbers in this volume is Market Code Rev 2.3 §§9–10, §14 and §15, written for this chair in docs/references/market/spec/market-dam.md. Nothing here invents a rule. Where the platform has had to interpret a silent clause, the interpretation is named ([D-nn]) and pointed at V9 §17.

1.2 Time and money

Every clock in this volume is SAST, a fixed UTC+02:00 with no daylight saving. D is the Trading Day — the calendar day the energy is actually produced or consumed. D−1 is the day before. A Trading Period is one hour, written as its start: 2026-07-15T18:00:00+02:00 means the hour from 18:00 to 19:00.

Money sign. Positive means the Market Operator pays the participant. Negative means the participant pays the Market Operator. Energy sign: positive means produced, negative means consumed.

The numeric worked day is the same golden fixture every other document uses: Trading Day 2026-07-15, hour 18:00.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

2. The people and the things they own

Before a single number, the seats. Confusing them is the fastest way to misread a statement.

Seat Everyday job What they do not do
Balance Responsible Party (BRP) The participant who bids. One organisation, one market seat. Owns Trading Units. Pays and is paid. Does not set the SMP. Does not dispatch the grid.
Market Operator (MO) Auctioneer, rulebook and clearing bank. Accepts bids, runs the auction, publishes prices, issues statements and invoices. Does not tell a plant to ramp for frequency. Does not invent a bid if a BRP is silent — except the rollover, which copies yesterday.
System Operator (SO) The grid. Forecasts demand, sets reserve requirements, publishes corridor limits, issues dispatch instructions. Does not set the SMP. Does not collect energy-market money.
Trading Unit One registered machine or load the market can schedule: a coal set, a solar farm, a factory, a battery. Bids are per Trading Unit, not per company. —
Market Governance Committee (MGC) Publishes the cap, the floors, the gate times. Does not pick tomorrow’s SMP.

Metaphor. The BRP is the stallholder. The Trading Unit is the stall. You are the market master who rings the bell and writes the day’s price on the board. The System Operator is the traffic police who decide which trucks may use which road. The MGC is the town council that set the stall fees and the closing time.

Who owns what on a market day
BRPone market seat
→owns 1‑n
Trading Unitthe stall that bids
→clears at
SMPone price, one hour
Other authorities
Market Operatorauction + till
System Operatorwires + reserve
MGCcap, floors, gates

Where this is taught. What a BRP does with those objects is V9. What the System Operator does with the wires is V12 §1. This chapter only names the seats so the rest of the volume can use them without repeating the job descriptions.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

3. The clock — when things happen

One table. Times are SAST. D is the Trading Day the energy is delivered.

When Who What Why it matters
08:00 D−1 BRP Last chance to change standing data (nameplate, Mingen, MCR) that will apply on D A bid’s elbows must match the registry. Change the registry after this and an already-accepted bid can be invalidated.
10:00 D−1 SO Publishes demand forecast and reserve requirements for D The auction needs to know how much reserve to hold back.
10:00 D−1 BRP DAM gate closes. Availability and price curves for D and the following six days must be in. A second late is a missed day. You then roll the unit forward from its previous submission.
after the gate MO Generates rolled-over submissions for any Trading Unit that did not submit The market must have a declaration for every registered unit. Silence is not “offer nothing”; it is “keep yesterday’s remaining plan”.
13:30 D−1 SO Interconnection schedule for D (how much is imported or exported on the ties) Arrives after the bid gate and before price publication. Imports are treated as a fixed, zero-cost injection.
14:00 D−1 MO Publish SMP, four reserve system prices, unconstrained and constrained schedules, unit prices, daily adequacy report This is the moment the plan becomes the plan. Solving and publishing are two different buttons.
18:00 D−1 MO / BRP IDM iteration 1 gate. Whole of D can still move. First chance to correct the day-ahead plan.
00:00 D MO / BRP IDM iteration 2 Hours already being delivered cannot be re-declared.
06:00 D MO / BRP IDM iteration 3
12:00 D MO / BRP IDM iteration 4 The worked example’s cloud arrives here.
18:00 D MO / BRP IDM iteration 5. Only 19:00–23:00 remain. A re-declaration for 18:00 at 18:00 is a re-declaration of the past. Refused.
+1 hour after each IDM gate MO Publish the revised schedule and the Intra-Day Price
17:00 D+1 MO Balancing payment calculations (after meters) Not DAM settlement. Different market, different price.
17:00, SD+1 working day MO Indicative Settlement Statement. Check the figures; they are not yet a bill.
17:00, SD+7 working days BRP Data Verification Period closes Argue about data now, not after the invoice.
12:00, Billing Period + 5 working days MO Initial Settlement Statement, Invoice (if the participant owes), Self-Billing Invoice (if the MO owes) This is when a DAM hour becomes a line on a bill.
12:00, invoice + 3 business days BRP Invoice due. Pay in full, no set-off. Shortfall if they pay less.
17:00, self-billing + 4 business days MO MO pays creditors The extra day is the cash-flow buffer: collect first, then pay out.
D−1 into D — the bells you ring (SAST)
00061218
  • 10:00 D−1 DAM gate · SO demand and reserve
  • 14:00 D−1 You publish SMP and both schedules
  • 18:00 IDM iteration 1 (D−1) and iteration 5 (D)

The DAM bid itself is not settled at 14:00 on D−1. What is published then is the arithmetic of the day — volumes × prices, already visible on the schedule report. The cash waits for the Billing Period. Treat 14:00 as the chalkboard and the invoice date as the till.

Where this is taught. The participant’s day is V1 §4 and V9 §4. Cadence on /mo/cadence is §14 — due / ran / missed for every callable on this table.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

4. How DAM bids are submitted

Your problem at intake is simple: every registered Trading Unit must have a declaration at the gate, and none of those declarations may be ones you wrote.

4.1 Who submits

The Balance Responsible Party submits, for each of its Trading Units. You do not write a participant’s prices. You accept, validate, store, and — if the participant is silent at the gate — roll over the last valid declaration.

A bid is not “the company’s bid for Tuesday”. It is “Trading Unit TU-COAL1’s declaration for Trading Day 2026-07-15 and the six days after it”. One company with five units sends five submissions.

Party state May submit? Why
ACTIVE Yes Ordinary case.
Commissioning (not yet a Party) Yes Market Code §6.2(10) lets a commissioning applicant bid so the unit can be tested in the market.
DEFAULT Yes A default is a money problem, not a bidding ban.
Suspended No SUB_PARTY_NOT_ACTIVE. A suspended unit may not bid (§6.4.1).
Deregistered unit No The unit’s own status, not the party’s.

4.2 Three doors into the same room

From your side, every accepted declaration is a WB.Sawem.Submission. How it got there is one of three doors.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 28, "rankSpacing": 36, "padding": 12, "subGraphTitleMargin": {"top": 8, "bottom": 26}}}}%%
flowchart TB
  subgraph door1 ["Door 1 — automatic, this platform as BRP"]
    S["Nightly strategy run"] --> W["SubmitDamBids · 03:00 D−1"]
    W --> G["MO Gateway"]
  end
  subgraph door2 ["Door 2 — the participant's own systems"]
    API["PUT /v1/dam/submissions/{date}/{tuid}"] --> I["Intake"]
  end
  subgraph door3 ["Door 3 — your act, not theirs"]
    MISS["Unit silent at 10:00"] --> R["Rollover: yesterday's day 2<br/>becomes today's day 1"]
  end
  G --> SUB["WB.Sawem.Submission<br/>168 periods, stored forever"]
  API --> I
  I --> SUB
  R --> SUB
  SUB --> V["Validation"]
  V -->|accepted| GATE["Counts at the gate"]
  V -->|rejected| ERR["Nothing stored"]

Door 1 — automatic. The organisation using this application has strategy books. Each night those books compute a net position. WB.Brp.BidBuilder turns that into a price curve. An Oban worker runs at 03:00 on D−1 and submits through the same gateway a third-party BRP would use. Those are still the BRP’s bids. You did not choose the volumes.

Door 2 — the Code path. Any BRP may PUT a conformant body to /v1/dam/submissions/{trading_date}/{tuid} as many times as it likes until the gate. Each replace is a new submission_seq. The newest valid version at the gate is the one that clears. The automatic door is just a client of this door.

Door 3 — rollover. If a Trading Unit has no accepted submission at 10:00, you must generate one (§9.3(2)). You do not invent prices. You take the unit’s previous submission and slide the horizon forward one day: previous day 2 becomes new day 1, …, previous day 7 is repeated as the new day 7. The new row is stored with source: :ROLLED_OVER, a pointer at the submission it was copied from, and a staleness_days counter. A unit that misses seven gates in a row is still offering its original day-7 profile. That is legal. It is also how a forgotten outage becomes a live schedule.

Rollover is not a bid the BRP made. It is the market’s rule for silence. The participant can still correct the day in the IDM.

Where this is taught. How a book chooses those reservation prices is V9 §4. The API contract is V13.

4.3 What “submit” actually does

WB.Sawem.Submission.Intake.put/1 is the only write path. It is a single database transaction: all 168 periods, or none; energy limits, or none; a new submission_seq, or a replay of the same seq with the same body.

Result Meaning What you do
Created New sequence, body accepted Store. Supersede the previous version. Keep the old one for disputes.
Replayed Same sequence, identical body (an Idempotency-Key retry after a timeout) Return the existing row. Do not create a second version.
Sequence conflict Same sequence, different body Reject. They have lost track of what they sent. Tell them to increment the sequence.

A late submission (after 10:00, no extension in force) is not stored. The API returns 409 gate_closed and the identifier of the rolled-over submission that was generated instead, plus the next IDM gate as the next opportunity.

A rejected submission is not stored. Validation errors come back with the Market Code clause, a JSON pointer at the offending field, the value, the constraint, and where useful a remedy.

4.4 Blind, binding, replaceable until the bell

4.5 What you do not do at intake

You do not fill in a missing price curve, “fix” an elbow that does not match the registry, accept a 24-period body and pad the other six days, accept a bid for a suspended party, or publish anyone’s curve to anyone else.

You do validate against the registry and the Code, stamp received_at (that instant decides the gate, even if the gate is later extended), keep every version, roll over silence, and tell the participant which rule broke and what to change.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

5. The DAM bid, field by field

A DAM “bid” in conversation is three nested things. Name them or the screens will lie.

Layer What it is Who sees it
WB.Brp.Bid + BidLine This platform’s BRP-side ledger: book, strategy run, flat opportunity-cost ladder, MO reference. The organisation’s Bid Desk.
WB.Sawem.Submission The Market Code object: 168 periods, structured curves, energy limits, consent flag. You. This is what clears.
The API body The JSON a participant PUTs. Same information as the Submission, in the wire shape. Both.

The rest of this chapter is the Submission. That is what the market determines prices from. The BRP Bid is how this platform produced one — V9 §4.

5.1 The envelope

PUT /v1/dam/submissions/2026-07-15/TU-COAL1

Field Required Plain meaning
market_code_version Yes Which edition of the rulebook this body claims to satisfy. Today "2.3". A body written to a withdrawn edition is not silently reinterpreted.
idm_rescheduling_consent Yes (defaults true) “May the Market Operator move my day-ahead schedule in the five intraday auctions?” false = hold my DAM schedule unless the System Operator imposes a new network constraint. See §9.3.
periods Yes Exactly 168 hourly rows: the Trading Day and the following six days. A 24-period body is the most common mistake and is rejected as a horizon fault, not as 144 missing hours.
production_curves When the unit generates One or more generation price curves, each effective from a named period onward.
consumption_curves When the unit consumes One or more willingness-to-pay curves, same effective-from rule.
energy_limits Mandatory for energy-constrained units; otherwise null Daily and weekly energy caps. null for a coal set or a solar farm that is not energy-constrained.

Headers the participant must send: Authorization (own Trading Units only), Idempotency-Key (retries are one submission), X-Sawem-Signature (a financially binding body without a signature is not a submission).

What you store in addition, which they do not send: submission_id, tuid, trading_date, submission_seq, source (:PARTICIPANT or :ROLLED_OVER), received_at (the instant that decides the gate), signature, the rollover chain (rolled_over_from_submission_id, staleness_days), supersession and invalidation stamps, gate_id, and provenance (strategy_run_id, market_rules_id, bid_id) when this platform built the body.

Invalidation is not supersession. A registry change can break an already-accepted future submission. The participant must be told before the next gate. There may be no replacement.

5.2 One period

Each of the 168 rows is one Trading Period.

Field Plain meaning
trading_period The hour’s start, on the hour, in SAST. A bare Z (UTC) at midnight is two hours out and is rejected.
declared_available_capacity_mw “How many megawatts can I produce this hour?” Capped by the registry MCR. null means “this unit does not generate”; 0.000 means “I will produce nothing”. A solar farm at night sends 0.000.
declared_consumption_mw “How many megawatts will I draw this hour?” A battery or a mixed unit sends both fields in the same hour.
flexible F — the market may move this unit and this unit may set the SMP. I — a commitment to the declared figure. An inflexible unit cannot set the SMP.
instantaneous_reserve / regulating_reserve / ten_minute_reserve A or U. A is refused if the System Operator has certified 0 MW for that category. Offline units may still offer Ten-Minute Reserve.
preferred_run On energy-constrained units only: prefer this hour (Y) or not (N). The energy limit says how much; this says when.

Idle is legal. A period with no capacity, no consumption and no reserve offer is a declaration of absence. “The unit submitted nothing” and “the unit submitted 168 declarations of zero” look the same on a summary and are different compliance positions. The desk must be able to name both.

5.3 The production price curve — a staircase

A generator does not say “my price is R900”. It says “the first 200 MW cost me R350, the next 100 cost R420, …” — a staircase. The market walks up the stairs until demand is filled. The last step it stood on is the SMP.

Field Plain meaning
effective_from_period This staircase applies from this hour onward, until a later curve supersedes it. You denormalise the curve onto every period it covers at write time, so a dispute about 14:00 on the 9th has one row as its answer.
mingen_mw Minimum Stable Generation. Must equal the registry Mingen. The must-run block (0 → Mingen) is priced at Cost Increment 0 and never sets the SMP.
elbow1_mw / elbow2_mw / elbow3_mw Bends. Elbow 3 must equal the registry MCR. The BRP does not invent a nameplate in a bid.
el1_mw Emergency limit, above MCR.
cost_increment_0 … 3 / el1_cost Prices of each step. CI0 may be higher than CI1 — that looks upside-down and is legal, because must-run cannot set the price. Flexible stairs (CI1 onward) only go up.

Zero-width blocks are dropped, not rejected. A solar farm submits Mingen = E1 = E2 = 0 and E3 = MCR — one step, often at R0/MWh. That is the ordinary renewable bid.

The curve is clamped to the hour’s Declared Available Capacity before it enters the stack.

Price-taker. A registration that has chosen to be a price-taker emits a floor-priced curve. It still has to send a legal staircase; the stairs just sit on the floor.

5.4 The consumption price curve

A generator’s curve answers one question: what does it cost me to make the next megawatt? (§5.3). A buyer’s curve answers the mirror question: what is the next megawatt worth to me?

The market needs that answer for a blunt reason. When there is not enough generation to go round, somebody has to stop drawing. Without prices on the demand side the only tool left is a blackout, which takes power away from the people who need it most and the people who barely notice, in equal measure. A consumption price curve lets a site say, in advance and in Rands: this much I will drop readily, this much only at real cost, this much only at severe cost, and this much I cannot drop at all. The market then sheds in that order, cheapest first, and pays for what it sheds.

The four numbers. One Declared Consumption and three cut lines beneath it.

Field Plain meaning
effective_from_period This ladder applies from this hour onward, until a later curve supersedes it. Denormalised onto every period it covers at write time, exactly as a production curve is.
declared_consumption_mw (DC) The whole draw for the hour — the same field as §5.2. Every ladder starts here and cuts downward.
elbow1_mw (E1) The first cut, counting down from DC. The slice between E1 and DC is the one you would give up first.
elbow2_mw (E2) The second cut, below E1.
elbow3_mw (E3) The floor. Everything below E3 is must-serve: the market may not take it away at any price.
cost_increment_1_r_mwh … 3 What each slice is worth to you, in Rand per MWh. CI1 prices the top slice, CI3 the deepest one.

Why it looks upside down. A production curve climbs: the elbows run from Mingen up to MCR, and the prices climb with them. A consumption curve does the opposite — the elbows descend from DC, and the prices rise as they descend. Both shapes obey the same single rule: the market always takes the cheapest option next. Read from the buyer’s side, the slice nearest DC is the last megawatt you added and the one you would miss least, so it is the cheapest to shed. The deeper the cut, the more it hurts, so the price goes up. Written as the Code writes it: E1 ≤ DC, E2 ≤ E1, 0 ≤ E3 ≤ E2, and CI3 ≥ CI2 ≥ CI1 ≥ 0.

So four slices come out of four numbers:

Slice Band Priced at What you are saying
Top E1 → DC CI1 Take this first. I will manage.
Middle E2 → E1 CI2 This one costs me something real.
Deep E3 → E2 CI3 Only in a genuine emergency, and it will be expensive.
Must-serve 0 → E3 unpriced Not at any price.

A worked ladder — TU-IND1, the 90 MW factory.

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10. The same factory the worked example clears in §11.

The factory sends DC 90, E1 70, E2 50, E3 40, and three prices:

Slice Band Width Priced at Shed order
Top 70 → 90 MW 20 MW R 1,500 first
Middle 50 → 70 MW 20 MW R 2,600 second
Deep 40 → 50 MW 10 MW R 4,800 third
Must-serve 0 → 40 MW 40 MW — never

The widths must account for the whole declared draw: 20 + 20 + 10 + 40 = 90 = DC ✓. If they did not, the market would be shedding megawatts the factory never said it would take.

Now walk the price up and watch the factory shrink. Each slice keeps drawing while it is worth more than the clearing price, and stops once the price climbs past it:

If the hour clears at The factory draws Because
R 900 90 MW Every slice is worth more than R 900 — this is what happens in §11
R 2,000 70 MW The top slice was only worth R 1,500, so it drops out
R 3,000 50 MW The middle slice was worth R 2,600
R 5,000 40 MW Only must-serve is left
R 5,396.40 (the cap) 40 MW Still 40 MW. Nothing takes a site below its E3

That is the whole mechanism. The elastic slices behave as bids in the same auction the generators offer into — a generator bids to supply the next megawatt, a consumer bids to keep it — and the clearing price decides which bids stand.

Must-serve comes from E3 itself, not from the priced slices. That distinction matters when a curve has no priced slices at all: the floor is still E3, so a site that declares no flexibility has its entire draw protected.

The fully inelastic declaration is E1 = E2 = E3 = DC. Every slice collapses to zero width, so there are no priced blocks — nothing to shed, nothing to price. This is the correct form for most industrial sites and for a distributor, and it is a one-field declaration: give the consumption and the platform builds the rest. TU-DIST1 in the worked example is exactly this: 440 MW, no stairs. Zero-width slices are dropped, not rejected — the mirror image of the solar farm’s single-step production curve in §5.3.

Two more mechanical facts, then the judgement call:

Choosing the numbers is a commercial decision, not a calculation. The shape above is settled by the Code. What a megawatt-hour is actually worth to a factory is not, and no amount of engineering will tell you. There are three defensible ways to answer it, plus the answer that declines the question — and which one was used is recorded on every curve, as curve_basis on the site’s demand-side profile (WB.Sawem.DemandSideProfile):

Recorded basis Where the numbers come from Why you would use it What it costs you
inflexible No ladder at all — E1 = E2 = E3 = DC The default, and the right answer for most industrial loads Forgoes demand-response revenue
site_declared You asked the site and it answered The strongest basis there is The slowest; many sites genuinely do not know
tariff_ladder Multiples of the site’s own retail energy rate at the applicable time of use Mechanical and defensible; the default derivation where a category has one Ignores that some processes are worth far more than the tariff
alternative_cost The cost of the alternative — a diesel generator, or a stopped production line Closest to the truth Much harder to obtain

The platform implements the shape and leaves the numbers to a configured policy per off-taker category. Recording the basis is what makes a curve auditable: two sites with identical ladders and different bases are not making the same claim, and if a curtailment is ever disputed, which question was answered is the first thing anybody will ask. The safe direction to be wrong in is inflexible — which is why it is the default.

Careful. Both ways of getting this wrong cost the participant, and they are not symmetrical. A site published as inflexible when it could in fact shed load forgoes demand-response revenue — quietly, forever. A site that publishes flexibility it does not have is worse: it gets shed, and it cannot comply.

What you check at intake. The consumption codes in §5.6 are all shape checks — CON_ELBOW1_GT_DC (you priced a slice you never said you would take), CON_ELBOW2_GT_ELBOW1 / CON_ELBOW3_GT_ELBOW2 / CON_ELBOW3_NEGATIVE (the elbows do not descend), and CON_CI1_NEGATIVE / CON_CI2_LT_CI1 / CON_CI3_LT_CI2 (the prices go the wrong way). You cannot check whether R 1,500 is the right number for that factory. Nobody at this desk can.

Where this is taught. The ladder turning into money — curtailment paid at max(own block price, IDP) — is §11.4. On screen, a submitted ladder is the Consumption curtailment order staircase in the declaration drawer (§13.8).

5.5 Energy limits — the reservoir, not the sum

Only energy-constrained units send this: hydro, a battery, a fuel-limited OCGT. For those units the block is mandatory.

Field Plain meaning
day_limits_mwh Exactly seven figures, day 1 … day 7.
seven_day_limit_mwh How much energy is in the reservoir for the whole week.
basis How the figures were derived — audit, not a commercial input.

The weekly figure is not the sum of the dailies. It is allowed to be less, and for a reservoir it usually is. Σ daily > weekly is rejected (EC_DAY_EXCEEDS_TOTAL). Rollover shifts the array by position: yesterday’s day 2 becomes today’s day 1.

5.6 Validation — every code you will fire

A rejection is a list of these, never a shrug. Each carries its clause, a JSON pointer, the offending value, the constraint, and where useful a remedy.

Code Everyday reading
SUB_GATE_CLOSED The bell has rung.
SUB_HORIZON You sent a day, not a week — or you left a hole.
SUB_PERIOD_ALIGNMENT The clock is SAST. UTC midnight is 02:00 here.
SUB_UNIT_NOT_REGISTERED You cannot bid a stall that is not on the plan.
SUB_PARTY_NOT_ACTIVE A suspended seat may not bid.
CRV_MINGEN_MISMATCH The stairs must start where the machine actually can.
CRV_ELBOW1_LT_MINGEN / CRV_ELBOW2_LT_ELBOW1 / CRV_ELBOW3_LT_ELBOW2 / CRV_EL1_LT_ELBOW3 Stairs cannot go backwards.
CRV_ELBOW3_NOT_MCR You do not get to change your nameplate in a bid. Change the registry by 08:00 D−1.
CRV_CI0_NEGATIVE / CRV_CI1_NEGATIVE You cannot offer to pay the market to take your energy by writing a negative price here.
CRV_CI2_LT_CI1 / CRV_CI3_LT_CI2 / CRV_EL1_COST_LT_CI3 Flexible stairs go down. “Cheapest next” becomes meaningless.
CON_ELBOW1_GT_DC You priced a slice you never said you would take.
CON_ELBOW2_GT_ELBOW1 / CON_ELBOW3_GT_ELBOW2 / CON_ELBOW3_NEGATIVE Consumption elbows do not descend.
CON_CI1_NEGATIVE / CON_CI2_LT_CI1 / CON_CI3_LT_CI2 Willingness-to-pay stairs go the wrong way.
AVL_DAC_EXCEEDS_MCR You cannot offer more than the machine.
AVL_INDICATOR_INVALID Flexible is F/I; reserve is A/U.
AVL_RESERVE_NOT_CERTIFIED You cannot sell a service the grid has not qualified you for.
EC_LIMIT_MISSING A hydro without a reservoir figure is offering an unbounded week.
EC_DAY_EXCEEDS_TOTAL The dam is smaller than seven full days.
EC_PREFERRED_RUN_MISSING The limit says how much; the flag says when.
STG_LEVEL_INFEASIBLE The battery cannot be in two states at once.

Two rules you must not add, even though they look tidy:

  1. CI1 ≥ CI0. The Code never requires it. Must-run may be priced above the first flexible block.
  2. A 24-period submission is “close enough”. It is not. The horizon is seven days.
You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

6. How the market determines the prices

6.1 Who sets the price

Nobody picks a number. You run an auction. The last megawatt-hour needed sets the System Marginal Price. The Market Governance Committee published the cap and the reserve floors months ago; those bound the auction, they do not replace it.

The market master does not decide that tomatoes are R20. The master stacks every seller’s crates from cheapest to dearest, serves every buyer who will pay at least that, and the last crate that was needed is today’s price. A farmer who offered R8 still receives R20 if that is where the last crate sat. How those two piles are actually stacked — crate by crate, for one hour — is §6.3.

6.2 Two schedules, one price

The architecture is the order of the runs. Swap them and somebody is paid twice or not at all.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 28, "rankSpacing": 36, "padding": 12}}}%%
flowchart TB
  SUB["Accepted submissions<br/>+ SO interconnect + SO reserve"] --> UC["Unconstrained run<br/>ignores the wires"]
  UC --> SMP["SMP and the four<br/>reserve system prices"]
  UC --> CS["Constrained run<br/>respects corridor limits"]
  CS --> UNIT["Per-unit reserve costs<br/>and constrained volumes"]
  SMP --> PUB["You review"]
  UNIT --> PUB
  PUB --> BOARD["Publish by 14:00 D−1"]
Run What it ignores / respects What it is for
Unconstrained Ignores the network. Energy must still balance (Σ generation + imports = Σ consumption). Prices the market. The SMP is read off this schedule. Energy payments (EPM) are struck on these volumes.
Constrained Respects the System Operator’s corridor and zonal limits. Runs the system. What units actually generate. Reserve unit costs are read off this schedule. The difference versus unconstrained is a separate money line, not a different SMP.

Solving and publishing are two buttons. An operator who has just re-run a day must be able to look at it first. A pipeline that published as a side-effect of solving would make “let me check that” impossible.

6.3 Building the stacks

This section answers one question: who runs and who draws in each hour. It does not yet produce the published number — reading the price off the result is §6.4.

The whole job is four moves, repeated for each of the 24 hours:

  1. Collect the offers. Take every generator’s price staircase (§5.3) and cut it down to what the unit said it could actually do this hour. Add the interconnection import as one free block.
  2. Collect the needs. Take every consumer’s protected must-serve load, then the slices it put a price on (§5.4).
  3. Match them, cheapest first. Keep taking the cheapest offered megawatt until every remaining need is met. The result is the unconstrained schedule — the plan the country would run if every cable were infinite.
  4. Solve it again with the wires on. Where a cable cannot carry the cheap plan, cut the trapped unit back and lift the next-cheapest machine that can get through. The result is the constrained schedule — the plan that actually runs.

Two players do not obey “cheapest first”, and both are deliberate:

Two piles of crates

Keep the produce-market picture from §6.1, and make it specific to the stacks.

Imagine the trading floor as a warehouse with two piles, rebuilt every hour.

The supply pile is every crate a farmer will sell, stacked cheap on the floor, dear on top. A coal set does not send one crate labelled “R 900”. It sends a staircase of crates — a cheap bottom shelf, then dearer shelves above (§5.3). A solar farm usually sends one shelf of free crates. The interconnector sends a fixed bundle that costs nothing. You always lift from the floor.

The demand pile is every buyer standing in a queue. At the front: people who must eat — a distributor’s must-serve load, a factory’s protected floor. They have no walk-away price. Behind them: buyers who will pay a lot, then buyers who will pay less (§5.4). If crates run short you do not thin everyone equally. You send home the buyer who values the crate least — the top of the demand pile — and you keep feeding the people who must eat.

You keep lifting supply crates until every remaining buyer is fed. The last crate you actually lifted is that hour’s price. A farmer whose floor crate was R 350 still receives that last-crate price. A peaker whose crate stayed on the floor sells nothing.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 28, "rankSpacing": 32, "padding": 12}}}%%
flowchart LR
  subgraph recipe ["Each hour"]
    A["Clamp every staircase<br/>to that hour's declaration"] --> B["Stack supply<br/>cheap → dear"]
    A --> C["Stack demand<br/>must-serve, then willing"]
    B --> D["Lift from the floor<br/>until the queue is fed"]
    C --> D
    D --> E["Meeting =<br/>unconstrained schedule"]
    E --> F["Re-solve with the wires on<br/>= constrained schedule"]
  end

Three stacking rules that stop most mistakes:

  1. Clamp first, then stack. A solar farm whose registry MCR is 75 MW but whose Declared Available Capacity this hour is 60 MW contributes a 60 MW crate, not 75. The emergency shelf above MCR only enters if the hour’s declaration reaches it.
  2. A promise sits in the pile even when it is expensive. An inflexible (I) unit is a must-take lump. You do not leave its crates on the floor because a flexible neighbour is cheaper. It promised.
  3. Must-serve has no price, and is never shed. The factory’s protected floor is not “a very high bid”. It is not a bid. Nothing in the auction is allowed to take it away.

Worked hour — stack the golden 18:00

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10. The same cast §11 takes from the door to the chalkboard. Here we only build the piles.

Step 1 — lay every staircase on the bench.

Who What they sent for 18:00 How it enters a pile
Interconnector +20 MWh import One free supply crate. Not a Trading Unit.
TU-PV1 0–75 MW @ R 0, declared I, available 75 One must-take supply crate, already cheap.
TU-COAL1 0–200 @ R 350, 200–300 @ R 420, 300–400 @ R 640, 400–500 @ R 900; F; available 500 Four supply shelves. The R 6,000 emergency shelf is above MCR and this hour’s 500 MW declaration, so it is clamped off.
TU-OCGT1 0–60 @ R 2,800 and up; F; available The expensive top of the supply pile.
TU-DIST1 440 MW must-serve, declared I One demand crate that cannot leave.
TU-IND1 40 MW must-serve; then 10 @ R 4,800, 20 @ R 2,600, 20 @ R 1,500; F Protected floor, then three priced crates. The R 1,500 crate is the first to walk away if supply runs short.

Step 2 — stack supply, cheap on the floor.

Read the pile from the floor upward. Row 1 is the floor — the cheapest crate, and the first you lift. Cumulative is how high the pile has grown after that crate is placed.

Place Crate MW R / MWh Cumulative MW
1 · floor Import, free 20 0 20
2 TU-PV1, must-take 75 0 95
3 TU-COAL1 0→200 200 350 295
4 TU-COAL1 200→300 100 420 395
5 TU-COAL1 300→400 100 640 495
6 TU-COAL1 400→500 100 900 595
7 · top TU-OCGT1 0→60 60 2,800 655

Offered supply 655 MW. 20 + 75 + 200 + 100 + 100 + 100 + 60 = 655 ✓.

Supply pile on its side — cheapest crate at the left — 2026-07-15 18:00
Floor → top655 MW offered
Cheapest first655 MW
Imp 20 PV 75 Coal 200 @ 350 100 @ 420 100 @ 640 100 @ 900 OCGT 60
Floor — import, first liftSolar and cheap coalMid coalLast coal shelfTop — OCGT

Step 3 — stack demand, must-eat at the front.

Most willing first. Must-serve has no Rand number. Priced crates follow from dearest to cheapest — that is willingness. Shed order is the mirror: the cheapest priced crate leaves first. Row 1 is the floor of the queue — must-serve, never shed. Row 5 is the top — first to walk away.

Place Crate MW Worth (R / MWh) If crates run short
1 · floor TU-DIST1 must-serve 440 — Never leaves
2 TU-IND1 must-serve 40 — Never leaves
3 TU-IND1 deep slice 10 4,800 Last priced crate to leave
4 TU-IND1 middle slice 20 2,600 Leaves after the R 1,500 crate
5 · top TU-IND1 top slice 20 1,500 First to walk away

Must-serve 480 MW (440 + 40). Elastic 50 MW (10 + 20 + 20). Total demand 530 MW. 440 + 40 + 10 + 20 + 20 = 530 ✓.

Demand pile on its side — must-serve at the left, then most willing — 2026-07-15 18:00
Front → back530 MW in the queue
Must-serve, then willingness530 MW
Dist 440 Ind 40 10 @ 4,800 20 @ 2,600 20 @ 1,500
Must-serve — never shedWould leave lastWould leave sooner

Step 4 — lift from the floor until the queue is fed.

Every remaining buyer this hour will pay at least R 1,500. That is above every coal shelf and far above the free crates, so nobody walks away. You only stop when 530 MW have been lifted.

Lift Crate taken Running total Still hungry
1 Import 20 @ R 0 20 510
2 Solar 75 @ R 0 95 435
3 Coal 200 @ R 350 295 235
4 Coal 100 @ R 420 395 135
5 Coal 100 @ R 640 495 35
6 Coal 35 of 100 @ R 900 530 0

Taken: 20 + 75 + 200 + 100 + 100 + 35 = 530 ✓. Left on the floor: 65 MW of the R 900 coal shelf, and the whole 60 MW peaker. 530 + 65 + 60 = 655 ✓.

The last crate you needed came from coal’s R 900 shelf, 35 MW into a 100 MW step — not on an elbow. That volume (TU-COAL1 at 435 MW) is what §6.4 will read. The meeting itself is 530 MW served.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 20, "rankSpacing": 28, "padding": 12}}}%%
flowchart TB
  subgraph supply ["Supply pile — cheap on the floor"]
    direction TB
    S1["Import 20 MW @ R 0 — taken"]
    S2["TU-PV1 75 MW @ R 0 — taken"]
    S3["Coal 200 MW @ R 350 — taken"]
    S4["Coal 100 MW @ R 420 — taken"]
    S5["Coal 100 MW @ R 640 — taken"]
    S6["Coal 35 of 100 MW @ R 900 — last crate"]
    S7["Coal 65 MW leftover + OCGT 60 MW — still on the floor"]
    S1 --> S2 --> S3 --> S4 --> S5 --> S6 --> S7
  end
  subgraph demand ["Demand pile — must-eat at the front"]
    direction TB
    D1["TU-DIST1 440 MW must-serve — fed"]
    D2["TU-IND1 40 MW must-serve — fed"]
    D3["Factory 10 MW @ R 4,800 — fed"]
    D4["Factory 20 MW @ R 2,600 — fed"]
    D5["Factory 20 MW @ R 1,500 — fed"]
    D1 --> D2 --> D3 --> D4 --> D5
  end
  S6 -->|"piles meet · 530 MW"| D5
The same meeting as a staircase — supply rises; demand stays willing past R 900 — 2026-07-15 18:00
Supply takenLast crate · R 900Meeting at 530 MWCrates still on the floor

  1. Lift from the floor

530 MW · last crate R 900 0 MW~300655

Read it: each step is a crate shelf. The red tick is where the queue was fed. Everything to the right stayed on the floor — leftover coal at R 900, then the peaker.

  1. Who was fed

taken 530 · left 125 ImpPVCoal cheapdear35

Read it: import and solar are the short cheap bars; coal is the bulk; the last sliver is the 35 MW that set the meeting. The peaker has no bar.

Step 5 — write the unconstrained schedule from the meeting.

The piles do not publish a price. They publish volumes.

TUID Unconstrained MWh Why
Interconnector +20 Floor crate, all taken
TU-PV1 +75 Must-take crate, all taken
TU-COAL1 +435 Three full shelves + 35 MW of the R 900 shelf
TU-OCGT1 0 Still on the floor
TU-DIST1 −440 Must-serve, fed
TU-IND1 −90 Must-serve and every priced crate, all fed
Σ 0 20 + 75 + 435 = 530 and 440 + 90 = 530 ✓

Energy payments in §7 are struck on these volumes, at the SMP §6.4 reads from the last flexible crate. In this hour that reading is R 900.00 — the walk to the chalkboard is §11.2.

Step 6 — the same piles, a narrower door.

The constrained run does not rebuild different crates. It walks the same warehouse with the wires on. This hour the System Operator says zone Z1 may not export more than 60 MW. TU-PV1’s 75 free crates cannot all fit through that door. Fifteen stay in the warehouse; coal lifts fifteen extra crates from the same R 900 shelf (435 → 450).

That is a different volume, not a different SMP. Energy is still paid on the unconstrained meeting. The fifteen megawatt-hours the wire moved are a separate money line (§6.2, §6.6).

Where this is taught. The full hour — reserve floors, the R 0 constrained-off charge, publish — is §11. The staircases themselves are §5.3 and §5.4.

What you will not see on a public board. This chapter names TUIDs so you can learn the stacking. A published stack — the IDM increment board, the balancing sold/bought piles — shows price and volume only. A TUID on a public stack would publish another participant’s curve.

6.4 The System Marginal Price

§6.3 decided who runs. This section reads the number.

The idea fits in three sentences. Find the machines that had a real choice this hour: they ran, and they could have run a little more or a little less. Among those, find the most expensive one. What that machine charges for the megawatts it was actually given — read off its own staircase, nobody else’s — is the hour’s price, and everyone trades at it.

Said the way Market Code §9.7.2 says it: the System Marginal Price is the incremental price, at the scheduled unconstrained volume, of the most expensive flexible Trading Unit scheduled to run.

Why is the cheap solar farm paid the same number? Because the SMP is not a reward for what you offered. It is the market’s measure of what one more megawatt-hour would have cost. Solar offered R 0 and is paid the SMP; the distributor pays the SMP; the farmer in §6.1 who offered R 8 still received R 20.

Three words in the Code sentence do all the work.

Word Plain meaning Why it is there
Unconstrained The meeting from §6.3, before the wires. The country price must not include a jammed corridor. The wire is a different money line (§6.2).
Flexible The machine could still have moved. A unit that promised a fixed output, or is stuck at its minimum, or cannot ramp, did not make the last decision. It cannot set the price.
Incremental The price of that unit’s shelf at the megawatts it was given. You do not average its cheaper shelves. You do not use the peaker that never started. You read one step on one staircase.

The SMP is one number for the country, for that hour. It is not per zone, not per Trading Unit, not per BRP.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 24, "rankSpacing": 30, "padding": 12}}}%%
flowchart TB
  A["Unconstrained volumes<br/>from the two piles"] --> B["Keep units that actually ran<br/>volume not zero"]
  B --> C["Throw out anyone stuck<br/>I · at Mingen · ramp · reg-down"]
  C --> D["Read each leftover unit's<br/>own shelf at its volume"]
  D --> E["Take the highest of those<br/>shelf prices"]
  E --> F{"Above the cap?"}
  F -->|no| G["That number is the SMP"]
  F -->|yes| H["SMP = cap<br/>and raise the capped flag"]
  C --> I{"Nobody leftover?"}
  I -->|yes| J["SMP = R 0.00<br/>all-inflexible flag"]

The six checks

Do these in order. Do not skip to “last crate on the pile = price” — that shortcut fails at a bend, and it fails when the last crate sat on a machine that was not allowed to set the price.

  1. Use the before-the-wires volumes. Read from the unconstrained schedule, never the constrained one. A jammed cable must not leak into the country’s price.
  2. Keep only machines that ran. Volume not zero. The idle peaker is out, however expensive its first shelf is.
  3. Throw out every machine that had no choice. There are four ways to have no choice:
    • it sits at or below Minimum Stable Generation — on its must-run floor, unable to come down;
    • it declared I for the hour — it promised a fixed figure;
    • it is ramp-bound — it physically cannot move any faster (a fact of the solution, not of the bid);
    • it is held up for Regulation downwards — kept high so it can drop if the grid surges.
  4. Ask each survivor one question: what does your own staircase say at the volume you were given? Do not average its cheaper shelves. Do not look at anyone else’s stairs. If the volume lands exactly on a bend, use the bend rule below.
  5. Take the highest answer. That is the uncapped SMP. If two units tie to the Rand, the lower Trading Unit identifier is named as the setter — the name must be stable; the price is the same either way.
  6. Cap it. Never publish above the Market Price Cap (Annexure 2; this worked day R 5,396.40/MWh). If the raw number was higher, publish the cap and the flag smp_capped — a capped price without the flag is a scarcity signal that has been switched off.

If step 3 emptied the list, stop. The SMP is R 0.00, not the dearest stuck machine, and not “no price” (§9.7.2(5)). Publish all_units_inflexible. An hour in which nothing flexible ran has no marginal cost to show.

Worked hour — read 18:00

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10.2. The piles that produced these volumes are §6.3.

Step 1 — the volumes the piles already wrote.

Who Unconstrained MWh Ran?
Interconnector +20 Yes, but it is not a Trading Unit. It cannot set the SMP.
TU-PV1 +75 Yes
TU-COAL1 +435 Yes
TU-OCGT1 0 No
TU-DIST1 −440 Yes
TU-IND1 −90 Yes

Step 2 — throw out anyone who may not set the price.

Who Why they drop out — or stay
Interconnector Not a Trading Unit.
TU-PV1 Declared I. A promise. Out.
TU-OCGT1 Did not run. Out.
TU-DIST1 Declared I, and the whole 440 MW is must-serve. Out.
TU-IND1 Flexible, and it ran — but it was fully served (90 of 90). Nothing of its priced load was shed, so it did not make the last decision. Out. See the factory rule below.
TU-COAL1 Declared F. Scheduled 435, well above Mingen 200. No ramp bind, no regulation-down bind. Stays.

One candidate remains.

Who may set 18:00 — one unit left after the four grounds — 2026-07-15
FilterScheduled → flexible → leftover
The six names on the hour1 candidate
Imp PV · I Coal · in OCGT · 0 Dist · I Ind · full
May set the priceThrown outNot a Trading Unit

Step 3 — read coal’s own shelves at 435 MW.

TU-COAL1 does not have “a” price. It has four energy shelves (§5.3):

Shelf Band Width R / MWh 435 sits here?
Must-run 0 → 200 200 350 no
1 200 → 300 100 420 no
2 300 → 400 100 640 no
3 400 → 500 100 900 yes — 35 MW into this shelf

435 is not a bend. It is inside the top energy shelf. The incremental price is R 900.

Coal’s staircase — the ruler you lay on 435 MW — 2026-07-15 18:00
Shelf that 435 sits onScheduled volumeCheaper shelves — not used for the SMP

Read the shelf, not the average

435 MW · shelf R 900 0200400500

Read it: the gold band is the R 900 shelf. The red tick is 435. Cheaper shelves to the left were taken first; they do not pull the SMP down.

Same unit, three places on the stairs

200 400 435 Mingen → outbend → R 640in → R 900

Read it: 435 is this hour. 400 and 200 are the same stairs, to show the bend rule — they are not two other auctions.

Step 4 — the highest leftover shelf is the uncapped SMP.

One reading: R 900. Highest of a list of one is R 900. No tie to break.

Step 5 — the cap.

R 900 is below R 5,396.40. The cap does not bind. smp_capped is false.

Step 6 — write the public number.

Field Value Meaning
SMP(18:00) R 900.00/MWh One number for the country
Marginal unit TU-COAL1 Told to that BRP, not on the public board
smp_capped false This is a real clear, not a switched-off scarcity flag
all_units_inflexible false Someone flexible ran

The chalkboard in §11.2 now multiplies every unconstrained megawatt-hour by this R 900. Cheap solar is paid R 900. The distributor pays R 900. Coal is paid R 900 on all 435 MWh, including the cheap shelves.

Do not re-read the price on the constrained volumes. This hour coal moved 435 → 450 and would still sit on the R 900 shelf — same number, wrong reason. Another hour the wire would change the shelf. The Code keeps that out of the SMP on purpose.

The bend on the stairs

A bend (an elbow) is where one shelf stops and the next starts: 200, 300, 400, and nameplate 500 on this coal set. The Code needs a rule for “exactly on the corner”, because two shelves touch there.

Think of the corner of a staircase. You have just finished a tread. The rule for the SMP is: price the tread you are standing on, not the riser you have not climbed. That is “take the step below” — the platform’s :below elbow convention.

If coal had been given… On a bend? What you read Why
435 MW (this hour) no R 900 Inside the 400–500 shelf
400 MW yes (E2) R 640 The shelf you just finished, not the R 900 shelf you have not started
500 MW (nameplate) yes (MCR) R 900 Nameplate counts as a bend; the shelf below is still CI3
200 MW (Mingen) yes unit is out Sitting on the must-run floor is inflexible. You never read the shelf. If someone read it anyway, the Code says take the step above (R 420), so the must-run block still cannot set the price.

The must-run block (0 → Mingen, R 350 here) never sets the SMP. That is why Mingen is the one bend that is treated the other way, and why a unit sitting there is thrown out in check 3 before the ruler comes out.

When a factory can set the price

The Code sentence is written about generators. It never says whether a factory that was asked to use less may be the dearest leftover unit.

[D-08]. The platform’s shipped default (smp_demand_setting: true) says yes — but only if some of its priced load was actually shed. Then the factory was the last decision. A factory that got every megawatt it asked for is not at the edge, and must not set the price. That is why TU-IND1 was out at 18:00: it drew the full 90 MW.

Every clearing also stores the other reading. The Market Governance Committee can see how often the two disagree, instead of arguing after the fact.

The disagreement is large on the next hour of the same fixture.

Data. Same day, hour 19:00 — SAWEM-SPEC §10.6, the tight hour. Sun down. TU-PV1 is 0. TU-DIST1 declares 520. TU-COAL1 is pushed to nameplate 500. TU-OCGT1 is on at its minimum 60. Import 20. The factory is cut from 90 to 60. Balance: 500 + 60 + 20 = 580 = 520 + 60 ✓.

Who is leftover at 19:00:

Who Volume Flexible? Shelf if read
TU-COAL1 500 yes — at nameplate, not at Mingen bend → R 900 (step below)
TU-OCGT1 60 no — sitting on Mingen cannot set
TU-PV1 0 — did not run
TU-IND1 −60 of 90 yes, and partly shed the cut sits in the R 2,600 slice
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 22, "rankSpacing": 28, "padding": 12}}}%%
flowchart LR
  subgraph on ["Shipped default — factory may set"]
    A1["Coal shelf R 900"] --> M1["highest = R 2,600"]
    A2["Factory shed slice R 2,600"] --> M1
  end
  subgraph off ["Literal — generators only"]
    B1["Coal shelf R 900"] --> M2["highest = R 900"]
    B2["Factory ignored"] --> M2
  end
Reading SMP(19:00) What a participant would think
Default (true) R 2,600.00 Energy was scarce. The last thing the market did was turn off load worth R 2,600.
Literal (false) R 900.00 Same as a comfortable hour. The factory lost load it valued at R 2,600 while the price says R 900.

The gap is R 1,700/MWh. Both numbers are stored. The default is the one that makes scarcity visible.

The factory’s 90 MW at 19:00 — only the shed slice can set the price — SAWEM-SPEC §10.6
TU-IND1served 60 · shed 30
What the factory asked for90 MW
must-serve 40 10 @ 4,800 10 kept @ 2,600 10 shed @ 2,600 20 shed @ 1,500
Never shedStill drawingKept part of the mid sliceShed — the R 2,600 cut is the default SMP

When nobody flexible ran

If every unit that ran is stuck — all I, or all sitting on Mingen — there is no leftover shelf to read. The SMP is R 0.00. You do not take the dearest stuck machine. You do not leave the hour blank. You publish zero and the all-inflexible flag.

That is rare. It is also the rule. An hour with no flexible machine has no last decision to price.

Where this is taught. The 18:00 chalkboard that uses this R 900 is §11.2. The four reserve prices that sit on their floors when the last energy unit still has headroom are §6.5.

6.5 The four reserve system prices

Reserve is a standby promise. The System Operator tells a unit: “stand ready to move at short notice — and because you are standing ready, do not sell that part of yourself as energy.”

Standing ready is work, so it is paid. The only question is how much.

The standby taxi. You ask a taxi driver to wait outside your door all evening, engine running, taking no fares. What do you owe him? At the very least, what the fares he turned away would have paid him. And if the street was empty — there were no fares to be had anyway — he gave up nothing, and you owe him the agreed minimum call-out fee.

In the story In the market
The fares he turned away The SMP earnings the held-back unit gave up — its cost of lost opportunity
An empty street The unit had spare megawatts that were not going to sell anyway
The minimum call-out fee The floor the MGC published for that category

That is the whole formula. Per category, per hour:

system price = the dearest unit’s lost earnings, or the floor — whichever is higher.

Four standby promises, four prices:

System price Category The promise
SMPIRC Instantaneous React within seconds.
SMPRURC Regulating Up Be held below your energy schedule, so you can push up if the grid sags.
SMPRDRC Regulating Down Be held above, so you can come down if the grid surges.
SMPMRC Ten-Minute Be delivering within ten minutes. Can sit on a machine that is not even running.
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 26, "rankSpacing": 34, "padding": 12}}}%%
flowchart TB
  REQ["SO reserve requirement<br/>for the hour"] --> Q{"Did anyone give up an<br/>energy sale to stand ready?"}
  Q -->|"no — spare capacity covered it"| FLOOR["Price = the MGC floor<br/>flag reserve_prices_at_floor"]
  Q -->|"yes"| LOSS["Price = the dearest unit's loss<br/>never below the floor"]

Worked hour — 18:00 is an empty street

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10. The same hour whose piles are §6.3.

The SO wants held ready: Regulating Up 15 MW, Regulating Down 10 MW, Instantaneous 20 MW, Ten-Minute 25 MW. The MGC floors are R 50, R 50, R 50 and R 0 per MW.

Now look back at the meeting. Coal was taken to 435 of its 500 MW, so 65 MW of it stayed on the floor, unsold. The peaker never started at all. Every standby megawatt the SO wants can come out of capacity that was not going to earn anything anyway. Nobody gives up a sale. The street is empty.

So the lost-earnings number is R 0 in every category, and every price lands on its floor:

Price max(lost earnings, floor) Published
SMPRURC — Regulating Up max(0, 50) R 50/MW
SMPRDRC — Regulating Down max(0, 50) R 50/MW
SMPIRC — Instantaneous max(0, 50) R 50/MW
SMPMRC — Ten-Minute max(0, 0) R 0/MW

The board also raises the flag reserve_prices_at_floor (§6.7), so a participant reading R 50 knows it is a quiet hour, not a computed scarcity.

When the street is busy. In a tight hour — think 19:00, when coal is pushed to nameplate and the factory is being cut — every megawatt would have sold. Holding a machine back then costs it real money: the SMP it would have been paid, less what those megawatts would have cost it to make. The dearest such loss in each category becomes the system price, and the floor stops mattering.

Who sees which number. The four system prices are public. Each unit’s own lost-earnings figures are computed on the constrained schedule and go only to that unit’s BRP — publishing them would hand the unit’s cost curve to its competitors.

6.6 Zones do not set the price

A Network Zone is a patch of the grid with a name (Z1 Northern Corridor, Z6 Highveld Load, …). The System Operator may say “this zone may not export more than 60 MW this hour”. That changes the constrained schedule. It does not produce a “Z1 SMP”.

Energy is still paid at the system SMP on the unconstrained volume. Being constrained off is a separate line, settled at the unit’s own offer, not at a local price. In the worked hour a solar farm cut from 75 to 60 MW keeps 75 × R 900 and pays back 15 × R 0 = R 0. That is the Code, not a bug.

Where this is taught. What a zone is, and why the map is provisional, is V12 §2.

6.7 What is published at 14:00 D−1

Artefact Who may see it Contents
System prices Public Per hour: SMP, four reserve system prices, smp_capped, all_units_inflexible, reserve_prices_at_floor.
Own schedule The unit’s BRP Unconstrained MWh, constrained MWh, reserve allocated, whether the unit was marginal, which constraints bound it, and the day-ahead settlement lines for that hour.
Own unit prices The unit’s BRP That unit’s four reserve opportunity-cost prices.
Impacted Network / Distribution Operators Those operators Scheduled generation and consumption per Point of Delivery / zone.
Daily general adequacy report Public Expected demand, reserve, capacity, sent-out, consumption, system prices. No participant names.

Events on the stream: prices.published, schedule.published. A BRP that is listening does not need to poll.

6.8 Residual clearing — registered schedules are constants

From stage 11 the day-ahead market clears the residual. A registered forward schedule is a C16-style constant on the energy balance (C1) and is subtracted from each zonal export limit (C17) before spot terms compete for the headroom that is left. It is not a decision variable, and it is not a tie-break: priority over spot is a consequence of the arithmetic.

The published formulation version moves when those expressions change (MO-SPEC-4.3/2026-08). That is a §9.5(7) amendment — the comment window is one month from the publication date, and the formulation may not take effect inside it.

Do not expect the System Marginal Price to stay still when a schedule is registered. Taking volume off both sides of the pool moves the residual merit order. What must stay still is the identity, per Trading Period: registered + residual spot = what the unit cleared with no register. On a binding corridor the schedule is delivered in full and the spot trade is cut to the remaining headroom. If the register alone exceeds the limit, the constrained run is infeasible on C17 — a loud failure, never a silent curtailment of a firm bilateral.

The day-ahead Solution reports residual spot only. Contracted Energy adds the forward base back, which is how §13 still measures deviations against the physical position. The balancing engine is not touched.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

7. How the market settles the day-ahead

“Settle the bids” is two clocks sharing one word. Separate them.

Clock When What it is
Commercial settlement of the hour Computed with the clearing; visible on the schedule report at 14:00 D−1 Volumes × prices, signed, tagged with an account. This is the chalkboard.
Financial settlement of the month Indicative on SD+1 WD; billable on BP+5 WD Those lines, plus IDM, metering, balancing, fees, rolled into a statement and an invoice. This is the till.

This chapter is the chalkboard. §8 is the till.

7.1 The three pots

Every line lands in exactly one account. The kind of the line decides the pot; a caller cannot file an energy payment on the fee account.

Account What goes in it Does it net to zero?
Energy Day-ahead energy payments (EPM = scheduled unconstrained MWh × SMP) Yes, exactly R 0.00 per hour, across all participants. You are a conduit, not a counterparty. Generators are paid what loads are charged.
Market Balancing Constrained-schedule adjustments, additional energy above the cap, reserve capacity, all IDM money, later balancing No. A surplus or deficit is recovered by the System Operator as an ancillary service.
MO Charge The Market Operator’s own fees Ring-fenced. Not mixed with energy.

A fourth pot, Bad Debt, is for unpaid invoices and default interest. It is not a DAM calculation.

Where this is taught. The participant’s reading of the same three pots is V9 §13. This chapter is the operator’s invariant: the energy pot must print R 0.00 or the day must not publish.

7.2 Energy payment — EPM

EPM = SG × SMP

SG is the unconstrained scheduled volume, signed: plus means produced (you are paid), minus means consumed (you pay). SMP is that hour’s one system price (§6.4).

In crate language: every accepted crate trades at the last-crate price. The note on the farmer’s crate got them into the pile. It does not set what they are paid.

Two things that catch people:

  1. Use the unconstrained volume. If the System Operator later cut you from 75 to 60, you are still paid 75 × SMP. The cut is a different line (§7.3).
  2. The same price for everyone. A coal plant that offered R 350 and a gas plant that offered R 880 are both paid R 900 if that is where the market cleared. The offer decided whether they cleared, not what they are paid.
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 24, "rankSpacing": 30, "padding": 12}}}%%
flowchart LR
  SG["SG<br/>unconstrained MWh<br/>+ produced · − consumed"] --> MUL["×"]
  SMP["SMP<br/>one number<br/>for the country"] --> MUL
  MUL --> EPM["EPM<br/>one signed Rand line<br/>on the Energy pot"]

Worked hour — six lines at 18:00

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10. Volumes from §6.3. Price from §6.4: SMP = R 900.00/MWh.

Write one line per name. Same multiplication every time.

1. Coal — the last crate, paid like everyone else.

TU-COAL1 was scheduled +435 MWh unconstrained. Its cheap shelves were R 350, R 420, R 640. The last 35 MW sat on the R 900 shelf, so it set the SMP. It is still paid the SMP on all 435 MWh, not only the dear ones.

EPM = +435 × 900 = +R 391,500.00

The Market Operator pays the coal BRP.

Example 1 — coal’s energy line — 2026-07-15 18:00
18:00unconstrained
TU-COAL1 · SG+435 MWhall four shelves
SMP×R 900 / MWh
EPM+ R 391,500.00MO pays the BRP
435 × 900R 391,500.00not 200 × 350 + …

2. Solar — offered R 0, paid R 900.

TU-PV1 offered one free crate. That got it into the pile. The payment is still the system price.

EPM = +75 × 900 = +R 67,500.00

The offer decided whether the 75 MWh cleared (it did — it was free). It did not decide the Rand number.

3. The peaker that did not run.

TU-OCGT1 stayed on the floor. Volume is zero.

EPM = 0 × 900 = R 0.00

An expensive unused crate is not a line you pay. It is a blank.

4. The import — not a Trading Unit, still a line.

The System Operator owns the interconnector. The 20 MWh still has to be paid, or the Energy pot would be short by 20 × 900.

EPM = +20 × 900 = +R 18,000.00

Without this row the account holes by −R 18,000.00. Imports are a settlement subject. They are not a TUID.

5. The distributor — a load pays the same R 900.

TU-DIST1 drew 440 MWh of must-serve. Sign is negative: the participant pays the Market Operator.

EPM = −440 × 900 = −R 396,000.00

6. The factory — fully served, still pays the SMP.

TU-IND1 asked for 90 MWh and got 90. Its own priced slices were worth R 1,500, R 2,600, R 4,800. Those numbers decided it would stay in the queue. They are not what it pays.

EPM = −90 × 900 = −R 81,000.00

7. Add them up — the Energy pot must print R 0.00.

Paid out (plus): 391,500 + 67,500 + 18,000 = R 477,000.00

Taken in (minus): 396,000 + 81,000 = R 477,000.00

Volumes: 435 + 75 + 20 = 530 and 440 + 90 = 530. Σ SG = 0. Then Σ EPM = 900 × 0 = R 0.00. ✓

That is the operator’s invariant. The platform checks it on the exact products, before rounding. If it fails, the market cleared wrongly and you must not publish.

Example 7 — Energy pot at 18:00 — every rand paid is a rand charged — 2026-07-15
Who SG (MWh) Arithmetic EPM
TU-COAL1 +435 435 × 900
  • R 391,500.00
TU-PV1 +75 75 × 900
  • R 67,500.00
TU-OCGT1 0 0 × 900 R 0.00
Interconnector +20 20 × 900
  • R 18,000.00
TU-DIST1 −440 440 × 900 − R 396,000.00
TU-IND1 −90 90 × 900 − R 81,000.00
Σ 0 MWh R 0.00 ✓

You are a conduit. Generators and the import are paid what the loads are charged. The peaker is on the board so a zero is visible, not missing.

The same R 477,000 leaves the loads and arrives at supply — 2026-07-15 18:00
Paid outR 477,000.00
MO paysR 477,000
Coal 391,500 PV 67,500 Imp 18,000
Taken inR 477,000.00
Participants payR 477,000
Dist 396,000 Factory 81,000
CoalSolar / factoryImportDistributor
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 22, "rankSpacing": 28, "padding": 12}}}%%
flowchart LR
  DIST["TU-DIST1 pays<br/>R 396,000"] --> POT["Energy pot<br/>R 0.00"]
  IND["TU-IND1 pays<br/>R 81,000"] --> POT
  POT --> COAL["TU-COAL1 is paid<br/>R 391,500"]
  POT --> PV["TU-PV1 is paid<br/>R 67,500"]
  POT --> IMP["Import is paid<br/>R 18,000"]

8. The wire does not rewrite this chalkboard.

After the piles met, the System Operator said zone Z1 may export only 60 MW. TU-PV1 is cut 75 → 60. Coal rises 435 → 450.

Solar’s EPM stays +R 67,500.00 — still 75 × 900. The 15 MWh the wire moved is §7.3, at solar’s own offer of R 0, and it lands on the Market Balancing pot, not here.

What changed What you write What you do not write
Solar 75 → 60 on the wires EPM still 75 × 900 60 × 900 on this pot
Coal 435 → 450 on the wires EPM still 435 × 900 450 × 900 on this pot

That is catch 1 with numbers. The Energy pot is the unconstrained meeting × the SMP. Nothing else.

Rounding is applied once, to the Rand amount. You do not round 435 or 900 first. Each line also keeps the exact product, because rounding twenty lines on their own can leave a one-cent residual on a set whose exact products sum to zero.

Where this is taught. The same six lines sit on the door-to- chalkboard walk in §11.2. The participant’s reading of the Energy pot is V9 §13.

7.3 Constrained-schedule adjustment — CPP / CSC

§7.2 already paid the plan. This section pays the move.

The Energy pot used unconstrained volumes × the SMP. Then the wires spoke. Some units cannot do what the plan said. Other units have to do more. That difference is not rewritten on the Energy pot. It is a new line, on the Market Balancing pot, at the unit’s own stairs — not at the SMP.

In crate language: you already paid the solar farm for 75 crates at R 900. The door only lets 60 through. You buy 15 crates back. The buy-back price is the number on the farmer’s own note, not today’s crate price. The note said R 0. Buying them back costs R 0. The farm keeps the R 900 on those 15. Coal has to send 15 extra crates. You pay coal’s own shelf for just those 15.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 22, "rankSpacing": 28, "padding": 12}}}%%
flowchart TB
  A["Energy pot already written<br/>SG × SMP"] --> B["Wires move a unit<br/>SG ≠ CG"]
  B --> C["Walk that unit's own stairs<br/>between the two volumes"]
  C --> D{"Moved up on its own axis?"}
  D -->|yes| E["CPP — Market Balancing<br/>pays the integral"]
  D -->|no| F["CSC — participant<br/>pays the integral"]
  B --> G{"SG = CG?"}
  G -->|yes| H["No line at all"]
Direction, on the unit’s own axis Kind Who pays whom
Constrained above unconstrained — a generator asked to make more, or a load asked to take less CPP — Constrained Purchases Payment Market Balancing pays the participant
Constrained below unconstrained — a generator cut back, or a load forced to take more CSC — Constrained Sales Charge The participant pays Market Balancing

“Own axis” means megawatts produced for a generator and megawatts consumed for a load. A factory cut from 90 to 70 has a signed volume that rose (−90 → −70) but it lost 20 MW it wanted. That is a CPP — it is compensated — not a CSC.

If nobody moved, there is no line. Do not write R 0.00 for a unit that stayed put. A R 0.00 CSC means “they moved, and their own stairs were worth nothing.”

How to walk one unit

Do these in order.

  1. Write SG (unconstrained) and CG (constrained). Same sign convention as §7.2.
  2. If they are equal, stop. No line.
  3. Face the unit’s own axis. For a generator, compare the two positive megawatts. For a load, compare how much it draws.
  4. Walk that unit’s own staircase from one volume to the other. Each shelf: width × that shelf’s price. Add the shelves. That sum is the integral. It is not ΔMW × SMP.
  5. Name the kind from the direction (table above). Put the Rand on Market Balancing.

A unit that sent no day-ahead price is walked on a flat R 0 curve (§9.8.2(2)). The integral is still R 0. The sentence on the board is different: no day-ahead price submitted, not own offer was zero.

Worked hour — the wire moves 15 MWh

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10. Energy lines from §7.2. Zone Z1 may export at most 60 MW.

1. Who moved?

Who SG CG Moved?
TU-PV1 +75 +60 Yes — cut 15
TU-COAL1 +435 +450 Yes — lifted 15
TU-OCGT1 0 0 no
Interconnector +20 +20 no
TU-DIST1 −440 −440 no
TU-IND1 −90 −90 no

Fifteen megawatt-hours left the solar farm and landed on coal. That is the whole constrained adjustment for this hour. Two lines.

2. Solar — walk 75 down to 60 on its own stairs.

TU-PV1 has one shelf: 0–75 MW at R 0. From 75 to 60 is 15 MW on that shelf.

15 × 0 = R 0.00 → CSC, because a generator was cut.

The board must show the sentence own offer was zero, not a blank. A blank looks like “we forgot the line.”

Example 2 — solar’s buy-back at its own note — 2026-07-15 18:00
18:00wires
TU-PV1 · SG75 MWhalready paid at SMP
Z1 door→15 MWh cannot leave
CG60 MWhwhat may inject
Walk 75 → 6015 × R 0own shelf
CSCR 0.00own offer was zero
EPM keptR 67,500.00still 75 × 900

3. That R 0.00 is the curtailment windfall.

The Energy pot already paid 75 × 900 = R 67,500. The buy-back is R 0. Net for the hour, before IDM:

Line Amount Why
EPM +R 67,500.00 75 MWh × R 900, never rewritten
CSC R 0.00 15 MWh × own R 0
Net +R 67,500.00 For 60 MWh actually generated

67,500 − 0 = 67,500 ✓. The fifteen megawatt-hours it will not make are still worth R 13,500 at the SMP (15 × 900). The Code keeps that with the farm (§9.8.2). It is not a bug.

Solar at 18:00 — paid for 75, door lets 60 through, buy-back is free — 2026-07-15
EPM75 MWh × R 900
What the Energy pot paid75 MWh
60 generated · still paid 15 cut · CSC R 0
Generated and paid at SMPCut by the wire — buy-back R 0

4. Coal — walk 435 up to 450 on its own stairs.

TU-COAL1 stairs (§5.3, §6.3):

Shelf Band R / MWh 435→450 sits here?
Must-run 0 → 200 350 no
1 200 → 300 420 no
2 300 → 400 640 no
3 400 → 500 900 yes — the whole 15 MW

Both 435 and 450 are inside the R 900 shelf. One shelf, no bend.

15 × 900 = +R 13,500.00 → CPP, because a generator was lifted.

Not 15 × SMP as a separate idea — it happens to be R 900 because that is coal’s own shelf here. If the extra megawatts had sat on the R 640 shelf, the CPP would be 15 × 640.

Example 4 — coal’s extra 15 MWh at its own shelf — 2026-07-15 18:00
18:00wires
TU-COAL1 · SG435 MWhEPM already +391,500
replace solar→+15 MWh
CG450 MWhR 900 shelf
Walk 435 → 45015 × R 900own shelf, not a new SMP
CPP+ R 13,500.00Market Balancing pays
Coal’s stairs — only the sliver from 435 to 450 is this line — 2026-07-15 18:00
The 15 MW walk435 and 450

One shelf, no bend

435 → 450 · 15 × R 900 0400500

Read it: the gold sliver is the only part this CPP walks. Cheaper shelves to the left are already inside the EPM. They are not walked again.

5. What if the walk crossed a bend?

This hour it does not. Same coal stairs, two other volumes, to show the ruler — not another auction.

Walk 390 → 410:

Piece Width Shelf Rand
390 → 400 10 R 640 6,400
400 → 410 10 R 900 9,000
Σ 20 R 15,400

20 × 900 would be wrong. You add the shelves you actually cross. That is all “integral” means here.

6. Who has no line?

TU-DIST1, TU-IND1, TU-OCGT1, the import: SG = CG. Nothing to walk. Leave them off this pot.

7. A load, on its own axis — same factory stairs, not this hour.

This hour the factory was not moved. The axis still matters, so walk the fixture curve as if the wires had said “draw 70, not 90.”

TU-IND1 draws 90, with a top slice 70→90 at R 1,500 (§5.4). Forced down to 70:

The factory would be paid for the 20 MWh it was not allowed to use, at what those megawatts were worth to it, not at the SMP.

8. Write the two lines, then look at the pots.

Example 8 — constrained adjustments at 18:00 — Market Balancing, not Energy — 2026-07-15
Who SG → CG Walk Line
TU-PV1 +75 → +60 15 × R 0 CSC R 0.00
TU-COAL1 +435 → +450 15 × R 900 CPP + R 13,500.00
Market Balancing net this hour
  • R 13,500.00

The Energy pot is still R 0.00. This R 13,500 is a different pot. The System Operator recovers it as an ancillary service.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 22, "rankSpacing": 28, "padding": 12}}}%%
flowchart LR
  MBA["Market Balancing"] -->|"CPP R 13,500"| COAL["TU-COAL1<br/>made 15 extra"]
  PV["TU-PV1<br/>cut 15"] -->|"CSC R 0"| MBA
  SO["System Operator"] -->|"recovers R 13,500<br/>as ancillary"| MBA

Solar keeps R 13,500 of SMP on energy it will not generate. Coal is paid R 13,500 for energy it will generate extra. The windfall and the CPP are the same Rand amount this hour because solar’s own offer was zero and coal’s extra shelf was R 900. They are still two lines, two reasons.

9. The System Operator cut is free. Cutting yourself is not.

If TU-PV1 later re-declares 60 → 20 in the IDM, those 40 MWh are priced at the Intra-Day Price, not at its own R 0. In the golden hour that charge is −R 37,800. Walked in §11.4.

That is the commercial fact this section exists to teach: the DAM pays you for the plan; the wire taking it away at your own R 0 costs you nothing; you taking it away yourself does.

Where this is taught. The same two lines sit in §11.2 step 4. The participant’s reading of the windfall is V9 §13.4.

7.4 Additional energy payment — AEPM

The Energy pot pays everyone the capped SMP (§7.2). A machine that offered above the Market Price Cap, and was still told to run, would otherwise be short the difference. AEPM makes that machine whole for the excess of its own stairs over a reference price. It lands on Market Balancing, not on Energy.

AEPM = Σ  width × max(shelf − reference, 0)
       over every scheduled shelf, from 0 to SG

The shipped reference is the SMP ([D-02]). The SMP itself cannot go above the cap (§6.4), so when that unit set the price the two readings agree. They only split when a unit above the cap ran as a cheaper neighbour set the SMP.

Three gates. Fail any one and there is no line — not a R 0.00.

  1. It must be a production staircase. A factory’s willingness to pay is not an offer. Paying a load the excess of what it would have paid is a different deal the Code does not have.
  2. The unit must be flexible (F). An I unit promised a figure. It is not made whole for a high note.
  3. Some scheduled shelf must sit above the cap. Walk only the megawatts that were actually scheduled (SG, unconstrained).
%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 22, "rankSpacing": 28, "padding": 12}}}%%
flowchart TB
  A["Unconstrained SG"] --> B{"Production · flexible ·<br/>a scheduled shelf above the cap?"}
  B -->|no| N["No AEPM line"]
  B -->|yes| C["Walk 0 → SG<br/>keep only shelf − reference"]
  C --> D["AEPM on Market Balancing"]

Worked hour — nobody is above the cap

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00. Cap R 5,396.40/MWh. SMP R 900.00.

1. Who could even be a candidate?

Who Flexible? Highest scheduled shelf Above R 5,396.40? AEPM
TU-COAL1 F R 900 (at 435 MW) no none
TU-PV1 I R 0 no none
TU-OCGT1 F did not run — none
TU-DIST1 I consumption — none
TU-IND1 F consumption — none
Interconnector — not a bid — none

This hour AEPM is absent. That is the ordinary uncongested day. Do not write six R 0.00 lines.

2. Same coal stairs, if emergency had run — not this hour.

TU-COAL1 has an emergency shelf 500–530 MW at R 6,000 (§5.3). This hour’s declaration stopped at 500, so that shelf was clamped off. If 20 MW of it had been scheduled (SG = 520), the shipped walk is against the SMP of R 900:

Piece Width Shelf max(shelf − 900, 0) Rand
0 → 500 500 R 350 … R 900 0 0
500 → 520 20 R 6,000 5,100 102,000.00
Σ AEPM +R 102,000.00

520 × 900 on the Energy pot would still be the EPM. The extra R 102,000 is only the excess of that machine’s own note over the SMP. The Energy pot does not move.

The other [D-02] reading uses the cap instead of the SMP. Same 20 MW: 20 × (6,000 − 5,396.40) = R 12,072.00. The two readings agree only when the SMP itself is sitting on the cap.

3. A factory must not be paid this.

If you walked TU-IND1’s R 4,800 slice against the SMP you would “owe” a served load tens of thousands of Rand. The first gate stops that. Consumption is out.

Where this is taught. [D-02] is on §25.4. This hour’s empty line sits on the schedule report in §7.6.

7.5 Reserve capacity payments

Reserve is the standby promise from §6.5. This section is the pay cheque: each megawatt that actually qualified, times that hour’s system price, times a performance factor.

PAYRURC = SMPRURC × qualifying MW × PerfAdj
PAYRDRC = SMPRDRC × qualifying MW × PerfAdj
PAYIRC  = SMPIRC  × qualifying MW × PerfAdj
PAYMRC  = SMPMRC  × qualifying MW

Ten-Minute has no performance factor in the Code. The other three use PerfAdj = 1.0 when the System Operator has not said otherwise.

Qualifying megawatts are read on the constrained schedule. A failed band (sitting outside the window the category needs) qualifies zero, not the contracted amount. They land on Market Balancing. The System Operator recovers them.

Kind Category Everyday meaning
PAYRURC Regulating Up Paid to be held below so you can push up
PAYRDRC Regulating Down Paid to be held above so you can come down
PAYIRC Instantaneous Paid for the very fast reserve
PAYMRC Ten-Minute Paid for the slower reserve. May sit on a machine that is not running

Worked hour — four hold-backs, one cheque

Data. Same 18:00. Requirements: RU 15, RD 10, IR 20, TM 25. Floors R 50 / R 50 / R 50 / R 0. Street empty (§6.5) → every system price is on its floor.

1. Who was asked to stand ready?

Category MW wanted Held on Why that unit
Regulating Up 15 TU-COAL1 Headroom above 435 toward 500
Regulating Down 10 TU-COAL1 Footroom down toward Mingen 200
Instantaneous 20 TU-COAL1 Certified and available
Ten-Minute 25 TU-OCGT1 Offline is allowed for this category

Coal energy + up-reserves: 435 + 15 + 20 = 470 of 500. Feasible.

2. Coal’s three payments.

PerfAdj = 1.0. Prices are the floors.

Kind MW Price Arithmetic Amount
PAYRURC 15 R 50 15 × 50 × 1.0 +R 750.00
PAYRDRC 10 R 50 10 × 50 × 1.0 +R 500.00
PAYIRC 20 R 50 20 × 50 × 1.0 +R 1,000.00
Coal reserve 45 +R 2,250.00

750 + 500 + 1,000 = 2,250 ✓. That is the R 2,250 on coal’s chalkboard in §11.2.

3. The peaker’s Ten-Minute line.

TU-OCGT1 holds 25 MW offline. The system price is R 0 (floor).

PAYMRC = 25 × 0 = R 0.00

The hold is real. The cheque is zero because this hour’s Ten-Minute floor is zero and nobody gave up a sale. Write the allocation on the schedule. Do not invent a R 50.

4. Who is not paid.

TU-PV1 declared reserve U. TU-DIST1 likewise. TU-IND1 offered some reserve but was not allocated this hour. No contracted megawatts → no line.

5. The pot.

Reserve this hour: +R 2,250.00 on Market Balancing (all coal). Add the §7.3 CPP of R 13,500. MBA energy-side net before IDM: 13,500 + 2,250 = R 15,750. The Energy pot is still R 0.00.

Reserve cheques at 18:00 — floors, PerfAdj 1.0 — 2026-07-15
Who Kind MW R / MW Amount
TU-COAL1 PAYRURC 15 50
  • R 750.00
TU-COAL1 PAYRDRC 10 50
  • R 500.00
TU-COAL1 PAYIRC 20 50
  • R 1,000.00
TU-OCGT1 PAYMRC 25 0 R 0.00
Market Balancing · reserve
  • R 2,250.00

System prices are public. Each unit’s own lost-opportunity figures stay with its BRP.

Where this is taught. How the four prices are found is §6.5. The same R 2,250 sits in §11.2 step 4 and on the schedule report in §7.6.

7.6 When the chalkboard is written — the schedule report

The day-ahead lines travel inside the schedule report (§9.10(2)). They are computed when the day is solved. You review them. Then you publish. A pipeline that published as a side-effect of solving would make “let me check that” impossible (§6.2).

They are not an invoice. They are the ingredients of next month’s invoice (§8). A BRP that fetches its schedule already has the chalkboard for that day. The till comes later.

What the report is

One Trading Day. Twenty-four hours. Two audiences:

Face Who What they may see
Public strip Everyone SMP, four reserve system prices, smp_capped, all_units_inflexible, reserve_prices_at_floor, the adequacy totals. No TUID.
Own hour That unit’s BRP SG, CG, reserve held, whether they were marginal, which constraint bound them, and every DAM line for that hour.
Operator board You Both faces, every unit, both pots. This is what you read before you press publish.

Events after publish: prices.published, schedule.published.

Worked report — 18:00, as you review it

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10. Numbers from §7.2–§7.5.

1. Public strip — what the country is told.

Field Value How to read it
Trading period 2026-07-15T18:00:00+02:00 SAST. The hour 18:00–19:00
SMP R 900.00/MWh One number. Set by TU-COAL1 at 435 MW
smp_capped false Not a switched-off scarcity signal
all_units_inflexible false Someone flexible ran
SMPRURC / SMPRDRC / SMPIRC / SMPMRC R 50 / 50 / 50 / 0 Floors. Empty street
reserve_prices_at_floor true Those R 50s are minima, not computed losses
Marginal unit TU-COAL1 On the operator board and that BRP’s own hour — not on the public wall

2. Own hours — volumes and why.

TUID SG CG Bound by Marginal? Reserve held
TU-COAL1 +435 +450 — yes RU 15 · RD 10 · IR 20
TU-PV1 +75 +60 zonal_export_limit:Z1 no none
TU-OCGT1 0 0 — no TM 25 (offline)
Interconnector +20 +20 SO schedule no —
TU-DIST1 −440 −440 — no none
TU-IND1 −90 −90 — no none

Σ SG = 0 ✓. The Z1 door is the only binding constraint.

3. DAM lines on the same report — Energy pot.

Who Kind Qty Price Amount Pot
TU-COAL1 EPM +435 900 +R 391,500.00 Energy
TU-PV1 EPM +75 900 +R 67,500.00 Energy
TU-OCGT1 EPM 0 900 R 0.00 Energy
Interconnector EPM +20 900 +R 18,000.00 Energy
TU-DIST1 EPM −440 900 −R 396,000.00 Energy
TU-IND1 EPM −90 900 −R 81,000.00 Energy
Σ Energy 0 R 0.00 ✓

If that last cell is not R 0.00, do not publish.

4. DAM lines — Market Balancing.

Who Kind Walk / MW Amount Note
TU-PV1 CSC 75 → 60 · 15 × R 0 R 0.00 own offer was zero
TU-COAL1 CPP 435 → 450 · 15 × R 900 +R 13,500.00 Extra energy at own shelf
TU-COAL1 PAYRURC 15 × R 50 +R 750.00
TU-COAL1 PAYRDRC 10 × R 50 +R 500.00
TU-COAL1 PAYIRC 20 × R 50 +R 1,000.00
TU-OCGT1 PAYMRC 25 × R 0 R 0.00 Held; floor is zero
— AEPM — none Nobody above the cap
Σ Market Balancing +R 15,750.00 SO recovers

13,500 + 2,250 = 15,750 ✓. This pot does not have to be zero.

Schedule report · 18:00 · both pots — review this before publish — 2026-07-15
Pot What it holds this hour Net
Energy Six EPM lines at R 900 R 0.00 ✓
Market Balancing CPP + CSC + reserve + no AEPM
  • R 15,750.00
MO Charge Fees — not a DAM hour line —

Solve wrote these cells. Publish makes them the thing every participant settles against. They are still not cash.

5. What each seat is allowed to see after you publish.

Who On their schedule report
Everyone The public strip. SMP R 900, floors, flags, adequacy.
TU-COAL1’s BRP SG 435, CG 450, you were marginal, EPM +391,500, CPP +13,500, reserve +2,250.
TU-PV1’s BRP SG 75, CG 60, bound by zonal_export_limit:Z1, EPM +67,500, CSC R 0.00 (own offer was zero).
TU-DIST1’s BRP −440 both sides, EPM −396,000. No constrained line.
TU-IND1’s BRP −90 both sides, EPM −81,000.
TU-OCGT1’s BRP 0 energy, TM 25 held, PAYMRC R 0.00.
Network Operator for Z1 TU-PV1 constrained to 60.

They must not see another unit’s stairs or another unit’s lost-opportunity prices.

6. What you check, in this order, before publish.

  1. Energy pot R 0.00 on the exact products.
  2. Every CSC of zero has a sentence, not a blank.
  3. Flags match the hour (smp_capped, all_units_inflexible, reserve_prices_at_floor).
  4. The Z1 door is named on solar’s own hour.
  5. Reserve megawatts match the SO requirement (15+10+20+25).
  6. Then publish. Events fire. Participants fetch.

The same hour, as a follow-along on the Settlement tab, is §13.10 and §11.2 step 5.

Where this is taught. Who may see which artefact is §6.7. The till that later uses these lines is §8.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

8. After settlement — charges and notices

8.1 From chalkboard to till

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 28, "rankSpacing": 36, "padding": 12}}}%%
flowchart TB
  P["14:00 D−1<br/>schedule + DAM lines published"] --> IDM["IDM lines accrue<br/>through the five auctions"]
  IDM --> M["Meters + instructions<br/>after delivery"]
  M --> BAL["Balancing lines<br/>17:00 D+1 / official D+7"]
  BAL --> IND["Indicative statement<br/>17:00, SD+1 WD"]
  IND --> VER["Data Verification<br/>closes SD+7 WD 17:00"]
  VER --> INI["Initial statement<br/>12:00, BP+5 WD"]
  INI --> INV["Invoice if participant owes<br/>Self-Billing Invoice if MO owes"]
  INV --> PAY["EFT only<br/>participant +3 BD 12:00<br/>MO +4 BD 17:00"]
Document When What it is Can it take money?
Schedule report (own) 14:00 D−1 Your hours, both schedules, DAM lines No. Preview.
Public prices / adequacy 14:00 D−1 The country’s hour-by-hour SMP No. Information.
IDM schedule + prices +1 h after each IDM gate What moved, at what Intra-Day Price No. Preview of IDM lines.
Indicative Settlement Statement 17:00, Settlement Date + 1 working day The month’s lines so far, for checking No. Raising an invoice from an indicative statement is refused.
Initial Settlement Statement 12:00, Billing Period + 5 working days The billable statement Yes — this is what the invoice is raised from.
Invoice Same moment, if the participant’s net is negative (they owe) Pay this, in full, no set-off, by EFT Yes. Due 12:00, +3 business days.
Self-Billing Invoice Same moment, if the net is positive (the MO owes them) You raise it on the participant’s behalf and pay it Yes. Paid 17:00, +4 business days.
Debit Note If a creditor must be clawed back because someone else did not pay The cascade Yes.

A statement whose net is exactly zero produces neither document. There is nothing to collect and nothing to pay.

Pay now, argue later. A Settlement Query or a dispute does not hold the invoice. The invoice engine never waits. If the query is later upheld, a correcting document follows. A participant who pays less than the invoice has not made a smaller payment — they have created a Shortfall, whatever they believe they are owed.

Where this is taught. The BRP query journey is V9 §8. The inbox on /mo/dispute is §20. The issued register is §19. The party tax document, the Debit Note Excess, and supply-only refusal: V15 §14. A rerun or a validated dispute arrives as a note, not a replacement invoice: V15 §17.

8.2 How a party is charged — the sign on the statement

Walk one hour for one unit, then zoom out to the month.

  1. Energy (EPM). Generator: positive (you pay). Load: negative (they pay). Same SMP.
  2. Constrained adjustment. Own-offer integral. Often R 0 for a renewable that was cut.
  3. Reserve. Positive if the unit was held for reserve.
  4. IDM legs. Accrue through the day; see §9.
  5. Balancing. After meters. Not this volume’s subject, but they land on the same statement.
  6. MO Charge. Your fee, on its own pot.
  7. Net the month. Negative → Invoice. Positive → Self-Billing Invoice.

VAT is applied on the document, not on each line.

8.3 How parties are notified

You do not rely on a person remembering to phone.

Channel What travels When
Public API GET /dam/prices/{date} SMP and reserve system prices From publication. No token.
Authenticated API GET /dam/schedules/{date}?tuid= Own volumes, constraints, DAM lines From publication.
Authenticated API GET /dam/settlement/{date}?tuid= Own day-ahead lines From publication.
Event stream gate.closing (T−30 and T−5), gate.extended, submission.rolled_over, schedule.published, prices.published, idm.cleared, statement.issued, invoice.issued, credit-cover notices As they happen.
Indicative / Initial statements The month’s lines, by account and kind, with the clause on each kind On the Settlement Calendar.
Invoice / Self-Billing Invoice Gross, VAT, due-at, the statement they were raised from With the Initial statement.
MO Notices board GENERAL, SYSTEM_STRESS, PRICE_CAP_EVENT When you broadcast. A capped SMP hour should be visible here as well as on the price flag.
Credit Cover Increase / Warning Recalculated cover 17:00 daily when the numbers move.
Invalidation notice An accepted future submission was broken by a registry change Before the next gate. Different from a rejection: they thought they were done.

The schedule report itself is a notification: §9.10(2) requires the settlement in it, so a BRP that fetched its schedule already has the chalkboard for that day.

8.4 What you must be able to answer

A participant will ask, in this order:

  1. Did you receive my bid? Which version counted?
  2. What was the SMP, and who set it? Was it capped?
  3. What was I scheduled unconstrained vs constrained, and why (which constraint)?
  4. Show me the EPM, the CPP/CSC, the reserve lines.
  5. What did the IDM then do to me?
  6. Where is that hour on my statement, and which invoice did it ride on?
  7. When is the money due, and has it been paid?

Every panel in §12–§26 exists so those seven questions have a clickable answer.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

9. How the IDM touches the DAM

The Intra-Day Market does not change the DAM bid, does not change the DAM price curve, and does not change the SMP. It changes how much of the remaining day is scheduled, using the same stairs the BRP already sent, and it prices only the megawatt-hours that actually moved.

Yesterday you booked a 75-seat coach at a fare of R 900 a seat. This morning only 20 passengers can travel. The original booking is not torn up. A smaller auction reallocates the 55 empty seats. You still have a 75-seat booking on yesterday’s ticket (that is the EPM). What you do about the 55 empties depends on who cancelled. If the traffic police closed the road, you keep the fare and pay back nothing (constrained sales at your own offer of R 0). If you cancelled, you buy the seats back at this morning’s price (against-instruction, Intra-Day Price flat).

Where this is taught. The BRP Intraday Desk is V9 §5. This chapter is what that desk does to your chalkboard.

9.1 What the IDM is allowed to move

Five fixed auctions, not a rolling “one hour before delivery” window.

Iteration Gate Hours it may still move
1 18:00 D−1 The whole of D
2 00:00 D 01:00–23:00
3 06:00 D 07:00–23:00
4 12:00 D 13:00–23:00
5 18:00 D 19:00–23:00

A re-declaration for an hour whose delivery has started is refused. It is not a late submission; it is a re-declaration of the past.

The IDM re-clears the remaining hours from the last standing schedule (DAM constrained, or the previous iteration), with updated availability and any new SO constraints. Instantaneous Reserve scheduled day-ahead is not re-optimised, except to replace what a unit has actually lost; replacements earn the day-ahead category price, not a new intraday one.

9.2 What a participant sends — not a new bid

The participant does not send a new staircase. The DAM curve stands. What they send is a new Declared Available Capacity and/or Declared Consumption for remaining hours, optionally a change to the day’s rescheduling-consent flag, and a reason. That is a re-declaration, not a re-bid. See §10.

idm_rescheduling_consent on the DAM submission is the standing answer to “may the intraday auction move me?”

Flag Ordinary IDM re-clear SO imposes an additional network constraint
Willing (true, default) Yes, the unit may be moved Yes
Non-willing (false) No — hold the DAM constrained schedule Yes anyway. A participant cannot hold a corridor hostage by opting out of a security re-clear.

The volumes look the same either way. The reason must travel with the movement: “not moved because you asked” and “moved anyway because the SO imposed a constraint” are two different facts.

The flag can also be updated for the day via PUT /idm/rescheduling-consent/{date}/{tuid} without sending a new DAM week.

9.4 On instruction versus against instruction

This is the most misread part of §10. The test is not what happened to the schedule. The test is whether the participant changed its own declaration.

Schedule moved Did the participant change its declaration? Classification Price
Down Yes — reduced available capacity, or raised declared consumption Purchase against instruction Intra-Day Price, flat
Down No — the MO / SO moved them Purchase on instruction The better of own offer and Intra-Day Price (they keep the good one)
Up Yes — raised capacity while inflexible, or lowered declared consumption Sale against instruction Intra-Day Price, flat
Up No, or in excess of the declaration change Sale on instruction The better of own offer and Intra-Day Price

A single hour can carry both legs. A unit that raises capacity by 10 MW and is then scheduled up by 15 has 10 against (it asked) and 5 on (the market took more). Returning one tag for the hour silently overcharges the 5.

Raising capacity is against-instruction only while declared inflexible. A flexible unit that raises capacity and is scheduled up offered the market a choice; the market took it — on instruction.

Ramping spillover counts. A re-declaration at 18:00 that forces a ramp change at 17:00 makes 17:00 against-instruction too, even though nothing was declared for 17:00.

9.5 The Intra-Day Price

Volume-weighted average of the on-instruction increments only, then collared at SMP ± 5 %.

Against-instruction volumes do not enter the stack. A unit that re-declared itself down does not get to drag the price it will then be charged at.

If nothing on-instruction moved, or the signed on-instruction volumes cancel to zero, the Intra-Day Price is the SMP.

The collar is implemented symmetrically ([D-03]): [0.95 × SMP, 1.05 × SMP]. Both the indicative (un-collared) and the applied (collared) prices are published, plus a flag if the collar bound.

9.6 What the IDM does to DAM money

DAM line Does the IDM change it?
EPM (unconstrained × SMP) No. The chalkboard for yesterday’s auction stays.
SMP No.
DAM price curve No. Re-used as-is.
Constrained adjustment (CPP/CSC) Can be reversed, in part, if an IDM movement walks back toward the unconstrained volume. §10(15) credits the reversed portion. A unit returned all the way to its DAM constrained schedule has a net IDM position of R 0.00.
Reserve capacity (day-ahead) Instantaneous Reserve is carried forward. Other categories may be re-allocated; Instantaneous replacements keep the day-ahead price.

New money is new lines on the Market Balancing Account (IDPM_ON, IDC_ON, IDPM_AGAINST, IDC_AGAINST, IDM_REVERSAL). They do not rewrite the DAM energy account.

9.7 Should a BRP even use the IDM?

Not automatically. Re-declaring a zero-priced renewable converts a deviation that would have been free (SO instruction, or inside the Metering Accuracy Band) into one that costs the Intra-Day Price. The platform’s WB.Sawem.Participant.IdmDecision answers, in this order:

  1. If an SO instruction is already expected — carry. Instructed deviation settles at own offer (often R 0).
  2. If the deviation is inside the Metering Accuracy Band — carry. It settles at the SMP with no penalty.
  3. Past the band, compare magnitude × IDP against magnitude × max(balancing price, SMP) and take the cheaper.

The desk should show that recommendation beside a lodged re-declaration, because the participant will ask “should I have?”.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

10. The IDM input, field by field

Two shapes share one lodgement table (WB.Sawem.Mo.IdmLodgement). They are one decision seen twice: what may this iteration do with my unit?

10.1 Re-declaration

PUT /v1/idm/redeclarations/2026-07-15/TU-PV1

Field Required Plain meaning
iteration Yes Which of the five auctions this lodgement is for. A body sent at 11:47 is for iteration 4 (gate 12:00). Sending iteration 3 after 06:00 is a closed gate.
periods Yes Only the hours you are changing, and only hours this iteration may still move. You do not resend the whole day.
periods[].trading_period Yes The hour. Must be strictly after this iteration’s gate.
periods[].declared_available_capacity_mw When generation is what changed The new “I can produce this much”. Same MCR cap as the DAM. Omitting it means “leave the previous declaration”.
periods[].declared_consumption_mw When consumption is what changed The new “I will draw this much”. A factory that suddenly needs more raises it — and that raise is against-instruction on the purchase side.
reason_code Strongly expected A short, stable token so the desk can filter: FORECAST_REVISION, FORCED_OUTAGE, DERATE, FUEL_CONSTRAINT, SOC_REVISION, LOAD_REVISION, OTHER. The Code does not enumerate these; the platform should.
reason_note Optional Free text. “Convective cloud, 11:30 nowcast”. Kept forever.

What is not on a re-declaration, and must not be added:

Absent field Why it is absent
Price curve / cost increments The DAM staircase stands. The IDM is not a second bid.
flexible / reserve indicators Those were the DAM hour’s commitment. Changing them mid-day would be a different product.
Energy limits The weekly reservoir does not get rewritten every six hours.
The other 20 hours of the day Only remaining, changed hours.

The API’s most useful response field is estimated_classification: before the gate, it tells the participant that this reduction will be charged at the Intra-Day Price rather than compensated at their own offer. The price is not known yet; the classification is deterministic from §10(6)–(9).

Last lodgement for the same (unit, date, iteration, period, kind) wins. Two rows for one hour would leave the clearing choosing between them.

PUT /v1/idm/rescheduling-consent/2026-07-15/TU-PV1

Field Plain meaning
rescheduling_consent WILLING or NON_WILLING. Same meaning as the DAM boolean, restated for the day. NON_WILLING still yields to a new SO constraint.
reason_code / reason_note Why they are opting out (or back in).

A consent has no Trading Period. It is a statement about the day.

10.3 What you add after the auction

The participant does not send these. The desk must still show them against the lodgement.

Output Plain meaning
Intra-Day Price, indicative and applied The auction’s price, and whether the ±5 % collar bound.
On / against split The pair of volumes, not a single tag.
Legs (IDC_AGAINST, IDPM_ON, …) The money, with the clause.
Reversal credits Ground this movement walked back over, negating an earlier DAM or IDM line.
Revised schedule The new standing instruction for remaining hours.
Instantaneous Reserve carry / replacement What was held, what was replaced, at the day-ahead category price.
You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

11. Worked example — Trading Day 2026-07-15, hour 18:00

Every number below is the golden fixture in SAWEM-SPEC §10. Same day, same hour, same units. If a screen or a test disagrees with this chapter, the screen or the test is wrong.

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10 / docs/references/market/spec/market-dam.md §11.

11.1 The cast, and what they sent

Five Trading Units, plus a 20 MWh import.

TUID What it is Zone Flexibility What it offered for 18:00
TU-COAL1 500 MW coal — F Stairs: 0–200 @ R 350, 200–300 @ R 420, 300–400 @ R 640, 400–500 @ R 900, emergency @ R 6,000. Available 500 MW. All three reserves A.
TU-PV1 75 MW solar Z1 Northern Corridor I One step, 0–75 @ R 0. Available 75 MW. No reserve.
TU-OCGT1 60 MW peaker — F Stairs from R 2,800 upward. Available. Instantaneous and Ten-Minute A.
TU-DIST1 440 MW distributor Z6 Highveld Load I 440 MW must-serve. No priced blocks.
TU-IND1 90 MW factory Z6 F 40 MW must-serve; then 10 @ R 4,800, 20 @ R 2,600, 20 @ R 1,500.
Interconnector Import — — +20 MWh, treated as a free fixed injection.

SO reserve requirements for 18:00: Regulating Up 15 MW, Regulating Down 10 MW, Instantaneous 20 MW, Ten-Minute 25 MW. Market Price Cap R 5,396.40. Reserve floors R 50 / R 50 / R 50 / R 0.

11.2 Door-to-chalkboard, step by step

%%{init: {"themeVariables": {"fontSize": "16px"}}}%%
sequenceDiagram
  participant BRP as BRPs
  participant MO as Market Operator
  participant SO as System Operator
  participant PUB as Public / BRP APIs
  Note over BRP,SO: D−1 (14 July)
  BRP->>MO: PUT DAM submissions (by 10:00)
  SO->>MO: Demand, reserves (10:00)
  SO->>MO: Interconnect +20 MWh (13:30)
  MO->>MO: Unconstrained solve
  MO->>MO: Constrained solve (Z1 export 60 MW)
  MO->>MO: SMP = R 900 (TU-COAL1 at 435 MW)
  MO->>PUB: Publish schedules + prices (14:00)
  Note over BRP,SO: D (15 July) 12:00 — IDM iteration 4
  BRP->>MO: TU-PV1 re-declares 18:00 DAC 60 → 20
  MO->>MO: Re-clear remaining hours
  MO->>MO: IDP indicative R 1,412.50, collared R 945
  MO->>PUB: Revised schedule + IDM prices

Step 1 — intake. Each BRP’s body is validated. TU-PV1’s single-block R 0 curve is legal. TU-DIST1’s collapsed consumption curve is legal. Nothing is published yet.

Step 2 — unconstrained stack, 18:00.

How the two piles are stacked, crate by crate, is §6.3. The roll-up for this hour:

Supply, cheapest first:

Rung Source Block MW Price Cumulative
1 Import fixed 20 0 20
2 TU-PV1 0→75 75 0 95
3 TU-COAL1 0→200 200 350 295
4 TU-COAL1 200→300 100 420 395
5 TU-COAL1 300→400 100 640 495
6 TU-COAL1 400→500 100 900 595
7 TU-OCGT1 0→60 60 2,800 655

Demand: 440 (TU-DIST1) + 40 (TU-IND1 must-serve) = 480 must-serve, then every elastic block of TU-IND1 (all worth more than R 900). Total demand 530. Generation needed 530 − 20 = 510: TU-PV1 75 + TU-COAL1 435.

TU-COAL1 at 435 MW is not an elbow, and the unit is flexible → it sets the price. How that reading is done — who is thrown out, which shelf, the cap — is §6.4.

SMP(18:00) = R 900.00/MWh. Not capped. Not all-inflexible. Marginal unit: TU-COAL1.

Reserve: the coal set has headroom, so every lost-opportunity cost is zero. All four system reserve prices sit on their floors: R 50, R 50, R 50, R 0. Ten-Minute (25 MW) is held on the offline OCGT.

Step 3 — energy chalkboard.

How each line is written — SG × SMP, the import, the R 0.00 invariant — is §7.2. The roll-up:

TUID SG (MWh) EPM (R)
TU-COAL1 +435 +391,500.00
TU-PV1 +75 +67,500.00
TU-OCGT1 0 0.00
Interconnector +20 +18,000.00
TU-DIST1 −440 −396,000.00
TU-IND1 −90 −81,000.00
Total 0 0.00

Step 4 — constrained run. The SO flags Z1 exports. TU-PV1 may inject at most 60 MW. 15 MWh moves onto TU-COAL1 (435 → 450). How those two lines are walked — own stairs, not the SMP — is §7.3.

TUID SG CG Line Arithmetic Amount
TU-PV1 75 60 CSC 15 MWh × R 0 R 0.00
TU-COAL1 435 450 CPP 15 MWh × R 900 +R 13,500.00

TU-PV1 keeps R 67,500 on 75 MWh it will not all generate. That is the R 13,500 windfall. The Market Balancing Account pays the coal set R 13,500; the SO recovers it as an ancillary service.

Reserve capacity: TU-COAL1 (15+10+20) × R 50 = R 2,250 → Market Balancing Account. How those four cheques are walked is §7.5. AEPM is absent this hour — nobody scheduled a shelf above the cap (§7.4).

Step 5 — publish. You review both schedules, the R 0 CSC (rendered with the sentence “own offer was zero”, not as a blank), the SMP flags, and press publish. Events fire. Participants fetch. The full hour as it sits on the schedule report is §7.6.

11.3 What each party sees at 14:00 D−1

Who What they are told
Everyone SMP R 900, reserve system prices, adequacy report.
TU-PV1’s BRP Unconstrained 75, constrained 60, binding constraint zonal_export_limit:Z1, EPM +67,500, CSC 0.00 (zero-priced curve).
TU-COAL1’s BRP Unconstrained 435, constrained 450, EPM +391,500, CPP +13,500, reserve +2,250, you were marginal.
TU-DIST1’s BRP −440 both schedules, EPM −396,000.
Network Operator for Z1 TU-PV1 constrained to 60.

11.4 Intraday iteration 4 — the cost of changing your own mind

Heavy cloud. At 11:47 on D, TU-PV1 lodges:

The API’s estimated classification for 18:00: PURCHASE_AGAINST_INSTRUCTION, pricing basis intra_day_price, clause 10(6)(i). The participant is told, before 12:00, that this will not be free.

The re-clear must replace 40 MWh. Coal can rise 15 (to 465, leaving room for the up-reserve it still holds). The other 25 come from curtailing TU-IND1 (90 → 65) — cheaper than starting the OCGT.

TUID Change vs DAM constrained Declaration changed? Classification
TU-COAL1 +15 no Sale on instruction
TU-IND1 +25 (consumption 90→65; signed energy rose) no Sale on instruction
TU-PV1 −40 yes (DAC 60→20) Purchase against instruction

On-instruction stack (only):

Increment ΔV IP IP × ΔV
Coal 450→465 @ R 900 15 900 13,500
Factory 90→70 @ R 1,500 20 1,500 30,000
Factory 70→65 @ R 2,600 5 2,600 13,000
Σ 40 56,500

Indicative IDP = 56,500 / 40 = R 1,412.50. Collar around SMP 900 is [855.00, 945.00]. Applied IDP = R 945.00. collared? is true. Both numbers are published.

TUID Leg Rule Price Amount
TU-COAL1 +15 on max(own 900, IDP 945) 945 +R 14,175.00
TU-IND1 +20 on max(1,500, 945) 1,500 +R 30,000.00
TU-IND1 +5 on max(2,600, 945) 2,600 +R 13,000.00
TU-PV1 −40 against IDP flat 945 −R 37,800.00
MBA net −R 19,375.00

11.5 TU-PV1’s running position for 18:00

Line Amount Why
DAM energy EPM +67,500 75 MWh × R 900, unconstrained, never rewritten
DAM constrained sales 0 15 MWh × own offer R 0 — SO cut, free
IDM against-instruction −37,800 40 MWh × R 945 — they cut
Net for the hour +29,700 For 20 MWh actually scheduled

Effective R 1,485/MWh against an SMP of R 900. Still favourable — because the SO’s 15 MWh cut was free. Had they re-declared the first 15 themselves as well, those 15 would also have cost R 945.

That is the whole DAM–IDM relationship in one unit: the DAM pays you for the plan; the IDM charges you for changing your own mind; the SO changing it for you does not.

11.6 What happens to that hour on the till

The +29,700 does not leave a bank on 15 July. It sits on the chalkboard with every other hour of the Billing Period. On the Initial Settlement Statement it appears as three lines (EPM, CSC, IDC_AGAINST) on two pots (Energy, Market Balancing). If TU-PV1’s BRP is a net creditor for the month, those lines ride a Self-Billing Invoice you pay four business days after issue. If the BRP is a net debtor, they ride an Invoice due in three.

A Settlement Query about the R 37,800 does not stop that invoice. Pay now, argue later. If the query is upheld, a correcting document follows.

Follow along. Seat: mo@webill.net / supersecret. Path: §13.13 walks the same hour on the current Bidding tabs.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

12. The sidebar — four operating groups

§§1–11 are the market from this seat — who bids, when the bell rings, how a price is found, and how money is written. This chapter is the current /mo console: the map of fourteen rooms. Market Desk and Bidding are two sidebar items and one chapter (§13); every other later chapter is one sidebar item, tab by tab and field by field.

The Market Operator console is one application with fourteen rooms. They share a left-hand sidebar, branded SAWEM MO. Every room is a first-class route. Nothing important hides behind a second kitchen write. From here on the pages are the thing you press.

Screen: Market Operator (/mo) lands on Bidding → Daily for the current Trading Day. Registry, pairing and standing-data review live one click away at /mo/registry. Fourth landing card when you sign in as MO. This is the other side of every BRP screen in V9 §§2–8.

Follow along. Seat: mo@webill.net with password supersecret. Path: / → Market Operator. You land on Bidding → Daily. You should see four group headings: Market day, Settlement, Eligibility, Reference. Only the group you are working in is open — landing on Daily opens Market day and folds the other three away.

12.1 Why the menu is grouped this way

The sidebar is not an alphabet. It follows the operating clock.

  1. Market day — what you do before and during delivery: land, run the cadence, clear the auctions, tell the market.
  2. Settlement — what you do after 14:00 and at month-end: meters, stacks, the three bank accounts, queries.
  3. Eligibility — who may trade and where they sit: registrations, the register, generator plants, zones.
  4. Reference — what the arithmetic is allowed to assume: published parameters, and every immutable run.

Frequent desks sit at the top of each group. Each group is a module row — an icon tile, the module name and a chevron — and the row is a button: click it to open or close that module. Its desks are indented beneath it on a hairline rail, and the desk you are in is a solid amber chip (#mo-nav-metering, #mo-nav-cadence, and so on). The module holding your desk opens itself, so the chip is never hidden, and the console remembers your open/closed shape in this browser. Collapse the whole sidebar with the chevron and the module rows disappear: an 80 px rail of desk icons with hover tooltips.

The action bar sits under the brand: Switch application (the squares icon) back to the landing cards, Sign out, and the chevron that narrows the sidebar.

Quick jump is the search box under it. Type and the sidebar filters as you go — matching desks, or every desk of a module whose name matches, with the matching modules opened for you. Esc or the × clears it and hands the sidebar back to your remembered shape.

Air-traffic metaphor. Market day is the tower radio for today’s flights. Settlement is the airport accounts office after the last wheel is on the ground. Eligibility is the licensing desk — who is allowed to fly, and from which runway. Reference is the published rulebook and the black-box flight recorder: you read it; you do not rewrite yesterday.

The four sidebar groups, in the order the clock actually runs
1Market daycadence · auctions · notices
→
2Settlementmeters · stacks · cash
→
3Eligibilitywho · what · where
→
4Referencerules · runs

Eligibility is drawn third because that is when you notice it on a busy day. In life it runs continuously: a plant filed on Tuesday still changes Wednesday’s solve.

12.2 Shared chrome on every page

Every room reuses the same shell. Learn it once.

Piece What it is How to read it
Brand SAWEM MO in the sidebar; SAWEM on the page header You are on the Market Operator seat, not a BRP book
Module row Icon tile + uppercase label + chevron — Market day, Settlement, Eligibility, Reference Click to open or close that module; the one you are working in opens itself
Quick jump Search box above the modules Filters desks and modules as you type; Esc clears
Page title One noun — Bidding, Cadence, Participants The room
Page description One sentence under the title The job of this room
Flash Green info or red error after a write Read it before you press again
SIMULATED ribbon Amber strip when a Scenario Lab run is live Lab, not the live market (V14)
Date / month picker Trading day or Billing Period Shared across Bidding tabs; Cadence, Metering and Balancing have their own

A Trading Day is one calendar day in SAST for which the market sold energy. A Billing Period is a calendar month. They are not synonyms. Daily work picks a day; month work picks a month. Default trading date: before 10:00 SAST the picker offers tomorrow (you are still in D−1); from 10:00 it offers today. Default billing month: the previous calendar month.

12.3 Market day — the four items

Path prefix: /mo. Group heading: Market day.

Sidebar Icon Lands on Taught in
Market Desk computer-desktop /mo/bidding → Daily — six tabs §13 · §13.5
Cadence clock /mo/cadence §14
Forward arrow-trending-up /mo/forward §27
Notices bell /mo/notices §15

Market Desk is not a second workbench. It is the landing pad. Press it and you are on Daily for the current Trading Day, same page as Bidding. There is no hidden Market Desk LiveView at /mo. The module named MarketDeskLive is the Registry (§22).

Cadence is the timetable. Every Market Code §1.2 callable as due, ran or missed. Run the day and Run the month live here. A miss is a row.

Bidding is the auction room. Six tabs share one date ribbon: Daily, Submissions, IDM, Settlement, Month, Clear.

Notices is the tannoy. GENERAL / SYSTEM_STRESS / PRICE_CAP_EVENT to every participating BRP. Not a System Operator instruction (V12 §3).

12.4 Settlement — the five items

Group heading: Settlement. After 14:00 the chalkboard is done.

Sidebar Icon Lands on Taught in
Metering signal /mo/metering §16
Balancing adjustments-horizontal /mo/balancing §17
Accounts wallet /mo/accounts §18
Billing document-chart-bar /mo/billing §19
Dispute exclamation-triangle /mo/dispute §20

Metering is pairing and the D+7 vintage gate. Empty registry is unready, not 100 % of nothing.

Balancing is anonymised stacks, BPB/BPS, the Market Balancing Account. Official is disabled while vintage is unverified.

Accounts is the till: three market bank pots, this month’s cash, who cannot pay, cover, and the cascade. Month is a Billing Period.

Billing is the issued-documents room: register, remittances, corrections, read-only run status. The register names the organisation, writes the period as 1 June 2026, and shows amounts in rands. The eye opens the stored PDF. Issuing still happens on Cadence (§14 — Run the month). The till is Accounts (§18). The walkthrough is §19.

Dispute is one inbox with the org Recon: Data Query, Settlement Query, Settlement Dispute. Pay now, argue later.

After 14:00 the job leaves the chalkboard — meters, then stacks, then cash
Meteringpair · verify · D+7
→vintage
Balancingpreliminary → official
→month
Accountsthree pots · cascade
→documents
Billingregister · PDFs
→query
Disputepay now, argue later

12.5 Eligibility — the five items

Group heading: Eligibility. Who may bid, what they filed, where they sit, and who may stand on the carbon venue.

Sidebar Icon Lands on Taught in
Participants building-office-2 /mo/participants — six tabs §21
Carbon activations clipboard-document-check /mo/carbon-activations V18 §1
Registry book-open /mo/registry §22
IPPs bolt /mo/ipps §23
Zones map-pin /mo/zones — two tabs §24

Participants is two boards that are not duplicates. Registrations asks may this seat bid today? Issued Suspension Orders sit on that board as Enforcement, not as extra tabs. Accession register is the §6.2(9) publication clock. Pending Clocks (and Extension Requests, Open Default, Balancing Groups) is the joining and enforcement lifecycle.

Carbon activations is the Q3 / CTD4 queue. A PENDING_APPROVAL carbon participant profile cannot trade, file a pack, or raise a bill until you Activate it (or Refuse it with a reason). Path: /mo/carbon-activations (#mo-carbon-activations).

Registry is Trading Units in force for tomorrow, pairing, and standing-data review.

IPPs is generator sites filed through the standing-data wizard. Certify, Chase, Suspend unit. The Market Operator does not file Trading Units.

Zones is the register in force, coverage, and sites the model cannot place. The CSV goes to the System Operator.

12.6 Reference — the two items

Group heading: Reference.

Sidebar Icon Lands on Taught in
Rules code-bracket-square /mo/rules §25
Runs play-circle /mo/runs §26

Rules publishes the twenty-four market parameters and the eight defect switches. A new version is compose → review → confirm. There is no inline edit of the live table.

Runs is every clearing and settlement computation as an immutable record: inputs hash, parameter hash, supersedes, kind. Two runs that differ by one intended input are not the same run.

12.7 How to walk the sidebar on a working day

Do not hop at random. The safe order is eligibility first (is anyone allowed?), then intake, then solve/publish, then the afternoon desks.

A working day on this console — press in this order
Participants
→may they bid?
Submissions
→did it arrive?
Daily / Clear
→solve, then publish
Metering
→after 14:00
Balancing
Month-end, on Cadence then Accounts then Billing: Run the month Dispute

Cadence is the scoreboard for the same day. Notices can go out whenever the market needs context. Rules and Runs are reference — you do not operate a day from them.

If you need to… Open Not
See whether today’s gate closed Cadence Bidding’s gate chip alone
Inspect a received bid Bidding → Submissions the BRP Bid Desk
Solve then publish Bidding → Daily or Clear a second “make it look clear” button
Pair meters after 14:00 Metering Daily
Run official prices Balancing (Official, vintage verified) Daily Publish
See who cannot pay Accounts Dispute
Open an issued invoice PDF Billing Accounts cash position
Decide an extension Participants → Extension Requests Registry
Acknowledge the SO model Zones Rules

12.8 What you will not find in the sidebar

Three rooms people look for here and that live elsewhere.

Looking for Where it actually is
System Operator dispatch, flags, reserve certification /so — V12
The BRP Bid Desk, Registration wizard, Recon /org/brp — V9
Scenario Lab / live meters /org/sim — V14 · live meters V21 §6

Handbook bookmarks /mo/dam, /mo/dam/submissions, /mo/dam/idm, /mo/dam/settlement and /mo/dam/month are 301 redirects onto the Bidding tabs. /mo/bid-desk is a 302 onto Daily. They are not extra rooms.

Where this is taught. The Market Code mechanics (why SMP is one price, why the energy pot nets to R 0.00, why a query never holds an invoice) stay in V9. This volume teaches the screens that operate those mechanics.

Data. full_demo · seed 42 · stage S08 (market loop). Demo seat mo@webill.net / supersecret. Worked Trading Day 2026-07-15.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

13. Market Desk

The first item in the Market day group is Market Desk. The path is /mo. The icon is a signal. When you pick the Market Operator card on / and sign in as mo@webill.net, this is where you land.

There is no separate Market Desk page. /mo is a 302 onto Bidding → Daily for the current Trading Day. This chapter is the landing hop and the six tabs you land on, so you stop looking for a second room.

13.1 The operator’s problem

You open the console at 09:10 on a Tuesday. You need today’s (or tomorrow’s) pulse in one click: is the gate open, have the System Operator parcels arrived, has anyone solved? You do not want a dashboard of every queue. You want the chalkboard.

That is why Market Desk is a hop, not a home of its own.

13.2 What the hop does

You typed Handler Result
/mo BiddingRedirectController.desk/2 302 → /mo/bidding?date={date}
/mo/bid-desk same 302 → /mo/bidding?date={date}
/mo?date=2026-07-15 same 302 → /mo/bidding?date=2026-07-15

Query params are preserved: date, month, tuid, seq, iteration, period. If date is omitted, the default Trading Day is used — before 10:00 SAST, tomorrow (you are still in D−1); from 10:00, today.

Handbook paths are permanent redirects, not rooms:

Old bookmark Status Lands on
/mo/dam 301 /mo/bidding
/mo/dam/submissions 301 /mo/bidding/submissions
/mo/dam/idm 301 /mo/bidding/idm
/mo/dam/settlement 301 /mo/bidding/settlement
/mo/dam/month 301 /mo/bidding/month

13.3 What you see after the hop

The browser title is Bidding. The header sentence is National day-ahead desk — gates, intake, the hourly SMP, and settlement pots. The Daily tab is active. The date ribbon shows the Trading Day the hop chose.

Read Daily as §13.7. In short: four pulse cards in two rows (Clock and gates · Intake health, then Energy and settlement · Notifications), then the Price board — status badge, Low / High / Average / Spread when a curve exists, Solve / Publish…, and the hourly SMP step chart. The energy-account pot must read R0.00 once the day is published.

After Market Desk /mo → /mo/bidding

You pressed 1 Address bar 2 Active tab 3 Date 4
Market Desk /mo/bidding?date=2026-07-15 Daily 2026-07-15
  1. 1Market Desk is the sidebar landing, not a LiveView.
  2. 2Address bar always shows a Bidding path after the hop.
  3. 3Daily is the pulse — same page as Bidding.
  4. 4Date in the address bar is ISO. Clock and gates shows it as 15 Jul’ 2026.

13.4 Do not confuse two names

The Elixir module WB.WheelingWeb.Mo.MarketDeskLive is not this sidebar item. That module is the Registry at /mo/registry (§22). The landing card still says “Market Desk” in older copy; the sidebar item named Market Desk is the hop to Daily.

BidDeskLive is gone. /mo/bid-desk redirects like /mo. There is no second Clear-day button hiding behind that URL.

Follow along. Seat: mo@webill.net. Path: / → Market Operator, or sidebar Market Desk. You should see /mo/bidding and the Daily tab. Change the date and you stay on Daily. Open Bidding in the sidebar: same page.

Where this is taught. The six tabs, Solve vs Publish, and the 2026-07-15 hour are §13.5–§13.13.

13.5 The six tabs

Path: Market Operator → Bidding (/mo/bidding). Third item in Market day. /mo and /mo/bid-desk land here on Daily (this chapter’s hop, §13.1–§13.4).

One parent, six tabs. The date on the ribbon is shared: change it and you stay on the tab you were on. Handbook bookmarks /mo/dam* land on the matching tab.

This is the auction room. You inspect what arrived, you solve, you publish, you watch the five intraday patches, you read the chalkboard, you roll the month. You cannot type a price.

Where this is taught. Why a bid is 168 periods, why Solve is not Publish, and how the BRP Bid Desk produces the payload: V9 §4. Intraday mechanics: V9 §5. Day-ahead money: V9 §13. This chapter is the screen you press.

13.6 Shared chrome — ribbon and tabs

Browser title: Bidding. Header: Bidding — National day-ahead desk — gates, intake, the hourly SMP, and settlement pots. Icon: hero-presentation-chart-line. Tab bar: #bidding-tabs.

Tab Icon Address Component id What it is
Daily calendar-days /mo/bidding bidding-daily Pulse cards + Price board
Submissions clipboard-document-list /mo/bidding/submissions bidding-submissions What arrived, what was refused
IDM bolt /mo/bidding/idm bidding-idm Five patches, anonymised stack
Settlement banknotes /mo/bidding/settlement bidding-settlement Hour chalkboard, energy pot
Month chart-bar /mo/bidding/month bidding-month-board Billing Period roll-up
Clear play /mo/bidding/clear bidding-clear G5 ledger + the same Solve

Active tab uses tab tab-active font-semibold. Deep links keep the date: /mo/bidding/submissions?date=2026-07-15, /mo/bidding/idm?date=2026-07-15&iteration=4, /mo/bidding/settlement?date=2026-07-15&period=18.

Ribbon (Bidding.Chrome.bar) is a rounded white bar under the header, not a second page title:

Control Id Shown on What it does
Trading date #bidding-date All tabs except Month type="date". Change patches the current tab
Billing period #bidding-month Month and Clear type="month"
Gate chip #bidding-gate Always See below
Market Code 2.3 #bidding-code-version Always Uppercase tracking on the right

Gate chip. Future day: DAM gate (D−1) — open or closed, plus #mo-gate-countdown and {n} silent. Today: Next IDM gate (open), countdown to 10 / 12 / 14 / 16 / 18 SAST. Past: Gate closed, no countdown.

Bid → Clear → IDM → Statement — the order you work a market day
1Bidintake
→
2Clearsolve then publish
→
3IDMfive patches
→
4Statementmonth

Solve is not publish. Daily, Settlement and Clear each show both buttons, and they are the same Solve — WB.Sawem.Cycles. On Daily they sit in the Price board toolbar, above the chart, to the right of the day/night key (#dam-price-board-actions). Solve is the emerald play control. Settlement and Clear keep the pair on their own card. After Solve the public noticeboard is still empty. After Publish it is not.

Control Id Enabled when Flash on success
Solve #dam-solve Always Both schedules solved and settled. Nothing is published yet.
Publish… #dam-publish Latest run is :SOLVED Opens confirm
Publish this run inside #dam-publish-confirm Confirm open Published. Every participant now settles against this run.
Cancel same panel Confirm open Closes confirm

Confirm copy: Publishing makes this the schedule and price set every participant settles against (clause 9.10(1)). It supersedes anything already published for this Trading Day.

Status sentence (@status.sentence):

A miss on Solve: Solve recorded a miss — a prior step is un-run or an SO input is absent (or there are no accepted submissions for this Trading Day). A miss on Publish: Publish recorded a miss — prices have not been calculated.

You cannot edit a price curve from this seat. If a curve is wrong, the BRP fixes the registry or sends a new sequence.

13.7 Daily — the pulse

Path: /mo/bidding. This is what Market Desk opens.

From md the page is two rows of two pulse cards, then the Price board full-width underneath. Narrow screens stack. Card titles are the ones on the screen, not the old four-across names.

Section Id How to read it
Pulse #dam-daily-pulse Two-by-two from md. Row 1: Clock and gates · Intake health. Row 2: Energy and settlement · Notifications and exceptions.
Clock and gates #clock-and-gates Badge All present / Waiting / {n} late. Date as Trading date 15 Jul’ 2026. Three SO lights. Constraint note at the foot.
SO inputs #so-inputs Demand · Reserves · Interconnect — each a chip present / unknown / late
Constraint note #constraint-binding-note Why constrained matched unconstrained — or how many constraints bind
Intake health #dam-daily-intake Header Units: {n}. Expected / Received / Rolled over (unit counts, links to Submissions). Declarations received bar when expected > 0
Energy and settlement #dam-daily-money-column One card stacking Energy account pot, Intraday (IDM), Adequacy. Header ZAR (R)
Energy account pot #dam-daily-energy-net The energy pot only. Chip Unpublished / Balanced / Open. Every possible reading is below
Intraday (IDM) #dam-daily-idm-now Whether any IDM iteration has cleared. Every possible reading is below
Adequacy report (§9.10(4)) #adequacy-report Public after publish; #adequacy-report-empty before. Every possible reading is below
Notifications and exceptions #dam-daily-exceptions Chip {n} notices. Risk bullets + #notification-ledger. Below
Price board #dam-daily-price-board Status badge, SMP stats, day/night key, Solve / Publish, step chart, status sentence. Below

Three traffic lights. Each answers one question only: has the System Operator sent this fact yet? It is not a score of how healthy the numbers look.

Hover on a light lifts it. Each light is a row with a present / unknown / late chip on the right (check, ellipsis, or warning triangle). The lights are not links. The Clock and gates card also carries a summary badge: All present (all three green), Waiting (none late, at least one still unknown), or {n} late.

Light Id Everyday name Due
Demand #so-input-demand How much the country will take 10:00 D−1
Reserves #so-input-reserves How much must stand ready 10:00 D−1
Interconnect #so-input-interconnect What the neighbours will send or take 13:30 D−1
State Colour Meaning
unknown Yellow Pigeonhole empty and the due time has not come
present Green A message is in the store — even if the box is empty
late Red Due time passed and still empty. 14:00 publication is at risk

If the parcel arrives after the due time, the light flips to present. Late means still missing, not arrived late. The teaching of those lights is V12 §1.4.

Constraint note — three honest sentences, never an invented corridor:

Intake tiles: Expected, Received, Rolled over. Click any to open Submissions. Hover lifts the row. Counts are units, not MW. The card header shows Units: {n} (expected census). When expected is greater than zero, a Declarations received bar shows received / expected as a percentage. Each row is colour-coded. What a submission is, the other three tiles, and what to look for live on §13.8.

Tile Everyday name Colour Meaning
Expected How many units should have sent Sky Census
Received Who sent a declaration Green / amber / red Participant submissions vs expected: complete, partial, or none
Rolled over Who was silent and carried forward Amber when > 0, green at 0 Carry-forward is amber, not alarm-red

Energy account

On the pulse, inside Energy and settlement (#dam-daily-money-column) — Energy, then Intraday, then Adequacy. The inner card #dam-daily-energy-net is labelled Energy account pot, with Three pots isolated on the right and Must read R0.00 under the figure. The whole card is coloured and is a link to Settlement — hover lifts it; there is no “click through” sentence. This is only the energy pot (EPM — scheduled unconstrained MWh × SMP). It is not Market Balancing, not the MO Charge, and not the three pots added together. The invariant and the arithmetic live in §7.1. Daily asks one question: does the closed loop still close?

A chip next to the Rand figure names the state: Unpublished, Balanced, or Open.

What you see Colour Chip When What it means
— Amber (:warn) Unpublished Nothing has been published for this Trading Day, or the published run has an empty settlement There is no energy account yet. Solve without Publish does not write a net. It is not R0.00 pretending to be empty. The card still opens Settlement.
R0.00 Green (:ok) Balanced A published settlement whose energy lines sum to zero The loop closed. Generators were paid what loads were charged. R0.00 is data — the energy pot nets to zero. It is not “nothing happened.”
R{n.nn} (any non-zero, including negative R-n.nn) Red (:incident) Open A published settlement whose energy lines do not sum to zero An incident. The market must not have been published in this state — settlement raises before it gets here, so a red card is a confirmation that something bypassed the invariant, not a statistic to live with. Open Settlement from the card and do not treat the day as done.

The amount is Chrome.money: R then the exact two-decimal figure, no thousands separator and no space (R0.00, R13500.00, R-12.50). Zero is Decimal equal to 0, so R0.00 and R0.0 do not both appear — it is always R0.00.

Daily does not show the §16(2)(g) rounding residual or the Market Balancing net. Those sit on Settlement (#dam-settlement-mba-net, the rounding residual on the legacy board). Mixing this tile with Balancing or with IDM’s MBA net is how operators invent a “total settlement” that the Code does not have.

Intraday now

In that same stack, below Energy account pot. The inner card is labelled Intraday (IDM). The whole card #dam-daily-idm-now is coloured and is a link to the IDM tab — hover lifts it. There is no Open IDM control. This is whether the intraday market has cleared at least one iteration for the selected Trading Day — not whether the DAM is solved. The DAM constrained schedule stands until an IDM iteration publishes.

What you see Colour When What it means
DAM constrained still standing. Amber (:warn) No IDM day is stored, or the stored day has zero iterations No patch has cleared. Participants are still on the DAM constrained schedule. This is the ordinary morning, and it is also a quiet afternoon if nobody moved. It is not an error.
MBA net R0.00 Green (:ok) Iterations exist and the signed net is zero The account neither paid out nor took in, net. A unit walked all the way back to its DAM constrained schedule has a net IDM position of R0.00 (§9).
MBA net R-n.nn or Rn.nn (not zero) Sky (:info) Iterations exist and the account has a signed position The Market Balancing Account’s own IDM position for the day. Negative means the account paid participants (recovered as ancillary, clause 10(17)). Positive means it took in. The golden teaching hour is −R19375.00. This is not the energy pot.

The Rand format is the same as Energy account (R0.00, R-19375.00). There is no third empty state — if the board loaded, you get an MBA net, including R0.00. Click the card to open §13.9. Daily does not list lodgements, the next gate, collars, or a per-iteration stack.

Adequacy report (§9.10(4))

In that same stack, below Intraday (IDM). The card is coloured (hover lifts it). It is not a link. The public daily general adequacy report. No participant names. Publish writes it; Solve does not. Daily shows a summary, not the hour-by-hour table. The two DOM ids are exclusive: #adequacy-report or #adequacy-report-empty.

Empty (#adequacy-report-empty, amber, dashed border, warning triangle):

What you see Colour When What it means
No public adequacy report has been published. Amber (:warn) No AdequacyPublication row for this Trading Date Participants do not yet have the public shape of the day. This is the state before Publish, and it stays the state if Publish never ran.

Published (#adequacy-report):

The first sentence is always Public. then the stamp, then a punctuality word.

Piece Possible values What it means
Public. Always, when the card is the populated one Clause 9.10(4) — this artefact is public. Daily will not show a private schedule report here.
Published {dd Mon yyyy, HH:MM} SAST stamp of published_at (Chrome.sast_stamp, e.g. 15 Jul 2026, 13:52) When the Market Operator published. The deadline for “on time” is 14:00 SAST on D−1, the same clock as schedule publication.
On time. Green card (:ok) on_time? is true — published at or before 14:00 SAST on D−1
Late. Red card (:incident) on_time? is false — published after 14:00 SAST on D−1
{n} period(s) reported. n = length of payload["periods"], or 0 if that list is missing How many Trading Periods the stored report covers. A normal day is 24. 0 means a row exists but carries no periods — the report was persisted empty, not that the day has no hours.
Contingency reserve is reported and never paid. Always, on the populated card Clause 9.1(5). Contingency is headroom after energy and reserve scheduling. It is not a settlement line. Daily states the rule; it does not print a Rand figure for it.

Daily does not print expected demand, sent-out, consumption, capacity available, capacity allocated to reserves, or SMP from the payload. Those fields exist on the stored report (and on GET adequacy). This card is the pulse: public, when, on time or late, how many periods, contingency unpaid.

Notifications and exceptions

On the pulse, to the right of Energy and settlement. Card #dam-daily-exceptions, titled Notifications and exceptions, with a chip {n} notices (n is the ledger length, including zero). Two lists: exception bullets (risks that are true right now) and the notification ledger (who was told what). They are not the same list. A quiet day can have an empty bullet list and an empty ledger.

Exception bullets — each appears only when its condition is true. All three can show together. There is no “all clear” sentence; silence is the all-clear.

Bullet When it appears What it means
Unpublished past 13:30 on D−1 — 14:00 publication is at risk. The selected Trading Date’s D−1 is today, SAST clock is 13:30 or later, and this day is not published You are on the afternoon before delivery and the 14:00 publish has not happened. It does not appear when you browse a past Trading Date from a later calendar day, even if that day published late or never. It does not appear before 13:30 on D−1.
{n} unit(s) invalidated and awaiting resubmit. n ≥ 1 distinct Trading Units whose last row for this date is invalidated A registry change broke an already-accepted declaration and there may be no replacement. They think they are done. Chase them before the gate. n is the count of those units, not of versions.
{n} event delivery(ies) failed. n ≥ 1 ledger rows for this date with delivery failed §16(2)(f) — someone was not told. n is failed rows, not distinct parties. The same event retried to success stays on the ledger as a later recorded row (or the failed row is resolved to recorded); the bullet counts whatever is still :failed now.

Notification ledger (#notification-ledger) — every notice stored for this Trading Date, oldest first. The Market Operator seat sees the full list, including party-scoped rows. A BRP inbox only sees public rows plus rows that name that BRP.

Empty ledger: a centred check in a green ring and No notices have been recorded for this day. Publish has not written schedule.published, and nothing else has been recorded.

Populated ledger — one row per stored notice (#notification-{id}). Four columns; every value each column can hold:

Time

Value Meaning
{dd Mon yyyy, HH:MM} SAST (Chrome.sast_stamp of occurred_at). Same clock as Adequacy’s published stamp.

Event (monospace). The stored event name. Daily does not rewrite it.

Value Meaning
schedule.published Publish ran. One public row (Day-ahead schedule published., clause 9.10(1)) plus one party row per settlement party (Your schedule report is published.). Event-delivery may write further schedule.published rows as receipts.
PRICE_CAP_EVENT A party-scoped market notice about the price cap. The named BRP receives it; a BRP that was not named does not.
Any other stored string Whatever NotificationLedgers.record / EventIncidents.deliver wrote (invalidation notices, other §16(2)(f) types). The column is the name, not a pick-list.

Audience

Value Meaning
public Broadcast. Every participant may see it. party_id is empty.
party {uuid} Named one registration. {uuid} is that party’s id.
network operator Scoped to a network operator (same naming rule as party when an id is present).
— A row whose audience_kind is none of the three. Should not appear; if it does, the store is dirty.

Delivery

Value Colour Meaning
recorded Emerald The notice was written as delivered (or a failed row was later resolved to recorded). Default for a successful Publish row.
failed Red Delivery did not land. A failed schedule.published is a row, not an omitted success. The exception bullet counts these.

Daily does not show channel (event_stream / api / notices / statement) or failure_reason. Failed detail lives on the event incident queue; this table is the receipt list.

Price board

Below the pulse. Card #dam-daily-price-board. Read it top to bottom, as the screen is laid out:

  1. Title row. Price board plus a status badge (#dam-daily-price-board-badge): Not solved, Solved, not published, or PUBLISHED. Subtitle: 24-hour system marginal price (R/MWh) · daylight 07:00–18:00 SAST.
  2. Stat cards (only when a curve exists): Low, High, Average, Spread — explained card by card below. Hidden when the chart is empty.
  3. Toolbar. Sun/moon key #dam-daily-smp-day-night-legend when a curve is drawn (Daylight (07:00–18:00) · Night). Solve (emerald play) and Publish… on the right (#dam-price-board-actions).
  4. Chart #dam-daily-smp-chart (380 px). Empty sentence, or the ECharts step line #dam-daily-smp-chart-line. When the run is published and the line is drawn, a green PUBLISHED pill sits on the chart (#dam-daily-smp-published-mark).
  5. Footer. Status sentence #dam-daily-price-board-status on the left; Resolution: 1 hour · Currency: ZAR (R) · Timezone: SAST (UTC+2) on the right.

There is no second card repeating the status.

Think of the System Marginal Price (SMP) as yesterday’s tomato price: one number for the whole country, for one hour. Nobody types it. The auction finds the last crate that was needed, and that crate’s price is the hour’s SMP. How the stacks are built is §6. Daily does not re-run that arithmetic. It draws the 24 hourly prices as one anonymous line, and the four cards in the header summarise those same hours.

The four stat cards

The four cards sit in the Price board header, to the right of the title on a wide screen and under the title on a narrow one (grid-cols-2 then sm:grid-cols-4). They appear only when at least one hour has an SMP. If the chart is empty they are absent — not zero. Hours with no price are dropped before any of the four is calculated, so a one-hour teaching run still fills the cards from that one hour.

Every Rand figure is Chrome.money: R then two decimals, no thousands separator and no space (R900.00, R0.00). These are not named TOU bands (Peak / Standard / Off-peak). They are statistics of this Trading Day’s hourly SMPs, the same numbers the step chart draws.

What they share. All four read only the solved (or published) hours on the ribbon’s date. They do not mix yesterday. They are not energy-weighted: a cheap overnight hour and an expensive evening hour count equally, whether 50 MWh or 5,000 MWh cleared. Settlement’s hour table is where you read a single hour; these cards are the day’s envelope.

Low

Slate card. Label Low. Figure in ink. Unit line / MWh.

Low is the cheapest hour of the day — the smallest hourly SMP that was drawn. On a normal day that is a night or early-morning shelf. It is not “the off-peak tariff” and it is not a floor the auction is forced to. If every hour is the same price, Low equals High.

Read it as: the quietest the tomato stall got. A very low Low next to a very high High is a peaky day, not a data error.

High

Amber card. Label High. Figure in amber. Unit line / MWh.

High is the dearest hour of the day — the largest hourly SMP that was drawn. On the teaching day that is the evening shelf (§11 — 18:00 at R 900). It is not the Market Price Cap unless the auction actually hit the cap that hour (capped hours are badged on Settlement, not here).

Read it as: the most expensive crate that was still needed. Hover the chart’s highest shelf to see which clock hour it was; the card does not print the hour.

Average

Slate card. Label Average. Figure in emerald. Unit line / MWh.

Average is the unweighted mean of the hours that have an SMP: add those hourly prices, divide by how many hours were added. Twenty-four priced hours ⇒ sum ÷ 24. A one-hour run ⇒ that hour’s SMP. It is not the median, not a TOU “standard” band, and not MWh-weighted (a 3 000 MWh peak hour does not pull the average more than a 200 MWh night hour).

Read it as: if every hour of this day had been the same price, this is that price. Compare it to Low and High: sitting near Low means most hours were cheap; sitting near High means the expensive hours dominated the clock, not the megawatts.

Spread

Slate card. Label Spread. Figure in sky. Unit line Delta (not “/ MWh” — it is a difference of two prices).

Spread is High minus Low. A flat day is R0.00 (Low = High = Average). A peaky day is a wide Rand gap between the cheapest night shelf and the dearest evening shelf. It is not volatility, not a standard deviation, and not a TOU peak/off-peak ratio. It does not tell you how long the expensive hours lasted — only how far the top of the stairs sits above the bottom.

Read it as: how much the day’s price moved, peak to trough. Average tells you the middle; Spread tells you the height of the staircase.

Card How it is made Unit line Hidden when
Low Minimum of this day’s hourly SMPs / MWh No hour has an SMP
High Maximum of this day’s hourly SMPs / MWh No hour has an SMP
Average Sum of those SMPs ÷ number of priced hours / MWh No hour has an SMP
Spread High − Low Delta No hour has an SMP

On the teaching day the evening High is R 900. Low, Average and Spread follow whatever other hours that solve produced — they are not typed; they are computed from the same curve you see.

What the four cards are not. They are not a forecast. They are not the three pots. They do not change when you Publish (the numbers were already the draft SMPs). They disappear rather than show R0.00 when there is nothing to summarise.

What you are looking at. A 24-hour step chart drawn with ECharts. The x-axis is Hour (SAST) (00:00 → 23:00). The y-axis is R/MWh, from zero up. The stroke is ink #212a34, not a coloured series. The line is a step, not a slope: the price is flat for the whole hour, then it jumps (or drops) at the next hour. There are no participant names, no TUIDs, no farm labels. A public wallboard could show the same picture. The plot is washed amber for daylight (07:00–18:00 SAST) and slate for night. Settlement’s 24-hour curve uses a tighter daylight window (07:00–17:00).

What Daily does not draw. Capped hours and all-inflexible hours are not marked here — those badges live on Settlement’s hour table. The y-axis starts at R 0, so a day that is R 900 every hour is a flat line at R 900, not a line glued to the top of the box.

What you see When How to read it
Badge Not solved; grey sentence This day has not been solved. inside the chart No clearing run stored The auction has not been run for this date. A table of zeroes would be a lie, so the board stays empty. Low / High / Average / Spread and the day/night key are hidden.
Badge Solved, not published or PUBLISHED; grey sentence This run has no hourly SMP to draw. A run exists, but it has no hourly price to plot (a one-hour teaching fixture still draws a shelf) The status sentence under the chart is the authority. Open Settlement’s hour table.
Ink step line (#dam-daily-smp-chart-line) A solved run exists (even if you have not published yet) or a published run exists Those are the SMPs on the ECharts canvas. Left → right is midnight through evening. Hover a shelf to read the hour and R/MWh. A single hour is a dot on the axes, not an empty box.
Green PUBLISHED pill on the chart (#dam-daily-smp-published-mark) The run is published and the line is drawn Official. Same word as the title badge.
Sentence under the chart: This day has not been solved. No clearing run stored Same as the empty chart.
Solved, not published. Solve succeeded; Publish has not You can see the curve. Participants still cannot settle against it. Energy account is still — / Unpublished. Adequacy is still empty.
Published at HH:MM. Publish succeeded, and the run has a SAST stamp The curve is now the official one. HH:MM is when you published, not when the auction ran.
Published. Publish succeeded but the stamp is missing Rare. Treat it as published.

How to read a step. Each shelf is one Trading Period. The price holds until the next hour. If 17:00 is R 640 and 18:00 is R 900, the line runs flat, then up, then flat again. You are not looking at a smooth “demand curve”. You are looking at 24 auction results glued together.

A picture — empty, then the teaching day

Data. full_demo · seed 42 · Trading Day 2026-07-15. Demo clearing uses deterministic TOU SMP bands. Same date ⇒ same stairs.

On that teaching day the evening hour 18:00 is R 900 / MWh, set by coal’s last shelf (§11). The Price board does not write “R 900” on the line. You read shape: night lower, evening higher. Settlement’s hour table is where you read the number.

Price board — empty, then a stepped SMP (teaching shape, not a screenshot)

  1. Before Solve

This day has not been solved. 00:0023:00

Read it: no auction, no line. The board refuses to invent a price.

  1. After Solve (and after Publish)

18:00 · R 900 00h23h

Read it: each flat is an hour. The peak shelf is evening. No farm names on the line.

A few hours from the same teaching day, so you can match the peak on the sketch to a number:

Hour (SAST) What the board is saying In words
03:00 A low shelf Overnight. Cheap. The line sits low.
12:00 A middle shelf Midday. Not the peak.
18:00 The high shelf — R 900 Evening. Coal’s last crate set the price. Energy payments for this hour all use R 900.
22:00 Down again After the evening peak the line drops.

If you Solve a second time, the line is redrawn from the new run. Until you Publish, the public (participants, the adequacy card, the energy account) still treat the previous published day — or nothing — as official.

You cannot drag the line. If an hour looks wrong, the BRP fixes the declaration or the registry and you Solve again. This seat does not edit prices.

Solve and Publish

The two buttons sit on the Price board, in the toolbar above the chart, to the right of the day/night key (#dam-solve, #dam-publish). Solve is emerald with a play icon. Settlement and Clear show the same pair (§13.6). One click here is one click there.

Solve is not Publish. Solve is you running the auction in the back room and looking at the answer. Publish is you pinning that answer on the town noticeboard. Until you pin it, nobody settles against it.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 22, "rankSpacing": 28, "padding": 12}}}%%
flowchart LR
  A["1. Solve<br/>run the auction"] --> B["You look<br/>Price board fills"]
  B --> C["2. Publish…<br/>confirm"]
  C --> D["Town noticeboard<br/>everyone settles"]
What Solve does

Solve (#dam-solve) is always on the Price board. It does three jobs, in order, for the Trading Date on the ribbon:

  1. Unconstrained clear — “If the wires could take everything, who would run?” That schedule sets the SMP.
  2. Constrained clear — “What may the wires actually carry?” That schedule is what injects. It does not rewrite the SMP.
  3. Calculate prices — write the hourly SMP (and the money lines) onto a solved run. Nothing is public yet.

If a System Operator parcel is missing and the run cannot proceed, the flash is Solve recorded a miss — a prior step is un-run or an SO input is absent. The Price board stays empty.

If there are no accepted submissions for the Trading Date, Solve is also a miss (there are no accepted submissions for this Trading Day) — it does not write an empty run and it does not fill the board with a fake flat line. Publish of a run with no hourly prices is likewise a miss, so a blank solve cannot replace a curve that was already on the noticeboard.

If it works, the flash is Both schedules solved and settled. Nothing is published yet.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 20, "rankSpacing": 26, "padding": 12}}}%%
flowchart TB
  S["You press Solve"] --> U["Auction ignoring the wires<br/>this sets the SMP"]
  U --> C["Auction with the wires<br/>this sets who actually runs"]
  C --> P["Write a solved run<br/>still private"]
  P --> Y["Price board: ink step line<br/>Badge: Solved, not published<br/>Publish… appears"]
  P --> N["Energy account pot still —<br/>Adequacy still empty<br/>Participants not told"]

Worked example — you Solve 2026-07-15 at 13:10.

You are mo@webill.net. Date ribbon: 15 Jul’ 2026. Clock and gates shows Trading date 15 Jul’ 2026. Demand / Reserves / Interconnect are present. Badge Not solved. Chart says This day has not been solved. There is no Publish… button. Low / High / Average / Spread are hidden.

You press Solve. The three jobs run. Flash: Both schedules solved and settled. Nothing is published yet.

On Daily after Solve What changed
Price board The ink step line appears. Badge Solved, not published. Low / High / Average / Spread fill. 18:00 is the high shelf (R 900 in the teaching set).
Status sentence Solved, not published.
Publish… Now visible. Latest run is solved.
Energy account pot Still — / Unpublished. Publish has not closed the energy pot for the public.
Adequacy Still No public adequacy report has been published.
Notification ledger Still empty of schedule.published.
Participant seats They do not yet see this as the plan.

You have a draft. You can open Settlement and read the chalkboard. You have not yet made it the plan.

What Publish does

Publish… (#dam-publish) only appears when the latest run is solved. After a successful publish the run is published, so the button hides until you Solve again.

It never publishes on the first click. It opens the amber confirm #dam-publish-confirm:

Publishing makes this the schedule and price set every participant settles against (clause 9.10(1)). It supersedes anything already published for this Trading Day.

Control What it does
Publish this run Pins this solved run as official.
Cancel Closes the confirm. Nothing is published.

Publish this run then:

Success flash: Published. Every participant now settles against this run.

Miss flash: Publish recorded a miss — prices have not been calculated. (You pressed Publish without a solved price run.) If there is no solved run at all: There is nothing solved to publish.

%%{init: {"themeVariables": {"fontSize": "16px"}, "flowchart": {"nodeSpacing": 20, "rankSpacing": 26, "padding": 12}}}%%
flowchart TB
  P["You press Publish…"] --> Q{"Confirm?"}
  Q -->|Cancel| X["Nothing changes"]
  Q -->|Publish this run| Y["Pin this run<br/>supersede any older published run"]
  Y --> A["Adequacy card fills<br/>On time or Late"]
  Y --> E["Energy account pot gets a net<br/>R0.00 Balanced or red Open"]
  Y --> N["Ledger: schedule.published<br/>participants are told"]
  Y --> S["Status: Published at HH:MM<br/>Publish… hides"]

Worked example — you Publish the same day at 13:40.

Status still says Solved, not published. You press Publish…, read the amber warning, press Publish this run.

On Daily after Publish What changed
Price board Same step line — it was already drawn at Solve. Badge PUBLISHED. Green PUBLISHED pill on the chart.
Status sentence Published at 13:40.
Publish… Gone, until you Solve again.
Energy account pot R0.00, green, chip Balanced. The closed loop is now the published pot.
Adequacy Public. Published 15 Jul 2026, 13:40. On time. (13:40 is before 14:00 D−1.)
Notification ledger schedule.published rows. Audience public and each party. Delivery recorded if the event landed.
Participant seats They now settle this day against this SMP and these schedules.

If you had published at 14:10, Adequacy would say Late. The prices would still be published. Late is a fact about this chair, not a second button.

If you Solve again after publish, you get a new solved run. The Price board follows the new draft. The public still sits on the old published run until you Publish the new one (which supersedes).

Follow along. Seat: mo@webill.net / supersecret. Path: Market Operator → Bidding → Daily ?date=2026-07-15 → Solve → read the Solved, not published badge and the ink step line → Publish… → Publish this run. You should see badge PUBLISHED, a green PUBLISHED pill on the chart, Energy R0.00 / Balanced, and Adequacy Public.

The control table, ids, and flashes are listed once in §13.6. Daily is where you use them.

Daily /mo/bidding

Pulse 1 Price board 2 Solve 3 Publish 4
2×2 cards badge · stats · ink steps emerald play confirm
  1. 1Pulse is Clock and gates, Intake health, Energy and settlement, Notifications — two rows, not four tiles across.
  2. 2Price board is the status badge, Low/High/Average/Spread, then 24 anonymous ink steps. Empty until Solve. PUBLISHED on the chart after you pin it.
  3. 3Solve is the emerald play on the toolbar. It runs the auction in the back room. It does not pin the noticeboard.
  4. 4Publish needs the confirm control; then everyone settles against this run.

13.8 Submissions — silent and rejected

Path: /mo/bidding/submissions. Date on the ribbon is the Trading Day you are inspecting. Daily’s Intake health card is the three-number headline; this tab is the ledger behind it.

This is intake, not a second Bid Desk. You cannot type a price, add an increment, or “fix” a curve. If a declaration is wrong, the BRP sends a new sequence (before the gate) or corrects in the IDM (after). You accept, refuse, roll silence, and read what was stored.

Where this is taught. Who may submit, the three doors, why a late PUT is not stored, and why every version is kept: §4. The 168-period body, consent, idle hours, energy limits, and every validation code: §5. This section is the screen you press, and what to look for on it.

What a submission is

A submission is one registered Trading Unit’s financially binding declaration for this Trading Day and the following six days — exactly 168 hourly periods. It is not “the company’s bid for Tuesday”. One BRP with five units sends five submissions. The market clears from the operative body: the highest submission_seq for that unit and date that has not been invalidated.

It arrived through one of three doors (§4.2):

  1. Participant — a PUT the BRP sent (this platform’s nightly worker is still a BRP client of the same door).
  2. Rolled over — the unit was silent at 10:00, so you generated today’s body from yesterday’s remaining horizon (§9.3(2)). You did not invent prices.
  3. Nothing stored — they never got in. A rejected or late attempt is not a submission. It lives in Rejected / late attempts below the table. Telling a BRP “we have nothing” when they have a 409 is an operational lie.

Accepted bodies are blind (nobody else sees the curve before the gate), binding, and replaceable until the bell. A 24-period body is refused as a horizon fault, not padded. A financially binding body without a signature is not a submission.

The main table shows one row per unit that has anything stored for the ribbon date — the newest sequence. Older sequences stay in the drawer under Version history. Solve reads the operative rows. If there are none, Daily’s Solve is a miss (there are no accepted submissions for this Trading Day).

What this tab is not. It is not the Price board, not Settlement, not the BRP Bid Desk, and not a place to publish. Filter Superseded is almost always empty on this table: the row is already the newest sequence, so “superseded” is a status you read in the drawer history, not a second row here.

Read the page top to bottom, as the screen is laid out:

  1. Six tiles — census, who sent, who was carried, who is broken, how many versions, who is still missing. Explained tile by tile below.
  2. Filters — search, source, status, CSV, and Extend (only while the DAM gate is still open). They hide rows; they do not change the tiles.
  3. Main table — stored declarations. Empty sentence plus jump links when this date has none.
  4. Rejected / late attempts — the intake audit. A 409 is a row.
  5. Declaration drawer — one version, read-only.

The Extend the DAM gate form is not a card on this page. It opens from Extend on the filter row, and only while the DAM gate is still open.

The six tiles

Counts are units (or versions), not MW and not Rand. The six cards sit in one row (#dam-submissions-tiles). Daily’s Intake health repeats Expected, Received, and Rolled over and links here. The other three exist only on this tab.

Colours are the same traffic lights as Daily, plus indigo for versions. data-tone on each card is the authority: info sky, ok green, warn amber, incident red, accent indigo.

The tiles do not all add to Units expected. Received and Rolled over count only operative newest rows. An invalidated unit is covered (it has a stored body) so it is not silent — it sits in Invalidated awaiting resubmit. Before you Solve, the identity to hold in your head is:

expected ≈ received + rolled over + invalidated + silent

A leftover of one is worth a look (a newest row that is somehow superseded). A leftover of many means the census and the store have drifted.

Units expected

Tile #dam-submissions-expected. Always sky (info). How many registered Trading Units the market owes a declaration. This is the census, the same Units: {n} on Daily. It does not care whether they have sent yet.

If this is 0, the registry is empty for SAWEM — intake has nothing to count, and Solve has nothing to clear.

Received (participant)

Tile #dam-submissions-received. Unique units whose newest stored body is operative and Participant. They sent (or this platform sent on their behalf). Green when this equals expected; amber when some; red when none — same lights as Daily.

Replaces before the gate do not inflate this tile — five sequences for TU-COAL1 still count as one unit received. The extra sequences sit in Versions today.

Rolled over

Tile #dam-submissions-rolled. Unique units whose newest stored body is operative and Rolled over. Amber when this is greater than zero — carry-forward is a look, not an incident. Zero rolled is green: everyone who is covered sent.

A rolled row is still a real submission. Solve will use it. The BRP can still correct the day in the IDM. What you look for is staleness on the row, not the badge colour.

Invalidated awaiting resubmit

Tile #dam-submissions-invalidated. Red when the count is above zero, otherwise green. Unique units whose newest stored body was broken by a registry change after it was accepted. They thought they were done. There may be no replacement. Daily’s Notifications card repeats this as {n} unit(s) invalidated and awaiting resubmit when the count is above zero.

Invalidation is not supersession and not a 409. Filter Status → Invalidated and open the row: the Operative? cell carries the clause-7.1(5) sentence and the codes. The participant must be told before the next gate (§8.3).

Versions today

Tile #dam-submissions-versions. Always indigo (accent) — a count, not an alarm. How many submission records are stored for this Trading Date — every sequence, every unit. If Received is 40 and Versions is 40, nobody replaced. If Versions is 90, they iterated. That is ordinary before the gate. After the gate it is a look: who was still replacing, and did a late PUT bounce into the rejected table instead?

Silent at last snapshot

Tile #dam-submissions-silent. Amber when anyone is missing, otherwise green. Registered units with no stored submission at all for this date. The ribbon’s gate chip on a future day shows the same count as {n} silent.

Before 10:00 on D−1, silence is ordinary — they have not sent yet. After the gate, silence is the thing rollover is supposed to have filled. A number still above zero means either rollover has not run, or the unit had no previous valid body to roll (new registration, never submitted). Those units will not appear in the main table. They also will not appear in Rejected / late attempts unless they tried and failed. Filter will not find them. The tile is the list length; open Registry if you need the names.

What to look for

Walk the tiles first, then the rejected table, then the amber rows. Do not start in the drawer.

Look for Where When it matters What you do
Silent > 0 after the gate Silent tile; gate chip {n} silent Rollover should already have written Confirm Cadence ran the rollover step (§14). A unit that never had a previous body cannot be rolled — that is a participant problem, not a missing button on this desk.
Received + Rolled over = 0 Received and Rolled tiles Any time you are about to Solve Solve will miss. There is nothing to clear.
Invalidated > 0 Invalidated tile; Daily exceptions Before the next gate Filter Invalidated. Tell the BRP. A registry change broke a body they thought was in.
Rejected / late rows #submissions-rejected All day, especially around 10:00 They tried. Read Reason and Codes. A gate_closed 409 means the rollover (if any) is what will clear, not this PUT. A horizon fault means they sent 24 periods. A seq conflict means they reused a sequence with a different body.
Staleness missed {n} gates, especially n ≥ 4 Staleness column; drawer Rolled-over rows Four days is the escalation threshold: most of the horizon is now the original day 7 repeated. Each individual rollover was legal; the week no longer describes this week. Notify — §9.3(2) is not a courtesy.
Horizon {n} / fault Horizon column Any accepted row Stored bodies should be 168. A 24-period attempt never lands here; it lands in Rejected. A fault on a stored row is a store that does not match the Code — do not Solve past it as if it were a display quirk.
Amber Rolled over rows Source badge; whole row wash After the gate, every day Expected. Open Rollover chain if you need the dates. Do not treat amber as alarm-red.
Idle hours high on a thermal or demand unit Idle hours column After you have coverage Idle is legal (§5.2): a solar farm at night is 24 − daylight. Twenty-four idle hours on a coal set that should have offered is a declaration of absence, not a missing row.
Consent non-willing Consent column Before IDM Standing flag on the DAM envelope: the MO may not move them in the five patches unless the System Operator imposes a new constraint. Not an error.
Versions ≫ Received Versions vs Received tiles; Seq replaced {n} times Before the gate, curiosity; after, a look They iterated. Open Version history for a dispute about “what did we declare at 09:12?”.
Empty table #dam-submissions-empty Wrong date, or a date before anyone sent Sentence: No submissions were stored for {long date}. The table headers and CSV are hidden. Cards #dam-submissions-jump-{ISO} under #dam-submissions-intake are days that do have intake, grouped Monday–Sunday — use them; do not assume the ribbon date is empty because the market is empty.

What you can ignore. A Participant badge. Seq 1 with no replaced note. Staleness 0. Horizon 168. Energy limits n/a on a coal or solar unit that is not energy-constrained. willing consent. Those are the ordinary healthy row.

What this tab will not show you. Capped hours, the SMP, the three pots, or who set the price — that is Daily and Settlement. Who is suspended and may not bid — that is Registry; their PUT never becomes a row here (it becomes a rejected attempt).

Filters (#dam-submissions-filters):

Control Id Options
Search #dam-submissions-search Placeholder TUID, BRP, party
Source #dam-submissions-source All · Participant · Rolled over
Status #dam-submissions-status All · Operative · Superseded · Invalidated

Main table (#dam-submissions-table):

Column How to read it
TUID Link #dam-tuid-{tuid} → Registry card. The row id is dam-unit-{tuid}.
BRP Registration code, with the organisation name underneath
Class Coloured badge: generation (emerald) · demand (sky) · storage (violet) · mixed (fuchsia)
Source Badge Participant or Rolled over. A rolled row is washed amber — not alarm-red
Seq Newest version for this date; replaced {n} times if more than one sequence exists
Received at SAST stamp. That instant decides the gate, even if you later extend it
Consent willing / non-willing — on the envelope, not implied from the IDM tab
Staleness 0 (current) or missed {n} gates (how many times this profile has been rolled)
Operative? Green tick if the newest body is operative; red cross otherwise. Hover the cross for the supersession or clause-7.1(5) sentence
Horizon Sortable (#dam-sort-horizon). 168 or {n} / fault — a 24-period attempt is not stored here
Idle hours Sortable (#dam-sort-idle-hours). Hours on this Trading Day with zero DAC and zero DC. Night solar is expected; a full idle thermal day is a declaration of absence
Energy limits Week MWh, or n/a. dailies have slack means the seven daily caps sum to more than the week reservoir — allowed, and usual for hydro
Actions Indigo clipboard View declaration, sky clock Version history, amber path Rollover chain (rolled-over rows only). Icon buttons; tooltip opens to the left

Empty: No submissions were stored for {long date}. The table (and its column headers) and CSV are gone. When other dates have intake, #dam-submissions-intake lists them as cards grouped by weekday Monday–Sunday (#dam-submissions-intake-monday … -sunday). Each card #dam-submissions-jump-{ISO} reads {day} {Mon} '{yy} — 24 Aug ’26, not the ISO date.

CSV (#submissions-csv) sits on the right of the Search / Source / Status card, with Extend (#dam-submissions-extend) immediately after it while the ribbon date is today or the DAM gate is still open. CSV is hidden when this date has no stored submissions. CSV exports accepted and refused rows: /mo/bidding/submissions.csv?date=…. Columns: kind, tuid, brp, source, seq, status, received_at, reason, codes. Kind is submission or rejected. Use this when a BRP says they sent something you cannot see — the refused line is the receipt.

Extend is amber, same height as CSV. It is shown while the ribbon date is today (the chrome then reads the next IDM gate) or still in D−1 with the DAM gate open. Once the DAM gate chip reads closed, or the Trading Date has passed, the button is gone and there is no Extend the DAM gate card at the bottom of the page. Clicking Extend opens the modal (#gate-extension-form). Cancel, the X, the backdrop, or Escape close it.

Rejected / late attempts (#submissions-rejected): Time · TUID · Reason · Codes. These are not submissions. A 409 gate_closed is a row; so is a horizon fault and a sequence conflict. Empty: No rejected or late attempts for this Trading Date. This is the intake audit. Row ids are intake-audit-{id}. The TUID (when known) links to Registry.

Extend the DAM gate (§9.3(3)) lives in that modal, not as a card under Rejected / late. Reason, authoriser and published_at are required. An extension is judged at receipt — it cannot resurrect an earlier rejection.

Field Id Required
Extends to #gate-extends-to yes (datetime-local)
Reason #gate-reason yes
Authoriser #gate-authorised-by yes
Published at #gate-published-at yes

Submit: Extend gate. Success: Gate extended under clause 9.3(3). A save without published_at fails.

Declaration drawer (#submission-drawer). Open from a row or ?tuid=&seq=. Branded header (#submission-drawer-header) in Webill indigo with the amber clipboard mark, sticky — the panel is long and the header stays put while the body scrolls under it, so you never lose track of which declaration you are reading. Eyebrow Declaration, then {TUID} · seq {n}, then a sub-line reading {Participant | Rolled over} · Trading Date {weekday d Mon yyyy} · {received stamp} — the Trading Date is spelled out in full, e.g. Wednesday 19 Aug 2026, because the weekday is what tells you whether the day is a business day.

Section What you see
Envelope Source, Received, Consent (IDM willing / non-willing), Staleness, Strategy run, Bid, Market rules, Signature (verified / not present)
Horizon day Day 1–7 buttons; 24-block hour band (#submission-hour-band), each block numbered by its SAST start hour — 0 is 00:00, 23 is 23:00
Pinned hour DAC, DC, Flexible, Instantaneous / Regulating / Ten-minute reserve; production & consumption staircases. Every label carries its definition on hover; every coded letter is spelled out beside it
Energy limits Week MWh + basis, or n/a — this unit is not energy-constrained.
Validation Accepted against the registry at {stamp}.
Version history seq · source · operative · stamp
Rollover chain Dates, or This version was not rolled over from another day.

Footer: Registry Mingen {mwh} · MCR {mwh}. Increments are not editable on this desk. Empty curves: No production curve. / Must-serve only — no priced blocks.

Nothing on this drawer is left as an abbreviation. Three affordances, and you need only one of them:

  1. Hover a label. Every dt in Envelope and Pinned hour carries an information mark and a one-sentence definition — DAC gives you Declared Available Capacity — megawatts this unit says it can produce this hour.
  2. Read the value. A coded letter is never left bare: F is followed by Flexible, I by Inflexible, A by Available, U by Unavailable, each in a badge tinted by what it means (I amber, A green, U grey). Staleness reads 0 — current or 3 gates missed rather than a naked integer.
  3. Open the legend. What these labels and letters mean (#submission-drawer-legend) sits under the pinned hour, collapsed. It spells out DAC, DC, F, I, A, U, the three reserve categories, Consent, Staleness, and Mingen / MCR in full — including that I is a commitment and not a ceiling, and that an A against a category the System Operator certified at 0 MW is refused at intake. Use this one on a touch screen, where hovering is not available.

The F / I sentences are the same text the BRP’s own submission desk shows, so a dispute about what was declared cannot turn on the two seats having been told different things.

Hour-band colours. A block is one Trading Period, addressable as #submission-hour-{h} where h is the SAST start hour. Declared hours are split by the sun: amber for daylight (06:00–18:00) and indigo for night. State outranks the clock — an inflexible :I hour stays dark grey and an idle hour stays light grey whatever the time, so a solar unit reads as grey night shoulders around an amber day. The pinned hour carries an indigo ring. The legend under the band names all four. Hovering gives {HH:MM} · {day | night | idle | inflexible}.

Follow along. Seat: mo@webill.net / supersecret. Path: Market Operator → Bidding → Submissions ?date=2026-07-15. Read the six tiles, then find TU-PV1. Horizon 168, Source Participant, no increment form. Open View declaration. You should see seven horizon-day buttons and a 24-block hour band. Golden units: TU-COAL1, TU-PV1, TU-OCGT1, TU-DIST1, TU-IND1. Then open Rejected / late attempts — on a clean teaching day it is empty; that emptiness is the receipt that nobody bounced.

Submissions /mo/bidding/submissions

Tiles 1 TUID 2 Source 3 Rejected 4
expected · received · silent TU-PV1 Participant audit, not a bid
  1. 1Tiles are the census. Silent after the gate is the first look; Received + Rolled over = 0 means Solve will miss.
  2. 2TUID opens a read-only drawer — no increment form.
  3. 3Source badges rollover in amber; it is not alarm-red. Staleness on that row is the look.
  4. 4Rejected / late is the intake audit. A 409 is a row. It is not stored as a submission.

13.9 IDM — five patches, no names

Path: /mo/bidding/idm. Optional ?iteration=4. Optional &period=18:00 opens the auction drawer.

The DAM has locked tomorrow’s (or today’s) schedule. Weather and load still move. The Intra-Day Market is five short auctions that patch the remaining hours — they do not tear up yesterday’s ticket. You do not type a price here. You do not lodge a re-declaration. You watch whether the five bells rang, who asked to move, what the market actually moved, and whether the Market Balancing Account paid out or took in.

That is a different job from Daily. Daily’s Solve / Publish are the day-ahead pair. This tab has neither. The five auctions fire from the clock. Your chair is to see them, explain them, and chase a miss.

Where this is taught. What a BRP sends, why re-declaring your own capacity costs money, the ±5 % collar, and carry-versus-re-declare: V9 §5. What the IDM is allowed to move, consent, on- versus against-instruction, and why EPM and SMP do not change: §9. Daily’s pulse card is §13.7 Intraday now. This section is the screen you press, what the clock already did, and what — if anything — you still have to do by hand.

What the IDM is

The IDM is not a second day-ahead market. It is not a rolling “one hour before delivery” window. It is five fixed auctions on the Trading Day (the first of them the evening before), each of which may still move only the hours whose delivery has not started.

Iteration Gate (SAST) Hours it may still move
1 18:00 D−1 The whole of D
2 00:00 D 01:00–23:00
3 06:00 D 07:00–23:00
4 12:00 D 13:00–23:00
5 18:00 D 19:00–23:00
The five IDM bells the Market Operator’s clock rings — not a T−60 window
1 · 18:00 D−1
→all of D
2 · 00:00
→01:00+
3 · 06:00
→07:00+
4 · 12:00
→13:00+
5 · 18:00

Iteration 4 is the golden-hour gate: 18:00 can still move; after 18:00 it cannot. The 18:00 SAST bell is both iteration 5 for today and iteration 1 for tomorrow.

A re-declaration for an hour whose delivery has started is refused. It is not a late DAM submission; it is a re-declaration of the past.

What a participant sends is a patch, never a new staircase. The DAM price curve stands. They change Declared Available Capacity and/or Declared Consumption for remaining hours, optionally the day’s rescheduling-consent flag, and a reason. You cannot re-price mid-day. If you could, you could watch the stack form and then move the price you are about to be paid at.

The IDM re-clears the remaining hours from the last standing schedule (the DAM constrained schedule, or the previous iteration), with updated availability and any new System Operator constraints. Instantaneous Reserve scheduled day-ahead is not re-optimised except to replace what a unit has actually lost; replacements keep the day-ahead category price.

What the IDM does not change. The DAM bid. The DAM price curve. The SMP. The energy-account pot (EPM). New money is new lines on the Market Balancing Account. A unit walked all the way back to its DAM constrained schedule has a net IDM position of R 0.00.

What this tab is not. It is not the BRP Bid Desk. It is not Daily’s Price board. It is not Settlement’s chalkboard. It is not a place to Solve or Publish the day-ahead run. Filter All vs Iteration n hides rows and stacks; it does not re-run an auction.

How it is managed

The IDM is a clocked market, not a button on this tab. Compare that with the DAM, where you (or Cadence Run the day) must Solve and then Publish. For the IDM, the five gates fire whether you are looking or not. Your job is to confirm they did, and to read the result.

What the clock already does

These run in the background. You do not press them on /mo/bidding/idm.

What When (SAST) What it does Where you prove it
Clear each IDM auction (:clear_idm) 18:00 D−1, then 00:00 / 06:00 / 12:00 / 18:00 D Screens lodgements for that iteration, re-clears remaining hours, collars the Intra-Day Price at SMP ± 5 %, writes MBA lines, records the iteration Cadence ledger, callable :clear_idm with /iteration. A miss is a rose row, not a missing stack
Screen late / past-hour patches Inside that clear A lodgement for a closed hour is rejected (or belongs to the next gate). The clear does not lodge Cadence outcome carries accepted / rejected counts
This platform’s BRP patches The same five bells The BRP worker lodges a re-declaration when the Bid Desk’s carry / re-declare decision says so. It writes a TUID patch, not a book-level bid Lodgements on this tab
External BRP patches Any time before the iteration’s gate PUT through the same door the Bid Desk uses Same lodgements table. A 409 is not a lodgement
Standing DAM body Always, until patched Price curves, technical parameters, availability carry into every iteration automatically You will not see a “copy bid” control. There isn’t one
Consent hold At re-clear A non-willing unit is not moved in an ordinary IDM re-clear Consent table. The volumes look the same either way; the reason must travel
SO security override When the System Operator imposes an additional network constraint A non-willing unit moves anyway. A participant cannot hold a corridor hostage Consent column SO override reads overridden
Collar At price formation Indicative IDP (on-instruction average) is clamped to [0.95 × SMP, 1.05 × SMP]. Against-instruction volume does not enter the stack Period line: indicative → applied, collared badge when they differ
Reversals Later iteration undoes an earlier movement Earlier IDM charge is credited for the part that was undone (§10(15)) Per-iteration {n} reversal(s); kinds table IDM_REVERSAL
Quiet iteration Gate fires, nothing on-instruction moved (or signed on-instruction volumes cancel) The Intra-Day Price is the SMP. The DAM constrained schedule still stands Board populated, stack empty or net zero, Daily card may still read DAM constrained still standing if no iteration has been stored

Prerequisite the clock cannot invent. :clear_idm needs a published day-ahead run. If you have not Published the DAM, the auction is a recorded miss (dam_not_published, clause 10(1)) — not a skipped healthy day, and not an empty sentence pretending the gate never came. Iteration 1 at 18:00 D−1 is the first that can bite: Publish is due 14:00 D−1. Four hours is plenty; it is also enough to miss if Solve never ran.

Run the day does not run the IDM. Cadence Run the day walks gate → rollover → unconstrained → constrained → prices → publish. It stops there. The five :clear_idm rows are a different timetable. Do not read a green Run the day as “the patches ran”.

18:00 SAST is two auctions. The same clock fires iteration 5 for today (hours 19:00–23:00) and iteration 1 for tomorrow (the whole of D+1). Cadence on today’s date shows iteration 5; Cadence on tomorrow’s date shows iteration 1. They are not the same row.

What you still do by hand

There is no Clear IDM and no Publish IDM on this tab. The operator actions that remain are these.

You do this Where When What it is not
Publish the DAM Daily (or Cadence Run the day) By 14:00 D−1, before 18:00 iteration 1 Not an IDM button. Without it every later :clear_idm misses
Watch the five rows Cadence After each gate, and if Daily’s IDM card stays amber into the afternoon Not “open IDM and press play”. :clear_idm ran / missed is the proof
Read this tab /mo/bidding/idm After an iteration has been published for the ribbon date Not a control. Filter, open a stack, read lodgements
Explain a movement to a BRP Lodgements + Consent + Cadence; not the stack When they ask “why was I moved?” The stack has no TUID. Naming a rung would publish their offer
Chase dam_not_published Daily → Publish, then wait for the next gate (or internal POST /api/v1/internal/cycles/clear_idm) Cadence :clear_idm is missed with that reason Re-Publishing the DAM does not resurrect a missed iteration by itself
Retry a failed idm.cleared delivery Cadence Event-delivery incidents A participant’s event stream dropped the publication Retry is not a re-clear
Take a new SO constraint The System Operator’s feed, then the next IDM gate A corridor appears after 14:00 You do not type the constraint on this tab. The next re-clear consumes it; non-willing units may show overridden

What you must not do from this chair

Publish within the hour (clause 10(5)). The Code obliges the revised schedule and the Intra-Day Price to be published within one hour of clearing. Clearing records the iteration; the board you are reading is the published day. There is no Publish IDM control on this screen — unlike Daily, where Solve and Publish are two buttons on purpose. If Cadence shows :clear_idm ran and this board still says No intraday iteration has cleared for this Trading Day, the run is recorded and not yet on the published board. That is a Cadence / Runs finding. It is not a missing play button here. Internal automation may POST :clear_idm at /api/v1/internal/cycles/clear_idm (operator / internal party header; a participant token is 404 — V13).

How you work a day — five pictures

These are the days you will actually have. Each one says what the clock already did and what you do.

1. Ordinary morning — nobody has patched yet

Ribbon date is today. Iteration 1 rang last night; maybe it moved nothing. Daily’s IDM card is amber: DAM constrained still standing. This tab: #idm-board-empty — No intraday iteration has cleared for this Trading Day. Lodgements empty. Consent empty.

Clock. Iteration 1 cleared (or missed). If it cleared with zero on-instruction movement and was not published, you still see the empty sentence. Participants are on the DAM constrained schedule. That is the ordinary morning. It is also a quiet afternoon if nobody moved. It is not an error.

You. Confirm Cadence :clear_idm /1 ran (or is still pending if you opened the page at 17:00 D−1). Do not invent a clearing from the empty sentence. Click Daily’s IDM card only when you want this tab — there is no Open IDM control.

2. Cloud at 11:30 — iteration 4, the teaching hour

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00. Seat: mo@webill.net / supersecret.

Heavy cloud. The solar farm re-declares from 60 MW to 20 MW before the 12:00 gate (iteration 4 can still move 13:00–23:00, including 18:00).

Clock. The BRP worker (or their PUT) lodged the patch. At 12:00 :clear_idm /4 screened it, re-cleared remaining hours, built an on-instruction stack from the units the market moved, averaged those offers to an indicative IDP, and collared it at SMP + 5 %.

You. Open /mo/bidding/idm?date=2026-07-15&iteration=4.

What you should see Why
Applied IDP R 945, badge collared Indicative wanted R 1,412.50; SMP is R 900; ±5 % pulls it to R 945
Stack of increment prices and ΔV, no TU- An increment price is the unit’s offer. Naming the rung would publish every cost curve to whoever can read /mo
MBA net not the energy pot The farm’s IDM charge is −R 37,800 (40 MWh × R 945). EPM on Settlement is still 75 × R 900 = R 67,500
Lodgement for TU-PV1, new DAC 20, reason (cloud) The named fact lives here, not on the stack
Estimated / Cleared columns filled Classification: purchase against instruction (they changed their own declaration)

Σ check: 67,500 − 0 − 37,800 = 29,700 — the farm keeps R 29,700 for the 20 MWh it actually generates. Constrained-off at a zero offer was free; this re-declaration was not. That arithmetic is §9.4 and V9 §5.2. You are here to see that it happened, not to key the 20 MW.

Follow along. Path: Market Operator → Bidding → IDM ?date=2026-07-15&iteration=4. You should see collared, R 945, a stack with prices and volumes and no TU-PV1. Then open Lodgements and find the named patch.

3. Publish never ran — iteration 1 is a miss

It is 18:05 D−1. Daily still says This day has not been solved (or Solved, not published). Cadence :clear_idm /1 is missed, reason dam_not_published.

Clock. The worker fired on time. It refused to invent a day-ahead schedule. That refusal is the row.

You. Publish the DAM (Daily Publish…, after Solve). The missed iteration does not auto-replay. Internal automation can POST :clear_idm for that iteration once the DAM is published; this tab still has no button. Until a later iteration (or a manual callable) succeeds, participants stay on whatever DAM schedule you eventually publish — which at 18:05 D−1 you have not.

This is the one miss you can cause from the DAM chair. Four hours after 14:00 is not “the IDM is broken”; it is “you never pinned the noticeboard”.

4. Non-willing, then the System Operator moves them anyway

A thermal unit set idm_rescheduling_consent to non-willing on the DAM envelope (or updated it for the day). Iteration 3 re-clears. The ordinary IDM must hold their DAM constrained schedule. The Consent table shows the flag and a reason. SO override is blank.

Later the System Operator imposes an additional network constraint. Iteration 4 re-clears with that constraint. The same unit moves. Consent SO override reads overridden.

Clock. Consent hold and SO override are both automatic. You did not tick a box.

You. When the BRP phones: the volumes look the same either way. The sentence that must travel is “not moved because you asked” versus “moved anyway because the SO imposed a constraint”. Read #idm-consents-table, not the anonymised stack. The stack will not name them.

5. Lodged, screened, not cleared

A BRP sends a patch for 18:00 at 18:01. Iteration 5’s gate has shut; 18:00 is an hour whose delivery is beginning. The lodgement is rejected as a re-declaration of the past. It may appear as a refused attempt in their API. It is not a stored DAM submission, and it is not a row this auction will move.

Clock. Screening is inside :clear_idm. You do not moderate a queue.

You. If they say “we sent it”, check the timestamp against the gate, then Cadence rejected counts. Do not “accept it from the console”. There is no such control.

The screen, top to bottom

Read it in this order. The ribbon date is the Trading Day you are inspecting. Daily’s IDM card is the one-line pulse; this tab is the ledger behind it.

  1. Iteration filter — which of the five bells, or all of them.
  2. Cleared board — MBA net, per-iteration movement, per-hour IDP and stack, kinds table. Empty sentence when nothing is published.
  3. Lodgements — named patches. Can have rows while the board is still empty (they lodged; the auction has not published).
  4. Consent — standing flags and SO override.
  5. Auction drawer — one iteration × one hour, still anonymised.
Iteration filter

#idm-iteration-tabs. All, then Iteration 1 … Iteration 5 (#idm-iteration-all, #idm-iteration-1 … #idm-iteration-5). The active chip is indigo. This is a filter, not a run control. It patches ?iteration=n (or drops the param for All). Lodgements follow the filter; Consent is the day’s standing flags (not per iteration).

Cleared board

Empty (#idm-board-empty): No intraday iteration has cleared for this Trading Day. Honest. A zero table would look like “the market moved nothing and netted R 0.00”, which is a different fact — and that fact only exists once an iteration is on the published board.

When populated (#idm-board):

Piece Id / where How to read it
Market Balancing Account #idm-account-net The account’s own IDM position for the day. Negative means the account paid participants out. Recovered by the System Operator as an ancillary service (clause 10(17)). Not the energy pot. Golden teaching net −R 19,375.00 on Daily’s card; this board shows the same account
Per iteration heading Iteration {n} {moved} unit-periods moved · {lines} lines · {reversals} reversal(s) plus that iteration’s MBA net
Per period {HH:MM} line indicative {R} → applied {R} · SMP {R}. collared when applied ≠ indicative. Hours with basis NO_CHANGE are omitted — the board is the hours that moved
Stack #idm-stack-{iter}-{HH:MM} Increment price · ΔV (MWh). On-instruction increments only (clause 10(10)) — anonymised, because an increment price is the unit’s own offer. Sorted cheap to dear
Kinds table #idm-board-kinds Line kind · Clause · Lines · Total. These are MBA kinds (IDPM_ON, IDC_ON, IDPM_AGAINST, IDC_AGAINST, IDM_REVERSAL, …), not EPM/CSC

The stack never shows a TUID. That is the point. If you need the name, it is in Lodgements.

Lodgements

#idm-lodgements-table (inside #idm-lodgements-scroll). One row per stored re-declaration for the filter. The header and TUID / BRP column stay put while you scroll. Rows highlight on hover (pointer cursor). Empty: No re-declarations were lodged for this filter.

Column How to read it
Iteration Which gate they aimed at
TUID / BRP Sticky left. TUID, then BRP code, then the organisation name under the cell (#idm-lodge-org-{id}). This is the column the stack refuses to have
Period Sortable (#idm-sort-period). SAST clock of the hour patched. Default ascending
New DAC / DC The patch — available capacity / declared consumption. Amounts are bold (#idm-dac-{id})
Reason Code; the sentence is on title
Estimated #idm-estimated-{id} — classification headline before the auction (what they asked). The MWh amount is bold
Cleared #idm-cleared-{id} — what the auction did with it. The MWh amount is bold
Consent Willing / non-willing on that lodgement

Lodgements without a published board are still lodgements. Do not tell a BRP “we have nothing” because #idm-board-empty is showing; look here first.

#idm-consents-table. Heading Consent. Empty: No standing consent changes for this day. (The DAM envelope’s flag can still be non-willing with no row here — a same-day change is what this table lists.)

Column How to read it
TUID Named
Consent WILLING / NON_WILLING
Reason Why they changed the flag
SO override #idm-override-{id}. overridden when a non-willing unit still moved. Blank is blank — not an em-dash pretending at a value
Auction drawer

#idm-auction-drawer when the URL has both iteration and period (e.g. ?date=2026-07-15&iteration=4&period=18:00). Click a period on the board. Close returns to the IDM tab without the period param.

Field What it is
Title Iteration {n} · {HH:MM}
Indicative IDP Un-collared on-instruction average
Applied IDP What they are charged at, with collared when the cap bound
SMP That hour’s day-ahead System Marginal Price — the collar’s centre
Basis Why this hour has a price at all
On-instruction stack (#idm-auction-stack) Same anonymised rungs. Subtitle: Price and volume only — a rung is an offer.

There is no TUID in the drawer either.

IDM /mo/bidding/idm

Iteration 1 IDP 2 Stack 3 Net 4
4 · clocked R 945 collared prices · MW · no TUID MBA, not EPM
  1. 1Iteration is one of the five gates. The clock clears it. There is no Solve on this tab.
  2. 2IDP shows indicative and applied when collared.
  3. 3Stack has no TUID. Named patches live in Lodgements.
  4. 4Net is the IDM account, not the energy pot. Publish the DAM by 14:00 or iteration 1 misses.

13.10 Settlement — the chalkboard

Path: /mo/bidding/settlement. Date on the ribbon is the Trading Day whose money you are reading. Optional ?period=18:00 opens that hour’s lines in the drawer.

Daily’s Energy account pot is the one-number pulse. This tab is the chalkboard behind it: every hour’s price, who set it, the energy lines that must sum to R 0.00, the constrained-schedule charge when the wires cut a unit, and the party totals that will ride the month. You do not type a price here. You do not send a bid. You Solve (the same auction as Daily), then you read.

Where this is taught. The three pots, EPM = SG × SMP, constrained adjustment, why energy must print R 0.00, and why that is not the invoice: §7. Daily’s pulse card: §13.7 Energy account. Solve’s three jobs (unconstrained, constrained, prices): §13.7 Solve and Publish. This section is the screen you press, how to read it, and when Solve is allowed — including after the DAM gate has closed.

What Settlement is

Settlement, on this tab, is the commercial settlement of the hour — volumes × prices, signed, tagged with an account. It is computed with the clear. It becomes the official chalkboard when you Publish (by 14:00 SAST on D−1). It is not the month’s invoice. The till is Month and §8.

Think of it as the school chalkboard after the auction, before anyone goes to the bank:

What this tab is not. It is not Submissions (who sent a body). It is not Daily’s Price board (the ink step line). It is not the IDM stack (patches do not rewrite EPM). It is not Accounts, Metering, or Dispute. A Settlement Query about a line does not live here.

The only action you press to fill a draft is Solve (#dam-solve) — emerald, play icon, on the top row beside the status sentence (#dam-settlement-actions). It is the same WB.Sawem.Cycles run as Daily. After a successful Solve, Publish… appears next to it when there is a solved run to pin; it is not a second auction. Until you Publish, participants still settle against the last published run — or against nothing. There is no Solve card at the bottom of the page.

What it displays

Top to bottom, in reading order.

Status sentence (#dam-settlement-status) sits on the top row, with Solve (and Publish… when a run is solved) on the right. There is no second copy of the sentence on a footer card.

Sentence Meaning
This day has not been solved. No run. Tiles are empty. Hours table is empty.
Solved, not published. You have a draft chalkboard. The public energy pot is still —.
Published at HH:MM. (SAST) This run is official. The energy pot is allowed to show R 0.00.
Published. Official, without a stamp on the latest row.

Summary tiles (#dam-settlement-tiles): one coloured row of five (grid-cols-5). White cards with a left-edge accent (emerald / sky / indigo / emerald / amber). Tones still follow Daily’s traffic lights (data-tone).

Id Label What it is showing Empty
#dam-settlement-energy-net Energy Account Net Signed sum of energy lines for the published day. Badge Balanced at R 0.00. Details (#dam-settlement-clause-981) opens the §9.8.1 note. — until Publish. Solve alone does not write this tile.
#dam-settlement-mba-net Market Balancing The MBA position for the published day — constrained adjustments, reserve capacity, later IDM money. Not the energy pot. — / R 0.00 from the published board
#dam-settlement-mo-charge MO Charge (Day) The Market Operator fee pot. Hint: Usually empty until month-end. R 0.00
#dam-settlement-hours Hours Published Count with a / 24 hrs suffix and a completion bar. Counts published hours, not draft hours on a solved-but-unpublished run. 0 / 24
#dam-settlement-smp SMP Price Range min – max of hourly SMPs. Badge Peak Spike when max is above R 1 000. — when there are no hour rows

Day-ahead Settlement Clearing (#settlement-board) is the published confirmation board. Empty (#settlement-board-empty): Nothing has been published and settled for this Trading Day. When published, Energy Account Residual, §16(2)(g) Rounding Residual, and the kinds table (#settlement-board-lines) sit on one row. Market Balancing is the tile above, not a fourth residual.

24-hour Market Price Curve (#dam-settlement-curve, chart #dam-settlement-smp-chart): SMP as an amber line against Σ|SG| as sky bars. Hidden until there are hour rows. The plot reuses the Strategy Chart day/night wash: amber daylight 07:00–17:00 SAST, slate night. The sun/moon key (#dam-settlement-smp-day-night-legend) sits just above the canvas. The SMP / Σ|SG| series legend is centred on the plot, a little below the top. The peak markPoint on the SMP curve uses white label text so it stays readable on the brown pin.

Hours table (#dam-settlement-hours-table inside #dam-settlement-hours-scroll). Sticky column headers (thead.sticky). Search (#dam-settlement-hour-search) and a Peak / Binding filter (#dam-settlement-hour-filter). Export CSV (#dam-settlement-export-csv) downloads the visible rows. Each header has an info icon (#dam-hours-hint-{period,smp,marginal,sg,epm,csc,binding}); hover opens the tip to the right. One row per Trading Period (#dam-hour-{HH:MM}). Peak hours (SMP > R 1 000) highlight amber. Click a period to open the drawer (?period=).

Column How to read it
Period SAST clock label (18:00)
SMP That hour’s one system price. Badge capped (red) if the cap bound; all-inflexible (grey) if every unit was inflexible and SMP printed R 0.00
Marginal unit Official name of the unit that set the price, with the organisation under it, or —. Amber [D-08] {counterfactual R} when a Demand Side Unit would have set the SMP and the default switch forbids it
Σ |SG| Gross unconstrained scheduled MWh that hour (absolute). Header and values are centred
EPM Energy-payment total for the hour. Header and values are centred
CSC Constrained-schedule charge total for the hour. Header and values are centred
Binding Constraint ids that bound the constrained run; empty if none. Each id is a coloured badge (data-constraint): declared_capacity sky, declared_consumption amber, security ids (zonal_export_limit:… and other kind:id atoms) indigo, other known grounds (ramp, mingen, inflexible, …) each their own chip, unknown ids slate and still readable

Charges that will ride the month and Notifications (#dam-settlement-notifications) sit on one row (#dam-settlement-lower). Charges empty: No party totals until the day is solved. Columns: Party · EPM · Constrained (CPP minus CSC) · Reserve · IDM. These are named parties. They are not the anonymised IDM stack. IDM money here is MBA kinds, not a rewrite of EPM. Notifications empty: No notices have been recorded for this day. Columns: Time · Event · Audience · Delivery.

Hour lines drawer (#hour-lines-drawer, table #dam-hour-lines): branded header (#hour-lines-drawer-header). Every settlement line for that hour. Kind (label + clause) · TUID (unit official name, with the organisation under it) · Qty (two decimal places) · Price · Amount. Column headers stay sticky in #hour-lines-scroll. Rows highlight on hover. A CSC of R 0.00 is not a blank — it carries a sentence: own offer was zero, no day-ahead price submitted, or constrained-schedule charge is R0.00.

How to read it
  1. Status sentence first. Unsolved means there is no chalkboard yet — do not treat — as R 0.00.
  2. Energy account net. After Publish it must be R 0.00. After Solve only, this tile stays —; look at the Hours table for the draft instead.
  3. Hours published. 24 / 24 is a published day. 0 / 24 with a full Hours table is a draft you have not pinned.
  4. SMP range against Daily’s Price board. They are the same hours. Capped and all-inflexible badges live here, not on Daily’s chart.
  5. Click 18:00 (or the hour you care about). Read Kind / TUID / Qty / Price / Amount. Check that EPM uses unconstrained MWh × SMP, and that a wire cut shows as CSC, not a quieter SMP.
  6. Party rollup for “who will see this on the month”.
  7. Notifications last — who was told, not what the money is.
Look for Where When it matters What you do
Energy tile — after you thought you were done #dam-settlement-energy-net After Solve, before Publish You have a draft. Publish… is beside the status sentence.
Energy R 0.00 Same tile; #energy-residual After Publish The loop closed. This is data, not “nothing happened.”
Energy R{n.nn} (not zero) Same After Publish Incident. Do not treat the day as done.
Hours 0 / 24 with a filled table #dam-settlement-hours vs the table Solved, not published Draft. Pin it if this is the plan.
capped on an hour Hours · SMP Scarcity / cap bound Expected as a flag; also on Notices as a price-cap event when you broadcast.
all-inflexible Hours · SMP Every unit inflexible SMP is R 0.00 that hour. Not a missing price.
[D-08] amber Marginal unit Demand-side would have set SMP Counterfactual is shown; the published SMP followed the switch.
CSC R 0.00 with a sentence Drawer Zero-priced offer or deemed no price Read the sentence. Do not “fix” a blank.
Party totals empty No party totals until the day is solved. Unsolved Solve first.
MBA net mixed into Energy Two different tiles Any time They are different pots (§7.1).

What you can ignore. MO Charge at R 0.00 on a Trading Day. A rounding residual of a few cents next to an energy residual of R 0.00. An empty notifications list on a quiet morning.

Solve

Solve (#dam-solve) is the only control that runs the auction from this tab. It sits beside the status sentence (#dam-settlement-actions). There is no “gate still open” grey-out.

It does the same three jobs as Daily, in order, for the ribbon date:

  1. Unconstrained clear — who would run if the wires could take everything. This sets the SMP.
  2. Constrained clear — what the wires may actually carry. This sets who injects. It does not rewrite the SMP.
  3. Calculate prices — write the hourly SMP and the money lines onto a solved run.

Success flash: Both schedules solved and settled. Nothing is published yet. The Hours table and party rollup fill from that draft. The public energy tile stays — until Publish.

A miss does not write an empty run:

Miss flash Typical cause
Solve recorded a miss — there are no accepted submissions for this Trading Day. Nobody stored a 168-period body (and rollover has not written).
Solve recorded a miss — this Trading Day has no hourly periods to clear. The date has no Trading Periods.
Solve recorded a miss — a prior step is un-run or an SO input is absent. Cadence order or a System Operator parcel the run still needs.

You cannot edit a curve from this seat. If an hour looks wrong, the BRP fixes the declaration or the registry and you Solve again. A second Solve redraws the draft. Until you Publish, the last published chalkboard (or nothing) remains official.

When you may Solve

The DAM gate closing is not a lock on Solve. The gate is when intake stops (§13.8). The auction is meant to run after that bell.

Clock May you press Solve? What you are looking at
Before 10:00 D−1 — DAM gate still open The button works. This is a rehearsal. The stack is still moving. A later PUT is not in this run until you Solve again. Rollover has not yet written silent units. Do not Publish this as the day’s plan.
After 10:00 D−1 — DAM gate closed Yes. This is the intended window. Intake is frozen (unless you extended the gate). Rollover should have written. Demand and reserves were due at 10:00. You Solve, read this chalkboard, and Publish by 14:00.
After 14:00 D−1, or on the Trading Date itself Still allowed. It does not reopen the DAM gate. A new solved run. Participants still settle on the last published run until you Publish again. IDM patches do not require you to re-Solve the DAM.
A past Trading Date The button is still there. Re-solving yesterday does not, by itself, unwind published money. Publish of a new run would supersede. That is a deliberate act, not a refresh.

You can Solve after the DAM gate is closed. You are supposed to. Closing the gate is what makes the stack the stack. Solving while the gate is still open is allowed by the button and refused by good operations.

Solve does not wait for interconnect (due 13:30). If that parcel is late, Cadence records it; you still Solve when the energy stack and the 10:00 SO facts are in. Solve does not wait for IDM iteration 1 (18:00 D−1) — that auction patches a published DAM.

Settlement /mo/bidding/settlement

Energy 1 CSC 2 Solve 3 Ledger 4
R 0.00 after Publish zero-priced curve after the DAM gate honest empty
  1. 1Energy nets to R 0.00 across the market once published. Solve alone leaves the tile —.
  2. 2CSC is a sentence when the amount is zero.
  3. 3Solve runs the auction; it does not publish. The gate closing does not disable it — that is when you use it.
  4. 4Ledger uses a sentence when the event store is empty.

13.11 Month — the Billing Period

Path: /mo/bidding/month. This is the month’s books, not a day’s chalkboard. Settlement answers “did this Trading Day clear?” Month answers “did this Billing Period add up, and has anyone been paid?”

The picker on the ribbon is a month (#bidding-month), not a day. Default: the previous calendar month — the period you are most likely still closing. Query: ?month=2026-07.

The billing board on this tab is the same board as Accounts §18.4. It is a real Mo.Settlement.Month after Run the month, not an empty shell.

What this tab is for

A Trading Day is 24 hours. A Billing Period is a calendar month of those days. Invoices, self-billing invoices, credit cover, and “who still owes whom” are monthly artefacts. You cannot see that from one hour’s SMP.

Come here to:

  1. Confirm the energy pot still nets to R 0.00 across every published day in the month (the same closed loop as Settlement, added up).
  2. See who the month touched — named parties, and whether the document they were sent is an invoice (they pay) or a self-billing invoice (they are paid).
  3. Read the settlement calendar clocks, the statement / invoice runs, any bad-debt cascade, credit cover, and the query inbox.
  4. Declare Administered Settlement only when the ordinary pipeline cannot be used — and only with the Market Governance Committee’s prior written approval.

Run the month is not on this tab. It lives on Cadence (#mo-run-the-month). This page shows the result; Cadence walks statements → verification → initial → invoices. If the billing board says No Billing Period has been settled, go to Cadence first.

What it displays

Three bands, top to bottom, matching the screen.

  1. Calendar and status — full width.
  2. #dam-month-stats — four of twelve columns: Energy market stacked above Curtailment windfall. Eight of twelve: SMP duration.
  3. #dam-month-lower — six of twelve: Billing Period settlement (first, left). Six of twelve: Parties (right, no taller than the billing card).

Calendar and status (#dam-month-calendar). Brand mark, title, and the gate-miss pill (#gate-miss-rate) on one line; the Billing Period sentence underneath. Billing Period {Month YYYY} · {start} – {end}. {n} published Trading Day(s). That count is published days only — a solved-but-unpublished day does not join the month’s energy pot. The month picker stays on the Bidding chrome (#bidding-month); it is not duplicated on this card. Admin (#dam-month-admin) is the SAWEM navy/gold control on the right of this header. It opens the Administered Settlement modal (clause 15.11) — not a clause-15.3.3 info dialog, and not an Export.

Gate-miss rate (#gate-miss-rate): Gate-miss rate {n.n}% from the cadence ledger. Emerald when the rate is 0.0%; amber otherwise. How often a §1.2 callable for this period was a miss rather than a run. It is a health number, not a Rand amount.

Energy market (EPM Exact Net) (#dam-month-epm-net) is the upper card in the left column of #dam-month-stats. The signed sum of every EPM line on every published day in the month. Headline is the same money string as Settlement’s energy tile. Under it:

Row Id How to read it
Target basis #dam-month-epm-target Always R0.00 — the exact-basis closed loop
Variance #dam-month-epm-variance The same signed headline. Zero is success; anything else is the open loop

Hint: Must be R0.00 on the exact basis. Not added to the other pots. Emerald when the headline is R 0.00; rose if the loop is open. Do not add this number to constrained, IDM, or MO Charge; those are other pots.

Curtailment windfall (#dam-month-windfall) sits below Energy market in that same left column — not beside it. Constrained-off MWh that carried a R 0.00 CSC (the classic case: a zero-priced offer that was cut by the wires). The headline is the MWh. Under it: Estimated value (the Rand those MWh would have been worth at the hour’s SMP) and SMP reference: Hourly rate. The footer repeats Would have been worth {R} at the hour’s SMP. That Rand is what the energy would have been worth, counted so NERSA and the operator can see it. It is not added into the energy pot. Golden teaching: 15.000 MWh that would have been worth R 13,500.00.

SMP duration is the right-hand card of #dam-month-stats. Title and the daylight sentence (Mean system price by hour of day (SAST) across published days. Daylight 07:00–17:00.) sit with the legend (#dam-month-smp-day-night-legend) in the card header. The chart (#dam-month-smp-duration) is an ECharts step line: Hour (SAST) on X, R/MWh on Y. Each point is the mean SMP for that clock hour across published days. Hover Mean SMP to two decimal places. Amber wash is daylight 07:00–17:00; slate is night. The footer (#dam-month-smp-metrics) is four figures from those same hourly means:

Figure Id
Peak SMP #dam-month-smp-peak
Min SMP #dam-month-smp-min
Daylight avg (07:00–17:00) #dam-month-smp-day-avg
Night avg #dam-month-smp-night-avg

Empty chart: No published hours in this period.

Billing Period settlement (#billing-board) is first on #dam-month-lower (left). Empty (#billing-board-empty): No Billing Period has been settled. After Cadence has run the month, the card is a calendar panel beside four coloured run pots, then cascade / cover / inbox when they have rows. The administered switch is not on this board on Month — it lives in the Admin modal. On Accounts the same board hides the calendar, cascade, and administered cards; NERSA Publish and Administered Settlement open the calendar and administered as modals. The debit-note cascade, credit-cover operations, and replenishment window live on Accounts → Credit/Debit.

Panel Id How to read it
Settlement calendar #board-calendar Clause 15.3.3 clocks (initial-statement, invoice-due, self-billing-due, timetabled-rerun) in SAST
Runs #board-runs Four pots: #run-statements (sky, {n} issued), #run-invoices (indigo, due 12:00 +3BD), #run-self-billing (emerald, paid 17:00 +4BD), #run-shortfalls (amber; rose if > 0, {n} credit call(s)). Invoice and self-billing counters open /mo/billing Invoices and Remittances (SB) for that month — the tax documents, not an empty count
Cascade #board-cascade Debit notes when someone did not pay. #cascade-none = No Unsecured Bad Debt this Billing Period.
Excess Participants #cascade-excess {party} owes {R} in cash within {n} business days — their debit note was larger than the self-billing invoice they were due, so they receive nothing this period and must pay the balance. That is a phone call
Credit cover #board-credit-cover Required · Posted · Headroom (red if negative) · Notices
Query inbox #board-query-inbox Tier · Participant · Raised · Deadline · Escalates to
Footer — Ledger clearing mode: Official balancing or Timetabled exact, plus SAST (+02:00)

Parties (#dam-month-parties) is second on #dam-month-lower (right). The card does not grow taller than the billing board; the table body scrolls. Header and the Party column stay sticky. #dam-month-party-search (form #dam-month-party-filter) filters name / MPID / document. Empty table: No published DAM hours in this Billing Period. No matches: No parties match this filter. Footer: Showing {n} entries (#dam-month-party-count) and a Settlement link to the month’s first day. A party name is the same hop. Negative DAM EPM is rose.

Column How to read it
Party Name / MPID
DAM EPM Their energy-market position for the month
Constrained net Constrained-schedule money (cuts and related charges)
IDM net Intra-day money on the Market Balancing Account — not a rewrite of EPM
Document #party-document-{id} — none (nothing issued yet), Invoice (they owe the market), or SBI (self-billing invoice: the market owes them)
How to read it
  1. Pick the Billing Period you are closing, not today’s Trading Day. The ribbon month picker (#bidding-month) and any Trading Date on other tabs are different controls.
  2. Gate-miss pill. 0.0% emerald is healthy cadence; amber means callables were misses. It is not a Rand amount.
  3. EPM net first — headline, then Variance. If it is not R 0.00, a published day in this month has an open energy loop. That is an incident, not a rounding curiosity. Open Settlement for the days in the period and find which chalkboard is not closed.
  4. Published-day count. If it is less than the days you think you traded, someone has not pressed Publish yet. Month does not invent those days.
  5. Windfall is a count, not a pot. A large MWh with a large estimated value and a still-zero EPM net is coherent: the wires cut a zero-priced offer; the closed loop is intact; the windfall is disclosed separately.
  6. SMP duration. Peak / Min are the month’s mean-by-hour extremes. Daylight avg is 07:00–17:00; Night avg is the rest. Hover shows Mean SMP to two decimals.
  7. Document column. Invoice means chase payment. SBI means the market pays them. none means Run the month has not issued that party’s document yet. Filter the table when the list is long.
  8. Billing board empty means Cadence has not run this month. Do not treat that as “nobody traded.”
  9. Cascade / Excess Participants is the month’s bad news. An Excess Participant is a creditor being asked to send money back. Read it before anyone phones you.
  10. Admin is Administered Settlement (clause 15.11), not the settlement calendar. The calendar clocks stay on the billing card.

Worked month: §18.11 on Accounts (July 2026, full_demo, seed 42).

Administered Settlement — the form

The Admin button (#dam-month-admin) sits on Calendar and status. It opens #administered-modal. The form #administered-switch-form is inside the modal, not at the bottom of the billing board. Submit is Switch to administered (#administered-switch). Fields: MGC approval reference (#administered-approval-ref) and Methodology (#administered-methodology-text). Close: #administered-modal-close-x, the backdrop, or Escape.

What it is, in ordinary English

In a normal month the market is settled from real numbers: the day-ahead schedule, the intra-day moves, the meters. Everyone is paid (or pays) from that chain.

Sometimes that chain is broken.

Administered Settlement (Market Code clause 15.11) is the emergency setting: “we cannot settle this period the ordinary way, so we reconstruct it as honestly as we can — and we still put those reconstructed numbers through the same settlement calculator.” It is not a second, secret engine that only exists in a crisis. A calculator that only ran in a crisis would be a calculator nobody had ever tested, and the crisis is the worst moment to find that out.

The Code names two triggers. The teaching lives in full at V9 §16 and in the glossary (Administered Settlement, Administered Schedule).

What went wrong What the reconstruction does Why
System Failure — the systems that run the market failed, so you do not have a trustworthy schedule or price set Compute an Administered Schedule: quantities per Trading Unit per period, and prices per period. Prices default to the Wholesale Tariff unless the Market Governance Committee says otherwise Downstream settlement then uses those figures, as close as practicable to what the ordinary algorithm would have produced
Electrical System Collapse — the grid itself collapsed Set both scheduled energy and instructed energy to what the meter showed at the moment of collapse Imbalance is “what you were told to do minus what you did.” If all three numbers are the same, every difference is zero, so nobody is charged a balancing penalty for a blackout they did not cause. Resetting only the schedule would leave every participant holding that penalty

This tab’s form declares the Billing Period as administered (the board then shows mode system_failure) after the two required fields are filled. It does not ask you to type quantities and prices by hand. The substitution is the engine’s job. The form is the governance gate.

When you would use it — and when you would not

Use it only when ordinary settlement is actually impossible: the market systems failed, or the electrical system collapsed, and you cannot produce a truthful ordinary run for the period.

Do not use it because a day looks ugly, a participant is unhappy, a gate was missed, or you want to “smooth” a price. Missed gates belong on Cadence. Ugly hours belong on Settlement. Unhappy participants belong in the query inbox. Administered Settlement is not a discretionary override of a month that otherwise worked.

You also cannot use it as a shortcut around Run the month. If no month row exists yet, the switch refuses: Run the month before switching to administered settlement.

Why the two fields exist

Clause 15.11.1(d) and (e) are the reason the form is shaped this way.

The Market Governance Committee (the market’s governing body — not the operator acting alone) must give prior written approval of the detailed calculations and the methodology before the administered run, not after it. “We reconstructed the day and will explain later” is exactly what that clause exists to prevent. The MGC approval reference is that written approval, recorded on the switch so the switch cannot be thrown first and justified afterwards.

The methodology is then published (clause 15.11.1(e)) so every participant can see how the reconstruction was done. An administered month with no published method is a reconstruction nobody can check.

Leave either field blank and the switch does nothing. Error flash: Administered settlement requires the Market Governance Committee’s prior written approval and a published methodology (clause 15.11.1(d),(e)).

While the period is still ordinary, the board reads (#administered-off): Mode: normal — the ordinary pipeline. Switching to an administered mode requires the Market Governance Committee’s prior written approval reference (clause 15.11.1(d)); the switch will not act without one.

What happens if you switch — the consequences

If both fields are filled and a month row exists, the period is marked administered. Success flash: Administered settlement is on. The form is replaced by #administered-on:

There is no switch-back on this form. Ordinary mode is the default until this declaration; once it is on, the record is that this Billing Period was administered.

Consequences that matter to people, not only to the ledger:

  1. Participants settle against the reconstructed figures for that period, not against a pretend “nothing happened.” Money still moves. Statements and invoices still issue. The clocks in the settlement calendar still apply.
  2. The same calculator still runs. The energy account must still net to R 0.00. Administered is a mode of the ordinary pipeline, not a forgiveness of the closed loop.
  3. Query and dispute rights are untouched. A participant who disagrees with the reconstruction uses the same inbox (#board-query-inbox). Administered is not “no complaints.”
  4. When the failure is corrected, the period is rerun properly. Settlement Reruns produce the ordinary answer as soon as reasonably possible. The difference between the reconstruction and the real answer is settled through revised statements and their invoices — not by silently editing a closed period. Nobody should be surprised by a later true-up; that true-up is the design.
  5. The methodology is public. Anyone reading #administered-on can see that an approval exists and when the method was published. That is the transparency the clause demanded in exchange for letting the operator reconstruct a broken day.

Treat the switch as a declared state with a paper trail, not a toggle you try because the chalkboard looks wrong.

Month /mo/bidding/month

Calendar 1 Pots + SMP 2 Billing board 3 Parties 4
gate-miss pill · Admin EPM above windfall · duration chart calendar | four pots filter · sticky Party
  1. 1Calendar and status is the header: published-day count, gate-miss pill, branded Admin (clause 15.11 modal). The month picker stays on the ribbon.
  2. 2Pots + SMP stacks Energy market (target / variance) above Curtailment windfall; SMP duration sits beside them with Peak / Min / Daylight avg / Night avg.
  3. 3Billing Period settlement is first on the lower row: clause 15.3.3 calendar beside Statements / Invoices / Self-billing / Shortfalls. No administered form on the board.
  4. 4Parties is beside billing, no taller than that card. Filter name / MPID / document; the Party column stays put while the rows scroll.

13.12 Clear — the G5 ledger

Path: /mo/bidding/clear. Date on the ribbon is the Trading Day you are clearing (#bidding-date). The month picker (#bidding-month) is also here: it is the default month for Settle, not the day-ahead run.

Daily is the pulse and the price board. Settlement is the hour chalkboard. Clear is the run room. It is where you see the two auctions the Code actually requires — unconstrained, then constrained — and where you pin that pair as the official day-ahead plan. It is also where you hand a month’s settlement file to reconciliation. Those are two different jobs on one tab. Mixing them up is the usual way to mis-operate this screen.

There is no second day-ahead engine. Run both schedules and Publish… are the same WB.Sawem.Cycles jobs as Daily’s Solve and Publish. This tab does not list bids and does not fetch a participant DAM schedule. It shows what G5 did.

What Clear is for

The Market Code does not clear “a schedule.” It clears twice:

  1. Unconstrained — if the wires could take everything, who would run? That run sets the SMP and the energy-pot volumes (SG).
  2. Constrained — given the System Operator’s security constraints, who may actually inject? That run sets the physical schedule. It does not rewrite the SMP.

Daily’s Price board shows you one ink line. Settlement shows you the money. Neither places the two schedules next to each other with the binding constraints on the same row. Clear does. That is why the tab exists.

Use it when you need to:

  1. See whether the wires moved anyone — constrained against unconstrained, unit by unit (#clear-day-differences). Matching schedules are not proof the network was clear; the constraint note tells you whether anything was even published to bind.
  2. Read the G5 cadence ledger for this Trading Day — which callable ran, which missed, at what time (#clear-day-cadence). Cadence (§14) is the month’s health of those rows; Clear is today’s.
  3. Run and pin the day-ahead plan with eyes on both schedules before every participant starts settling against them (clause 9.10(1), publish by 14:00 D−1).
  4. Publish the MO settlement file for one registration and month and reconcile it immediately — the §4 artefact, not a second auction.

What this tab is not. It is not Submissions. It is not the IDM stack. It is not Month’s invoice. It is not a place to type a price. Embedded #settlement-board and #idm-board are the same boards as those tabs, parked here so you can review money and patches without leaving the run room.

Why you should use it

Pressing Solve on Daily and never opening Clear will still clear the day — the jobs are the same. You should still come here because:

What it displays
Section Id What it is
Clear day panel #clear-day-panel First on the tab. Title Clear day — 15 ’Jul ’26 (#clear-day-date). Status badge (#clear-day-status) sits under the title (SOLVED / PUBLISHED / SUPERSEDED)
Steps #clear-day-steps Unconstrained Ran → SO Constraints applied → Constrained Ran → Published. DaisyUI numbers the circles 1–4. Run time under a step when G5 has it
Run both schedules #clear-day-solve Same row as the title, to the right. Disabled while solving (Solving…)
Settle #clear-day-settle Same row, after Run both. Opens the settlement-file modal
Publish… #clear-day-publish Only when latest status is :SOLVED. Pins the DAM. Confirm: #clear-day-publish-confirm
Security notice #clear-day-network-notice After the steps, when the run carries a network-model notice. Info alert (bg-info/10) labelled Security Notice:. Emphasis words (degenerate, assumed) are underlined; clause refs sit in a mono chip.
Timelines #clear-day-timelines Two equal-width cards after the Clear day panel (md:grid-cols-2): Published Hours | G5 Run Ledger
Published hours #clear-day-schedules Card header Published Hours. Body is the daisyUI vertical timeline: bold hour · SMP · Marginal unit · binding count. After Publish
Binding modal #clear-binding-modal Click a binding count greater than 0. Each constraint is coloured by its title (declared_capacity, declared_consumption, …)
Differences #clear-day-differences Constrained against unconstrained — or no unit was moved by a security constraint.
G5 run ledger #clear-day-cadence Card header G5 Run Ledger with a {n} Callables badge. Body is the daisyUI vertical timeline: bold start time · Callable · Outcome. Empty: No cadence rows for this Trading Day. Solve writes the G5 run here.
Constraint note #clear-day-constraint-note Same three sentences as Daily: nothing published / empty published list / {n} published security constraint(s) will bind the constrained run.
Embedded boards #settlement-board, #idm-board Same boards as those tabs
Settlement file (§4) #clear-settle-modal · #clear-settlement-file Settle opens this. Registration + month → Publish & reconcile. This is not a second day-ahead clear.

Empty panel: Nothing has been solved for this Trading Day yet.

Run both schedules

Run both schedules (#clear-day-solve) is Daily’s Solve with the name that tells the truth. It runs both day-ahead auctions for the ribbon Trading Day, then writes prices onto a solved run. It does not publish.

Where this is taught. The two auctions and why solving does not publish: §13.7 Solve and Publish. When the DAM gate is a lock on intake but not on Solve: §13.10 When you may Solve. This section owns what Clear is for, and the two buttons that are easy to mix up: Run both schedules (day-ahead) and Publish & reconcile (the monthly file).

The three jobs, in order:

  1. Unconstrained clear — who would run if the wires could take everything. This sets the SMP and the energy-pot volumes.
  2. Constrained clear — apply the System Operator’s security constraints; who may actually inject. This does not rewrite the SMP.
  3. Calculate prices — write the hourly SMP and the money lines onto a solved run.

Success flash: Both schedules solved and settled. Nothing is published yet. The first three steps light. Publish… appears. The fourth step (Publish) stays unlit. Participants still settle against the last published run — or against nothing.

A miss does not write an empty published plan:

Miss flash Typical cause
Solve recorded a miss — there are no accepted submissions for this Trading Day. Nobody stored a 168-period body (and rollover has not written).
Solve recorded a miss — this Trading Day has no hourly periods to clear. The date has no Trading Periods.
Solve recorded a miss — a prior step is un-run or an SO input is absent. Cadence order or a System Operator parcel the run still needs.
When you must use it

The DAM gate closing is not a lock on this button. The gate is when intake stops. The auction is meant to run after that bell.

Clock May you press it? What you are doing
Before 10:00 D−1 — DAM gate still open The button works. This is a rehearsal. The stack is still moving. Do not Publish this as the day’s plan.
After 10:00 D−1 — DAM gate closed Yes. This is the intended window. Intake is frozen (unless you extended the gate). Rollover should have written. You run both schedules, read the two results, and Publish by 14:00.
After 14:00 D−1, or on the Trading Date Still allowed. It does not reopen the DAM gate. A new solved draft. The last published run remains official until you Publish again. IDM patches do not require you to re-run the DAM.
A past Trading Date The button is still there. Re-solving yesterday does not, by itself, unwind published money.

You must use it (or Daily’s Solve — same jobs) whenever this Trading Day has no solved run and you intend to publish a plan. You must use it again after a miss, after late SO constraints arrive, or after a BRP has corrected a declaration you accepted — a second press draws a new run. It does not edit the previous one.

Do not use it as an IDM clear. Do not treat a successful press as “everyone is on this schedule.” That is Publish.

Consequences of using it
Publish… — pin the day-ahead plan

Publish… (#clear-day-publish) is not Publish & reconcile. It only appears when the latest run is SOLVED. It never publishes on the first click. Confirm (#clear-day-publish-confirm):

Publishing makes this the schedule and price set every participant settles against (clause 9.10(1)). It supersedes anything already published for this Trading Day, and the superseded run stays readable. Solving again afterwards produces a new run rather than editing this one.

Control What it does
Publish this run (#clear-day-publish-confirmed) Pins this solved pair as official.
Cancel Closes the confirm. Nothing is published.

When you must use it. After a successful Run both schedules, once you have read the two schedules and the differences, by 14:00 D−1. That is the Code’s publication obligation. A solved run that never publishes is a rehearsal the market cannot settle against. Re-publishing a later solved run is allowed; it supersedes the previous published run (status SUPERSEDED) rather than editing it — so “why did my statement change?” still has an answer.

Consequences. Success flash: Published. Every participant now settles against this run. The Publish step lights. #clear-day-schedules fills (Period · SMP · Marginal unit · Binding constraints). Energy account on Daily/Settlement may now show R 0.00. Adequacy and schedule.published notices go out. Until this press, they do not.

Miss: Publish recorded a miss — prices have not been calculated. Or There is nothing solved to publish.

After Publish, the two-schedule table is what you came to Clear to see. Empty differences: no unit was moved by a security constraint. Read the constraint note before you treat that as a healthy network.

Publish & reconcile — the monthly file

Publish & reconcile lives on Settlement file (§4) (#clear-settlement-file), opened by Settle (#clear-day-settle) — not a card at the bottom of the tab. It is a monthly control. Form #clear-settlement-form: pick a Registration (BRP code) and a Month, then submit. Close: #clear-settle-modal-close-x, backdrop, Escape.

It does two things in one press:

  1. Publish an MO settlement file for that registration and month — the §4 artefact — built from the platform’s internal expectation (the lines the books already hold).
  2. Reconcile immediately — the same join the clock runs at 07:00 on the 3rd: internal lines against that file. Success flash: Settlement file published and reconciled — {n} % matched.

The card’s own sentence: This is not a second day-ahead clear. It does not run unconstrained or constrained. It does not set an SMP. It does not pin #clear-day-panel.

When you must use it
Situation Use it?
The day-ahead plan is unsolved or unpublished No. That is Run both schedules then Publish….
Cadence has not run this Billing Period (no internal lines) It will refuse: Could not publish/reconcile (no internal lines?). Run the month first (§14, #mo-run-the-month).
A registration needs the §4 file now (or again after a correction) Yes. Do not wait for 07:00 on the 3rd if the month is ready.
You selected no registration Refuses: Choose a registration first.
You want to see match-% on Reconciliation Yes — that view shows the newest run, so do this last in a demo if an older injected-error month should stay on screen.

The automatic 3rd-of-month job still runs. This button is the operator-initiated issue (and re-issue) of the same file for one BRP.

Consequences of using it

Clear /mo/bidding/clear

Clear day 1 Run both 2 Settle 3 Hours | G5 4
title · status · steps unconstrained + constrained file modal two vertical timelines
  1. 1Clear day is first on the tab. The date reads 15 ’Jul ’26. The status badge sits under the title. Steps stay on the header: Unconstrained Ran → SO Constraints applied → Constrained Ran → Published, with the run time under each step when G5 has it.
  2. 2Run both schedules is on the title row, to the right — Daily’s Solve. Nothing is published yet.
  3. 3Settle opens the §4 file modal. Publish & reconcile inside it is not a second day-ahead clear.
  4. 4Hours and G5 sit beside each other as equal-width cards. Left Published Hours: bold hour · SMP · Marginal unit · a binding-constraint count (click for the coloured list). Right G5 Run Ledger: bold start time · Callable · Outcome.

13.13 Operate 2026-07-15 18:00

Data. full_demo · seed 42 · Trading Day 2026-07-15 · hour 18:00 · SAWEM-SPEC §10 / market-dam.md §11.

Seat: mo@webill.net / supersecret.

  1. Open Submissions with ?date=2026-07-15. Find TU-PV1. Open the drawer. You should see 168 periods and no edit form. Golden units: TU-COAL1, TU-PV1, TU-OCGT1, TU-DIST1, TU-IND1.
  2. Open Settlement for that date, hour 18:00. Unconstrained 75 / constrained 60. Energy pot R 0.00. CSC R 0.00 with the zero-priced-curve sentence (own offer was zero on TU-PV1). SMP R 900.
  3. Solve if the day is unsolved; confirm the public board is still empty. Publish. The status sentence becomes Published at HH:MM.
  4. Open IDM, iteration 4. Applied IDP R 945, collared. The stack has prices and volumes and no TU-. The farm’s IDM charge is −R 37,800.
  5. Open Month for July 2026. EPM nets to R 0.00. Windfall 15.000 MWh, would have been worth R 13,500 at the hour’s SMP. It is not added into the energy pot.
Teaching hour 18:00 on 2026-07-15 — market wanted 75 MWh; the wire allowed 60
18:00 SASTSMP R 900 · energy pot R 0.00
Unconstrained (energy pot)75 MWh
paid at SMP
Constrained (what may inject)60 MWh
60 delivered 15 cut → windfall tile
Energy pot15 MWh counted, not added

Follow along. Path: Market Operator → Bidding → Submissions ?date=2026-07-15 → Settlement → Daily/Clear Publish → IDM iteration 4 → Month. You should see R 0.00 on the energy account, a collared R 945, and a drawer that will not let you type a price.

Demo clearing is deterministic (TOU SMP bands). Same trading date ⇒ same curve — reproducibility for screenshots and gates.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

14. Cadence

Path: Market Operator → Cadence (/mo/cadence). Second item in Market day. The icon is a clock.

This is the §1.2 operating-cadence ledger: every Market Operator callable as due, ran or missed. A miss is a row. A missed 14:00 publish is not a green day. Stopping after publish without allocate is visible as un-run.

Think of it as the station clock and the delay board. Bidding is the platform. Cadence is whether the 14:00 actually left.

What this page is not. It is not a roster of BRPs, Trading Units or bids. There is no search, no TUID column, no silent-unit tile. You hunt callables and failed deliveries here, then jump to the desk that names the party (§14.4).

14.1 Why Cadence is significant

Cron will run the callables. You still need to see them. Did gate close? Did rollover write? Did unconstrained run before constrained? Did publish happen on time? Did allocate ever run? If a §16(2)(f) delivery failed, who still has not been told?

Without this page those questions hide in logs. With it they are rows.

What it is for

The Market Code’s day is a timetable, not a mood. §1.2 names every callable and when it is due. Cadence is the operator view of that table for one Trading Day: the same names the Oban shells and POST /api/v1/internal/cycles/:callable fire, written as pending / due / ran / missed with the Outcome the engine recorded.

Bidding Solve and Publish call the same WB.Sawem.Cycles wrappers. They do not replace this page. A chalkboard that looks solved is not proof the 14:00 left, that IDM iteration 1 rang, or that allocate ever ran. Cadence is that proof.

Why it matters on a trading day

A Trading Day is a chain. Each callable has a predecessor and a clock. If you only watch Daily, you watch the auction room. Cadence watches whether the bells rang, in order.

Clock (SAST) Callable you must see move If it does not
10:00 D−1 #mo-cadence-close_dam_gate then #mo-cadence-generate_rolled_over_submissions Intake never froze. Silent units still have no body. Daily Solve can miss (no_submissions) or clear an incomplete stack.
after the gate #mo-cadence-clear_unconstrained No economic solve. The System Operator’s reserve parcel is a recorded miss (so_reserve_requirements_absent), not invented zeros.
13:30 D−1 #mo-cadence-clear_constrained Wires and interconnect never applied. Downstream prices miss with prior_clear_missing / unconstrained_not_run.
14:00 D−1 #mo-cadence-calculate_prices and #mo-cadence-publish_schedule_reports The plan never became the plan. A missed 14:00 is a rose row, not a green day. Every later #mo-cadence-clear_idm-{n} can miss with dam_not_published.
18:00 D−1, then 00:00 / 06:00 / 12:00 / 18:00 D Five #mo-cadence-clear_idm-{1..5} rows The patches never rang. The IDM tab is the board; these rows are whether the bell fired. Not inside Run the day.
D and D+1 #mo-cadence-ingest_metering, #mo-cadence-allocate_metering Empty ingest is a miss (empty_ingest), not a skipped healthy day. Official balancing cannot become official.
D+1 … D+7 17:00 #mo-cadence-run_balancing-d{1..7} Preliminary then official never computed. D+7 VERIFIED can run and still refuse if vintage is unverified — emerald is not “official is out”.
SD+1 WD / BP+5 WD / BP+1M Statements, invoices, rerun, credit cover, calendar The month never closed. Accounts and Billing show the board; they do not have Run the month.

The clocks are in §3. This page is whether they actually rang.

What goes wrong if you ignore it

You will believe Daily. Daily can look finished while Cadence is not.

A miss is a row so you cannot skip it as healthy silence. Empty ingest, absent SO reserves, a Saturday credit-cover pass, official balancing on unverified metering — each is recorded.

14.2 How the page is laid out

Browser title: Cadence. Header: Operating cadence — Every Market Code §1.2 callable as due, ran or missed. A miss is a row.

No tabs. No filters. Three blocks, top to bottom. If a simulation is active, the simulated-clock ribbon sits under the header — same ribbon as Daily.

Block DOM id Job
Date and actions #mo-cadence-date-form Pick the Trading Day; run the day or the month
Ledger #mo-cadence-ledger Every callable for that day
Event-delivery incidents #mo-event-incidents Failed §16(2)(f) deliveries
Reading order

Read the page the way the clock bites, not the way the table is sorted.

  1. Confirm the Trading Day (#mo-cadence-date). Wrong date, wrong bells. Before 10:00 SAST the default is tomorrow (you are still in D−1); from 10:00 it is today — same rule as Bidding.
  2. Read the four header counts on #mo-cadence-ledger — pending, due, ran, missed. Start with missed (rose) and due (dark). Do not start by scrolling for a favourite name.
  3. Open the rose and dark rows. Outcome plus the rose — {reason} is the finding. A blank Outcome on a missed row means the deadline passed and nothing was recorded — still a miss.
  4. Then Event-delivery incidents. {n} open in rose is who was not told, even if publish ran.
  5. Only then press a button. Run the day is the six day-ahead steps. It will not allocate, will not clear IDM, and will not issue invoices.

A day runs to a couple of dozen callables (six day-ahead, five IDM, ingest + allocate, seven balancing vintages, then the settlement cluster). The ledger scrolls inside #mo-cadence-ledger-scroll; the column headers are sticky.

14.3 Trading day and the two run buttons

Control Id What it does
Trading day #mo-cadence-date Date input. Change it and the address becomes /mo/cadence?date=YYYY-MM-DD. An invalid date is ignored.
Run the day #mo-run-the-day Left branch of #mo-cadence-run-actions. Walks gate → rollover → unconstrained → constrained → prices → publish. Hover lifts and paints brand amber. Flash: Run the day — {ok} ok, {miss} miss(es). Allocate is a separate row.
Run the month #mo-run-the-month Right branch of the same pair. Walks indicative → initial → invoices → timetabled rerun → credit cover (the same G5 job) for the Billing Period that contains the selected day, then persists the month run the billing board reads. Hover lifts and paints indigo. Flash: Run the month — {ok} step(s) recorded.

Help text under the buttons:

Run the day walks gate → rollover → unconstrained → constrained → prices → publish. Stopping after publish without allocate is visible as un-run, not success. A missed 14:00 publish is a row, not a green day.

Run the day does not allocate. :allocate_metering is a later ledger row. A green publish with allocate still pending is an honest unfinished day.

Run the day does not clear the IDM. The five :clear_idm rows stay on their own clocks.

Run the month is the month trigger. Bidding → Month and Accounts show the billing board; they do not have this button.

External automation POSTs each MO-SPEC §1.2 name at /api/v1/internal/cycles/:callable. A participant token is 404 (V13).

14.4 The ledger — how to read a row

Header counts, left to right, are filters (#mo-cadence-status-filters): All, {n} pending (amber), {n} due, {n} ran (emerald), {n} missed (rose). Click a status to show only that chip’s rows; click it again or All to restore the full ledger. The counts still describe the whole day, not the filtered slice.

Column What it is
Callable The §1.2 name. May append /iteration (IDM) or a vintage (PROVISIONAL / VERIFIED)
Trigger When the engine expected it — the §1.2 sentence, not a wall-clock you type
Due SAST clock as 23 'Aug '26 00:00 (#mo-cadence-{callable}-due), or blank. Click Due (#mo-cadence-sort-due) to sort earliest first, click again for latest first. Rows with no due time sink to the end on earliest-first and rise to the top on latest-first.
Status pending · due · ran · missed
Outcome What was recorded (ok, miss, error, refused, skipped). A miss, error, refuse or skip appends — {reason} in rose when the engine stored one

Row ids: #mo-cadence-{callable} — e.g. #mo-cadence-close_dam_gate, #mo-cadence-publish_schedule_reports, #mo-cadence-allocate_metering. IDM adds the iteration: #mo-cadence-clear_idm-1 … #mo-cadence-clear_idm-5. Balancing adds the offset: #mo-cadence-run_balancing-d1 … -d7.

A day runs to dozens of callables, so the ledger scrolls inside its own box (#mo-cadence-ledger-scroll) rather than dragging the page down, and the column headers are sticky — they stay put while the rows pass under them. You can be forty rows in and still know which column the rose chip is sitting in.

Status Colour Meaning
pending Amber Not yet due
due Dark chip, white text Deadline reached, not yet run
ran Emerald Completed (ok, refused, or skipped — it ran)
missed Rose Due time passed without success, or outcome :miss / :error

Emerald is not always good news. refused and skipped count as ran. Official balancing that refused unverified metering is a green chip with Outcome refused. Read the Outcome column; do not stop at the counts.

Metaphor. Pending is the train still in the timetable. Due is the announced departure with no movement. Ran is a departure logged — even if the destination refused the train. Missed is an empty platform after the clock.

Day-ahead callables you will see on a normal D−1:

Callable Everyday name
:close_dam_gate Freeze intake
:generate_rolled_over_submissions Fill silence with yesterday
:clear_unconstrained Economic solve
:clear_constrained Apply the wires
:calculate_prices SMP and pots
:publish_schedule_reports 14:00 publication
:allocate_metering After 14:00 — not inside Run the day
:clear_idm /iteration Five IDM auctions — 18:00 D−1 then 00:00 / 06:00 / 12:00 / 18:00 D. Not inside Run the day. A miss with dam_not_published means Daily never Published. The IDM tab is the board; this row is whether the bell rang (§13.9)
D−1 on Cadence — the callables the ledger is watching (SAST)
00061218
  • 10:00 DAM gate · demand & reserves due
  • 13:30 Interconnect due
  • 14:00 Publish — a miss is a rose row
Who to look for

Cadence does not name a BRP or a TUID. You look for which bell failed, then take the names from the desk that holds them.

Walk missed and due first, then any ran row whose Outcome is refused or skipped. The hunts below are the ones this screen can actually raise.

Hunt Row on this page Who / what you are after Where the names live
Gate never froze #mo-cadence-close_dam_gate due or missed Intake is still moving. Late PUTs may still land. Bidding → Daily gate chip; Submissions Rejected / late for the 409s that did bounce (§13.8)
Silent units #mo-cadence-generate_rolled_over_submissions still pending after 10:00, or missed Registered units with no body at the gate. Rollover is supposed to copy yesterday. Submissions Silent at last snapshot and Rolled over tiles. A unit that never had a previous body cannot be rolled — Registry, not a missing Cadence button.
Late submissions Gate row ran, plus the clock past 10:00 They tried after the bell. Cadence will not list those PUTs. #submissions-rejected — gate_closed is the usual code. The operative body (if any) is the rollover, not the late PUT.
Nobody to clear #mo-cadence-clear_unconstrained Outcome — no_submissions The stack is empty. Received + Rolled over = 0. Submissions tiles. Do not Solve past this as a display quirk.
System Operator reserve parcel #mo-cadence-clear_unconstrained Outcome — so_reserve_requirements_absent The SO, not a BRP. The engine will not invent zeros. An operator Run the day may proceed with the absence recorded in the inputs hash. Daily / Clear — reserve input state. Chase the SO feed, not a participant.
Wires / 13:30 interconnect #mo-cadence-clear_constrained due after 13:30, or — unconstrained_not_run Constrained waits on unconstrained and the interconnect clock. Absent security constraints are a recorded input state, not a silent []. Clear / Daily constrained notice. The SO and the ties, not a TUID.
Prices or 14:00 publish #mo-cadence-calculate_prices, #mo-cadence-publish_schedule_reports missed (prior_clear_missing, prices_not_calculated) The plan never pinned. This is the finding — not a solved chalkboard. Daily Publish. Then come back: publish ran is the Cadence row, not the ink on the Price board.
IDM gate failures #mo-cadence-clear_idm-1 … -5 missed, especially — dam_not_published Iteration that never cleared. Iteration 1 at 18:00 D−1 needs a Published DAM. IDM tab is the board (§13.9). Today’s date shows iteration 5; tomorrow’s date shows that day’s iteration 1 — they are not the same row.
Missing metering #mo-cadence-ingest_metering or #mo-cadence-allocate_metering missed with — empty_ingest Network Operator feed / no batch. Empty ingest is a desk state, not a skipped healthy day. Run the day will not fix this. Metering — Re-ingest, Allocate, unpaired points, exception inbox.
Balancing vintages #mo-cadence-run_balancing-d1 … -d7 (Callable shows PROVISIONAL or VERIFIED) D+1–D+6 preliminary; D+7 official. Official refused is still ran. Balancing. Official stays gated on verified vintage.
Statements / invoices / cover #mo-cadence-issue_indicative_statements, #mo-cadence-issue_initial_statements, #mo-cadence-issue_invoices, #mo-cadence-run_timetabled_rerun, #mo-cadence-recalculate_credit_cover, #mo-cadence-publish_settlement_calendar Parties with no lines (no_parties, no_statements), or a year with no calendar (settlement_calendar_not_published). Credit cover is every business day by 17:00. Accounts and Billing. Press Run the month here, then read the board there and open the PDFs on Billing.
Who was not told #mo-event-incidents — {n} open in rose Failed §16(2)(f) machine delivery. Typical event schedule.published. The mono event id is {event}:{source} — for publish, the source includes the Trading Day and the party. This list. Retry (#retry-event-{id}) is the control. Notices (§15) is the tannoy, a different channel.

What you will not find on this screen. A TUID, a BRP code, a silent count, a rejected PUT, a meter point, or a credit-cover headroom figure. Those desks exist. Cadence tells you which job failed so you know which desk to open.

What you can ignore (for a moment). Amber pending rows whose Due is still in the future. IDM iterations 2–5 on a morning D−1. D+7 balancing on a day that has not happened. They are the timetable, not the delay board.

14.5 Event-delivery incidents

Heading: Event-delivery incidents. A failed schedule.published (or any §16(2)(f) delivery) appears here — not as a missing chalkboard line. Publish writes one delivery per party that settled the day, plus the public row. A down webhook is an incident, not a quiet gap.

State Copy
Empty No failed §16(2)(f) deliveries. A miss is a row, not a missing Panel C line. (#mo-event-incidents-empty)
Open Header shows {n} open in rose

Each open incident is #mo-event-incident-{safe-id}:

You see What it is
Mono event id {event}:{source} — shared with the org day board. Dots and colons are not CSS-safe; Retry uses the sanitised id.
{event} · {reason} Event name (schedule.published, and any other §16(2)(f) type that failed) and failure_reason, or delivery failed.
Retry #retry-event-{id}

Success flashes Delivery retried. and the row clears. Failure shows the incident’s failure_reason. Retry is not a re-publish and not a re-clear. The schedule already left; this is the doorbell.

If publish is ran and this list is not empty, start here before you tell a BRP the noticeboard is up.

14.6 Worked day — 2026-07-15

Data. full_demo · seed 42 · Trading Day 2026-07-15.

Open /mo/cadence?date=2026-07-15. You should see the day-ahead rows. Press Run the day. Gate, rollover, unconstrained, constrained, prices and publish move to ran. Allocate stays off that list — look for #mo-cadence-allocate_metering still pending or due.

If you freeze the clock at D−1 14:30 SAST with publish un-run, the publish row is missed. That is the finding. Do not read a solved Daily chalkboard as a green cadence day.

Then look down the same date for the hunts in §14.4: five IDM rows, ingest / allocate, seven balancing offsets, and the settlement cluster. Run the day will not have touched them.

Follow along. Path: Market Operator → Cadence → set 2026-07-15 → Run the day. Then open Bidding → Daily for the same date. Solve/Publish on Daily call the same WB.Sawem.Cycles wrappers. Cadence is how you prove they ran.

Careful. A participant token cannot POST a callable. Internal automation uses the internal party header (V13).

14.7 How to act

You do not “fix a unit” from this chair. You prove which callable failed, then act on the matching desk — or fire the missing step.

Finding What you press or open
Day-ahead chain still pending / missed before 14:00 Run the day (#mo-run-the-day), or Daily Solve / Publish — same wrappers. Then re-read the six rows.
Publish ran, allocate still pending Leave it. Allocate is #mo-cadence-allocate_metering / Metering Allocate. Do not read Run the day as done.
:clear_idm missed dam_not_published Publish the DAM on Daily first. Re-publishing does not resurrect a missed iteration by itself.
empty_ingest Metering Re-ingest, then Allocate. Not Run the day.
Open event incidents Retry on the row. If it fails again, the failure_reason is the ticket.
Month rows missed Run the month (#mo-run-the-month), then Accounts / Billing.
Silent > 0 after rollover ran Submissions / Registry — those units had nothing to roll.

Do not treat a second Run the day as a way to hide a miss. Each press records rows. The ledger is the product; the buttons are how it becomes true.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

15. Notices

Path: Market Operator → Notices (/mo/notices). Fourth item in Market day. The icon is a megaphone.

A notice is a dated message the market keeps so someone can prove they were told. It is words (or a named event) with a time, an audience, and a record. It is not a price. It is not a bid. It is not a System Operator order that moves a plant.

This page is the tannoy: New + opens a modal, you type a sentence, pick a type, and Publish. Every participating BRP (Balance Responsible Party — the firm that bids and settles) hears the same text. The table is how you prove you said it.

Other screens keep other messages. Those are also “notices” in the Code. They are not this form. This chapter first teaches the tannoy. Then it lists every kind the product actually issues or records, and says which console holds it.

Metaphor. Daily’s notification ledger is the pigeonholes for machine events (schedule.published). This page is the station announcement: words a human wrote, heard by every BRP notice feed.

Where this is taught. What a notice is, and how a BRP reads it: V9 §9. System Operator orders and SYSTEM_CONDITION: V12 §3. Event-delivery failures: §14.5. Daily’s receipt list: §13.7. This chapter is the send form and the catalogue.

15.1 The operator’s problem

The market needs context that is not a price. A gate was held. The grid is stressed. The price cap bound. Every BRP must see the same text, and you must be able to prove you sent it — including last month’s wording.

You also need to know the other messages that are not this tannoy. A credit-cover call is a notice. A default is a notice. A schedule that failed to reach a webhook is a notice. Mixing them up is how a party says “nobody told us” when you told them on a different desk.

15.2 What a notice is — and what it is not

In plain words: someone was told something, on the record.

It is It is not
A dated row with a type (or event name), a body or payload, and an audience A change to Instructed Energy
Proof you broadcast, or proof a machine event left A bid, a schedule, or a price
Something a BRP can open on Market → Notices when you used this form A System Operator plant order
Searchable later A delete

Three audiences appear in this product:

Audience Everyday meaning
Public / broadcast Every participating BRP (and the public feed, when the event is public)
Party One named registration. A BRP that was not named does not see it
Network operator One named network operator — same naming rule as party

This tannoy always broadcasts. The form has no party picker. A party-scoped PRICE_CAP_EVENT is written on Daily’s ledger, not here.

15.3 Why one is created

Someone creates a notice because a fact needs to travel before the next decision. Typical triggers:

Trigger Everyday example
You need every BRP to read the same sentence Gate held to 10:15 under §9.3(3)
The room is stressed, or a cap bound High demand; SMP hit the Market Price Cap
A machine event happened 14:00 publish; an IDM auction cleared; a bid was rolled over
Money or eligibility moved Credit cover short; an account was opened; a party is in default
The registry changed A meter point was added; a balancing group was designated
Delivery failed A schedule.published webhook did not land
The System Operator missed a parcel Reserve requirements late — specified as a SYSTEM_STRESS notice

If nobody needed to act or know, you would not write one.

15.4 Who issues, and to whom — the map

Only list what this app actually writes or names. This console means /mo/notices. Other rows live on other desks.

Issuer Typical audience Where you see it
You (MO) on this form Every participating BRP This page; the BRP Market → Notices inbox; event notice.published
Cadence / Publish (automated) Public + each settlement party Daily / Settlement #notification-ledger; Cadence incidents if delivery failed
Daily credit-cover job (17:00, business days) The named party Accounts / Billing Credit cover · Notices; the party’s cover dashboard; events credit_cover.increase_notice / credit_cover.warning
The party (written notice) You (MO) Accounts #mo-account-notifications — they tell you an account exists
You (MO) on Participants The named party Open Default — a Default Notice
The registry write (same transaction as the change) System Operator SO Registry Inbox — a RegistrationNotice
The registry write (§7.1(6)) The other party at the meter That party’s counterparty inbox; event registry.counterparty_change
System Operator Target BRP, or every Bid Desk Not this page — V12 §3

Cadence does not publish tannoy text. It records whether a callable ran, and whether a machine event failed to arrive (§14.5).

15.5 How this page is laid out

Browser title: Notices. Header: Notices — Broadcast market notices to every participating BRP and search the month.

One card, #mo-notice-log, headed Market notices. The table is the log. New + (#mo-notices-new) opens the publish modal.

Default range: the current SAST month (first day through last day of the month on the market clock). Change From / To (#mo-notices-period, #mo-notices-from, #mo-notices-to) to another period. To cannot precede From — if you pick an end before the start, the end snaps to the start. The end date’s min is the start date.

Type chips (#mo-notices-type-filters): All, General, System stress, Price-cap event. Click a type to show only that badge; click it again or All to restore.

Read the page top to bottom: period → type chips → table → New + when you need to speak.

15.6 The table

#mo-notices-table, sticky headers, scrolls inside #mo-notices-scroll. Empty: No notices in this period. (#mo-notices-empty).

Column What it is
Type Coloured badge — General (slate), System stress (amber), Price-cap event (violet). #mo-notice-{id}-type
Date/Time SAST clock as 24 'Aug '26 10:20. Click Date/Time (#mo-notices-sort-published) to toggle oldest-first / newest-first. Default is newest first. #mo-notice-{id}-at
Notice The text that was published. #mo-notice-{id}-message

Row id: #mo-notice-{id}. There is no twenty-notice cap on this console. The period is the window.

A BRP still archives for themselves on their inbox. That does not hide a row here. Their archive is “I have filed this.” Yours is “this period.”

15.7 New + — the publish modal

New + opens #mo-notice-new-modal (Escape, the X, Cancel, or the backdrop close it). Title: New notice — Market day. phx-submit="publish_notice" on #mo-notice-new-form.

Control Id What it means
Type #mo-notice-type General (GENERAL) · System stress (SYSTEM_STRESS) · Price-cap event (PRICE_CAP_EVENT)
Notice #mo-notice-text Placeholder Publish a notice to all BRPs… — required
Submit Publish (#mo-notice-publish) Writes one row and fans it to every participating BRP
Outcome Flash
Empty text Notice text is required.
Success Market notice published to all BRPs. — modal closes; the table returns to the current month
Failure Could not publish the notice.

There is no party field. party_id on the stored row stays empty. That is a broadcast.

A PRICE_CAP_EVENT on this form is a broadcast. Party-scoped price-cap events that name one BRP are recorded on Daily’s #notification-ledger. A BRP that was not named does not receive those.

The same publish also becomes event notice.published on the public event feed (type + message, clause §9.3(3)).

15.8 Period and type — how to hunt

Need last month’s wording? Set From to that month’s first day and To to its last. Need only stress? Press System stress. Need the first announcement of the month? Sort Date/Time oldest-first.

The chips do not change the period. The period does not change the type filter until you press All or a different type.

15.9 The three types this form can send

These are the only types the Type select offers. They are the only types this console records.

Type When you would send it Who hears it What they must do If they ignore it
General (GENERAL) Any operational sentence that is not stress and not a cap Every participating BRP Read it before they change a clock, chase a variance, or assume a gate They miss why a gate moved or a band looks wrong. The bid they already lodged is unchanged
System stress (SYSTEM_STRESS) Grid or market stress you need every BRP to see in the same words Every participating BRP Treat it as context for the day They may misread a thin or volatile hour. No MWh, no curtailment, no Instructed Energy. Only an SO order does that
Price-cap event (PRICE_CAP_EVENT) A cap or floor that changes how a clearing result should be read Every participating BRP (this form) Look at the price flag and the notice together They may not understand why SMP sat on the cap. Settlement still uses the capped price

The Code also specifies a SYSTEM_STRESS notice when the System Operator misses reserve requirements by 10:00 D−1 (carry the last equivalent period, and tell people). Cadence records that miss as a row. This form is how you put the sentence on the tannoy. Cycles does not auto-write a Market Notice row today. If the reserves were carried forward and you did not broadcast, the substitution can still have been used — the honesty gap is yours.

Careful. A SYSTEM_STRESS notice here is context. It has no target MWh and creates no curtailment line. Only a System Operator instruction does that (V12 §3).

15.10 Every other notice this product issues or records

The rest of the product uses the word “notice” for several families. Each family has a home. This console only stores the three types above.

How to read the Where column. This console = /mo/notices. Daily / Settlement = the notification ledger. Cadence = event incidents. Specified = named in the Code or the event vocabulary, not issued from this form (and, where said, not yet in the feed).

A. Machine receipts — Daily and Settlement

After Publish on Daily, the chalkboard is pinned. The notification ledger (#notification-ledger on Daily; #dam-settlement-notifications on Settlement) is who was told what for that Trading Date. Oldest first. You see every row. A BRP sees public rows plus rows that name them.

Event name Who issues To whom Trigger Consequence if ignored
schedule.published Publish (automated) One public row (Day-ahead schedule published., §9.10(1)) plus one party row per settlement party (Your schedule report is published.) You pin the 14:00 noticeboard The schedule still exists. A party that never fetched it still settles against it. A failed delivery is a row, not a missing success — retry on Cadence
PRICE_CAP_EVENT (party-scoped) Ledger write that names a party_id That BRP only A cap event recorded for one party Other BRPs do not see it. The named BRP should read it with the price flag
Any other stored string NotificationLedgers.record / EventIncidents.deliver Public or the named party Invalidation, a retry, any §16(2)(f) type that was delivered or failed The Event column is the name, not a pick-list. Failed detail is on Cadence

Empty ledger: No notices have been recorded for this day. Publish has not written schedule.published, and nothing else has been recorded.

Delivery recorded (emerald) vs failed (red): §13.7. Retry: §14.5.

B. The event stream — named kinds

The Market Code requires you to publish how events travel, and what happens when they fail (§16(2)(f)). The feed is GET /api/v1/events (live stream or a JSON poll). There is no event table. Each kind is projected from a row the market already wrote.

In the feed today (projected from a persisted row):

Event Who issues To whom Trigger What the recipient should do If they ignore it
notice.published You, on this form Public feed A tannoy publish Read the type and message Same as §15.9
schedule.published Publish Public A clearing run is published Fetch their schedule They still settle; they may miss the hours until they poll
prices.published Publish Public Same instant as schedule — a second event Read SMP / reserve prices Settlement still uses the published prices
idm.cleared IDM publish Public An intra-day auction published Read the new volumes and Intra-Day Price Their contracted position may have moved without them looking
balancing.prices.published Balancing publish Public A balancing run published Read the vintage (provisional vs official) Official D+7 is what money follows
submission.rolled_over Gate / rollover callable That party They were silent; yesterday’s body was copied Check the rolled-over bid before the next gate They trade on stale volume. Staleness can escalate
registry.counterparty_change Registry write (§7.1(6)) The notified party A Point of Delivery was ADDED or REMOVED Confirm or Dispute Silence leaves the meter at pending reciprocity. Energy at that node may not reconcile
credit_cover.increase_notice Daily 17:00 cover job (or an opened cover window) That party Posted cover is short of required Post more cover or pay an outstanding invoice early, by 17:00 on the second working day Path toward default. A Default Notice can follow. Suspension is a later, gated step
credit_cover.warning Same daily job That party Headroom has fallen to the Warning Limit — they are still covered Top up or reduce exposure before it becomes a call The next business day can be an Increase Notice
invoice.issued Billing issue The recipient organisation A tax invoice (or self-billing invoice, same event name unless it is a credit note) Pay in full by EFT on the due clock — pay now, argue later Shortfall. A query does not hold the invoice
credit_note.issued Billing issue The recipient A credit note Apply it to the account The ledger still moved
document.received Billing issue The recipient Another issued document kind Open the document Same as any issued paper they did not open

Named in the vocabulary, not yet in the feed (specified; a participant waiting forever should be told these will not arrive yet):

Event Intended trigger Why it is listed
gate.closing T−30 and T−5 before a gate Specified reminder. Not projected today
gate.extended You extend a gate on Submissions The desk can show extended. The event is not in the feed yet
statement.issued Indicative or Initial statement Specified. Statements exist on Accounts / the party desk; this event name is not projected
bill.updated A bill line changed Specified; not projected
credit_call.made You draw posted cover The call is computed on the billing month. The event name is not projected
query.resolved A settlement query closes Specified; not projected

Note. The stream is a speed-up, never the system of record. If a party’s webhook drops at 09:58, they can still poll. A failed schedule.published is an incident on Cadence, not a missing chalkboard line.

C. Credit cover and money

These are not tannoy types. Accounts and the billing board show Required · Posted · Headroom · Notices.

Kind Who issues To whom Trigger What they must do If they ignore it
Credit Cover Increase Notice Daily recalculation, by 17:00 on a business day The named party Posted < Required Post additional cover, or pay an unpaid invoice early (§15.10.2(3)), by 17:00 +2 working days They can fall into default. You may then issue a Default Notice. A Suspension Order is not automatic, and cannot be solely because cover was absent in a lawful replenishment window
Warning Notice Same job The named party Headroom ≤ Warning Limit, cover still enough Treat it as the last quiet warning Next shortfall is an Increase Notice, then a possible call
Credit Call Settlement / cover engine when cover is drawn The named party (rapid means in the Code) Posted cover is called for a shortfall Re-establish cover within two business days Remaining cover falls. Further default grounds can open
Replenishment window / new-provider window You, on Accounts That party (and the enforcement engine) You open a window so cover may lawfully be absent Replenish, or appoint a new Credit Cover Provider (ten business days) When the window lapses, a cover-only Suspension Order can become lawful

A party that pays an invoice early shrinks Actual Exposure, so the requirement falls. That is a real way to satisfy an Increase Notice without new cash.

D. Accounts, default, and who may trade

Kind Who issues To whom Trigger What they must do If they ignore it
Account notice (§6.2(11)) The party You They opened a Collateral Reserve or Trading Clearing Account You Review, then Remove from the inbox once read Opening the account is not enough. Until they tell you in writing, the Code’s notice has not happened. Remove dismisses the inbox item; it does not un-notify the account. Home: §18.4
Default Notice (§6.3.1) You The named party Material default (Code, another Code, licence, MPA, Balancing Agreement, credit-cover shortfall, payment, insolvency) Remedy by the stored date — at least two business days. Do anything else you wrote on the notice After the deadline you may escalate. A Suspension Order may issue no earlier than one business day after the notice, and not solely for cover-absent-in-a-window. Home: §21.9
Party’s own default report (§6.3(3)) The party You They became aware they were in default Tell you as soon as reasonably practicable The gap between “knew” and “said” is the finding. It is recorded on the notice, not guessed
Suspension Order You, from an open Default Notice The party (then each Trading Unit) Remedy expired / you choose to order, after the floors Stop when Enforcement is in effect — not when the badge first appears They may still bid in the delay period. Once in effect, those units are out. Home: §21.10

Participants at risk on Accounts (owes / short by) is an early warning, not a Default Notice.

E. Registry notes — System Operator share

When the books change, the System Operator must be told in the same write — not as a side-effect of the public event feed. That row is a registration notice. It lands on the SO Registry Inbox. Acknowledge is a signed receipt.

Kind Trigger Who else feels it If the SO ignores the inbox
TRADING_UNIT_REGISTERED A unit finishes registration The unit exists for tomorrow’s solve. Reserve stays 0.000 until they certify No signed receipt. The unit can still be on the MO register
TRADING_UNIT_MODIFIED Standing data changed, or you Chase an IPP (#ipp-chase-{id} — Chase recorded for {tuid}.) Completeness / certification may still be open The chase is recorded; the SO still has to act
POD_ADDED / POD_REMOVED A Point of Delivery was added or taken off The other party also gets a §7.1(6) notice (below) Pairing can stall
CERTIFICATION_REQUESTED You Certify on IPPs Certified MW stays 0.000 until the SO agrees a figure They cannot truthfully offer reserve
BALANCING_GROUP_DESIGNATED / AMENDED / CANCELLED A group is named, changed, or ended Members net (or stop netting). Participants shows Notified vs overdue An uncommunicated designation is a finding against you
ZONE_CONSTRAINT_RAISED / LIFTED The SO raises or lifts a runtime zone flag Members pushing that direction drop out of a balancing group for those hours only Settlement still uses the flag. The notice is the receipt that they were told

Home for the SO inbox: V12 §3 and §22 / §23 / §24.

F. The other party at the meter

§7.1(6): when a change adds or removes a Point of Delivery, you must tell the other Party. That row is a counterparty notification.

Kind Who issues To whom What they must do If they ignore it
ADDED The registry write (MO duty) The notified party Confirm the same electrical node, or Dispute with a reason Status stays PENDING. The pairing is one-sided. It is not a settlement basis
REMOVED Same The notified party Acknowledge that the pairing is gone They may still think the node is live. Energy stops reconciling on their side

PENDING is silence. DISPUTED is “we looked and this is wrong”. Only CONFIRMED promotes the point out of pending reciprocity.

G. System Operator notices — not this page

Do not issue a tannoy SYSTEM_STRESS to obtain curtailment treatment. The SO desk issues orders that change Instructed Energy.

Kind Everyday name Audience Money / eligibility
CURTAILMENT Do not generate above this cap Target BRP Instructed Energy drops. 5 % slack off for instructed hours
DISPATCH_CONSTRAINT Stay inside these MW / ramp bounds Target BRP Yardstick is the instructed path
OUTAGE_PLANNED / OUTAGE_UNPLANNED This site is offline Target BRP Instructed Energy is the outage
RESERVE_ACTIVATION Move the reserve you were holding Target BRP Reserve settlement, not a new SMP
SYSTEM_CONDITION The grid is stressed (LOW / MEDIUM / HIGH) Every Bid Desk Banner only. No MWh

Full teaching: V12 §3.

H. Nearby things that look like notices

Thing What it actually is This console?
Clear Security Notice (#clear-day-network-notice) An on-screen alert about the network model on that run (degenerate / assumed). Not a BRP inbox item No
Network-model Acknowledge (§24) Two-month notice before a new SO model binds. You record the ack No
Silent units on Submissions They did not bid. Rollover may copy yesterday. Not a tannoy No
Invalidated units on Daily A registry change broke an accepted future bid. They think they are done. Chase them before the next gate. The exception bullet is the count. A party-scoped ledger row can be stored; this form cannot send one No
Event-delivery incidents Machine doorbell failed. Retry is not a re-publish No — Cadence
Indicative / Initial statement The month’s lines. Not this tannoy. statement.issued is specified, not yet in the feed No
Schedule report itself §9.10(2) puts settlement in the schedule. Fetching the schedule is being notified of that day’s chalkboard No

15.11 Consequences — a short list you can defend

A notice’s job is to change what the recipient does next. Money and eligibility change only when the underlying fact changes — the notice is how they were told.

If this was ignored What can happen in this market
Tannoy General / System stress / Price-cap event They trade without the context. Prices, gates, and Instructed Energy do not move because of the ignore
schedule.published (especially failed) They may not have pulled their hours. They still settle. You still have an incident to retry
submission.rolled_over They run yesterday’s volume. Wrong for a changed plant
Increase Notice Cover stays short. Default grounds open. Suspension is later and gated
Warning Notice They get no second quiet day. The next print can be a call
Default Notice Remedy clock runs out. You may escalate and, after the floors, order a suspension
Account notice (they never sent it) The account exists at the bank but the Code’s written notice to you did not
ADDED / REMOVED at a meter Pairing stays pending or disputed. That node is not a settlement basis
ZONE_CONSTRAINT_RAISED Balancing-group netting already changed for those hours. The notice was the receipt
SO CURTAILMENT (wrong desk) If they ignore an order, Instructed Energy still moved. Imbalance is priced against the cap they did not follow

Pay now, argue later still holds. A Settlement Query does not hold an invoice. A notice about a query is not a stay of payment (§8).

15.12 How to prove a BRP saw the tannoy

Publish, then open a BRP seat (trader_1@webill.net) → Market → Notices. The same text is there. That equality is the check.

Cadence’s event-delivery incidents are a different channel — machine delivery of schedule.published, retried from §14.5.

A BRP can Archive a card on their inbox. That is their filing. It does not retract your log.

Follow along. Seat: mo@webill.net. Path: Notices → type General → text Gate held to 10:15 under §9.3(3) → Publish. You should see the card on Recent. Then trader_1@webill.net → Market → Notices. Same sentence.

Careful. Do not use this page to dispatch a plant, to invalidate a bid, to call credit cover, or to start a default. Those have their own desks. This page is the sentence every BRP was supposed to hear.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

16. Metering

Path: Market Operator → Metering (/mo/metering). First item in Settlement. The icon is a queue-list.

After 14:00 the job moves here. The chalkboard is done. This desk is pairing, verification, and the D+7 vintage gate. Re-ingest and Allocate are the two jobs that turn a Network Operator batch into Actual Energy the balancing desk can price. They are the same callables Cadence and the cron fire (ingest_metering, allocate_metering). No Network Operator batch is an empty-ingest desk state, not a missing page.

Where this is taught. How a meter becomes an interval and how pairing works: V9 §14. This chapter is the inbox.

16.1 The operator’s problem

Energy was sold. Now the meters have to confess. Until every Point of Delivery is paired, and until readings are verified inside seven business days, you cannot publish official balancing prices. An empty registry that looks “100 % paired of nothing” is the most dangerous green of all.

16.2 How the page is laid out

Browser title: Metering. Header: Metering — After 14:00 the job moves to meters. Pairing, verification, and the D+7 vintage gate.

No tabs. Query param: ?date=YYYY-MM-DD (same default Trading Day as Bidding). Previous / next (#mo-metering-prev, #mo-metering-next) step that date by one day. The selected window is always 00:00 – 23:59 SAST for that Trading Day.

Block Id Job
Action bar #mo-metering-date-form Date. Previous/next (#mo-metering-prev, #mo-metering-next) sit beside the input, not inside the form. Re-ingest / Allocate on the right.
Intake banner #metering-feed-status Feed label, note, batch id when present
Last ingest / allocate #metering-last-ingest, #metering-last-allocate Outcome chips and the last run
Metering and allocation #allocation-status-board Verification, pairing, exceptions

16.3 Controls — date, ingest, allocate

Control Id What it does
Trading day #mo-metering-date Patches ?date=. Both buttons run against this day, not “today” on the wall. Previous / next step one day.
Re-ingest #reingest-metering Pull the Network Operator’s readings into the day (Cycles.ingest_metering/2). Flash Re-ingest {tag}. or Re-ingest recorded a miss ({reason}). Empty ingest is the state.
Allocate #allocate-metering Turn those readings into Actual Energy per Trading Unit (Cycles.allocate_metering/2). Flash Allocate {tag}.
Status chip Id How to read it
Feed #metering-feed-status Label + note from the desk
LAST INGEST #metering-last-ingest Stamp, or No ingest run for this day.
LAST ALLOCATE #metering-last-allocate Stamp, vintage, and how many actuals, or No allocate run for this day.
Feed label Meaning
Network Operator feed absent No production adapter; demo overlay is labelled in the spec
Empty ingest A miss / no batch — #metering-ingest-empty says Empty ingest is a desk state, not a missing page.

The two buttons are not one job with two names. Ingest collects. Allocate assigns. Pressing the wrong one, or only one, is how a day looks busy on Cadence while Balancing still has nothing to price.

Metaphor. Re-ingest is collecting the meter books from the Network Operator. Allocate is writing each kilowatt-hour twice — once for the party at the point, once (sign reversed) for the party on the other side — so someone can be billed and someone can be paid.

What Re-ingest does

Re-ingest asks: did this Trading Day receive meter readings?

The Network Operator (not you, not a BRP) owns the meters and submits the batch for points in its area. The market settles by the hour, so the job counts and records what arrived for the selected day. Cadence writes a row on #mo-cadence-ingest_metering.

Outcome What it means
ok At least one reading exists for the day. Last ingest shows accepted / rejected counts.
miss (empty_ingest) Zero readings. The desk stays on empty ingest. That is a recorded miss, not a skipped healthy day.

What it does not do: it does not pair points, it does not write Actual Energy, it does not invent meters when the feed is absent, and it does not run balancing. A green Re-ingest with Allocate still pending is an honest unfinished day.

Cron already calls the same job on a continuous / daily cadence (in the seeded month: D+1 06:00). The button is for when you cannot wait for the next bell, or when a late or corrected batch arrived after the bell had already rung.

When you should Re-ingest — and why

Situation Why you press it
Cadence #mo-cadence-ingest_metering is pending, due, or missed with empty_ingest The day never received a batch. Official balancing cannot become official on silence.
The Network Operator sent a late or replacement batch The last ingest is stale. A new count must be on the record before Allocate sees it.
Last ingest is No ingest run for this day Nobody has called the job for this date yet — cron missed it, or you are walking a day by hand.
Feed says Empty ingest and you believe a batch exists Prove it. If Re-ingest still misses, the feed really is empty; hunt the Network Operator, not Balancing.

Do not press Re-ingest because pairing is Unready or an exception names REGISTRY. That is not a missing batch; that is a missing counterparty. Re-ingest will not register a party. Fix the registry, then Allocate.

Do not press it as a substitute for Run the day. Run the day stops at publish. It never ingests.

What Allocate does

Allocate asks: who does each metered hour belong to?

It takes the day’s ingested readings, rolls them to Trading Periods, and for every hour at every Point of Delivery writes two legs (Market Code §12.3(1)):

  1. The point’s own Trading Unit, with the signed megawatt-hours.
  2. The counterparty’s Trading Unit, with the sign reversed.

The net across a unit’s points is that unit’s Actual Energy — the number Balancing subtracts from the schedule. Allocation always runs. One unpaired point must not halt the market: every other unit still gets its figure, and the broken point becomes an exception (sorted by MWh at risk on the board below). An empty ingest still produces an empty allocation and a miss, not a skipped healthy day.

Cadence writes a row on #mo-cadence-allocate_metering. Last allocate shows the vintage (PROVISIONAL / VERIFIED / REVISED) and how many actuals were written.

Vintage When it appears What it may feed
Provisional From D+1, while any reading is still an estimate Preliminary balancing, indicative statements. Never invoiced.
Verified Once every reading in force is an actual, by D+7 Official balancing prices, initial statements.
Revised After a query, dispute, or meter test A settlement rerun. The old vintage stays readable.

Official balancing refuses unverified vintage. That refusal is a Cadence row (refused), not a missing page. Allocate is how the vintage gets onto the record so Balancing can see it.

Cron already calls the same job daily and again at verification (seeded month: D+1 06:30 provisional, D+7 06:30 verified). The button is the same callable, on this day, now.

What it does not do: it does not fetch a new Network Operator batch, it does not net across a party’s Trading Units (that is a Balancing Group), and it does not add network losses (those are the Network Operator’s own purchase).

When you should Allocate — and why

Situation Why you press it
Re-ingest just ok’d, and last allocate is missing or older than last ingest Actual Energy is still yesterday’s (or nobody’s). Balancing will price the wrong meters, or none.
Cadence #mo-cadence-allocate_metering is pending / due / missed The D+1 (or D+7) bell was skipped. Preliminary or official prices cannot be honest without this row.
You paired a Point of Delivery that was Unready Ingest already had the kWh. Allocate is what writes the two legs now that both names exist.
Readings moved from estimate to actual (the D+7 verification) Vintage must move from provisional to verified. Official balancing stays disabled until this run says VERIFIED.
A revised batch landed after a query Allocate again so the new vintage is a new row, not an overwrite.

Do not Allocate before there is anything to ingest. You will get a miss (empty_ingest) and an empty board. Re-ingest first.

Do not Allocate to “clear” a registry exception. If the point still has one BRP, Allocate will raise :single_brp_at_point again. The hunt is Participants / Registry, then Allocate.

Run the day does not allocate. A green publish with allocate still pending is unfinished. Cadence will show it; this button is how you finish it.

Order, and what happens if you skip a step

The honest sequence for a day is:

  1. Network Operator batch exists (or you accept empty ingest as the state).
  2. Re-ingest — the day has readings on the record.
  3. Pairing is ready enough that Allocate can write legs (unpaired points become exceptions; they do not halt the rest).
  4. Allocate — Actual Energy exists at a vintage.
  5. Balancing can run. Official waits for verified.
If you… What you get
Skip Re-ingest, press Allocate Miss. Empty allocation. Board: No metering has been submitted for this Trading Day.
Re-ingest and stop Cadence ingest ran, allocate still pending. No Actual Energy. Balancing has nothing new.
Allocate, then a late batch arrives, and you do not Re-ingest + Allocate again Balancing prices the previous meters. Last allocate is a lie about “now”.
Only watch Daily / Publish The chalkboard can look solved while meters never arrived.

Read Last ingest and Last allocate after every press. Then read Cadence for the same two rows. Then read the allocation board.

16.4 The allocation board — how to read it

Empty (#allocation-status-empty): No metering has been submitted for this Trading Day.

Stat Id How to read it
Verification #verification-progress State PENDING / VERIFIED / OVERDUE, verify-by date, days remaining or days past (clause 12.2(2))
Not yet actual #unverified-readings Count still unverified
Interrogation failures #failed-interrogations Count
Deadline alert #deadline-risk Only when OVERDUE — This Trading Day is past its clause 12.2(2) deadline with {n} reading(s) still unverified. Official balancing prices cannot be published on it, and an estimate carried past the deadline becomes an official figure.
Pairing #registry-readiness data-ready="true|false"
Exceptions by class #exceptions-by-class Sorted by MWh at risk, not by count

Pairing sentences:

Exceptions table: Class · Clause · Owner · Points · MWh at risk. Row #mo-class-{reason}. Footnote: Sorted by megawatt-hours at risk, not by count: one unpaired point carrying 400 MWh matters more than forty carrying a tenth of one each.

Metaphor. Pairing is matching two names on a hotel register — the meter’s name and the market’s name. Verification is the night audit within seven days. Official balancing will not check out a guest whose bill is still a pencil estimate.

16.5 Worked day — 2026-07-15

Data. full_demo · seed 42 · Trading Day 2026-07-15.

Field What you should see
Verification PENDING, verify by 2026-07-22, 4 day(s) remaining
Unverified 3
Failed interrogations 1
Exception :single_brp_at_point, clause §12.3(1), owner REGISTRY, 400.000 MWh at risk
Pairing (3 points) 1 of 3 points paired · 2 unpaired

Official on Balancing stays disabled until this vintage is verified. That is the same refusal G5 already enforces.

Follow along. Path: Metering ?date=2026-07-15. Read #registry-readiness before you celebrate a quiet exceptions table. Press Re-ingest only if you mean to call the same job cron calls — a missing batch, a late batch, or no ingest row yet. Press Allocate after ingest (and after a pairing fix) so Actual Energy exists; D+7 official balancing will not run on a provisional vintage. Do not press either as a substitute for Run the day.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

17. Balancing

Path: Market Operator → Balancing (/mo/balancing). Second item in Settlement. The icon is a chart-bar.

The day-ahead and intra-day markets settled what was scheduled. This desk settles what the meters did instead. After 14:00 the chalkboard is finished; the job is stacks, two prices, and a residual that does not net to zero. Run preliminary then Run official — the same callable Cadence and the cron fire (run_balancing). Official is disabled while metering vintage is unverified — the same refusal G5’s job already enforces.

Where this is taught. Imbalance arithmetic, BPB/BPS, the against-instruction split, and the eleven payment legs: V9 §6. This chapter is the Market Operator board: what you press, when, and how to read the result.

17.1 What balancing is, and why it is required

A Trading Day sold energy at a System Marginal Price and patched it five times on the intra-day market. None of that asked the meters. By the next morning, some units over-produced, some under-consumed, some followed a System Operator instruction and some did not. The difference between Contracted Energy (the last IDM schedule, else the DAM constrained schedule) and Actual Energy (what Metering allocated) is imbalance. Someone is long. Someone is short. The market has to price that gap.

Balancing is that price, hour by hour, under Market Code §13. It is not a rewrite of yesterday’s SMP, and it is not the PPA till. Contract settlement prices delivered energy under a deal; balancing prices schedule error on the wholesale ledger. They share meters. They are not the same invoice.

Without it:

The mechanism builds two merit orders from submitted offer curves, not from what happened in real time:

Stack What it is Price it feeds
Sold What the System Operator could have bought to raise generation or cut consumption Balancing Price (Buying) — BPB
Bought The mirror, floored at Minimum Stable Generation Balancing Price (Selling) — BPS

Both prices are market-wide. You were 1.5 MWh short; you pay the price computed over the market’s shortfall that hour. Both stacks are published anonymised: an increment price is a unit’s own offer, and a named stack is every competitor’s cost curve. This desk is the view that gets screenshotted. TUIDs stay off it.

The Market Balancing Account is the residual. A positive figure is paid out to participants; a negative one is collected from them; what is left accrues to the System Operator (clause 13.3(4)). It does not net to zero the way the energy account does. Mixing this tile with Daily’s R 0.00 energy pot is how people invent a third invoice.

Prices come in two vintages because meters do. Preliminary is the pencil total the morning after, from provisional readings — what BRPs plan against. Official is ink on day seven, once readings are verified — what they are invoiced on. A dispute does not hold either up: payment first, argument after; a correction is a Settlement Rerun, not an erase.

Eleven payment legs cannot be operated from the DAM chalkboard. This is the room that produces them.

17.2 The operator’s problem

Meters arrived. Allocate wrote Actual Energy. You need a price for the gap that is not a quiet SMP, and you must not publish official prices on unverified readings. A button that inks a scorecard whose wickets are still under review would close the query window before the data exists (§12.2(2), §13.1(1)).

You also need to see when the penalty vanished. A period where the Out of Merit Energy allowance excluded the whole Sold stack settles perfectly normally and produces no penalty at all — BPB falls to the SMP. Nothing else on this screen would say so. That is the [D-07] alarm, and it is why the board exists.

17.3 How the page is laid out

Browser title: Balancing. Header: Balancing — After 14:00 the job moves to stacks. Preliminary then official, gated on verified vintage.

Query params: date (Trading Day) and stage (PRELIMINARY default, or OFFICIAL). Example: /mo/balancing?date=2026-07-15&stage=PRELIMINARY. Previous / next (#mo-balancing-prev, #mo-balancing-next) step the date by one day and keep the selected stage.

The stage switch and the run buttons are not the same control. Preliminary / Official shows which published run you are reading. Run preliminary / Run official compute that run.

Block Id Job
Trading-day card #mo-balancing-date-form Date. Previous/next sit beside the input, not inside the form. Stage switch and the two run buttons. Last-run cards on the right.
Vintage gate #official-vintage-gate Why Run official is disabled (when it is)
Balancing mechanism #balancing-board Date badge, status badges, alarm/metric counts, 24 hour buttons, day-level MBA
Hour drawer #balancing-hour-drawer One hour: SMP / BPB / BPS, volumes, Sold / Bought stacks
Reserve performance-factor inbox #reserve-performance-inbox SO [S11] judgements; default 1.0

17.4 Controls — date, stage, last run

Control Id What it does
Trading day #mo-balancing-date Patches ?date=. Both run buttons fire against this day, not “today” on the wall. Previous / next step one day and keep stage.
Preliminary #balancing-stage-preliminary Patches stage=PRELIMINARY — shows the preliminary publication for that day
Official #balancing-stage-official Patches stage=OFFICIAL — shows the official publication, if one exists
Run preliminary #run-preliminary-balancing Computes and publishes a preliminary run (see §17.5)
Run official #run-official-balancing Computes and publishes an official run — disabled when @desk.official_disabled? (see §17.6)

Last-run cards: #balancing-last-preliminary, #balancing-last-official. Outcome as a lowercase chip with a colour dot (emerald ok, amber miss, rose error / refused). Clock is SAST HH:MM:SS. Empty: No preliminary run for this day. / No official run for this day.

The cards answer did this button already fire for this date? They do not select the stage. A day can have an ok preliminary and a refused official at the same time — Cadence will show the official row as ran with outcome refused. Emerald on Cadence is not “official is out”.

Metaphor. The stage switch is which scorecard you are holding. Run preliminary is the pencil total at close of play. Run official is ink. You do not ink a scorecard whose wickets are still under review.

17.5 Run preliminary

Run preliminary asks: given the meters we have today, what would §13 charge for this Trading Day?

It calls Cycles.run_balancing/3 with vintage PROVISIONAL and status PRELIMINARY. The engine builds both stacks, both prices, the market-wide imbalance volumes, and the Market Balancing Account, then records a publication the board can show. Flash: Preliminary balancing {tag}. Cadence writes #mo-cadence-run_balancing-d{1..6} with callable vintage PROVISIONAL.

What it does not do: it does not ingest meters, it does not allocate Actual Energy, it does not verify vintage, and it does not invoice anyone. A green preliminary with Allocate still pending is an honest unfinished day — the prices are a sketch over whatever AE exists.

Cron already calls the same job at 17:00 SAST on D+1 through D+6 (Market Code: a preliminary figure by 17:00 the day after the Trading Day). The button is for when you cannot wait for the next bell, or when the inputs moved after the bell had already rung.

When you should Run preliminary — and why

Situation Why you press it
Cadence #mo-cadence-run_balancing-d1 (or d2…d6) is pending, due, or missed The timetable expected a sketch and did not get one. BRPs have nothing to plan against.
You just Allocated (or Re-ingested then Allocated) Last night’s sketch is stale. The new Actual Energy must be priced before anyone trusts the board.
Last preliminary is No preliminary run for this day Nobody has called the job for this date yet — cron missed it, or you are walking a day by hand.
You are inspecting a teaching hour or a dispute before 17:00 The drawer is empty until a run exists. Preliminary is the legal way to fill it on unverified meters.
A late meter batch changed AE on a day that already had a sketch Re-run so the stacks and MBA match the meters now in force. The old preliminary stays readable as history; the latest fill the board.

Do not press Run preliminary because Run official is disabled. That is a vintage problem, not a missing sketch. Hunt Metering — Allocate until vintage is VERIFIED — then official.

Do not press it as a substitute for Run the day. Run the day stops at publish. It never balances.

Do not press it to “fix” an unpaired meter. Balancing prices the Actual Energy Allocate wrote. An unpaired point is an exception on Metering, not a missing stack rung.

17.6 Run official

Run official asks: are the meters verified, and if so, what does §13 charge for the invoice?

It calls Cycles.run_balancing/3 with status OFFICIAL. Vintage is VERIFIED when Metering says so, otherwise PROVISIONAL — and the engine refuses that combination. The refusal is the row (official_artefact_requires_verified_metering, clauses §12.2(2) and §13.1(1)). Flash on refuse: Official refused — {reason}. The same refusal G5’s job already enforces. Flash on success: Official balancing {tag}.

Cadence’s D+7 row is #mo-cadence-run_balancing-d7 with vintage VERIFIED. Official refused is still ran. The button is disabled (#run-official-balancing[disabled]) while @desk.official_disabled? — while vintage is unverified. When it is disabled, #official-vintage-gate says:

Official balancing is gated on verified vintage. The same refusal G5’s job already enforces (§12.2(2), §13.1(1)). A button that publishes unverified prices would close the query window before the data exists.

Cron already calls the same job at 17:00 SAST on D+7. Clause 12.2(2) wants verified data within seven days of the Trading Day; clause 13.1(1) builds official balancing prices on it. The button is for when D+7 has arrived, Allocate has moved vintage to VERIFIED, and you cannot wait for 17:00 — or the bell ran and refused, and you are retrying after fixing Metering.

The one exception is administered settlement (clause 15.11.2): a declared state that permits an official artefact from estimated data because the alternative is not settling at all. It is not a fallback this button invents. When an official run is administered, the board adds Administered settlement — clause 15.11.2. (instruction log not verified). The declaration itself is on Bidding → Month, not here.

When you should Run official — and why

Situation Why you press it
Cadence #mo-cadence-run_balancing-d7 is due or missed, and Metering vintage is VERIFIED The invoice clock arrived. Preliminary is no longer the figure money follows.
Cadence D+7 ran with outcome refused The bell tried. Vintage was still provisional. Allocate (D+7 verification), then press here so the refusal is not the last word.
Last official is No official run for this day, vintage is verified, and it is D+7 or later The sketch exists; ink does not. Statements and invoices will follow the official publication, not the pencil.
A revised meter batch landed after official was already out That is a Settlement Rerun, not a silent overwrite. The old official stays readable. Do not expect this button to erase it.

Do not press Run official to hurry verification. The button cannot turn estimates into actuals. If it is disabled, the gate copy is the finding — go to Metering, Re-ingest / Allocate until the last-allocate chip says VERIFIED.

Do not press it on D+1 because the preliminary numbers look final. They are not. Official on unverified meters would close queries before the Data Verification Period exists.

Do not press it as a substitute for Run the month. Official balancing is a Trading Day artefact. Statements, invoices and cover are a Billing Period job on Cadence.

17.7 The balancing board — how to read a day

Empty (#balancing-board-empty): No balancing run has been produced for this Trading Day. Press Run preliminary (or wait for D+1 17:00) before hunting a missing hour.

Header: date badge #balancing-board-date as YYYY/MM/DD. Status badges (#balancing-board-stage) for the selected stage and vintage — no number, not clickable. They describe the publication you are looking at, not the last-run cards.

Badge Id Colour What it shows
Stage #balancing-badge-status slate Selected PRELIMINARY / OFFICIAL
Vintage #balancing-badge-vintage amber provisional / emerald verified Selected PROVISIONAL / VERIFIED
Alarms #balancing-badge-alarms rose Count of [D-07] and other integrity events — click the number
Metrics #balancing-badge-metrics amber Count of warning metrics — click the number

Alarms and metrics (when present) are titled count badges. Click #balancing-badge-{kind}-count to open #balancing-badge-modal (unique badges, branded header). [D-07] is on Alarms: the balancing penalty does not exist — Out of Merit Energy excluded the whole Sold stack, so BPB fell to the SMP.

Administered official still adds Administered settlement — clause 15.11.2.

Hours (#balancing-hours): two equal rows of twelve (#balancing-hours-row-0 = 00:00–11:00, #balancing-hours-row-1 = 12:00–23:00). Button #board-period-{HHMM}. Daylight hours (07:00–17:00) are sky with a sun; night hours are dark slate with a moon. The selected hour is sky with a ring. Click opens the right-hand drawer — not a per-hour MBA card. Day-level MBA stays below the grid.

Market Balancing Account (#market-balancing-account) does not net to zero. Net Settlement is the day’s total_r. Footnote: Clause 13.3(4). A positive figure is paid out to participants and a negative one collected from them; the residual accrues to the System Operator and does not net to zero the way the energy account does.

D-10 sits on #board-unpriced: {mwh} of deviation across the day is unpriced (D-10). or No unpriced deviation (D-10). That is the gap the Code does not price (instruction vs contract vs delivery). It is reported, not invented into a twelfth leg.

17.8 The hour drawer

Click an hour. #balancing-hour-drawer opens from the right.

Branded header (#balancing-hour-drawer-header): the hour, SMP / BPB / BPS (#board-prices-{HHMM}), and imbalance volumes (#board-volumes-{HHMM}) — Bought and Sold megawatt-hours across how many Trading Units (clause 13.2). Close (#balancing-hour-drawer-close) or Escape-equivalent via the control; changing date or stage also clears the drawer.

Two tabs — Sold stack (#balancing-stack-tab-sold) and Bought stack (#balancing-stack-tab-bought). Both tables stay in the document (one hidden) so a screenshot of either side still has no TUID. Stacks: #stack-sold-{HHMM}, #stack-bought-{HHMM}. Caption: Sold stack — anonymised (clause 13.1).

Price and Volume headers (#stack-{sold,bought}-sort-price, -volume) are sortable. First click is ascending, second is descending; opening a new hour restores merit order. Column headers are sticky while the rungs scroll. The two columns sit on the left.

Degenerate copy lives in the drawer (#board-degenerate-{HHMM}): the indicative price is undefined and the clause 13.7(4) floor is the whole answer.

Stacks never show a TUID. Screenshot-safe by construction. The per-unit decomposition lives in the run, one query away, for the person who actually needs it.

17.9 Reserve performance-factor inbox

#reserve-performance-inbox — read-only. The System Operator’s performance-adjustment judgement ([S11]). The factor is consumed as a plain input at whatever grain arrives. It is never interpolated and never derived. The desk cannot type a factor the System Operator did not send.

Absent criteria show as an amber notice (1 Notice / Default applied). There is no clause-modal button.

State Copy
Absent criteria #reserve-performance-absent — Factor 1.0 — absent criteria (clause 9.8.3(2)). Every contracted resource is deemed to have performed acceptably. The counterfactual “would have performed” cannot be derived.
Filed #reserve-performance-judgements — Grain · Factor · Source · Note

Never MO-authored. If the factor looks wrong, hunt the System Operator, not a missing field on this page.

17.10 Worked hour — 2026-07-15 18:00

Data. full_demo · seed 42 · §10.5 teaching hour (component fixture). A live demo day may already show last-run ok and a verified vintage; the empty last-run copy is for a date nobody has called.

Field Value
Imbalance Energy Bought 3.734 MWh
Sold 3.000 MWh
SMP / BPB (degenerate hour) R 900.00 / MWh
Sold stack rungs (anonymised) R 900, R 2,600, R 4,800 / MWh
Market Balancing Account R 8,550.00
Unpriced deviation (D-10) 1.234 MWh
Reserve factor 1.0 absent

A tight hour (§10.6) with 20 MW Out-of-Merit: BPB R 2,600.00 / MWh, no D-07 alarm.

Follow along. Path: Balancing ?date=2026-07-15&stage=PRELIMINARY. Confirm the stage switch is Preliminary and the board badge says PRELIMINARY. If #run-official-balancing is disabled, read #official-vintage-gate and open Metering — that is the finding, not a broken button. Click 18:00: drawer with SMP / BPB / BPS, Sold stack prices and MW, no TU-. Sort Price / Volume; headers stay put. Click the Alarms number for [D-07]. Previous / next keep the stage. Switch Official only to read an official publication — press Run official only when vintage is verified and you mean to ink the day.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

18. Accounts

Path: Market Operator → Accounts (/mo/accounts). Third item in Settlement. The icon is banknotes.

This is the till. Bidding wrote tickets. Metering said what happened. Balancing priced the gap. Someone now has to hold the cash, match the ledger to the bank, collect from the short, pay the long, and notice who cannot pay — without dipping into the Market Operator’s own fee to paper over a default.

The auctions do not move rands. A participant who bought energy does not pay the seller. They pay you. You pay the seller. That is the whole job of this desk: three bank accounts in the Market Operator’s name, and the month’s story of who paid, who is owed, and who is short.

Where this is taught. Which money is whose, and why MO Charge is ring-fenced: V9 §3.16 · V9 §15. This chapter is the operator’s board: what you read, in which order, and what each number is for.

Follow along. Seat: mo@webill.net with password supersecret. Path: / → Market Operator → Accounts. You land on Billing Period Settlement.

18.1 What Accounts are for

Wholesale electricity is cleared through a central counterparty. Every invoice and every payment goes through the Market Operator. If Buyer A owes Seller B, A does not send B a transfer. A pays the market. The market pays B. That way a default is your problem to contain, not a private argument between two participants.

To do that work the Code gives you three pots at one bank — the Market Bank — all in your name:

Pot Everyday name What it is for
Trading Clearing The coffee tin Energy and imbalance money in and out this month
Collateral Reserve (the Central Reserve tab) The rental deposit Posted credit cover you may draw if someone does not pay
MO Charge The shop’s own till Your fee. Walled off. Never used to plug a hole

They look like one account with three labels. They are not. Mixing them is how an operator accidentally underwrites the market with its own income.

Coffee-tin metaphor. Everyone who owes for coffee drops money in; the person who bought the beans takes money out. The tin is one tin. Whose money is whose is a list stuck to the lid — a designation — not a separate tin per participant. The deposit jar on the shelf is not the coffee tin. The shopkeeper’s own till is not either of those.

Three pots, three jobs — do not add them together
Market Bank · MO name
Trading Clearingenergy · imbalance · on trust
Collateral Reserveposted cover · locked
MO Chargeyour fee · ring-fenced

Without this desk you would discover a shortfall from the complaint, a broken ledger from the auditor, and an Excess Participant from the creditor who was asked to send money back. The board exists so those facts are visible before anyone phones you.

18.2 How the desk informs the operator

Read left to right, then down. The questions are in a fixed order because later numbers are meaningless if an earlier one is wrong.

  1. Does the ledger match the bank? If a money event wrote one layer and not the other, every figure below is scenery. That is the green or red reconciliation banner.
  2. Did this month collect what it billed? Expected in, received, the gap, owed out, paid out, still to pay. That is cash position. It tells you whether a cascade is coming.
  3. Who cannot pay, while there is still time? Participants whose own balance is short of their invoices, before the due date. That is at risk — an early warning, not a Default Notice.
  4. Has the month been invoiced? Four pots on the billing board: statements, invoices, self-billing invoices, shortfalls.
  5. Is anyone’s cover thin? Required versus posted, market-wide on the billing board; party operations on Credit/Debit.
  6. If someone did not pay, who takes the haircut? Debit notes on Credit/Debit. MO Charge is never in that arithmetic.

What you do not do here: rewrite yesterday’s SMP, pair a meter, or hold an invoice because someone raised a query. Payment first, argument after (V9 §15.2). The PDFs live on Billing. The query lifecycle lives on Dispute.

Run the month is not on this page. It lives on Cadence (#mo-run-the-month). This desk shows the result.

18.3 How the page is laid out

Browser title: Accounts. Header: Accounts — Billing-period cash, the three market accounts, deposits, and the movement audit.

Seven icon tabs (#mo-accounts-tabs), same pattern as Bidding (bordered tabs, heroicon, label). Default is Billing Period Settlement. Query params: ?tab=, ?month= (ledger YYYY-MM), and ?settle= (Billing Period YYYY-MM). Ledger tabs default to the current calendar month; their month picker loads a previous one. Billing Period Settlement defaults to the previous calendar month (Load.default_settle_month/0) — the same month as Bidding → Month — and its own picker (#mo-billing-month) opens an earlier period.

Tab Id What it answers
Billing Period Settlement #mo-accounts-tab-billing Did this month get paid? Calendar, cash, notices, the billing board
Trading Clearing #mo-accounts-tab-trading_clearing The energy pot — balance and every movement this month
Central Reserve #mo-accounts-tab-central_reserve Posted cover — balance and every movement this month
MO Charge #mo-accounts-tab-mo_charge Your fee pot, the monthly tariff, and its ledger
Recent Deposits #mo-accounts-tab-deposits Collateral that arrived into Central Reserve this month
Movement Audit #mo-accounts-tab-movement Every money event, filterable, across the three pots
Credit/Debit #mo-accounts-tab-credit_debit Cover operations, the debit-note cascade, replenishment windows

Empty market (#mo-accounts-empty): No market accounts have been opened yet. / The Trading Clearing, Collateral Reserve and MO Charge accounts appear here once the money layer is in use.

18.4 Billing Period Settlement

This is the month-end room. Come here after Cadence has run the month. The tab does not hold the three ledgers — those have their own tabs — it holds the story of the Billing Period: did we collect, did we pay, who is short, which documents went out, and which clocks are gazetted.

Billing period (#mo-billing-month) sits at the left of the action bar. It is a month picker, labelled Billing period, same control as Bidding → Month. Changing it reloads cash position and the billing board for that month. A period Cadence has not run shows No Billing Period has been settled. The choice is kept in ?settle= when you move to another tab, so Credit/Debit shows the same month’s cascade.

The three action buttons

#mo-accounts-billing-actions is the top row: picker on the left, three buttons on the right. The buttons used to be cards stacked under the board; they are now doors into modals so the board can stay the month’s scorecard.

Button Id Opens What it is for
NERSA Publish #mo-accounts-nersa-publish #mo-calendar-modal Write the clause 15.3.3 clocks for a year
Download NERSA Pack #mo-accounts-nersa-pack #mo-nersa-pack-modal The Market Operator half of the regulator pack
Administered Settlement #mo-accounts-administered #administered-modal Switch off the ordinary pipeline, with MGC approval

Close any modal with #…-close-x, the backdrop, or Escape.

NERSA Publish (#mo-settlement-calendar inside the modal). The Code requires the settlement calendar four months before the year starts. Year (#calendar-year) + Publish (#calendar-publish) writes the dates. Once published: Published for {year} (#calendar-published). Under the form, #board-calendar lists the gazetted clocks for the open Billing Period (SAST, clause 15.3.3):

Row id Clock In ordinary English
#calendar-initial-statement initial-statement When the month’s Initial Settlement Statement is due out
#calendar-invoice-due invoice-due When participants must have paid their invoices (12:00, three business days)
#calendar-self-billing-due self-billing-due When you must have paid the longs (17:00, four business days)
#calendar-timetabled-rerun timetabled-rerun The scheduled Settlement Rerun for the month

You pay in four business days; they pay in three. That lag is deliberate: you have to have collected before you can distribute.

Download NERSA Pack (#mo-nersa-pack). Copy on the card is the honest split: The System Operator report side is not mounted. This is the Market Operator half. Download curtailment-with-cost (#nersa-pack-download) → /mo/nersa/curtailment-cost.csv?trading_date={month}.

Administered Settlement (#board-administered). Ordinary mode (#administered-off): badge normal — the pipeline Cadence already ran. Switching requires the Market Governance Committee’s prior written approval (clause 15.11.1(d)). The switch will not act without both fields:

Field Id What you type
MGC approval reference #administered-approval-ref The Committee’s written reference. Empty refuses
Methodology #administered-methodology-text The published methodology (clause 15.11.1(e)). Empty refuses
Switch to administered #administered-switch Throws the switch

Once on (#administered-on): mode badge, trigger, clause, the stored approval (#administered-approval), and when the methodology was published (#administered-methodology). This is not a calendar publish, and it is not “make the numbers nicer”. It is the Code’s escape hatch when the ordinary pipeline cannot be used.

Reconciliation banner

#mo-accounts-reconciliation sits above cash. Read it first. A cash position computed from a ledger that does not match the bank is a number with no meaning.

State Copy Colour
Reconciled Reconciled — every account’s balance equals the designations inside it. Green
Not reconciled Not reconciled. A money event has written one layer and not the other; the figures below cannot be relied on until it is found. Red

When it is out, the banner lists each unbalanced pot: {label}: bank {R} against {R} designated — {R} out, and how many bank transactions have no matching entry on the other side. If this banner is red, stop. Find the unpaired write. Do not pay, draw cover, or explain the cash tiles to anyone until it is green.

The same banner repeats above each of the three ledger tabs. It is the same fact, not a second reconciliation.

Cash position

#mo-accounts-cash-position — Cash position — {Month Year}. The month is the Billing Period on #mo-billing-month, not the ledger month. This is the period’s two-way till tape: what you asked for, what arrived, what you must pay, what you have paid.

Empty: No invoices raised for this period yet. After invoices exist, six rows:

Row What it means How to use it
Expected in from participants The sum of invoices you raised The ask
Received What has actually arrived in Trading Clearing The take
Shortfall Expected − received. Bold rose when greater than zero Someone has not paid. This is the hole
Owed out to participants Self-billing invoices you must pay The promise
Paid out What you have already paid The keep
Still to pay Owed − paid What is left to send on +4BD

A cascade is needed (#mo-accounts-cascade-needed) appears in amber when collected is less than owed and money is still to pay out. The copy tells you the next act: draw the defaulters’ posted cover first; whatever remains comes off the creditors pro rata (§15.3.4). The MO Charge Account is not available for this. That sentence is the whole point of ring-fencing.

Cash position, in the order you collect then pay
1Expected inthe invoices
→
2Receivedwhat arrived
→
3Owed outthe self-bills
→
4Paid out+4 business days

Participants short of what they owe

#mo-accounts-at-risk only renders when someone is short. It is visible before the due date, which is the only time it is useful — after due date the shortfall is already a fact.

Column What it is
Party The BRP code
Owes Outstanding invoices
Own balance What sits in their own bank account, not in posted cover
Short by Owes − own balance, in rose
Cover posted Credit cover already in Central Reserve — the next place you draw

This is not a Default Notice and not a Suspension Order. It is the list of people you may need to call. Row id: #mo-at-risk-{party_id}.

Account notices

#mo-account-notifications. Clause 6.2(11) requires a written notice that a Collateral Reserve Account or Trading Clearing Account has been established. Opening the account is not enough. Until they tell you in writing, the Code’s notice has not happened.

The heading carries a count (#mo-account-notifications-count). Empty: No outstanding account notices (#mo-account-notifications-empty).

Each row (#mo-account-notification-{id}):

You see What it is
Subject The notice title
BRP · notified {date time} Who, and when the written notice landed
Review Opens the body of the form
Remove Clears it from the inbox once it is registered. It does not un-notify the account

Home for the notice kind: §15.

The billing board

#billing-board. Same component as Bidding → Month. Empty (#billing-board-empty): No Billing Period has been settled. Press Run the month on Cadence, then come back.

Title: Billing Period settlement. Footer: ledger clearing mode (Official balancing or Timetabled exact) and SAST (+02:00).

On this tab the board hides the calendar, the cascade, and the administered switch — those live in the buttons and on Credit/Debit. What remains is the month’s count.

Runs (#board-runs) — four coloured pots:

Pot Id Colour Number Subtitle Click
Statements #run-statements Sky How many settlement statements were issued {n} issued Display only
Invoices #run-invoices Indigo Tax invoices on the billing register for the month due 12:00 +3BD Opens /mo/billing?month={YYYY-MM}&tab=invoices
Self-billing invoices #run-self-billing Emerald Self-billing invoices on the register paid 17:00 +4BD Opens /mo/billing?month={YYYY-MM}&tab=remittances
Shortfalls #run-shortfalls Amber; rose if any How many invoices were not paid in full {n} credit call(s) Display only

An invoice is a bill to a participant (they pay the market). A self-billing invoice is a bill the market writes to itself, on the participant’s behalf (the market pays them). You do not wait for sellers to invoice you. How those tax documents are raised: V15 §14. The register that lists them: §19. Empty register means the month has not been invoiced yet.

Credit cover, market-wide (#board-credit-cover) — a snapshot, not the operations desk. Party-level calls live on Credit/Debit.

Column What it is
Participant Party id
Required Cover the daily job says they must hold
Posted What is actually in Central Reserve
Headroom Posted − required. Red if negative
Notices Warning and/or Increase Notice kinds outstanding

Queries and disputes (#board-query-inbox) — only when the inbox has rows. This is a clock, not the Dispute room.

Column What it is
Tier Data Query, Settlement Query, or Settlement Dispute
Participant Who raised it
Raised When
Deadline Effective deadline (or the MO deadline)
Escalates to What happens if they miss it

Pay now, argue later. A query does not pause an invoice.

18.5 Trading Clearing

The energy and imbalance pot. Everyone who owes the market pays in; everyone the market owes is paid out. The money is held on trust — it is theirs, you control the movements, you may not mix it with MO Charge (V9 §3.16).

Come here to see the running balance and the month’s tape. The reconciliation banner is above the card; if it is red, the balance below is not to be trusted.

The account card

#mo-account-TRADING_CLEARING.

You see What it is
Label Trading Clearing Account
Large figure Bank balance — what the Market Bank says is in the pot
designated {R} Sum of labels inside the pot. A green tick if it equals the bank balance; a rose cross if it does not
participants’ own positions {R} Only if this differs from designated. The gap is cascade write-offs, which move no money

There is no designation list under the total. The tape below is the detail.

Transactions

#mo-account-TRADING_CLEARING-statement. Every movement on this Market Bank account for the selected month.

Control Id What it does
Month #mo-ledger-month-TRADING_CLEARING Loads that calendar month. Shared with the other ledger tabs
Search #mo-ledger-search-TRADING_CLEARING Organisation name or BRP, 300 ms debounce

Empty: No transactions on this account for {Month Year}.

Column What it is
Date Value date as 10 'Aug '26. Sticky. Sortable (#mo-TRADING_CLEARING-sort-date) — click toggles newest-first / oldest-first
BRP BRP code on top, organisation underneath. If the identifier is a Trading Unit, the TUID is on top instead. A dash if the row has no party (rare)
What Happened Human label (see below) and a one-line narrative
Amount Signed rands. Inflows +R … in green; outflows −R …
Balance Running balance on this pot after the row

Rows highlight on hover. Date is sticky as you scroll sideways. The same table shape is on Central Reserve and MO Charge — only the pot changes.

What Happened labels you will see:

Label on the tape In ordinary English
Opening balance The pot at the start of the month
Market invoice paid A participant paid an invoice into Trading Clearing
Market payment received You paid a self-billing invoice out
Credit cover posted Cover arriving — usually on Central Reserve, not here
Credit cover drawn You pulled posted cover into Trading Clearing to fund a shortfall
Credit cover released Cover going back to the participant
Interest Interest earned on their money, credited to them
Market Operator charge A fee movement — usually on MO Charge
Debit-note reversal A cascade haircut being put back after a late payment
Shortfall recovered A late payment filling a hole
Set-off against amounts owed The MO’s set-off right against a defaulter

Interest and other non-EFT rows still name the BRP and organisation. The tape is the legal story, not only the bank’s EFT list.

18.6 Central Reserve

The locked jar. This tab is the Collateral Reserve Account (#mo-account-COLLATERAL_RESERVE) — posted credit cover. Participants cannot withdraw it on request. You may draw it if they default. Interest on it is still theirs.

Rental-deposit metaphor. The landlord holds the deposit in their name. You cannot ask for it back to pay the grocer. If you skip the rent, the landlord may apply it. That is this pot.

The card and the Transactions table are the same shape as Trading Clearing (#mo-account-COLLATERAL_RESERVE-statement, month #mo-ledger-month-COLLATERAL_RESERVE, search #mo-ledger-search-COLLATERAL_RESERVE, date sort #mo-COLLATERAL_RESERVE-sort-date). Typical rows here are Credit cover posted, Credit cover drawn, Credit cover released, and Interest.

A draw is your act, not theirs: cover leaves this pot and lands in Trading Clearing to fund their unpaid invoice. After that, if a hole remains, it is Unsecured Bad Debt — and that is the cascade on Credit/Debit.

18.7 MO Charge

Your fee pot. Ring-fenced — walled off from every shortfall, every cascade, every “just this once”. The card says so in amber: Ring-fenced — never applied to a shortfall.

Shop-till metaphor. Customers’ layby money is in one drawer. The shop’s own takings are in another. When a customer vanishes, you do not make the other customers whole from the takings drawer. That is this tab.

#mo-account-MO_CHARGE repeats the balance / designated / tick-or-cross pattern, then a Monthly tariff block (#mo-charge-tariff).

You see What it is
Tariff copy Each organisation is billed R {amount} a month. {n} issued this month, {n} paid.
No tariff yet No monthly tariff yet. Set the amount charged to every organisation. Demo: R 5,000 / month
Set Monthly Charge #mo-charge-tariff-open — opens the modal
Issue this month’s invoices #mo-charge-tariff-issue — only if a tariff is already set

The modal (#mo-charge-tariff-modal):

Control Id What it does
Amount in Rands #mo-charge-tariff-amount Number, minimum 0.01
Save and charge this month #mo-charge-tariff-save Sets the monthly tariff and issues this month
Close #mo-charge-tariff-modal backdrop / Escape Leaves the tariff unchanged

Transactions (#mo-account-MO_CHARGE-statement) are the same five columns. Typical What Happened: Market Operator charge. Month and search ids follow the same MO_CHARGE suffix.

18.8 Recent Deposits

Collateral arriving into Central Reserve, for the selected month only. This is not the full Central Reserve tape — it is the inflows of cover, so you can see who posted what without reading every interest line.

#mo-recent-deposits. Heading includes the count. Month picker #mo-deposits-month. Empty: No collateral deposits yet.

Column What it is
Date When the cover landed (10 'Aug '26)
BRP BRP on top, organisation underneath
Designation The label inside Collateral Reserve this money sits under ({BRP}/COLLATERAL_RESERVE)
Amount Always an inflow, shown +R … in green

Row id: #mo-deposit-{id}.

18.9 Movement Audit

The combined tape. Trading Clearing, Central Reserve, and MO Charge each tell one pot’s story. This tab tells every money event in the month, so you can answer “what moved for this BRP?” without hopping pots.

#mo-movement-audit. Month picker #mo-movement-month (same shared ledger month as the other tabs). Empty: No movements match. (#mo-movement-audit-empty).

Filters (#mo-movement-filter) apply together:

Filter Id What it matches
Party #movement-party BRP, organisation name, or trading unit. Search, 300 ms debounce
Kind select#movement-kind Which pot or source. Prompt All kinds
Reason select#movement-reason Why the money moved. Prompt All reasons

Kind options: Trading Clearing, Collateral Reserve, MO Charge, Market invoice, Credit cover call, Cascade, EFT payment, Interest run, Manual.

Reason options: Opening balance, Market invoice paid, Market payment received, Credit cover posted / drawn / released, Interest, Cascade reduction, Debit-note reversal, Market Operator charge, Shortfall recovered, Set-off against amounts owed.

Column What it is
Date Value date (10 'Aug '26)
Party BRP or Trading Unit on top, organisation underneath
Kind Source kind, or the account kind if source is blank
Reason Why it moved
Amount Rands

Cells are centred. Row id: #movement-{id}. Default order is newest date first.

18.10 Credit/Debit

Last tab (#mo-accounts-tab-credit_debit). This is the bad-news room: who must post more cover, who takes a haircut when someone does not pay, and the dated grace in which a party may lawfully be short of cover.

The billing board on the first tab still shows a market-wide cover snapshot. Operations — the call, the cascade, the window — live here. The cascade follows ?settle=, the same Billing Period as the first tab’s picker.

Credit Cover Operations

#mo-credit-cover-ops. Cover is the bond you hold so that if a participant does not pay, there is something to draw before you touch creditors. It is assessed every business day by 17:00.

Warning Limit is the yellow line on a fuel gauge. Below it, a Warning Notice. Below required, a Credit Cover Increase Notice — post more cover, or pay an unpaid invoice early (that shrinks actual exposure) by 17:00 on the second working day (clause 15.10.2(3)).

Column What it is
Party Name / MPID
Required What the daily job says they must hold
Posted What is in Central Reserve
Warning The Warning Limit in rands
Notices Outstanding kinds. An Increase Notice also spells out how to satisfy it (#cover-satisfy-{party_id})

Row id: #cover-ops-{party_id}.

Instruments (#mo-cover-instruments):

Instrument State
Cash Enabled
Letter of credit (#mo-cover-lc-disabled) Disabled — [S28]

Cash only. A letter of credit is specified; it is not mounted.

Debit-note cascade

#mo-debit-note-cascade. When an invoice is not paid, you draw that party’s posted cover first. Whatever is still unpaid is Unsecured Bad Debt. The Code does not leave that hole sitting until next month, and it does not take it out of MO Charge. It takes it off the people the market was about to pay.

Haircut metaphor. Ten creditors were due R 1,000,000 in total. One debtor left a R 100,000 hole after cover was drawn. Each creditor’s self-billing invoice is reduced by their share of R 100,000, in proportion to what they were paid this month. They still get paid — just less. That reduction is a debit note.

If no Billing Period has been settled: No Billing Period has been settled (#board-cascade-empty). After a run with nothing unpaid: No Unsecured Bad Debt this Billing Period (#cascade-none).

When there is a hole (#board-cascade, #cascade-total): {R} of Unsecured Bad Debt, allocated on total payments in the month (clause 15.7); recovered {R}.

Column (#cascade-notes) What it is
Participant Who takes the haircut
Debit note Their share of the hole
Net receipt What they still receive this period (self-billing minus debit)

Excess Participants (#cascade-excess) is the phone call. Their debit note is larger than the self-billing invoice it was meant to come off. They receive nothing this period and must pay the balance in cash within two business days. Copy: {party} owes {R} in cash within {n} business days ({clause}). An Excess Participant is a creditor being asked to send money back. A total would hide them.

Over-recovery (#cascade-over-recovery), if the arithmetic overshoots: Over-recovery of {R} plus the stored note.

Replenishment Window

#mo-replenishment-window. A dated grace in which a party may lawfully have too little cover while they top it up. Clause 6.4(4) bars a Suspension Order solely because cover was missing during this window. The window is the defence; the form is how you record it.

The Code does not set how long the window lasts. That period comes from clause 15.10 and the Market Governance Committee. The form will not invent a close date.

Open a replenishment window (#mo-open-replenishment-window):

Field Id What you supply
Party id #cover-window-party The party
Opened-on #cover-window-opened-on Start date
Closes-on #cover-window-closes-on Required. Empty is refused (#mo-cover-window-error)
Open window #cover-window-open Writes the record

The card foot: {n} window(s) on record. There is no window table on this screen — the count is the audit that a later cover-only suspension can be shown to have been unlawful.

18.11 Worked month — July 2026

Data. full_demo · seed 42 · Billing Period 2026-07 · §10.7 golden month.

MP-ZETA does not pay. Cover does not cover the hole. The remainder is Unsecured Bad Debt and is taken off the creditors. MO Charge is not touched.

July 2026 cascade — MP-ZETA defaults; someone has to make the cash call
Participant Statement net Paid Cascade
MP-ALPHA R 600,000 R 600,000 Debit R 250,000 · net R 350,000
MP-BETA R 300,000 R 300,000 Debit R 150,000 · net R 150,000
MP-GAMMA R 60,000 R 60,000 Excess: owes R 40,000 in 2 BD
MP-ZETA − R 500,000 R 0 Starts the cascade
Unsecured bad debt R 500,000

Initial statement example: 07 Aug 2026, 12:00. Debits 250 + 150 + 100 = 500. GAMMA’s R 100,000 debit eats the whole R 60,000 self-bill and leaves R 40,000 to pay in cash. MO Charge is not available to plug the hole.

Conservation: ALPHA 250 + BETA 150 + GAMMA 100 = 500 = ZETA’s unpaid. GAMMA was owed R 60,000 and is asked for R 100,000 — that is the Excess Participant, and that is the phone call.

A second demo on the cash tile (load/1 with a payer and a broke party): expected in R 5,100,000, received R 100,000, shortfall R 5,000,000; an at-risk party short R 2,000,000 on R 5,000,000 owed vs R 3,000,000 own balance.

Follow along. Path: Cadence → Run the month for a July date → Accounts. Read the reconciliation banner on Billing Period Settlement, then Trading Clearing / Central Reserve / MO Charge, then Credit/Debit until you see #cascade-excess. Do not add MO Charge into the shortfall.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

19. Billing

Path: Market Operator → Billing (/mo/billing). Fourth item in Settlement. The icon is a document with a currency sign.

This is the issued-documents room. Cadence ran the month. Accounts holds the cash. Here you open what that run actually put out: every tax invoice, self-billing invoice, debit note and credit note the Market Operator issued.

You do not raise documents on this page. Run the month lives on Cadence. The till, the cascade and who cannot pay live on Accounts. The PDFs live here.

Where this is taught. Why a party gets an invoice or a remittance, the two clocks, VAT, debit-note excess, and supply-only BRPs: V15 §14. This chapter is the operator’s register: what you click, in which order, and what each column is for.

Follow along. Seat: mo@webill.net with password supersecret. Path: / → Market Operator → Billing. Default month is the previous calendar month — the same Billing Period as Accounts → Billing Period Settlement and Bidding → Month. Overview ignores that picker: it is to date. The other tabs use it.

19.1 The operator’s problem

A participant phones and names a number. You need to find that document, see whether it was paid, open the PDF they hold, and — if it is a note — walk back to the original. You also need a lifetime picture: how much has been invoiced, remitted, and debit-noted, month by month, that agrees with the pots on the Accounts billing board.

Mixing that hunt into the till is how an operator loses the document in the cash. This room is the filing cabinet. Accounts is the safe.

19.2 How the page is laid out

Browser title: Billing. Header: Billing — Every document the Market Operator issued — invoices, remittances, notes. Page id: #mo-billing-page.

Query params: ?month= (YYYY-MM), ?tab= (overview · invoices · remittances · debit_notes · notes · corrections · run), plus the document-tab facets (q, direction, status). An old ?tab=register&kind=TAX_INVOICE still opens Invoices.

Block Id Job
Month picker #mo-billing-month-picker Which Billing Period the document tabs use
Export CSV #mo-billing-csv On tabs 2–6. Same rows as that tab, GET /mo/billing.csv
Tabs #mo-billing-tabs Seven icon tabs, same chrome as Accounts
Default tab #mo-billing-overview Lifetime roll-up

19.3 The month picker

#mo-billing-month-picker. Same control the operator Billing hub uses: previous (#mo-billing-month-picker-prev), a month input (#mo-billing-month-picker-input), next (#mo-billing-month-picker-next). Changing it reloads the document tabs for that period. Overview stays to date.

Default is the previous calendar month (Format.default_month/0). Today in August 2026 opens July 2026.

19.4 The seven tabs

Bordered icon tabs (#mo-billing-tab-{id}), same pattern as Accounts and Bidding: an icon plus a label, not a pill of the tab id.

Tab Id Icon What it answers
Overview #mo-billing-tab-overview squares Lifetime invoiced / remitted / debit-noted, by month
Invoices #mo-billing-tab-invoices document Tax invoices for the picker month
Remittances (SB) #mo-billing-tab-remittances banknotes Self-billing invoices, with utility acknowledgement
Debit Notes #mo-billing-tab-debit_notes triangle Debit notes for the picker month
Notes #mo-billing-tab-notes document-minus Credit notes for the picker month
Correction #mo-billing-tab-corrections arrow-path Notes that name the original they correct
Run #mo-billing-tab-run play Cadence rows for the month — read-only

There is no combined Register tab. Each kind is its own room so the totals strip is only that kind. The Accounts billing board’s Invoices and Self-billing invoices pots open Invoices and Remittances (SB) for that month.

19.5 Overview

#mo-billing-overview. Three coloured cards, then a month table newest-first from the last billed month. Void, draft and reissued rows are left out so a replacement does not double-count.

Card Id Colour Figure
Total Invoiced to date #mo-billing-stat-invoiced Indigo Tax invoices, incl VAT (excl and VAT underneath)
Total Remitted to date #mo-billing-stat-remitted Emerald Self-billing invoices
Total Debit Noted to date #mo-billing-stat-debit-notes Amber Debit notes

Table (#mo-billing-overview-table). Row id: #mo-billing-overview-row-{YYYY-MM-DD}.

Group Columns Background
Month Written July 2026 White
Invoiced Ex. VAT · VAT · Total Invoiced Indigo
Remitted Ex. VAT · VAT · Total Remitted Emerald
Debit Notes Ex. VAT · VAT · Total Debit Noted Amber

Footer (#mo-billing-overview-totals): Totals, summing every numeric column. The three cards are the same three Total columns. Empty (#mo-billing-overview-empty): No billed months yet.

Credit notes are not on this table. They live on Notes and Correction.

19.6 Document tabs

Invoices, Remittances (SB), Debit Notes, Notes, and Correction share the same documents card — the totals strip and table the old register used — filtered to that tab’s kind. Totals (#mo-billing-invoices-totals and the matching id on each tab) are Documents, Excl VAT, VAT, Incl VAT for that kind only, in rands, matching the visible (unpaged) set and the CSV to the cent.

Tab Panel id Kind
Invoices #mo-billing-invoices TAX_INVOICE
Remittances (SB) #mo-billing-remittances SELF_BILLING_INVOICE
Debit Notes #mo-billing-debit-notes DEBIT_NOTE
Notes #mo-billing-notes CREDIT_NOTE
Correction #mo-billing-corrections Credit and debit notes that name an original

Export CSV (#mo-billing-csv) on each of these tabs. GET /mo/billing.csv?tab=invoices&month=… (and the matching tab for the others). Facets ride on the query string.

Facets (#mo-billing-facets):

Facet Id What it filters
Search #mo-facet-q BRP, trading unit, organisation name, or document number
Direction #mo-facet-direction Invoice or Credit
Status #mo-facet-status Issued · Paid · Short paid

Empty (#mo-billing-invoices-empty on Invoices, and the matching empty id on the other tabs): No documents for {YYYY-MM}.

The table is paged at 50 rows. Invoice / debit-note / note row id: #mo-doc-{id}. Remittance rows keep the older ids so a utility acknowledge still has a stable hook: #mo-remit-{id} (utility) or #mo-remit-part-{id} (participant). Correction rows: #mo-correction-{id}.

Column What it is
Number Gapless tax-invoice number. Opens /mo/billing/documents/{id}
Kind Coloured chip (#mo-doc-kind-{id}): Invoice, Remittance (SBI), Debit note, Note
Party / entity BRP or Trading Unit label, not a uuid if the directory knows it
Organization Legal name
Type / Ack On Invoices, Remittances (SB), and Debit Notes — the same columns on all three. Utility or Participant. A utility remittance shows acknowledged or unacknowledged (#mo-remit-ack-{id}); other rows show —
Original Correction only. The number of the document the note corrects, as a link
Period Written 1 June 2026, not 2026-06-01
Excl / VAT / Incl Rands
Due Date, plus an aging chip (#mo-doc-aging-{id}): paid · current · 1–30 · 31–60 · 61–90 · 90+
Status Badge (#mo-doc-status-{id}): Issued · Paid · Short paid · Void · Reissued · Draft. Under it, payment state (#mo-doc-pay-{id})
Delivery #mo-doc-delivery-{id} — pending or delivered
Action Eye (#mo-doc-view-{id}) opens the stored PDF on this page

The eye opens #mo-billing-document-modal with #mo-billing-document-modal-viewer. Close it and you are still on the tab. The number itself navigates to the document page.

Kind chips say both the Code term and the plain word on remittances (Remittance (SBI)). That is B8 as shipped.

A utility remittance is one whose recipient organisation is the supply-only org on an Eskom or municipal issuer. Participants are everyone else. Acknowledgement is the same timestamp the utility sets on Received.

Where this is taught. A rerun or a validated dispute arrives as a note, not a replacement invoice: V15 §17.

19.7 Run status

#mo-billing-run. Read-only. The copy says so: issuing still happens on Accounts. What you see are Cadence rows for this Billing Period (#mo-cadence-{id}): callable · outcome, and in rose when the outcome is a miss, the reason.

This is the same timetable as Cadence, scoped to the month on the picker. You do not press Run the month here. There is no CSV on this tab.

19.8 The document page

Path: /mo/billing/documents/:id. Only documents this Market Operator issued — another issuer’s row redirects home with not found.

Header: the document number. Description: The artifact the counterparty holds. Body id: #mo-document-{id}.

Block Id What it is
Header #mo-document-header Kind chip, number, issuer → recipient, period, version, status, payment state (#mo-document-payment)
Supersedes / successor / references / original #mo-document-supersedes · #mo-document-successor · #mo-document-references · #mo-document-original Version chain and the note’s parent, when they exist
Lines #mo-document-lines Grouped (wheeling energy, UoS, credits, …). Each #mo-document-line-{id}: description, TOU, unit, market line kind, amount + VAT
Annexures #mo-document-annexures Trading Unit and Balancing Group pro formas attached to the party tax document
File /mo/billing/documents/{id}/file The stored PDF

Where this is taught. What is on the face, why the bank reference is not the tax number, and why a Trading Unit document is an annexure: V15 §14. The issued register that this room shares a lens with: V15 §9.

19.9 How this room sits next to Accounts

You need to… Open
Raise the month’s invoices Cadence → Run the month
See whether they were paid Accounts → Billing Period Settlement, cash position
See lifetime invoiced / remitted / debit-noted Billing → Overview
Open the PDF / filter one kind Billing Invoices, Remittances (SB), Debit Notes, or Notes
Argue a line Dispute — the invoice was never paused

The four pots on Accounts (#run-invoices, #run-self-billing) are counts into these kind tabs. A count that disagrees with its own drill-down is worse than no count.

Follow along. From Accounts, click Invoices on the billing board. You land here with ?tab=invoices for that month. Open an eye. The PDF is the artefact the participant holds.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

20. Dispute

Path: Market Operator → Dispute (/mo/dispute). Fifth item in Settlement. The icon is a scale.

Mo.Settlement.Query tiers: Data Query, Settlement Query, Settlement Dispute. Clocks, materiality, recalculation-threshold gate. Pay now, argue later — a query never holds an invoice.

This is one resource with the org Recon. There is not a second inbox.

Where this is taught. How a BRP raises a query and what evidence looks like: V9 §8. This chapter is the MO side.

### 20.1 The operator’s problem

A participant disagrees with a line. The invoice is still due. You have a deadline, a materiality test, and — if the change is big enough — a rerun that applies to every participant, not just the complainant. You must not pause cash to be polite.

### 20.2 How the page is laid out

Browser title: Dispute. Header: Queries and disputes — Data Query, Settlement Query, Settlement Dispute — one resource with the org Recon.

No tabs. No URL params. The first query is selected for you.

Block Id Job
Policy banner #due-notwithstanding-dispute The rule, in one sentence
Query inbox #query-inbox Every open (and recently moved) query
Query detail #query-workflow Clock, evidence, resolve, rerun

### 20.3 The policy banner

Pay now, argue later. Amounts fall due notwithstanding any query or dispute (clause 15.5(1)). Resolving a query does not pause an invoice.

The detail repeats it as Invoice held? {yes|no} — clause 15.5(1) forbids it. Expect no.

Metaphor. The restaurant bill is paid tonight. The complaint about the wine is a letter tomorrow. Holding the bill hostage is not a remedy the Code allows.

### 20.4 The inbox — how to read a row

Empty: No queries.

Each #query-row-{id} is a button. Click selects it.

Piece What it is
Tier badge DATA_QUERY · SETTLEMENT_QUERY · SETTLEMENT_DISPUTE
Status badge Open / resolved / written off — as stored
Subject What they dispute
Party id Mono — who raised it

A query opened from org Recon appears here as a Settlement Query. Watch the BRP kanban move to RESOLVED when you resolve it.

### 20.5 The detail — clock, evidence, actions

#query-clock:

Row Id How to read it
Market Operator’s deadline #query-mo-deadline SAST datetime — yours
Materiality #query-materiality Class, or — . Engine default threshold R 50.00
Correction / statement #query-correction {correction_r} / {statement_value_r}

#query-lines shows the evidenced charge line when one is attached. You should not resolve an aggregate difference: a decision refers to one identified line.

Control Id What it does
Resolve #resolve-query-{id} Closes the query. Flash: Query resolved. The invoice was never paused.
Settlement Recalculation Threshold (%) #rerun-threshold Required to request a rerun
Rerun for all participants #request-rerun A diff statement (clause 15.3.5(4)), applied to every participant

Rerun refused (#rerun-refused): Rerun refused ({reason}) — e.g. threshold_not_determined if the box is empty. Success flash: Rerun is a diff and applies to every participant. #query-rerun-diff shows the total difference and the changed line count.

You should not resolve a case that has no evidence pack. You should not treat Resolve as a payment holiday.

### 20.6 Worked query

Data. Recon console tests · internal −R 2,793.50 vs MO −R 3,108.00.

Field Example
Tier SETTLEMENT_QUERY
Variance Those two numbers — the correction context
Threshold typed 5 → #query-rerun-diff appears
Billing-board sibling DATA_QUERY, party MP-BETA, deadline 03 Aug 2026, 17:00 SAST, escalates to SETTLEMENT_DISPUTE

Accounts’ #board-query-inbox is the summary of the same objects. This page is where you work them.

Follow along. Raise a query from a BRP Recon seat (V9 §8). Open /mo/dispute. Select the row. Read #due-notwithstanding-dispute. Resolve only after the evidence pack names the line. The invoice was never paused.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

21. Participants

Path: Market Operator → Participants (/mo/participants). First item in Eligibility. The icon is a user-group.

Two boards sit above each other and they are not duplicates. Registrations is the operational question — may this registration bid today? Pending Clocks (and the rest of the board) is the joining and enforcement lifecycle. A party can be DEFAULT on the enforcement queue and ACTIVE on Registrations, and both are correct.

Where this is taught. Every joining status, every screen, and every agreement step is V9 §3.13A. This chapter is the Market Operator’s queues.

### 21.1 The operator’s problem

Someone wants in. The Code gives them clocks, and you clocks, in business days. An undecided extension is itself a finding. A suspension that cannot bite looks complete from every angle and does nothing. You need worklists because your next action differs on each — but issued suspensions and blocked units are status on Registrations, not separate queues.

### 21.2 How the page is laid out

Browser title: Participants. Header: Participants — BRP admission, accession publication, enforcement clocks, and D2 registration status transitions.

Tab bar #mo-participants-nav. Eight tabs — there is no Suspension Queue tab and no Blocked Suspensions tab. Each tab is #mo-participants-tab-{id}. Worklist tabs show a count (unpublished accessions, pending clocks, extensions, open notices, balancing groups).

Tab Path live_action Tab id What it is
Registrations /mo/participants :registrations #mo-participants-tab-registrations D2 seats. Defaults to Active — may they bid today?
Accession register /mo/participants/accession :accession #mo-participants-tab-accession Who acceded and is still unpublished (§6.2(9))
Pending Clocks /mo/participants/clocks :clocks #mo-participants-tab-clocks Every running admission clock
Extension Requests /mo/participants/extensions :extensions #mo-participants-tab-extensions Undecided written requests
Open Default /mo/participants/defaults :defaults #mo-participants-tab-defaults Default notices and remedy dates
Balancing Groups /mo/participants/balancing-groups :balancing_groups #mo-participants-tab-balancing_groups Every party’s designation — who nets with whom
Credentials /mo/participants/credentials :credentials #mo-participants-tab-credentials Issue, rotate and revoke OAuth, mTLS and HMAC credentials (§21.12)
Vesting /mo/participants/vesting :vesting #mo-participants-tab-vesting The vesting book: who is vested, on which unit, against which counterparty (§21.13)

Bookmarks to /mo/participants/suspensions and /mo/participants/blocked still resolve; they patch to Registrations. Those are not tabs.

Above every tab: the Registration board header (#mo-registration-board) and the seven-state cards. There is no #accession-sla-summary under the stats — the Accession register is the tab, not a card.

### 21.3 The seven states — orientation, not a worklist

Heading: The seven states (§6.2, §6.3, §6.4, §6.5). #mo-registration-as-of stamps as at {date}. Empty: No parties registered yet.

Card id State Everyday name
#mo-registration-state-APPLICANT APPLICANT applicant
#mo-registration-state-OFFERED OFFERED agreements issued
#mo-registration-state-ACTIVE ACTIVE active
#mo-registration-state-DEFAULT DEFAULT in default
#mo-registration-state-SUSPENDED SUSPENDED suspended
#mo-registration-state-TERMINATED TERMINATED terminated
#mo-registration-state-WITHDRAWN WITHDRAWN withdrawn

Counts only. Work happens on the tabs. The tiles use the same tinted chrome as the registry standing-data cards: sky applicant, violet agreements issued, emerald active, amber in default, orange suspended, rose terminated, slate withdrawn.

§6 party states — the header cards
APPLICANT
→agreements
OFFERED
→activate
ACTIVE
From ACTIVE, enforcement — not a second application: DEFAULT SUSPENDED TERMINATED WITHDRAWN

Do not press Activate on a freshly filed PENDING row; that move is refused. Work Pending Clocks.

Days remaining is in business days. A clock five days out can be a calendar week away. Whose clock it is, is shown. Two of the five admission clocks are yours and three are the applicant’s.

One clock is a window, not a duty. §6.2(4) says you may request further information within ten business days. Letting it lapse breaches nothing — the application is simply complete as filed. §6.2(6) is a shall.

21.4 Registrations — may they bid today?

#mo-brp-status-board — Registrations (D2). Defaults to Active. Change Status for Pending, Suspended, or Revoked — or All statuses. In-flight applications are also on Pending Clocks. Issued Suspension Orders show on the row as scheduled, in effect, or blocked (§21.10, §21.11) — not as extra tabs.

Totals #mo-brp-registration-totals: N registration(s) and N trading unit(s), with (M shown) when a search or status filter hides some. Form #mo-brp-registrations-filters.

Control Id What it does
Search #mo-brp-registrations-search-input Placeholder Search BRP REF or Organization
Status #mo-brp-filter-status All statuses · PENDING · ACTIVE · SUSPENDED · REVOKED. Default ACTIVE
Sort BRP REF #mo-brp-sort-brp-code Toggle asc/desc
Sort Organization #mo-brp-sort-organization Same
Expand units #mo-brp-registration-{id}-units Chevron + count. Detail #mo-brp-registration-{id}-units-detail
View #mo-brp-registration-view-{id} Opens the clock drawer (§21.6). ACTIVE: Suspend / Revoke. SUSPENDED: Activate / Revoke. REVOKED: Reactivate only (#mo-application-action-{id}-ACTIVE). A revoked seat cannot be suspended.

Each row #mo-brp-registration-{id}.

Column Meaning
BRP REF Registration code
Organization Name + status badge
Registered Date + N months in status (Less than 1 month in status when under a month)
Trading Units Count; expands TUID · Official name · Class · Zone · Status · Enforcement · Site / Pool. Unit row #mo-brp-registration-{id}-unit-{unit id}
Enforcement #mo-brp-registration-{id}-enforcement — compact badges for issued Suspension Orders: scheduled, in effect (rose), blocked (amber). Dash if none.
API auth #mo-brp-registration-{id}-adoption — most recent successful /api/v1 call: Bearer or Header, and when. Dash if the party has not called yet. Header-only is sandbox/test; production callers present a token (V13 §2).
Actions View

Expanded unit cell #mo-brp-registration-{id}-unit-{unit id}-enforcement: delay period ({N} business days ({parameter})), takes-effect ISO date, and (when blocked) the reason. A unit on both the issued-order list and the blocked list shows blocked, not scheduled.

Class labels: Demand side, Generating, Storage, Mixed, Interconnector. Empty: No BRP registrations. Filter miss: No registrations match the current filters. Demo: BRP-T1-DEMO.

You should not activate a registration merely because it is needed for a demo day: verify the code, roles and guarantee first.

21.5 Accession register — the 7-business-day SLA

Path: /mo/participants/accession. Widget #accession-sla. Tab badge is the unpublished count. There is no #accession-sla-summary card under the seven-state tiles — this tab is the register.

What an accession is

An applicant who has paid the fee and signed both agreements is still an applicant. They become a Party on the agreements’ effective date (§6.2(8)) — not when they apply, not when they sign. That step is the accession. Until it happens they cannot trade (commissioning aside). After it, they are in the market.

On this console, Activate on Registrations is the accession. The clocks, the two agreements, and the account notification that lead there are V9 §3.13. Reinstating a suspended participant is not an accession: nothing new is being acceded to.

What the table is

§6.2(9) obliges you to publish every accession on a public register within seven business days of that effective date. Weekends and gazetted public holidays do not count.

That register is not this table. The public surface is GET /api/v1/registry/accession-register (V13 §5.1): MPID, legal name, party type, qualifying criterion, acceded-on date, published-at. No credit cover, no Warning Limit, no account numbers — §6.2(9) makes the accession public, not the exposure.

This table is your compliance clock against that duty. It lists parties that already have an agreement effective date and shows whether you have stamped them onto the public register yet. Overdue first, then awaiting, then published.

Worklist tabs (Pending Clocks, Extension Requests, Open Default, Balancing Groups) carry an Accession badge on the party they already list, so you do not have to leave a chase to see the publication finding. Registrations does not — publication lives on this tab. Issued Suspension Orders and blocked units are Enforcement status on Registrations, not worklist tabs.

What each row means

Header summary: {unpublished} acceded, unpublished. {overdue} past the seven-business-day SLA. Empty: No parties with an agreement effective date yet. (#accession-sla-empty)

Each #accession-sla-{party_id}:

Column Meaning
BRP REF Registration code
Organization Name
Effective date agreement_effective_date — §6.2(8)
Acceded on acceded_on — the day Activate actually ran (may be later)
Publish by Effective date + seven business days
Status #accession-sla-status-{id} — awaiting publication / overdue / published
Published at published_at, or —
Actions View #accession-sla-view-{id} — clock drawer, read-only
Status Meaning
awaiting publication Acceded (effective date set). Still within the seven business days. Not yet on the public register.
overdue Same, but today is past the deadline. A compliance finding against you, not against the participant.
published published_at is set. They appear on the public accession register.

Metaphor. The licensing office issued the licence. The Code says the register must show it within seven business days. Overdue is not “the party is inactive” — it is you have not published the accession. Activate on Registrations makes them a Party; publication is the separate stamp that lets anyone else verify that they are one.

How to remedy it

  1. Finish accession first if they are not yet ACTIVE — work Pending Clocks, then Activate when the agreements and effective date allow it.
  2. Publish within seven business days of the effective date. Publishing stamps published_at. Until that stamp exists, the public register omits them and this table keeps counting.
  3. Treat overdue as your queue, not theirs. Chase your own publication backlog. Calling the participant does not clear an overdue row — only publishing does.
  4. Re-check the public surface. After publication, GET /api/v1/registry/accession-register must include them. Anyone considering trading with that party uses that endpoint to confirm standing.

Note. This panel is observational — it has no Publish button. It exists so you see the SLA before someone else notices the gap. Late publication is still a finding (published but not on time); the overdue flag clears once published_at is set, but the on-time record remains in the party’s publication status.

21.6 Pending Clocks

Path: /mo/participants/clocks. #mo-registration-clocks — applications still in the admission machine. ACTIVE seats are on Registrations, not here.

Where this is taught. The four Code clocks and the fifteen application states are V9 §3.13 and V9 §3.13A. This section is the Market Operator’s worklist and the View drawer.

Every period is in business days (§2.3(2)(a)). A deadline five days away can be a calendar week. The panel names the three lapses the daily clock will take for you: unanswered information requests expire, reviewed applications become contractable, and contractable ones have agreements issued.

Empty: No pending application is on file. (#mo-registration-clocks-empty) Overdue rows sort first and tint rose (bg-rose-50).

Chasing a participant over your §6.2(6) deadline to issue the agreements sends the wrong person after the wrong thing.

The table

Each #mo-registration-clock-{id}:

Column How to read it
Party BRP REF + organisation name
Accession #mo-registration-clock-accession-{id} — awaiting publication / overdue / published / —
State Application-state badge (the fifteen-state machine)
Whose Market Operator (amber) or applicant (slate) — who owns the next move
Deadline Long date (%-d %B %Y). Then N business days left of P, overdue — the daily clock will move it to {STATE}, overdue — nothing happens automatically, or no clock
Actions Eye #mo-registration-clock-view-{id} — tooltip View pending application. Opens the drawer

Whose is whose clock is running, not who may act. You may still Decline or ask for information while the badge says applicant.

A Market Operator overdue with nothing happens automatically (PENDING, CONTRACTS_ISSUED, CONTRACTS_SIGNED, APPROVED) is your finding. An applicant overdue on INFO_REQUESTED is taken by the daily clock to EXPIRED.

The clock drawer

#mo-clock-drawer — #mo-clock-drawer-backdrop click or #mo-clock-drawer-close closes it. Header #mo-clock-drawer-header: eyebrow SAWEM · Pending application, title #mo-clock-drawer-title (BRP REF), application-state badge, organisation · MPID.

The same drawer opens from Registrations and Accession register, but those tabs set it read-only except D2 status buttons (Activate / Suspend / Revoke / Reactivate). The header eyebrow is SAWEM · Registration on those tabs, SAWEM · Pending application on Pending Clocks. Pending Clocks is where you work the application.

Tab Id When
Application details #mo-clock-drawer-tab-details Always
Files #mo-clock-drawer-tab-files Always
History #mo-clock-drawer-tab-history Always
Ask for information #mo-clock-drawer-tab-ask Writable drawer, and state PENDING or INFO_SUBMITTED

Jargon labels carry an i (hero-information-circle). Hover for the definition. Ids #mo-clock-drawer-hint-{field}. The details grid is two columns. Left-column hints open to the right (tooltip-right) so they are not clipped off the drawer edge. Right-column hints open to the left (tooltip-left). Full-width labels (Current clock, Agreements, the note modal, Ask-tab textarea) sit on the left and also open right.

Application details

#mo-clock-drawer-details. Four blocks, then the actions footer.

Current clock. Hint #mo-clock-drawer-hint-clock. Empty: No period is running. Otherwise: state label, §{clause} · Market Operator|applicant, Deadline {long date}, then the same remaining / overdue sentence as the table.

Information request (#mo-clock-drawer-correspondence). One pair per round: Question (your note + when) and Response (theirs, or a dashed empty). Hidden when there has been no round.

Standing fields. #mo-clock-drawer-field-{id} — i on each label (#mo-clock-drawer-hint-{id}).

Label Field id Column Hint What it is
Organisation organisation left tooltip-right Applicant organisation name
BRP code brp-code right tooltip-left Registration reference
MPID mpid left tooltip-right Market Participant ID; on the public accession register
Roles roles right tooltip-left Generator / load / trader / distributor
Party type party-type left tooltip-right Entity kind under §2.1
Qualifying criterion qualifying-criterion right tooltip-left Annexure 1 ground
Market participant market-participant left tooltip-right Yes / no — not the same as “may bid today”
Balance responsible balance-responsible right tooltip-left Yes / no — who settlement holds for imbalance
Registration status registration-status left tooltip-right D2: PENDING / ACTIVE / SUSPENDED / REVOKED
Application state application-state right tooltip-left Fifteen-state machine — the field you work
Party state party-state left tooltip-right Seven §6 states
Applied applied right tooltip-left Date received (§6.2(2))
VAT number vat-number left tooltip-right As declared
Guarantee type guarantee-type right tooltip-left Form of credit cover declared
Guarantee amount guarantee-amount left tooltip-right Cover in rand
Warning limit warning-limit right tooltip-left Exposure warning threshold in rand
Clarification requested clarification-requested left tooltip-right Last §6.2(4) ask
Clarification received clarification-received right tooltip-left Last §6.2(5) answer

Agreements. #mo-clock-drawer-agreements-{party id}, hint #mo-clock-drawer-hint-agreements. Empty (writable, contracts may be prepared): Prepare the Market Participation Agreement and Balancing Agreement, then digitally sign both to issue them to the applicant. Empty (read-only): No agreements on file.

Each #mo-clock-drawer-agreement-{id}: MPA or BA badge (#mo-clock-drawer-agreement-view-{id}) opens the PDF modal; title; status (Draft — awaiting Market Operator signature / Signed by the Market Operator / Sent to the applicant / Signed by both parties); optional sent {date}; #mo-clock-drawer-agreement-mo-sign-{id} / #mo-clock-drawer-agreement-applicant-sign-{id}.

Digitally sign #mo-clock-drawer-agreement-sign-{id} — only while the agreement is GENERATED and you have not signed. Hidden on read-only tabs.

PDF modal #mo-participation-agreement-pdf-modal: Close, Download, Digitally sign when still unsigned. Viewer #mo-participation-agreement-pdf-modal-viewer.

#mo-clock-drawer-actions-{id}. Buttons that are lawful from this application state for the Market Operator. Id #mo-application-action-{id}-{TARGET}. Hover title is the state’s one-line description. A refusal from the Code is shown verbatim — it names what is missing and which clause requires it.

Empty: Waiting on the applicant — no Market Operator move is available. After Prepare contracts and before both signatures: Digitally sign both agreements to issue them to the applicant.

There is no Issue contracts button. Issuing is Prepare → digitally sign both. CONTRACTS_ISSUED is withheld from this footer on purpose.

Button Target / id suffix When Note modal?
Prepare contracts PREPARE_CONTRACTS You may issue contracts and no pair exists yet No
Request information INFO_REQUESTED PENDING or INFO_SUBMITTED Yes
Mark contractable CONTRACTABLE PENDING or INFO_SUBMITTED No
Approve APPROVED CONTRACTS_SIGNED No
Activate ACTIVE APPROVED — this is accession (§6.2(8)) No
Decline DECLINED Lawful non-admission from this state Yes
Revoke REVOKED After contracts are out / live participation Yes
Suspend SUSPENDED Needs an open Default Notice / Suspension Order (§6.4) Yes

On Registrations / Accession (read-only drawer) the footer is D2 only, as RegistrationStatus.mo_transitions allows:

Current D2 status Buttons
PENDING Activate
ACTIVE Suspend, Revoke
SUSPENDED Activate, Revoke
REVOKED Reactivate only (#mo-application-action-{id}-ACTIVE)

A revoked seat cannot be suspended. Participation has ended; the only D2 move is back to ACTIVE. The applicant may also Request reinstatement on their Registration page (§6).

Moves that need a note open #mo-application-note-modal. Title is {action} — {BRP REF}. Field Note (#mo-application-note-text) with i #mo-application-note-hint (tooltip-right — the label sits on the left of a centred modal). Placeholder is the prompt for that move. Cancel / #mo-application-note-submit (label is the action, e.g. Decline).

Files

#mo-clock-drawer-files. Files the applicant attached when answering an information request. Empty #mo-clock-drawer-files-empty: No files have been uploaded yet.

Each #mo-clock-drawer-file-{id}: title, original filename, optional description. View #mo-clock-drawer-file-view-{id} (new tab) and Download #mo-clock-drawer-file-download-{id}.

History

#mo-clock-drawer-history. The same trail the applicant sees under History on Registration. Empty #mo-clock-drawer-history-empty: No history has been recorded yet. Timeline #mo-clock-drawer-history-list — each circle has a state icon; the box is {from} → {to} (or Application opened at {to}), date, actor, frozen deadline, note.

Ask for information

#mo-clock-drawer-ask — only while PENDING or INFO_SUBMITTED on the writable drawer. Form #mo-clock-clarification-form.

Control What it is
Information requested Required textarea. i on the label (tooltip-right): what you type is the whole of what the applicant is told
Cancel Returns to Application details
Send request #mo-clock-clarification-submit Moves to INFO_REQUESTED under §6.2(4). The applicant then has 20 business days, unless extended

The tab disappears once the state leaves PENDING / INFO_SUBMITTED. Request information in the footer is the same move via the note modal.

Careful. An unanswered information request that runs out is taken by the daily clock to EXPIRED — deemed withdrawn, not declined. Do not ask for a document you cannot describe; the note is the request.

### 21.7 The clock drawer

The View drawer is documented under §21.6. Pending Clocks is writable. Registrations and Accession register open the same chrome read-only except Activate / Suspend / Revoke / Reactivate.

### 21.8 Extension Requests

Path: /mo/participants/extensions. #mo-registration-extensions. Only undecided requests. Heading: Extension requests awaiting a decision (§6.2(5)/(7)). Empty: No extension request is outstanding. (#mo-registration-extensions-empty)

Each #mo-registration-extension-{id}.

When an applicant submits Request more time on BRP / Market → Registration, the row appears without refreshing. The applicant’s due date has not moved yet — only a grant changes it. They can only ask on INFO_REQUESTED or CONTRACTS_ISSUED. They cannot file a second request for that clock while one is pending, and they cannot ask again for that clock after you decline.

Column What it is
BRP REF Registration code
Organization Applicant
Accession #mo-registration-extension-accession-{id}
Status INFO_REQUESTED or CONTRACTS_ISSUED
Deadline Clock still in force + business days + clause
Days asked Business days beyond that deadline
Reason Why they need longer
Actions Grant / Grant with days… / Decline
Action Id Effect
Grant #mo-extension-grant-{id} Accept the days asked. Row leaves. Deadline moves. Applicant’s page updates live.
Grant with days… #mo-extension-grant-custom-{id} Modal: 1–60 business days from the current deadline; optional note
Decline #mo-extension-decline-{id} Modal: mandatory reason. Original deadline stays. Applicant cannot ask again for this clock.

Modal #mo-extension-decision-form: #mo-extension-business-days, #mo-extension-decision-note, submit Grant extension or Decline extension. Decline without a reason: A refusal must give a reason (§6.2(5)).

Decided requests do not remain on this tab. After a grant, a later second extension for the same clock may appear (extensions stack). After a decline, no further row for that clock until the application moves.

Careful. Leaving a request undecided is itself the finding the Code warns about: the applicant’s clock is still running on the old date. An applicant who asked in good time and heard nothing can be deemed withdrawn while waiting for you.

21.9 Open Default

Path: /mo/participants/defaults. Tab #mo-participants-tab-defaults. #mo-registration-notices — Open Default Notices (§6.3.1). Empty: No Default Notice is open. (#mo-registration-notices-empty)

Each #mo-registration-notice-{id}: {mpid|brp_code} — remedy by {ISO date}, nature, optional Also required: …, the Accession badge (#mo-registration-notice-accession-{id}), and if expired: remedy time expired — a Suspension Order may issue (rose). Escalate the expired ones.

21.10 Issued suspensions on Registrations

Not a tab. Path: /mo/participants — the Enforcement column on Registrations. Bookmarks to /mo/participants/suspensions still resolve and patch here. Empty is a dash on #mo-brp-registration-{id}-enforcement, not a dedicated panel. There is no #mo-participants-tab-suspensions and no #mo-registration-suspensions worklist.

Where this is taught. Default → notice → order → delay → suspended is V9 §3.14. This section is the Code: who is on a Suspension Order, per Trading Unit, and whether it has bitten. The console shows that as Enforcement on the BRP row and on each expanded unit.

A default does not stop a party bidding. Neither does issuing the order. The gap is deliberate. §6.3.1 gives at least two business days to remedy; §6.4(2) forbids an order until one further business day after the notice; §6.4(3) then adds an MGC delay period before any unit actually stops. This is the stretch after the order exists and before — or after — it bites. Watch the dates. Do not read a badge as “they cannot trade today” unless Enforcement is in effect.

This status is observational. There is no Issue, Lift, Amend, or Activate on the Enforcement cell. You issue from the enforcement path (an open Default Notice on Open Default); the Market Governance Committee lifts or amends; Activate on Registrations is D2 seating after the party is allowed to bid again.

What the status is

One issued Suspension Order, exploded onto each Trading Unit the order covers. BRP badges #mo-brp-registration-{id}-enforcement. Unit cell #mo-brp-registration-{id}-unit-{unit id}-enforcement.

That split is the point of §6.4(3). The MGC may amend or lift any or all of a party’s units. Demand-side and generating units use different delay parameters, so two units of the same party take effect on different dates. A Demand Side Unit may be covered by the order and still unable to bite — that unit is also blocked.

Every unit on an order whose status is still ISSUED shows a badge. A unit that has already bitten reads in effect. A unit the MGC lifted alone stays scheduled / listed while the rest of the order stands (LIFTED on that unit). Enforcement clears when the whole order is lifted (LIFTED) — then none of its units appear.

Who shows under Enforcement

Not every party in DEFAULT. Not every expired Default Notice. The path is:

  1. They are a Party who may be suspended. Typically ACTIVE, then recorded in default (§6.3(2)). They keep trading. That is on the seven-state tiles and on Open Default. Enforcement stays a dash until an order issues.
  2. An open Default Notice exists (§6.3.1). Remedy time at least two business days. Open Default is the chase list until an order issues.
  3. At least one business day after that notice (§6.4(2)). Earlier is refused.
  4. The order is not barred by §6.4(4). No suspension solely because credit cover was absent during a permitted replenishment window, or during the ten business days to appoint a new Credit Cover Provider. Solely: another live ground is not protected.
  5. A Suspension Order is issued. Every registered Trading Unit of that party shows under Enforcement.

Who you will not see under Enforcement:

A generating, storage, mixed or interconnector unit lands as SCHEDULED for issued-on + Generator Suspension Delay Period (business days). A Demand Side Unit with a Default Retailer direction in force is SCHEDULED for the later of its DSU delay and the direction’s date. A Demand Side Unit without that direction, or any unit whose MGC delay parameter is unset, lands as WITHHELD — blocked on the unit (preferred over scheduled when both lists apply).

What each cell means

On the row Meaning
BRP Enforcement badges #mo-brp-registration-{id}-enforcement — scheduled, in effect (rose), blocked (amber). Dash if no issued order.
Unit Enforcement #mo-brp-registration-{id}-unit-{unit id}-enforcement — badge plus delay {N} business days ({parameter}), takes-effect ISO date, and blocked reason when withheld
Delay period dsu_suspension_delay_days or generator_suspension_delay_days, stored so a later MGC revision cannot rewrite the date this unit was given
Takes effect ISO date, or omitted if the unit cannot bite yet (withheld, or no delay parameter)

in effect is the only badge that means the unit has stopped for today. scheduled with a future date means they are still trading on that unit. blocked means the order covers them and is doing nothing — see §21.11.

When the first unit actually bites, the party’s §6 state becomes SUSPENDED. Until then they can still be DEFAULT on the seven-state tiles and still scheduled on Registrations. Both are correct.

How to get out

Leaving Enforcement and leaving suspension are not always the same step.

Before it bites (badge is scheduled or blocked). The Market Governance Committee may, per unit or for the whole order (§6.4(3)):

A blocked Demand Side Unit. Recording a Default Retailer direction does not take the unit off Registrations. It stops being blocked (§21.11) and can then take effect on the later of the delay and the direction. That is how they enter enforcement, not how they leave it.

After it has bitten (badge is in effect). The unit is suspended. The party cannot bid on it. Ways out:

There is no “undo the order from this table.” If Enforcement still reads in effect, they are still under that order.

Careful. Issuing the order is not the same as stopping the party. If Takes effect is tomorrow, they may still be in the DAM today. If a demand-side unit shows blocked, the load is still being served by nobody the Code has named — that is a blocked-enforcement finding, not a successful enforcement.

21.11 Blocked units on Registrations

Not a tab. Path: /mo/participants — amber blocked on #mo-brp-registration-{id}-enforcement and on #mo-brp-registration-{id}-unit-{unit id}-enforcement. Bookmarks to /mo/participants/blocked still resolve and patch to Registrations. Empty is a dash. There is no #mo-participants-tab-blocked and no #mo-registration-blocked panel.

A suspension against a demand-side unit cannot take effect at all until the Market Governance Committee has directed that the demand will be met by a Default Retailer. Without this status the order looks complete — it issued, the default stands, the paperwork is filed — and does nothing. The unit cell names the reason (clause 6.4(3), Default Retailer, would leave it with no supplier). The action is an MGC direction, not anything on this screen.

Careful. Do not read a missing blocked badge as “no suspensions pending”. It means every issued order can take effect on its date. scheduled / in effect is where you see the dates.

21.12 Balancing Groups

Path: /mo/participants/balancing-groups. Tab #mo-participants-tab-balancing_groups (badge is the number of groups). Heading on the board: Balancing Groups. Intro: Every party’s designation. You may suspend or cancel; you may not compose membership (§13.10(1)).

Where this is taught. What a group is, why a BRP asks for one, and the worked hour, are V9 §3.6 and V9 §6.7. This section is your market-wide board: who designated, whether the System Operator was told, whether cover will hold tomorrow, and the two acts that are yours.

Why this tab is here

A Balancing Group is a settlement overlay. The market, left to itself, balances each Trading Unit alone. Being long in one zone does not cancel being short in another. Two or more of one party’s units, designated together, net against each other so a mismatch that cancelled out inside that portfolio is not penalised twice.

The BRP designates. You do not. §13.10(1) makes membership their act. They file on Trading Units; the API does the same for a machine. You still need this tab, because three jobs sit with you after they file:

  1. See every designation in the market — not one party’s registry card. When a BRP asks “why did my cover lapse?”, this is the picture that answers it.
  2. Tell the System Operator — §7.1(2). A designation that has no communicated notice is overdue. That is a finding against you, not against the BRP.
  3. Pause or end a group you did not compose — an administrative suspension (a window and a reason), or a cancellation with a mandatory reason. You cannot add or remove members.

It lives on Participants, not on Registry. Registry is Trading Units in force for tomorrow and the pairing board (§22). A group is a fact about a Party — who they asked to net with whom. The seven-state cards stay above the tab because the party is still the subject. A Balancing Group pause is not a §6.4 Suspension Order (§21.10): the seat can still bid; only the netting overlay is off inside the window.

What it is for

Question you are answering Where on this tab
Who has asked to net, and on which units? The table — Party, Group, Members, Zones, Window
Is that party even in the market yet? Accession badge — same publication clock as the other worklists
Did we tell the System Operator? Notified — ✓ date, or overdue
Will cover hold tomorrow? Cover line under the group name
Is the overlay actually on today? Status
Should netting stop for a while, or for good? Suspend / Cancel
Is a congested zone knocking members out this hour? §3.3(6) flags in force, below the table

Empty: No Balancing Groups designated. (#mo-balancing-groups-empty)

Overdue-notice rows sort first, then administratively suspended, then the rest by BRP REF and name. Work the rose overdue cells before you admire the green in force ones.

What each row means

Widget #mo-balancing-groups. Table #mo-balancing-groups-table. Each #mo-balancing-group-{id}.

Column How to read it
Party Who designated — BRP REF (row.party_code)
Accession #mo-balancing-group-accession-{id} — awaiting publication / overdue / published / —
Group Name. Under it, #mo-balancing-group-cover-{id}: Cover forecast (expectation): full cover expected next Trading Day or exclusions expected in hours …
Members Count of Trading Units in the designation. A live group needs two or more (§2.1(21)). One remaining unit is a registry failure (§22.4)
Zones Distinct network zones those members sit in, joined with ·
Window from {ISO date} — effective_from. Duration to a date is effective_to on the record, not a fifth status
Status in force (emerald) · designated (not yet in the window, or past it) · suspended (amber — your administrative pause) · cancelled (slate)
Notified #mo-balancing-group-notified-{id} — ✓ {YYYY-MM-DD} when the §7.1(2) designation notice has communicated_at; otherwise overdue (rose)
Actions Suspend #mo-balancing-group-suspend-{id} · Cancel #mo-balancing-group-cancel-{id}

Cover forecast is an expectation for the next Trading Day. It uses the scheduled position as a direction proxy because actuals do not exist yet. Full cover expected does not promise the hour will clear that way; a zone constraint flag raised later still knocks members out. Exclusions expected in hours … is the honest answer to “why might cover lapse” before the day runs.

Status is not one knob. Four ways a group stops, kept distinct (V9 §3.6):

What you see What happened
in force Designated, inside the window, no administrative suspension today
designated Filed, but not in force on today’s date (window has not started, or has ended by duration)
suspended You paused it. The group is still the current designation; it is not in force inside that window
cancelled Ended early, with a reason. Designate a fresh group if they still need one

A §3.3(6) exclusion does not change this Status. The group stays in force (or designated). Members pushing in the constrained direction drop out for those Trading Periods only. That is why the flags panel sits under the table — so you do not read a green badge as “cover is intact this hour”.

Suspend and Cancel

You cannot designate or amend. Composing a group from this console would be an act the Code does not authorise. The BRP adds a live unit or files a successor group. You only pause or end.

Action Modal What it is
Suspend #mo-bg-modal / #mo-bg-suspend-form — title Suspend {name}. From #mo-bg-suspend-from (defaults today), To #mo-bg-suspend-to, Reason #mo-bg-suspend-reason (mandatory). Submit #mo-bg-suspend-submit. Back closes Administrative pause. The group stays the current designation; it is not in force inside the window. Not a §6.4 Suspension Order. Not a §3.3(6) exclusion
Cancel #mo-bg-cancel-form — title Cancel {name}. Reason #mo-bg-cancel-reason (mandatory). Submit #mo-bg-cancel-submit (Cancel group) End the group from a date. The Code does not say you may; we read that you may, with a reason (V9 §17.12)

Use Cancel when the group can no longer do its job — typically it has fallen below two live units after a member deregistered. Leaving it designated until the BRP notices is a settlement dispute waiting for a night. Use Suspend when you expect it to resume.

Backdrop #mo-bg-modal-backdrop closes without writing.

Careful. Do not press Suspend because a zone is congested. That is the System Operator’s flag. An administrative pause stops the whole overlay for every hour in the window. A flag stops only the members pushing in the constrained direction, and only for those periods.

§3.3(6) flags in force

#mo-zone-constraint-flags. Heading: §3.3(6) flags in force. Read-only. The System Operator raises and lifts these on /so/network-model (Map). Empty: None in force.

This panel is the other half of “why did cover lapse”. A zone constraint flag is a temporary lane closed sign. It is not a change to the published network model, not an administrative Suspend on the table above, and not a §6.4 Suspension Order. The System Operator puts it up; you watch it here. Raise and lift live on /so/network-model?tab=map (V12 §5.5).

In force means: not lifted, and the clock is inside the flag’s window (from inclusive, to exclusive; a missing from or to means open-ended that way). A flag from 17:00 to 20:00 does not appear at 00:00. A lifted flag leaves this list — lifting is a dated event, not a delete.

Each #mo-zone-flag-{id}:

{zone_code} · {direction} · {reason}

Piece What it is
Zone The network zone the sign is on (network_zone_code). Only members in that zone can be excluded. Members in other zones stay in the group
Direction EXPORT, IMPORT, or BOTH. That is the whole closed set. There is no fourth direction
Reason Free text the System Operator typed when they raised it. Required on their form. There is no pick-list of reasons on this platform — the clause is whatever they wrote

Two flags on the same zone at once do not cancel. Export and import bits OR together, and the tightest window wins — a second flag cannot silently widen the first.

The three flags, and who drops out of the group

Exclusion is per Trading Period and per member. It is computed from actual minus scheduled (AE − SE). A member exactly on schedule is never excluded: there is no direction to a deviation of nothing. A member in an unflagged zone is never excluded.

The group row’s Status does not change. Members who drop out balance alone for those hours; the others still net.

Flag on the row What the System Operator is saying Who loses Balancing Group cover in that zone, that period
EXPORT The zone cannot push more power out. Too much trying to leave Anyone who would increase net export: a generator delivering above schedule, or a load consuming below schedule (AE − SE > 0). A member who is short (helping the constraint) stays in
IMPORT The zone cannot draw more power in. Too much trying to enter Anyone who would increase net import: a load consuming above schedule, or a generator delivering below schedule (AE − SE < 0). A member who is long (helping the constraint) stays in
BOTH Too much trying to leave and to enter — both directions at once Both of the above: anyone off schedule in that zone. Only a member exactly on schedule stays in
One hour, one flagged zone — who stays in the group
EXPORTcannot push more out
Member longAE > SE
adds export→
Coverlapses this period
Same EXPORTother member
Member shortAE < SE
relieves the line→
Coverstill in
IMPORTcannot draw more in
Member shortAE < SE
adds import→
Coverlapses this period
BOTHleave and enter
Anyone off scheduleAE ≠ SE
either way→
Coverlapses this period

The Cover forecast line on the group is an expectation for tomorrow using schedule as a direction proxy. This flags panel is now: which signs are actually up. If the list is empty, no sign is up — that is not the same as “the network is unconstrained forever”.

You do not raise, lift, or edit a flag from Participants. If a BRP asks why cover vanished for three hours, read this list first, then the group’s cover line. If the sign should come down, that is a System Operator Lift with a reason, not your Suspend.

Follow along. Seat: mo@webill.net / password supersecret. Path: Participants → Balancing Groups. Scroll to §3.3(6) flags in force. Empty is None in force. If a row is present, read zone · EXPORT/IMPORT/BOTH · reason, and do not confuse it with Suspend on the table. Raising a flag is V12 §5.5.

21.12 Credentials

Path: /mo/participants/credentials. Panel #mo-participants-credentials.

This is the Market Operator’s view of every credential Stage 7 issues. One row per registration; three kinds; issue, rotate and revoke are the same lifecycle on each. Rotation is a new row plus a revoke of the old — never an overwrite — so a secret that later fails is two facts, and the first one’s record is why the second exists.

Kind What it proves Issue
OAuth client secret Who is calling. Exchanged at POST /api/v1/oauth/token for a short-lived JWT whose mpid claim is the party. #mo-cred-issue-oauth_client_secret-{id}. The plaintext is shown once (#mo-credential-plaintext) and never stored in recoverable form.
mTLS fingerprint What is calling. SHA-256 of the DER-encoded client certificate, pinned on the dedicated API listener. Opt-in: a registration with no pin is unaffected. Pin fingerprint #mo-cred-pin-open-{id} then form #mo-cred-pin-form-{id}.
HMAC signing key That this write is the one that was signed. Required on unsafe methods only after the registration opts in. #mo-cred-issue-hmac_signing_key-{id}. Shown once, like the client secret. The Market Operator retains the key material so signatures can be verified.

Rotate (#mo-cred-rotate-{kind}-{id}) and Revoke (#mo-cred-revoke-{kind}-{id}) on an active row. There is no destroy: WB.Brp.RegistrationCredentialEvent is append-only.

Audit #mo-credential-events. Every issue, rotation and revocation, and every authentication failure this stage introduced — expired or wrong-issuer token, header refused as retired, certificate mismatch or revoked certificate, missing / tampered / stale signature — carries the same clause the refusal itself named. An operator sees why a participant is failing, not only that it is.

Where this is taught on the wire. V13 §2.

Follow along. Seat: mo@webill.net / password supersecret. Path: Participants. Confirm an ACTIVE seat (e.g. BRP-T1-DEMO) or work a pending application through Pending Clocks — do not press Activate on a freshly filed PENDING row. Change Status to see Suspended or Revoked (Reactivate only). Issued Suspension Orders show under Enforcement. There is no Suspension Queue tab and no Blocked Suspensions tab. Open Accession register and read unpublished / overdue. Open Extension Requests and decide anything sitting there. Open Balancing Groups and read Notified and the cover line — do not designate from that tab. Open Credentials and issue an OAuth secret for a demo seat; copy it once. Open Vesting and read the illustrative Mpumalanga Mid-Merit contract: determination, CPA counterparty, declining curve. A dormant badge names the activating phase, not zero MW.

21.13 Vesting book

Path: /mo/participants/vesting. Panel #mo-participants-vesting.

A plant that sold power under a long, regulated tariff cannot be dumped onto the spot market overnight. Lenders priced that tariff; staff and fuel contracts assumed it. The day SAWEM starts, every megawatt-hour clears at the System Marginal Price — which can be far above or far below the old number. Something has to walk that plant from the old world to the new one without a cliff.

That walk is a vesting contract: a regulator-imposed two-way contract for difference on a named Trading Unit. It is not a Bid Desk trade, not a PPA you negotiate in the deal wizard, and not a price the generator and a buyer agree. A published determination (typically NERSA, recorded on the book with its document reference) names four things:

For each Trading Period the platform takes the lesser of the scheduled vested MWh and what the unit actually delivered, then multiplies that quantity by (vesting price − SMP). If the result is positive, the Market Operator pays the generator and the counterparty is charged the same amount. If it is negative, the generator pays and the counterparty receives. Energy above the vested cap trades merchant at spot, like any other unhedged megawatt-hour. Energy the unit did not produce does not vest at all.

The schedule declines. Year 1 may vest most of the plant; later years vest less, until the asset is mostly merchant. That declining curve is the instrument: its job is to hand the plant its spot exposure in instalments. A later period that raises vested MW for a block is refused — that would re-hedge the plant, which is the opposite of vesting. A genuine increase is a new determination, written as its own contract with its own source reference.

When one is created. A vesting contract is created when a determination is published and ingested — typically at market opening, or when a later determination covers a unit that was left out or that needs a new price or a new end date. You do not create one from this console. You do not amend MW, price, or counterparty here. The book is read-only on purpose: a console that let an operator type a vested MW would put the platform’s number and the regulator’s number out of step with no document between them.

When one is not created. A new merchant plant that entered SAWEM without a regulated legacy tariff has no vesting contract. An ordinary physical or virtual PPA between an IPP and an off-taker is a commercial deal, not vesting. A seat with no contract on this book is simply not vested.

A one-hour picture. The demo estate’s Mpumalanga Mid-Merit unit (BRP-SIM-IPP-12) is vested at R 650/MWh. In the first step of its curve the peak block is 180 MW. Take one peak hour in which the unit actually delivered 180 MWh:

Three years on the same book the peak step is 60 MW, not 180. Same price, same counterparty, less hedge: that is the curve doing its job.

The settlement kinds, the delivered-energy cap, missing-SMP carry-forward, and the participant’s hedged-versus-merchant panel are taught in V9 §19. A vested BRP reads that month on Month → Published results → Explain vesting (V10 §13.5). This page is the Market Operator’s register of every contract on file: who is vested, on which Trading Unit, under which determination, against which counterparty, and how far down the declining curve each contract has travelled.

Each contract #mo-vesting-contract-{id} shows:

The CPA has no separate book: it settles like any party and reads its statements like any party.

Empty #mo-vesting-empty: No vesting contracts on file. The demo estate seeds one illustrative contract on Mpumalanga Mid-Merit (BRP-SIM-IPP-12) against BRP-CPA-SAWEM under NERSA-VEST-ILLUSTRATIVE-2026.

Follow along. Seat: mo@webill.net / password supersecret. Path: Participants → Vesting. Confirm the mid-merit unit, the illustrative determination, the CPA counterparty, and three steps on the curve (180 / 140 / 90 MW peak-standard-off, then 120 / 90 / 60, then 60 / 45 / 30) at R 650/MWh.

Data. full_demo · seed 42 · stage S08. Gallery codes BRP-CODEX-PENDING / SUSPENDED / REVOKED are not all on Registrations — status filter.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

22. Registry

Path: Market Operator → Registry (/mo/registry). Second item in Eligibility. The icon is a clipboard. Optional ?tuid=TU-PV1 highlights #mo-registry-unit-TU-PV1 and survives tab changes.

Trading Units, Points of Delivery, reciprocity state, and standing-data review for the next trading day. This is the module named MarketDeskLive — not the Market Desk sidebar hop (§13). The accession-register 7-BD SLA lives on Participants (§21.5).

Where this is taught. What a Trading Unit is, and the participant wizards: V9 §3.9B. What accession is, and the joining clocks: V9 §3.13. The accession publication SLA: §21.5. Counterparty pairing from the BRP’s chair: V9 §3.4–§3.5. The System Operator’s inbox for the same share: V12 §6. Public accession register API: V13 §5.1.

### 22.1 The operator’s problem

Tomorrow’s solve will treat every registered plant as real. You need to know who is in force tomorrow, whether every meter has two owners, whether §7.2 fields are assumed, incomplete, or waiting on the System Operator. Today is too late. Who has acceded, and whether you have published that fact, is Participants → Accession register (§21.5).

### 22.2 How the page is laid out

Browser title: Registry. Header: Registry — Trading-unit registry and standing-data review for the next trading day.

Three icon tabs (#mo-registry-tabs), same tabs tabs-bordered chrome as Bidding and Zones.

Tab Path What it holds
Trading Units /mo/registry Registry board
Counter Party /mo/registry/counterparty Waiting on a declaration · no counterparty derived
Standing Data /mo/registry/standing-data Incomplete filings · SO certification queue
Section Id Tab Job
Registry board (§7.1, §7.2) #mo-registry-board Trading Units Units in force for tomorrow, standing-data cards
Counterparty pairing (§7.1(6), §12.3(1)) #mo-registry-counterparty Counter Party Two exception lists — chase vs commercial gap
Waiting on a declaration #mo-registry-pending-reciprocity Counter Party Reciprocity not yet filed — §7.1(6)
No counterparty derived #mo-registry-pending-counterparty Counter Party Nothing to derive from — §12.3(1)
Standing-data review (§7.2) #mo-standing-data Standing Data Incomplete / SO certification queue

### 22.3 Accession register — moved to Participants

The §6.2(9) publication SLA is a party clock, not a unit clock. It lives on Participants → Accession register (§21.5). This page is the §7 register of Trading Units, pairing, and standing data.

22.4 The registry board — units and today’s failures

Trading Units tab. Section #mo-registry-board.

Re-assert for tomorrow (#mo-registry-refresh) re-runs the checks for the next Trading Day, not today. The quiet line #mo-registry-model-version names that day, the zone-model version, how many units were checked, and §7.1(5). There is no red pairing banner — failures sit on the unit they belong to.

Standing-data cards (#mo-standing-data-summary) sit above the Trading Units table: units, fully evidenced, on assumptions, incomplete. The lists themselves stay in §22.6.

Find a unit. #mo-registry-units-filters searches TUID or name (#mo-registry-search) and filters by class (#mo-registry-filter-class), zone (#mo-registry-filter-zone), and Today’s failures (#mo-registry-filter-failures). Failures: all units, has a failure, no failure, or a Code clause that is on the board right now (§7.2(1)(i), §12.3(1), …). Combine with search, class, and zone.

Trading Units (#mo-registry-unit-count). The header stays in view as you scroll. Sort name, MCR (MW), and effective with #mo-registry-sort-name, -mcr, -effective.

Column How to read it
TUID Row #mo-registry-unit-{tuid}. An assumed badge (#mo-registry-assumed-{tuid}) opens the yellow assumption card in #mo-registry-assumption-modal.
Name Official name — sortable
Class Coloured badge: generating, demand side, storage, interconnector, mixed
Zone Colour swatch, then the code. Provisional models keep the honesty note on the swatch — they do not add *
MCR (MW) Maximum continuous rating — sortable by megawatts
Status Badge: registered / suspended / deregistered
Effective 1 Jan' 2026 — sortable
Today’s failures Centred Code clauses #mo-registry-failure-clause-{tuid}-{i} when the nightly re-assertion failed this unit. Hover #mo-registry-failure-tip-{tuid}-{i} on each clause for that failure’s message. An em-dash means this unit passed

Empty: No Trading Units registered yet. / None in force for this day.

The two Point-of-Delivery exception lists do not live on this tab. They are on Counter Party (§22.5). The same pairing failures also appear in Today’s failures on the unit — the lists are the worklist; the cell is the unit’s score.

What the clauses mean

Each red clause is one registry rule this Trading Unit currently breaks for tomorrow. Hover that clause for the sentence that explains it. Several clauses can sit on the same unit at once — fixing one does not clear the others. The same clause can appear twice when two meters fail the same rule; each hover names its own meter.

An em-dash (—) means this unit passed. It does not mean the network is clear, the pairing lists are empty, or standing data is fully evidenced. Read the cell, then Counter Party, then Standing Data.

The check is re-run against time, not against a save. A zone map published today with effect from tomorrow, a counterparty suspended this afternoon, or a bid accepted yesterday that no longer matches the plant — none of those need anyone to edit the unit. That is why you re-assert every morning, and why a unit that was clean yesterday can fail today.

The D−1 08:00 cutoff (§7.1(5)) is the last moment a registry change can take effect for tomorrow. A failure you find after that sits until the day after.

After you fix something

You do not type the remedy on this board. The BRP files standing data and meters; the named counterparty confirms pairing; the System Operator covers a location or certifies a rating. Your move is to chase the right person, then press Re-assert for tomorrow and watch the clause leave — or the cell go back to an em-dash.

Finder — every failure that can sit in the cell

These are the only failures the nightly re-assertion can put here. The hover on each clause is the source of truth; the names below match what that text is saying.

Clause In plain words Who usually fixes it
7.2(1)(i) The unit has no meters BRP — register and pair at least one Point of Delivery
3.3(4)(a) A meter sits off the published zone map System Operator — extend or publish the model
7.2(d) The named zone is not where the meters sit BRP — re-file the declared zone
2.1(212)(a) Meters sit in more than one zone BRP — split into one unit per zone
2.1(212)(b) Generator bigger than 1 000 MW, no SO letter BRP with SO — approval reference, or lower MCR
7.2 Standing-data fields still blank BRP and/or SO — whoever owns each missing field
7.2(f) Minimum generation is below zero BRP — file a non-negative floor
7.2(e) Nameplate is smaller than the floor BRP — raise MCR or lower Mingen
9.3(4)(c)(vi) Emergency Level 1 is below nameplate BRP — raise EL1 to at least MCR
7.2(h) Called storage, no storage form — or the reverse BRP — tick and file together, or clear both
7.2(g) Called energy-constrained, no energy budget — or the reverse BRP — tick and file together, or clear both
12.1 A factory in this unit has no meter BRP — fit or link a conforming meter
9.3(4)(c) An accepted bid no longer matches the plant BRP — resubmit the curve
12.3(1) A meter has no other owner Commercial — signed physical PPA, then re-assert
7.1(6) Named itself; named party cannot take energy; or the other side has not said yes BRP / named counterparty — see pairing below
2.1(21) A balancing group has fewer than two live units BRP — add a live unit or cancel the group
3.3(5) A grouped unit moved zone after a new map BRP — re-designate the group
13.10 A unit sits in two groups at once BRP — close the overlap

No meters on the unit — §7.2(1)(i)

What it means. The Trading Unit has no Points of Delivery. The market schedules and settles energy at meters. A plant with no meter is a name on a list — nothing can be dispatched, and nothing can be billed.

What it is not. It is not “the meters exist but pairing is incomplete.” That is a different failure (pairing, below). Here there is no meter on the unit at all. It is also not “this BRP may not bid”: the auction till can still pay the schedule. Why those two tills are different, and how an off-taker, IPP, or trader pool attaches a meter: V9 §3.4.

How to remedy it

  1. Send the BRP back to the Trading Unit registration wizard (V9 §3.9B).
  2. They register at least one Point of Delivery and complete pairing (§22.5).
  3. Re-assert for tomorrow. The cell should lose this line.

Meters the map cannot place — §3.3(4)(a)

What it means. One or more meters sit in a location the published zone model does not cover. Under a provisional model that is common — the map may cover only part of the country. The platform will not guess a zone. Guessing would put the plant in the wrong traffic jam and the wrong balancing group.

What it is not. It is not a typing error on the unit, and it is not “the unit spans two zones.” The unit does not span zones; it has a pin the map cannot see.

How to remedy it

  1. Read the hover — it names the affected Point of Delivery ids.
  2. This is a System Operator problem. Chase Zones / the SO to cover that location and publish the model (V12 §6).
  3. Do not invent a zone on the unit to clear the cell.
  4. Re-assert after the model that covers the pin is in force for tomorrow.

The named zone is not where the meters sit — §7.2(d)

What it means. The form says the plant is in one zone; the meters sit in another. The market schedules the unit against the declared zone’s congestion. A mismatch means the plant is treated as if it sits on the wrong road.

How to remedy it

  1. The BRP must re-file standing data so the declared zone matches the meters.
  2. After the §7.1(5) cutoff, that change waits until the day after tomorrow.
  3. Re-assert and confirm the zones agree.

One plant, two zones — §2.1(212)(a)

What it means. The unit’s meters fall in more than one network zone. One Trading Unit may not straddle two zones. It would be scheduled as if it were in one place while its energy appeared in two.

How to remedy it

  1. The BRP splits the plant into one Trading Unit per zone.
  2. Those units can later share a Balancing Group if the party wants to net imbalance (§21.12).
  3. You do not merge zones on this board to keep one TUID.

Plant bigger than 1 000 MW with no SO letter — §2.1(212)(b)

What it means. A generating unit’s maximum continuous rating is above 1 000 MW, and nobody has recorded a System Operator approval reference. The Code caps generators at that size unless the SO has said otherwise. Demand, storage, and interconnectors are not judged against this ceiling.

How to remedy it

  1. The BRP obtains an SO approval reference and files it on the unit, or lowers MCR to 1 000 MW or below.
  2. Re-assert. The hover names the megawatt figure that breached.

Standing data not filled in — §7.2

What it means. Required nameplate fields are still blank. A blank field is read as zero. Zero is a true answer for a solar farm’s minimum run time and a lie for a coal plant — so the platform will not treat “we left it empty” as zero. Until the fields are supplied, the unit cannot be treated as registered for tomorrow.

The hover names how many fields, who owns them (the party or the System Operator), and the first few labels.

How to remedy it

  1. Open Standing Data (§22.6). See who owns each missing field.
  2. Chase that owner — the BRP for party fields, the SO for certification fields.
  3. Incomplete cannot be papered over on this board. Re-assert when the cards move off incomplete.

Minimum generation is negative — §7.2(f)

What it means. The floor of the plant’s output is below zero. You cannot generate minus megawatts. The number is a floor for how little the plant can run, not a sign error.

How to remedy it

  1. The BRP files a Mingen of zero or more.
  2. Re-assert.

Nameplate smaller than the floor — §7.2(e)

What it means. Maximum Continuous Rating is below minimum generation. The ceiling is under the floor — the plant would have no operating range at all. The market cannot schedule a machine that must run at 80 MW and must not exceed 50 MW.

How to remedy it

  1. The BRP raises MCR, or lowers Mingen, so that MCR ≥ Mingen ≥ 0.
  2. Re-assert. If a bid was already accepted against the old numbers, you may also see the submission failure below.

Emergency Level 1 is below nameplate — §9.3(4)(c)(vi)

What it means. Emergency Level 1 is the top step of the production curve. It must sit at or above MCR. If EL1 is lower, the stairs stop short of the rating the market requires the curve to equal — every bid on that unit would be invalid.

How to remedy it

  1. The BRP raises EL1 so it equals or exceeds MCR, and aligns the bid elbows to match.
  2. Re-assert.

Called storage, no storage form — §7.2(h)

What it means. The unit is ticked as storage (a battery or pumped scheme) but has no §7.4 storage profile. The market is told it stores energy and has no charge rating, no tank levels, and no efficiency to schedule it with.

How to remedy it

  1. The BRP files the storage profile, or unticks storage if the tick was a mistake.
  2. Re-assert.

Storage form, not called storage — §7.2(h)

What it means. The §7.4 numbers exist, but the storage tick is off. The profile will never be read. It looks like data and behaves like nothing.

How to remedy it

  1. The BRP ticks storage, or removes the stray profile.
  2. Re-assert. Tick and profile must travel together.

Called energy-constrained, no energy budget — §7.2(g)

What it means. The unit is ticked as energy-constrained (limited fuel, water, or sun budget) but has no §7.3 profile. The market would dispatch it all day on its megawatt rating, and it would run out of energy partway through.

How to remedy it

  1. The BRP files the energy-constrained profile, or unticks the flag.
  2. Re-assert.

Energy budget, flag off — §7.2(g)

What it means. A §7.3 budget exists, but the unit is not designated energy-constrained, so the budget will not be applied.

How to remedy it

  1. The BRP ticks the flag, or removes the stray profile.
  2. Re-assert.

A factory in the unit has no meter — §12.1

What it means. An off-taker site belongs to this Trading Unit and has no metering installation. A site can exist as an ordinary customer without a wholesale meter. The moment it is part of a market registration, §12.1 applies: the market settles against a meter, not against a factory name. The hover names the site.

How to remedy it

  1. The BRP fits or links a conforming meter on that off-taker site.
  2. Re-assert. Do not drop the site from the unit just to clear the cell unless that is the real commercial answer.

Yesterday’s bid no longer matches the plant — §9.3(4)(c)

What it means. A day-ahead curve was already accepted. Standing data then changed (or is about to, for tomorrow). The bid’s elbows no longer match Mingen or MCR. Clearing would reject it. The hover says how many submissions are now stale.

How to remedy it

  1. The BRP must resubmit a curve that matches the registered ratings.
  2. You cannot edit the old bid on this board, and you cannot ignore it — the unit remains failed until a consistent sequence is in.
  3. Re-assert after the new submission is accepted.

Meter has no other owner — §12.3(1)

What it means. Every metered megawatt-hour must leave one party and arrive at another. This Point of Delivery names nobody on the other side. Usually there is no signed, active physical PPA to derive a counterparty from. Energy through that meter cannot be settled for anyone.

This is the same finding as Counter Party → No counterparty could be derived (PENDING_COUNTERPARTY). The cell puts it on the unit; the tab is the chase list.

How to remedy it

Follow §22.5 — get a governing physical contract in force, then re-assert. Do not type a name to clear the row.

The plant named itself as the other side — §7.1(6)

What it means. A Point of Delivery names its own party as counterparty. You cannot sell to yourself through the meter. The clause requires two different parties, one on each side.

How to remedy it

  1. The BRP names a different active BRP as counterparty — the real taker or supplier at that node.
  2. That party must then reciprocate (next failure).
  3. Re-assert.

The named other side cannot take the energy — §7.1(6)

What it means. A counterparty is named, but they are not an active balance-responsible party. Suspended, not a BRP, or inactive — they cannot carry the other half of the meter.

How to remedy it

  1. Check Participants → Registrations (§21.4) for that party’s status.
  2. Either they return to ACTIVE, or the declaring BRP names a different active BRP.
  3. Re-assert. Do not keep a suspended name in place “until they are back” if tomorrow’s day still needs a live pairing.

The other side has not said yes — §7.1(6)

What it means. A counterparty has been named and notified. They have not yet declared the same electrical node in their own registry (or confirmed the notification). The pairing is one-sided. A one-sided pairing is not a settlement basis.

This is the same finding as Counter Party → Waiting on a counterparty’s declaration (PENDING_RECIPROCITY).

How to remedy it

Follow §22.5 — chase Confirm (or a reasoned Dispute) on their counterparty inbox. Do not invent a substitute. Re-assert after they confirm.

Balancing group shrunk below two live units — §2.1(21)

What it means. A Balancing Group exists to net two or more live Trading Units against each other. This group has fallen to one — or none. Usually a member deregistered after the group was designated. One plant has nothing to net against, so the group no longer does its job. The failure is attached to a member unit’s cell.

How to remedy it

  1. Open Participants → Balancing Groups (§21.12).
  2. The BRP adds another live unit, or cancels the group.
  3. You cannot compose membership on the registry board. Re-assert after they file.

A grouped plant moved zone — §3.3(5)

What it means. The System Operator republished the zone map. A Trading Unit that belongs to a Balancing Group moved from one zone to another. The group’s cover is still designated, but the mix of zones inside it has changed. The hover names the unit and the from / to zones.

How to remedy it

  1. The BRP re-designates the group against the new zones (§21.12).
  2. Acknowledge the published model on Zones if that is still outstanding.
  3. Re-assert. Do not keep the old designation and hope the map reverts.

Plant in two groups at once — §13.10

What it means. The same Trading Unit sits in two Balancing Groups whose effective windows overlap. A unit may only be in one in-force group at a time. An amendment with a start date in the future can create an overlap that the original save could not see. The hover names the other group.

How to remedy it

  1. The BRP amends or cancels one group so the windows no longer overlap (§21.12).
  2. Do not pick a winner in the registry. Re-assert after the overlap is gone.

Careful. Four refusals happen on the form, not in this cell: creating a group with fewer than two units, grouping two different parties, adding a unit that is already grouped for that window, or registering a generator site that is already a Trading Unit. Those never appear as Today’s failures — the save is rejected on the spot.

Careful. Pairing failures on this cell and the two lists on Counter Party are the same facts. Clearing the wrong list with the wrong action wastes a day you do not have after the §7.1(5) cutoff. Read §22.5 before you chase.

22.5 Counter Party — pairing exceptions

Tab: Counter Party (/mo/registry/counterparty). Section #mo-registry-counterparty.

Header: Counterparty pairing (§7.1(6), §12.3(1)) — Every Point of Delivery needs two owners. One list is a chase; the other is a commercial gap. They are kept apart so the remedy is not mixed.

Re-assert for tomorrow (#mo-registry-counterparty-refresh) is the same re-assertion as on Trading Units — tomorrow’s Trading Day, not today.

§12.3(1) requires every metered megawatt-hour to be exported by exactly one party and imported by exactly one other. A Point of Delivery missing its other half cannot be settled — not for the party that declared it, and not for its counterparty either. The platform derives the counterparty from signed / active physical PPAs; it does not invent one (V9 §3.4).

Two lists. Same columns on both: pod_id · electrical_node · tuid · message. Empty state: None.

Waiting on a counterparty’s declaration — §7.1(6)

List: #mo-registry-pending-reciprocity. Status behind the row: PENDING_RECIPROCITY.

What it signifies. A counterparty has already been named — usually because derivation found a signed contract, or because a party declared one — and that counterparty has been notified. Until they declare the same electrical node in their own registry (or confirm the notification), the pairing is one-sided. A one-sided pairing is not a settlement basis.

The Code obliges you to inform the other party when a Point of Delivery is added or removed (§7.1(6)). This list is the open half of that handshake: notified, not yet answered.

What it is not. It is not “we do not know who the other party is.” You do know. The other party has not reciprocated yet.

How to remedy it

  1. Identify the named counterparty from the row (electrical node + declaring TUID + message).
  2. Chase that party — they clear it on BRP / Market → Market registry via the counterparty inbox: Confirm (pairing goes live) or Dispute with a written reason (V9 §3.5).
  3. Do not invent a substitute or re-derive past the named party. Confirmation is the reciprocal declaration for §7.1(6).
  4. Escalate silence. An unanswered declaration leaves both sides unsettleable at that node. If the declaration looks wrong, a dispute with a usable reason (“that busbar feeds the plant next door”) is faster than letting it sit.
  5. Re-assert for tomorrow after they confirm, and confirm the row leaves #mo-registry-pending-reciprocity.

No counterparty could be derived — §12.3(1)

List: #mo-registry-pending-counterparty. Status behind the row: PENDING_COUNTERPARTY.

What it signifies. No active contract names anyone at this Point of Delivery, so there was nothing to derive a counterparty from. The platform leaves the point empty and lists it here. That emptiness is the finding: either an unregistered commercial arrangement, a missing / unsigned physical PPA, or a Virtual PPA that never creates a wheeling pairing while the plant still injects real energy that needs a real taker.

What it is not. It is not a data-entry typo you fix by typing a name. It is not reciprocity waiting on a known party. Collapsing this list with the one above would send you to chase a counterparty who does not exist.

Only SIGNED and ACTIVE physical contracts count for derivation. NEGOTIATING or agreed-but-unsigned PPAs govern nothing yet. Ambiguous derivation (two active contracts naming different counterparties at the same point) is a registry conflict, not something the desk papers over.

How to remedy it

  1. Treat it as a commercial worklist. Ask: who is actually taking / supplying energy at this meter?
  2. Get a governing physical contract in force — signed and active — that names exactly one counterparty for that site and side. Then re-assert; derivation should name them and move the point to PENDING_RECIPROCITY (the chase list above).
  3. If only a Virtual PPA exists, remember it creates no Point of Delivery pairing. The injection still needs whoever physically takes the energy under a physical arrangement (V0 §5).
  4. If two contracts disagree, resolve the commercial conflict — §12.3(1) allows exactly one importer and one exporter per megawatt-hour. Do not pick a winner in the registry by hand.
  5. Never invent a counterparty to clear the row. A plausible-looking name would settle real energy against a party that never agreed to take it.
List Status Meaning Your move
Waiting on a counterparty’s declaration — §7.1(6) PENDING_RECIPROCITY Named and notified; reciprocity not filed Chase / confirm via their counterparty inbox
No counterparty could be derived — §12.3(1) PENDING_COUNTERPARTY No active contract to derive from Commercial fix — signed physical PPA (or resolve conflict)

Careful. Both exceptions block settlement at that node for everyone on the meter. Clearing the wrong list with the wrong action wastes a day you do not have after the §7.1(5) D−1 cutoff.

22.6 Standing-data review

Tab: Standing Data (/mo/registry/standing-data). Section #mo-standing-data.

Refresh standing data (#mo-standing-data-refresh). The four summary cards (#mo-standing-data-summary, -evidenced-count, -assumed-count, -incomplete-count) sit only above Trading Units (§22.4). This tab is the incomplete list and the SO certification queue (#mo-standing-data-queue-count).

Panel Id How to read it
Incomplete — §7.2 #mo-standing-data-incomplete Cannot register: missing count (#mo-standing-data-incomplete-count), by owner
System Operator certification queue — §7.2(q)–(t) #mo-standing-data-certification-queue Unit · Capability · Clause · Requested · Effective from · Status

Assumed standing data is flagged on the Trading Units table (amber assumed badge → detail modal), not as a separate yellow-card list.

You can see certification; you cannot make it. Until the SO certifies, capacity is 0.000 and availability indicators are U (V12 §6). Empty queue: Nothing awaiting a decision.

Follow along. Path: Registry. If you came from Submissions, the address already has ?tuid=. Confirm the highlighted row on Trading Units. Then open Counter Party and read both exception lists — they are different chases. Then read Today’s failures — a blank cell is invariants for that unit, not “the network is clear.”

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

23. IPPs

Path: Market Operator → IPPs (/mo/ipps). Third item in Eligibility. The icon is a bolt.

Generator sites filed through the standing-data wizard — organisation, BRP ref, TUID (deep-link to Submissions), fields supplied. Actions are icons with hover tooltips and distinct colours. View is first and expands certified reserve and the §7.2 field cards; then Certify, Chase, and Suspend unit (or Restore when the unit is already suspended). The Market Operator does not file Trading Units.

Where this is taught. The three participant wizards: V9 §3.9B. Reserve certification is the System Operator’s: V12 §6.

### 23.1 The operator’s problem

A plant exists in the org app. You need the market’s view of that plant: who owns it, which BRP speaks for it, how complete the §7.2 filing is, whether reserve is certified, a chase when the filing is stale, and a confirmed suspend when the unit must stop.

### 23.2 How the page is laid out

Browser title: IPPs. Header: IPPs — Generator sites registered with the market — organisation, BRP ref, and the §7.2 standing data filed for each plant.

No tabs. One table #mo-ipp-registry headed IPPs — {count}. Empty: No generator sites have been registered with the market yet. Search #mo-ipp-registry-search filters by IPP / site, organisation, or BRP ref. Sort headers: IPP / site (#mo-ipp-registry-sort-site) and MCR (#mo-ipp-registry-sort-mcr) by MW. The MCR header has an i icon #mo-ipp-registry-mcr-info whose tooltip is Maximum continuous rating.

### 23.3 The table — how to read a row

Row #ipp-row-{id}.

Column Meaning
IPP / site Generator site name
Organisation Who owns the plant
BRP ref The registration that bids it
TUID #ipp-tuid-{id} — navigates to /mo/bidding/submissions?tuid=
MCR Maximum continuous rating — i icon #mo-ipp-registry-mcr-info
Fields {supplied}/{total} §7.2 completeness (#ipp-fields-{id})
Actions Coloured icons with hover tooltips. View · Certify · Chase · Suspend unit (or Restore)
Button Id Colour What it does
View #ipp-view-{id} Brand purple Expands #ipp-expand-{id}
Certify #ipp-certify-{id} Amber Requests SO regulating-reserve certification. Flash on failure: Could not request certification: …
Chase #ipp-chase-{id} Sky Emits a registration notification. Chase recorded for {tuid}.
Suspend unit #ipp-suspend-unit-{id} Rose Opens confirm #ipp-suspend-confirm. Only after you OK: {tuid} is suspended.
Restore #ipp-restore-unit-{id} Emerald Shown instead of Suspend when the unit is already suspended. {tuid} is restored.

Suspend is not one click. #ipp-suspend-unit-{id} opens the confirm modal; #ipp-suspend-confirm writes the suspension. Back (#ipp-suspend-cancel) leaves the unit registered. Once suspended the row stays on the register and the icon becomes Restore.

Certify is a request. The SO still has to agree a MW figure and a reference. Until then certified capacity is 0.000.

### 23.4 The expanded card

Block Id How to read it
Completeness gate #standing-data-completeness {tuid} cannot be registered: N of M fields have not been supplied.
Certified reserve capability §7.2(q)–(t) #standing-data-reserve Capability · Clause · Certified · Status · SO reference · Indicator (A or U)
{tuid} — every §7.2 field #standing-data-editor Grouped as the Code groups them. Field · Clause · Value · Provenance · Data owner

Storage / energy-constrained edit forms appear only when editable: true — not on this seat. You inspect; the participant files.

Demo rows: IPP2 Atlantis Wind, IPP1 Sandton Solar, IPP3 Midrand Hybrid.

Follow along. Path: IPPs. Open IPP2 Atlantis Wind → View. Read the Fields ratio, then reserve indicators. Click the TUID to land on Submissions for that unit.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

24. Zones

Path: Market Operator → Zones (/mo/zones). Fourth item in Eligibility. The icon is a map.

Network Zone coverage, the gap list, the CSV that goes to the System Operator, and MO acknowledgement of the SO network-model version (§3.3(5)). Two tabs.

Where this is taught. What a zone is, and why a book can become three registrations: V12 §2. Editing corridors and flags: V12 §5. This chapter is the Market Operator’s coverage desk.

### 24.1 The operator’s problem

Tomorrow’s constrained solve needs every Trading Unit in exactly one zone. Sites the model cannot place are silent failures until someone exports the gap list. An SO model version you have not acknowledged is not yet the register you will clear against.

### 24.2 How the page is laid out

Browser title: Zones. Header: Zones — Network-zone register in force, coverage, and sites the model cannot place.

Tab bar #mo-zones-nav.

Tab Path live_action What it is
Zones /mo/zones :zones Register in force, coverage, ack
Unplaced Sites ({N}) /mo/zones/unplaced :unplaced Gaps + overlaps + CSV

CSV (not a LiveView): GET /mo/zones/gaps.csv.

### 24.3 Zones tab — acknowledge, then read the register

SO network-model version (§3.3(5)) (#network-model-ack):

Control Id What it does
Acknowledged by #network-model-ack-by Authoriser — required
Effective from #network-model-ack-from Date — required
Acknowledge #network-model-ack-form Records the ack. Two-month notice before the model binds.

No SO version yet: No SO network-model version has been received. The register below is provisional until one is. Errors: Acknowledgement needs an authoriser and an effective date.

Network zones (§3.3(4)) (#mo-zones-panel). Recompute coverage (#mo-zones-refresh). Banner is either #mo-zones-provisional-banner (Mutually exclusive, Not exhaustive, no inter-zonal capability figures) or #mo-zones-published-banner.

Coverage stats: Zones · Total Trading Units · Market sites · Allocated (#mo-zones-stat-zones, -stat-trading-units, -stat-total, -stat-assigned). Only ACTIVE BRP units count.

Column How to read it
Zone Code; row #mo-zone-{code}
Name Everyday name (Northern Corridor, Highveld Load, …)
Sites Click #mo-zone-{code}-site-count to expand
Trading Units Click #mo-zone-{code}-tu-count
Dominant character What the zone mostly is
Core nodes e.g. Apollo, Minerva, Kendal
Market implication What a constraint here does to clearing
Effective From when

Expanded sites: Organization · Site Name · Type (Generator / OffTaker) · Address (opens the map modal) · Meter Number.

Expanded units: TUID · Name · Organization · Kind (IPP / OffTaker / Trader Pool) · Site / Pool · Class · Status · MCR · BRP.

No model: No zone model loaded. The provisional register lives in docs/references/market/spec/zones/fullspec.json.

Nine provisional zones Z1–Z9 until the SO publishes. The areas do not overlap (good); they cover only about a fifth of the country (not good). Every corridor figure is an estimate until declared (V12 §2.3).

### 24.4 Unplaced Sites — gaps, overlaps, include

#mo-zones-unplaced-panel — Sites the model cannot place. Recompute coverage (#mo-zones-unplaced-refresh). Export for the SO (#mo-zones-gap-export) → /mo/zones/gaps.csv.

All placed: Every market site falls inside a zone. No model: No zone model loaded — coverage (and therefore unplaced sites) cannot be computed yet.

Column Meaning
Organization Who
Site Name
Kind Generator / OffTaker
Address Opens #mo-zone-site-map-modal (Leaflet — pin + distance line to nearest zone)
Nearest zone Best guess
Distance How far the pin sits outside
Which way Direction of the miss
Action Include (#mo-zone-gap-{site_id}-include) — expands the nearest zone polygon

Include is a Market Operator action. Overlay #mo-zones-include-overlay: Including site in nearest zone… Failures flash (overlap, already allocated, no nearest zone).

Overlaps (#mo-zones-overlaps): {n} site(s) fall in more than one zone — the model overlaps and allocation is undecidable there. That is a model bug, not a site bug.

Follow along. Path: Zones. If the banner is provisional, read it before you plan a corridor. Open Unplaced Sites. If the count is zero, every market site is inside a zone — not “the network is unconstrained.” Export the CSV only when you mean to send it to the SO.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

25. Rules

Path: Market Operator → Rules (/mo/rules). First item in Reference. The icon is a book.

Publish market parameter versions — gates, floor and cap, and the eight [D-nn] defect switches with their clause. A published version with effective scope is the safe completion signal. There is no inline edit of the live table.

Where this is taught. Why the eight switches exist: V9 §17. This chapter is the publish ceremony.

### 25.1 The operator’s problem

Tomorrow’s solve will hash the parameters it used. If you quietly change the price cap on the live table, yesterday’s run and tomorrow’s run pretend to share a rulebook. A new version must be composed, reviewed, and confirmed — with an effective date — so two runs that differ by one intended input are visible as different.

### 25.2 How the page is laid out

Browser title: Rules. Header: Rules — Market Code parameters, defect switches, and confirmed version publishing.

No route tabs. Three stages: :closed (read) → :edit (compose) → :confirm (review). Panel #mo-rules-panel — Market rules — all twenty-four parameters. Empty: No parameter version published yet.

Metadata strip: Effective from (#mo-rules-effective-from) · Stated until · Determined by · Snapshot hash (#mo-rules-snapshot-hash). Badge #mo-rules-carried-forward: Carried forward past its stated period (§2.3(r)) — values stay live after effective_to.

View Market rules (#mo-rules-view-pdf) opens #mo-rules-pdf-modal with Market Code Rev 2.3 in a PDF viewer. Tabs switch to the four SAWEM Rules (conduct, CPA, disputes, BRPs). Close, print, or download from the footer.

Publish new version… (#mo-rules-publish-open) opens the compose form. You cannot type into the read table.

### 25.3 The twenty-four parameters — how to read a row

Eight groups. Each row #mo-param-{key}: Label [D-nn] · Value · Unit · Clause · Effective date. Sentinels: MGC determines, not set, —.

Group What lives here
Prices and caps Market Price Cap [D-18], Price Floor, IDM collar (% of SMP)
Reserve floor prices Instantaneous / Regulating / Ten-minute floors (R/MW)
Gates and auctions DAM gate (SAST, D−1), five IDM gate times
Metering and balancing Accuracy band, Out of Merit Energy [D-07], Balancing Penalty Factor [D-04]
Settlement and disputes Materiality (R), Recalculation threshold (%), Default interest, Risk period
Credit cover Undefined Exposure Factor, Warning Limit max, Adjustment trigger
Registry thresholds DSU / Generator suspension delay (days), MCR ceiling, participant threshold (kW)
Market grain and bid format Trading Period length (minutes), Maximum bid lines

Shipped commencement (tests): effective 2026-01-01, Market Price Cap R 5,396.40 / MWh (not the legacy 32,000). A staged future version may show cap R 5,800.00 and gate 09:30:00.

25.4 The eight defect switches

Table Defect switches — which setting is live. Row #mo-switch-{key}: [D-nn] · Label · Live setting · Clause · Effective date.

Defect Question the switch answers
D-08 May a flexible Demand Side Unit set the SMP?
D-09 Which volume the on-instruction balancing leg prices
D-07 Fraction of the Out of Merit Energy allowance that binds
D-06 How the Balancing Price Selling is clamped to the SMP
D-11 Must a unit be deliverable to enter the balancing stack?
D-13 How the debit-note cascade recovers an excess
D-02 Reference price for the additional energy payment
D-10 Pricing of the gap in the against-instruction leg

Defaults include true, delivered, 1.0, floor_at_smp, sequential, smp, none. Changing a switch is a new version, not a toggle on today’s run.

### 25.5 Compose → review → confirm

Compose (#mo-rules-publish-form): every parameter (number / text / time; IDM gates are five time fields, captions Iter 1 D−1 …), every switch, Effective from (default tomorrow), Stated until (optional), Determined by (default MGC determination). MGC-determined params carry placeholder MGC determines — leave blank.

Review version… (#mo-rules-review) opens #mo-rules-publish-review. Changed rows only: Parameter · Clause · In force · Proposed (#mo-rules-change-{key}). No diffs: No parameter differs from the version in force. Publishing will record a new version with identical values.

Confirm and publish version (#mo-rules-confirm-publish). Flash: Parameter version published, effective {date}. Failure: Could not publish the parameter version — check the values. Back to edit returns to compose. Cancel abandons.

A parameter version is a ceremony, not an inline edit
closed
→Publish new version…
edit
→Review
confirm

Cancel from edit or review returns to closed. The live table never becomes a spreadsheet.

Follow along. Path: Rules. Read #mo-rules-snapshot-hash — that hash is what Runs pins. Do not publish a version whose effective date is today unless you mean today’s remaining callables to see it.

Careful. Rules changes the future validation boundary. They do not rewrite a published schedule.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

26. Runs

Path: Market Operator → Runs (/mo/runs). Second item in Reference. The icon is a rectangle-stack.

Every Mo.Run: inputs hash, parameter hash, supersedes, kind. Two runs that differ by one intended input are not the same run. Read-only. No refresh button — the list follows the month (and optional kind) in the URL.

### 26.1 The operator’s problem

Someone will ask which solve produced this SMP? Cadence tells you whether publish ran. Daily tells you the sentence Published at 13:40. Runs tells you the fingerprint: the inputs that went in, the parameter version that bound the arithmetic, and whether this run superseded another. That is the flight recorder.

### 26.2 How the page is laid out

Browser title: Runs. Header: Runs — Every clearing and settlement computation as an immutable run: inputs hash, parameter hash, supersedes, kind.

One table #mo-run-browser. You land on the current SAST month (label like August 2026). ‹ (#mo-runs-month-prev) and › (#mo-runs-month-next) step a month; next is disabled once you are on the current month. Deep-link with ?month=2026-07. The header row stays visible while you scroll (#mo-run-browser-scroll, sticky th).

Empty is month-aware: There are no runs in August 2026. when that month is quiet; No runs recorded yet. only when the browser has nothing at all. A load error also presents as empty.

Kind filter #mo-runs-kind-filter — eleven coloured chips, one per kind, plus All. Default is every kind in the selected month. Click a chip to keep that family; click more to combine; All clears back to the full month. Optional ?kind=dam-prices. If the month has rows but none match, you see No runs of the selected kind in August 2026.

Click Date (#mo-runs-sort-date) to toggle newest-first and oldest-first on trading_date (then started_at). Default is newest-first. Dates read 18 Aug 2026, not ISO.

Column How to read it
Kind Coloured badge #run-kind-{run_id} — DAM (sky), IDM (violet), metering (amber), balancing (emerald), settlement (orange), administered (zinc)
Date The Trading Day or Billing Period the run is about (%-d %b %Y)
Inputs hash #run-inputs-{run_id} — click to open the stored intended-inputs payload (#mo-run-payload-modal). The hex is a seal, not a cipher.
Parameters hash #run-parameters-{run_id} — click to open the stored Rules-snapshot payload in the same modal
Supersedes The prior run this one replaced, or —

Row #run-{run_id}. Matching inputs hash and parameters hash means Run.reproduces?/2 — same answer if you ran it again. A correction chain is the Supersedes column, not a silent overwrite.

Metaphor. Cadence is whether the train left. Daily is the arrival board. Runs is the sealed logbook: locomotive number, timetable version, and which earlier logbook this one replaces.

One published day, three fingerprints you can audit
Cadenceran / missed
→wrote
Runinputs · params · supersedes
→shown as
DailyPublished at HH:MM

You cannot delete a run. You cannot edit a hash. If a curve is wrong, the BRP sends a new sequence and you solve again — a new row, a new inputs hash, and (after publish) a supersede.

Follow along. After you Solve then Publish on Daily for 2026-07-15, open Runs and step back to July 2026 (or open /mo/runs?month=2026-07) — the default month is today, so July is one click behind. You should see a new row whose parameters hash matches #mo-rules-snapshot-hash on Rules. Two solves with the same submissions and the same rules reproduce; change one offer and the inputs hash moves.

Where this is taught. Publication, hashes and the sandbox: V9 §12 · V13.

You are here
1Setup
→
2Deal
→
3Strategy
→
4Nominate
→
5Market day
→
6Settle
→
7Statement

27. The forward register

Path: Market Operator → Forward (/mo/forward). Third item in Market day, after Cadence. The icon is a calendar.

This is the book of physical bilateral schedules registered before the day-ahead gate, and the transfer capability they consume. Residual clearing — why a registered schedule is a constant, not a bid — is §6.8. The instrument, the gate and the participant API are V9 §20.

27.1 The register

Screen: /mo/forward (#mo-forward-register). Pick a delivery day. Every schedule whose horizon covers that day is listed: seller Trading Unit, buyer, horizon, version, status, and the per-period profile.

Status is a closed machine. You do not skip steps.

Status What you may do
SUBMITTED Validate (#mo-forward-validate-…). The remaining-capability check.
VALIDATED Register (#mo-forward-register-…). Your act, not the participant’s.
REGISTERED Live. Consumes transmission. Enters the day-ahead run as a C1 constant.
SUPERSEDED History. The profile is kept so a Settlement Rerun can say what the register was.

A skip from SUBMITTED to REGISTERED is refused: validation cannot be skipped. A participant caller registering is Isolation’s 404, never a 403.

If validate refuses, the flash names the Trading Period, the edge (for example zone Z1 export), the megawatts over, and any earlier registrations that already took the room. Capability is consumed first-come. Nothing is pro-rated.

27.2 The capacity view

Screen: /mo/forward/capacity (#mo-forward-capacity). Same delivery day.

Remaining transfer capability is capability minus registered flow, per Trading Period, per edge. The definition is written down in V9 §20.6 and nowhere else — stage 13 inherits this figure as the “remaining” half of available transfer capability.

Each row stamps provenance on its face:

Stamp Meaning
DECLARED The underlying capability is a System Operator declaration. The remaining figure may be published as a network limit if the rest of the model is publishable.
ASSUMED The underlying capability is the corridor roll-up (or an assumed interconnector). The remaining figure is not publishable as a network limit.

An assumed stamp that fell off on the way to a quoted ATC would be a number nobody can stand behind. The stamp stays on the screen.

The platform still implements exactly one security-constraint kind, :ZONAL_EXPORT_LIMIT. This view does not invent a corridor-flow constraint. Corridor remaining is reported; it is not a new LP family.

27.3 Why the stamp matters

Provisional.publishable?/1 still decides whether the network model may be published as a limit. Remaining capability inherits that verdict. Publishing an ASSUMED remaining figure as if it were declared capability would tell a neighbouring operator — and, later, a SAPP counterparty — a number this System Operator cannot stand behind.

If the figure you need is not on this screen, the model does not have it. Do not copy a corridor sum into a declaration by hand.