Ground Truth

When You Automate the Gatekeeper Away, Every Check They Made By Eye Becomes a Rule You Have to Enforce

Mostafa DhouibMostafa Dhouib·9 min read
The short answer

A platform that lets a counterparty accept a binding quote without a human looking at it has not removed the gate, it has moved it into code. Every check the trader used to perform by judgement now has to exist as an enforced rule, the binding action has to be idempotent, and the number the engine computes has to equal the number the human would have produced, to the cent. The rounding trap that makes a parity test agree with itself is the one that costs money.

When You Automate the Gatekeeper Away, Every Check They Made By Eye Becomes a Rule You Have to Enforce

The short answer. Letting a counterparty accept a binding quote on their phone, with no human in the loop, does not remove the gate that human was. It relocates it into software, and everything that person did by judgement now has to be written down as an enforced rule. Three things follow and all three are load-bearing: every check they made by eye has to be enumerated and encoded, the binding action has to be idempotent because a double tap must not become a second trade, and the number the engine computes has to equal the number they would have produced to the cent. That last one has a trap in it, because a parity test built from a spreadsheet export compares your engine against a number that was already rounded, and therefore agrees with itself.

There is a category of product whose real specification is not written anywhere, because it lives in the head of the person being automated away.

A trader quotes prices. Before a price goes out, they look at it. That glance is not idle: they are checking a dozen things at once, drawn from years of doing it, most of which they could not enumerate if asked. Is this counterparty entitled to this grade. Is this volume plausible. Does this margin look right for this corridor this week. Has something moved since we last quoted them.

Then you build a platform where the quote goes out executable, and the supplier can accept it on their phone, and nobody looks at it first.

That is the product. It is also the risk, and they are the same thing.

The gate did not disappear

The appealing story is that the platform removes a bottleneck. The accurate story is that it moves a decision from a person to a system, and the system now has to make that decision on every quote, correctly, without judgement available to it.

A person can look at a number and think "that cannot be right". Software cannot, unless somebody wrote down what right looks like.

So the first real task is not building screens. It is enumeration: sitting with the person being automated and extracting every check they perform, including the ones they do not know they perform. This is slow, it feels like requirements-gathering rather than engineering, and skipping it is how these platforms fail. The checks do not stop being necessary when they stop being performed.

The honest framing for what you cannot get out of them: a rule the trader held in their head and never stated is a gap in the platform until it is written down. The platform should stop on a case no stated rule covers, rather than proceeding on a default that nobody chose.

The trader's glance
Is this counterparty entitled to this grade
Is this volume plausible
Does this margin look right for this corridor this week
Has something moved since we last quoted them
A dozen checks they could not enumerate
drawn from years of doing it, and the real specification is not written anywhere
What the platform has to hold
Every check enumerated and encoded
slow, feels like requirements gathering rather than engineering, and skipping it is how these platforms fail
An idempotency key on the binding transition
a double tap on poor signal must not become a second trade
Explicit states with defined transitions
quoted, accepted, executed, recorded, rejected, so an impossible combination is unrepresentable rather than unlikely
A stop on any case no stated rule covers
rather than proceeding on a default that nobody chose
judgement becomes specification
A person can look at a number and think that cannot be right. Software cannot, unless somebody wrote down what right looks like. The checks do not stop being necessary when they stop being performed.
FigureLetting a counterparty accept a binding quote with nobody looking at it first does not remove the gate that person was. It relocates the gate into software, and everything they did by judgement now has to be written down as an enforced rule, including the checks they could not enumerate if asked.

Accept is binding, so accept is idempotent

Once acceptance creates an obligation, the transition that records it has to be correct the first time and harmless every time after.

This is not a theoretical concern on a mobile product. A supplier taps accept on a phone with poor signal. Nothing visibly happens. They tap again. Without an idempotency key on that transition, that is two trades, and the operator is now holding a position twice the size they intended against a counterparty who believes they agreed once.

The same applies to any retry in the path: a client that retries on timeout, a proxy that replays, a webhook redelivered. The defence is the same one in every case. The acceptance carries a key, the key is checked before the transition is applied, and a repeat resolves to the same single execution.

Model the trade as a state machine with explicit states rather than a row with flags. Quoted, accepted, executed, recorded, rejected, with defined transitions between them. An impossible combination then becomes unrepresentable rather than merely unlikely, and the record of what happened is append-only rather than a mutable current value, which is what lets settlement and reporting both read from one history instead of maintaining two copies that can disagree.

The number has to match, to the cent

Here is the part that is genuinely easy to get wrong while believing you got it right.

The platform computes a price. The business has been computing that price in a workbook for years. If the two disagree by a cent, the operator is exposed on every quote, and the exposure is silent, because a wrong number looks exactly like a right one.

So before any counterparty sees an executable price, you prove parity: the engine's output equals what the business's own historic quotes produced, on the same inputs.

The obvious way to do this is to export the historic quotes to CSV and compare. That is the trap.

Why the CSV export cannot find the bug

Rounding is not one behaviour, it is several, and they disagree on exactly the inputs that matter.

A spreadsheet rounds half away from zero. Given 2.15 at two decimal places it produces 2.2. Common implementations in application code round half to even, or operate on binary floating point where 2.15 is not exactly 2.15 to begin with, and produce 2.1 on the same input. A double-precision column in a database can do the same.

