Risk control exists to stop you when the money runs out. But if it treats "cannot read" as "is zero", it will also stop you when the money is fine — and you will believe it worked. Two real misfires, and the one rule behind both: "unknown" must not be wrong in either direction.
A real-money line had a rule: stop ordering when wallet cash falls below a floor. About five and a half hours after launch it read $145.41, below the $150 floor, wrote a halt flag and stopped.
| Amount | |
|---|---|
| Wallet cash (what risk control saw) | $145.41 |
| Already won, mid-redemption | $94.8 |
| True net worth | about $240 — half again over the floor |
The cause: the floor used a pure cash basis, inherited from a four-hour line where redemption lag does not matter. On five-minute windows the lag (measured at six to eleven minutes) is permanently overhead, so wallet cash systematically understates itself.
The same code that is correct on a slow cadence gets punched through by settlement lag on a fast one.
Generalised: any judgement that depends on "the money has arrived" needs one question — "how long does arrival take, and how often do I check?" Check faster than money arrives and you will misjudge, guaranteed.
The same error in a display layer. A monitoring panel took a metric with "use it if present, otherwise zero" — so when the read failed, the page displayed a tidy $0.
| Page shows | Could mean | What you do |
|---|---|---|
| $0 | it genuinely is zero | correct response |
| read failed / endpoint down / field renamed | you act on fabricated data |
This one is insidious because $0 looks like a legitimate number. Show "—" or "read failed" and anyone knows to investigate. Show $0 and they treat it as a fact.
| Treat unknown as | Consequence | Example |
|---|---|---|
| zero | false halt: money present, stopped anyway | in-flight funds not counted |
| fine | blind running: floor breached, nothing stops | feed dies, risk control reads a stale value and keeps allowing |
The correct treatment is to make unknown a third state, handled separately:
| Situation | Do |
|---|---|
| Risk control cannot read the balance | pause without writing a permanent flag — wait a cycle, take no irreversible action |
| Display cannot read a value | render "—" or "read failed", never 0 |
| Funds in transit | model them explicitly, not "they will land shortly" |
| Data going stale | add a staleness alarm: no update for N minutes triggers a warning |
The first row deserves expansion: halting comes in reversible and irreversible forms. Pausing a cycle because a read failed is reversible; writing a halt flag that needs manual clearing is not. When information is insufficient, take only reversible actions.
I found this hole in one of my own dashboards: the page had a slot for a staleness warning, styled and positioned — and no code ever wrote to it. Which is to say the page had no staleness alarm at all.
Consequence: if the data source dies quietly, the page keeps displaying the last good numbers and everything looks fine. A monitor that always reads "normal" is more dangerous than no monitor, because it makes you stop asking.
| Ask | Failing answer |
|---|---|
| What is this variable when the read fails? | "defaults to 0" |
| Does the risk basis include funds in transit? | "they should arrive soon" |
| How long without an update before it alarms? | "not set" |
| Where was this risk rule copied from? | "another line" — at what cadence? |
| Is the halt reversible? | do not know = probably not |
No. That floor basis stayed on the "to decide" list until the line closed. Which means the final fifteen-odd hours of risk control ran on a basis that understates itself.
That is written here not for self-criticism but because it is what a kill file is for: a defect found, recorded, and not fixed — that fact belongs on the page too.
Risk control's most dangerous failure is not "it did not fire" — it is "it fired for the wrong reason", because then you believe it protected you. And nearly every failure of that kind traces to one sentence: treating "I do not know" as a number.