← All posts

The Reassuring Number Was the Honest One

Two of our readings disagreed about whether a position was still open. One said exposure, one said flat. We flagged a defect in the calm one — because trusting the alarming reading feels like the responsible choice. It was backwards, and the same mistake turned up on a different desk the next day.

Closing a position is not an instant. It looks like one from the outside — you were exposed, then you weren't — but inside a trading system it's a short interval in which several independent records each learn about the exit and update themselves. For a few seconds, they disagree.

We knew that. We still got it wrong, and the way we got it wrong is more interesting than the fact of it.

The call, and the correction

One of our monitors reported that a position had gone flat. Other readings, consulted at the same moment, still showed live exposure.

That's a contradiction, and it needed resolving. Our agent resolved it the way most people would: it treated the reading that disagreed with its expectation as the suspect one and filed a monitoring defect — a field claiming no exposure while exposure demonstrably existed. That's the frightening version of the story, and it's the one that got written down first.

Half an hour later, the same agent retracted it:

My defect call was backwards. The exit had already filled, and the reading I flagged had updated correctly. The other readings were the stale ones. A close is a transition boundary where different records settle at different times; resolve the inconsistency against the authoritative ledger — not by assuming the reassuring reading is the liar.

The calm number was the honest one. The alarming numbers were simply behind.

The bias worth naming

There was no carelessness here. The agent saw a genuine contradiction and had to pick a side under time pressure, and it picked the one that felt responsible.

That instinct deserves to be stated plainly, because it's nearly universal and it's wrong:

When two readings disagree, believing the alarming one feels like the conservative choice. It isn't. It's just a different bias — and it inverts your diagnosis exactly as often as the opposite bias would.

"Assume the worst" is good advice about consequences. It is not a method for determining facts. Applied to a factual question — is this position open or closed? — it doesn't add caution, it adds error, and it adds it in a direction that's hard to see because the resulting mistake looks like diligence.

In this case the cost was small: a false defect report, retracted in thirty minutes. But run that bias the other way and the same reasoning tells you a real exposure is a stale reading. The bias isn't safe in one direction; it's just differently unsafe.

The same mistake, one day later, on a different desk

If this were one agent's bad afternoon it wouldn't be worth publishing. It happened again the next day, in a different shape, in a different part of the system — and the second instance is the one that makes it a pattern.

A shared helper that classifies whether a position is still in flight reported five positions as open, and a risk flag was raised on the strength of it.

All five had already closed. The book was flat. There was nothing to be exposed to.

The helper inferred "still open" from status alone, without requiring confirmation that an exit had actually filled — so during the interval before every record agreed, it would call a closed position live. Again the alarming reading was the wrong one. Again what settled it was going to the authoritative record, rather than taking a second look at the instrument that raised the alarm.

And the detail that stings: this was the shared, canonical check — the one built precisely so that consumers would stop hand-rolling their own status logic. Centralising a test is genuinely worth doing; it's how you stop twelve slightly different answers to the same question. But it's worth being clear-eyed about what it buys you. Consolidating a check doesn't make it correct. It makes it uniformly whatever it is — and if it's subtly wrong, you've bought consistency in being wrong, in more places, with more confidence.

What we changed, and what we only decided

The fix isn't a better instrument. It's a rule about which instrument wins — and we should be precise about which parts of it are actually in force.

There is one authoritative record for whether a position closed: the broker's own ledger. Everything else — our monitors, our derived views, our helpers — is a convenience that may be ahead of it or behind it at any given moment. When they disagree, the ledger settles it. Not the scariest reading, not the most recent one, not the one that matches what we expected.

Two consequences we didn't appreciate before:

A disagreement between readings is not automatically a defect. It's the expected behaviour of independent records during a transition. Filing a bug against whichever reading happens to be ahead of the others is a way of punishing an instrument for being quick. The agent that made the first error now requires several signals to agree before it will call a book flat, and treats a lone dissenting reading during a close as ordinary settling rather than as evidence.

"Still open" needs a positive test, not the absence of a negative one. The shared helper's flaw was inferring continued exposure from a status that hadn't yet moved. Asking has an exit actually filled? is a different question from does this still look open?, and only the first one has an answer that doesn't depend on timing.

Now the honest part: only the first of those is a rule anyone can point to, and none of it is yet a deployed control. The truth-ordering doctrine is written down and is what we operate by. The multi-signal check is one agent's own practice, adopted after its own mistake — not a change to a monitoring service, and nothing stops the next consumer from doing what the first one did. The shared helper's positive-confirmation flaw is diagnosed, not fixed. We are publishing this with the remediation half-done, because the alternative is telling you we closed something we haven't.

The good

Both errors were caught by the people who made them, within an hour, and written down as corrections rather than quietly amended. The second was volunteered specifically so the first wouldn't read as one agent's bad day — which is the only reason you're reading a pattern instead of an anecdote.

Neither produced a bad trade. In both cases the false reading led to an investigation, not an intervention. That's the system's protections working in the boring, correct way: the gap between "something looks wrong" and "act on it" is where both of these got caught.

And the resolution rule that came out of it was already half-built. We'd adopted broker-truth-over-derived-numbers for profit and loss months ago, after a different incident where our internal accounting and the broker disagreed about money. What we hadn't done was extend the same ordering to position state. The principle was right; we'd just applied it to one question and not the neighbouring one.

The bad

We wrote the wrong conclusion down first, and in both cases the wrong conclusion was the alarming one. A reader can reasonably ask how many other findings in our logs are that shape and simply weren't revisited. We don't know. The two we caught were caught because somebody chose to re-examine a conclusion nobody had challenged.

The shared helper had been wrong for as long as it had existed. It passed review, it was adopted deliberately as the canonical implementation, and nothing in that process asked whether "in flight" needed a positive confirmation. It took a false alarm on a flat book to surface it.

The ugly

We had already learned this lesson in a neighbouring domain and didn't carry it across.

The rule "when our numbers disagree with the broker's, the broker is right" was established, documented, and in force — for money. Nobody thought to ask whether the same ordering applied to state. So we re-learned it, from scratch, in a second domain, at the cost of two false findings and the time to chase them.

That's the generalisable failure, and it's not about trading: a truth-ordering rule is almost never scoped correctly on the first pass. You establish it for the question that hurt you, and it sits there, narrowly applied, while the identical ambiguity exists three feet away in a different question. The lesson didn't need re-learning. It needed re-scoping, and nothing in our process was looking for that.

What we'd tell another team

  1. Name your authoritative source per question, in advance. Not "the broker is the source of truth" in general — for this specific question, which record settles it? Vague truth-ordering resolves nothing at 3 a.m.
  2. Treat "assume the worst" as advice about consequences, never about facts. For a factual question it isn't caution, it's a coin-flip wearing a hard hat.
  3. Expect disagreement during transitions and don't file it as a bug. Independent records settling at different rates is design, not defect. Require agreement across several signals before you believe a state change.
  4. Prefer positive confirmation over the absence of a negative. "Has the exit filled?" beats "does it still look open?" every time, because only the first has an answer that doesn't depend on when you asked.
  5. When you establish a truth-ordering rule, immediately ask what else it applies to. That's where ours failed — not in the rule, but in its scope.

The calm reading was right both times. That's not a reason to start trusting calm readings; it's a reason to stop resolving contradictions by vibe and go ask the record that actually knows.


Part of an ongoing series on what actually happens when you automate trading with AI agents — published including the parts that don't flatter us.