That is a one-cent divergence on a boundary value, which is precisely the kind of difference that is invisible until it is a wrong binding quote.

Now the trap. A spreadsheet writes CSV as displayed values, not stored ones. So when you export the historic quotes, the export has already applied the spreadsheet's rounding. Your harness compares your engine's output against a number that was rounded by the very mechanism you are trying to test. If your engine is wrong in a way that only shows at the boundary, the export has helpfully removed the evidence.

The test passes. The test was always going to pass. It is comparing a rounded number against a rounded number and confirming they agree.

The spreadsheet rounds half away from zero
2.15 at two decimal places produces 2.2
Application code often rounds half to even
or operates on binary floating point where 2.15 is not exactly 2.15, and returns 2.1 on the same input
A double precision database column does the same
The export writes displayed values
the spreadsheet's rounding is already applied before your harness sees anything
The failure point
The harness compares a rounded number against a rounded number and confirms they agree. The test passes, and the test was always going to pass.
If the engine is wrong in a way that only shows at the boundary, the export has helpfully removed the evidence. A one cent divergence on a binding quote is invisible until it is expensive, because a wrong number looks exactly like a right one.
Read stored workbook values at full precision rather than an export, and pin the rounding mode explicitly instead of inheriting whichever one the language or the database happens to use. Prove parity against the quotes the business actually issued, not against a formula reconstructed from memory.
FigureThe parity harness is supposed to prove the engine's number equals the number the business would have produced. Built from a spreadsheet export it proves something else, because a spreadsheet writes its displayed values rather than its stored ones, so the comparison has already been through the mechanism under test.

The fix is to read stored workbook values at full precision rather than an export, and to pin the rounding mode explicitly in the engine rather than inheriting whichever one your language or database happens to use. The rounding behaviour should be a stated decision, not an accident of the stack.

Parity against history, not against the specification

Prove the engine against the quotes the business actually issued, not against a formula someone wrote down for you.

Two reasons. The written formula is usually incomplete, because the person writing it reconstructs it from memory and leaves out the adjustments they apply without thinking. And the historic quotes cover the cases that actually occur, in the proportions they occur in, which no synthetic test set will.

A case never quoted historically is untested until it happens. The right behaviour there is for the engine to flag the unknown case rather than guess at it, which is the same principle as stopping on a case no rule covers.

Report divergence, do not absorb it

When the harness finds a mismatch, resist the pull to tune until the totals agree. A mismatch has a cause: a rounding boundary, an entitlement the engine does not know about, an adjustment nobody mentioned. Report it with its cause.

Tuning until the numbers match produces an engine that agrees with history and does not know why, which is an engine nobody can reason about the next time the rules change.

The general shape

Automating a human gatekeeper is a recognisable pattern with a recognisable failure mode, and it recurs well outside commodity trading: underwriting, pricing approvals, credit limits, discount authority, clinical triage, content moderation.

Enumerate every check the person made, including the ones they cannot articulate, and encode each one. Make the binding action idempotent, because the client will retry and the user will double-tap. Prove the machine's number equals the human's number at stored precision with the rounding mode pinned, never against an export of displayed values. And make the system stop on a case no rule covers, rather than proceeding on a default nobody chose.

The gate does not disappear when you automate the gatekeeper. It just stops being a person's judgement and starts being your specification.

FAQ

What actually changes when a quote becomes executable without a human reviewing it? Every check that person performed by eye becomes a check the software has to perform, including the ones they could not articulate. The gate has not been removed, it has been moved into code, and a platform that does not enumerate those checks has simply stopped performing them while continuing to issue binding prices.

Why does accepting a quote need an idempotency key? Because acceptance creates an obligation and the action will be repeated. A supplier on poor signal taps accept, sees nothing happen, and taps again. Clients retry on timeout and proxies replay requests. Without a key checked before the transition is applied, that is two trades against a counterparty who believes they agreed once.

Why can't I test pricing parity using a CSV export of the spreadsheet? Because a spreadsheet writes CSV as displayed values rather than stored ones, so the export has already applied the spreadsheet's rounding. Your harness then compares your engine against a number that was rounded by the mechanism you are trying to test, and it agrees with itself. Read stored values at full precision instead.

How does a one-cent rounding difference actually arise? A spreadsheet rounds half away from zero, so 2.15 becomes 2.2 at two decimal places. Common implementations in application code round half to even, or work in binary floating point where 2.15 is not exactly representable, and return 2.1 on the same input. A double-precision database column can do the same. Pin the rounding mode explicitly rather than inheriting it.

Should parity be proven against the written pricing formula or against historic quotes? Against historic quotes. A written formula is usually an incomplete reconstruction that omits the adjustments the author applies without thinking, whereas historic quotes cover the cases that genuinely occur in the proportions they occur in. A case never quoted historically stays untested until it happens, and the engine should flag it rather than guess.

What should the engine do with a case no rule covers? Stop and escalate rather than apply a default. A default that nobody chose is a decision the platform made on the operator's behalf, on a binding quote, and it is indistinguishable from a correct answer until it is expensive. The same applies to a pricing case with no historic precedent in the parity harness.

Carrying a program like this one?

Tell us the system, the stakes, and the date that matters. You get a straight technical reply from the person who would lead the work, within 24 hours.

Bring us the program