A Retry Is Not a Trading Decision
Suneet Malhotra
Aug 27, 2026
A retry is usually described as reliability work. In a trading system, that description is incomplete. A retry changes the system's behavior in the market, so it is a trading decision and needs the same evidence as an entry or an exit.
I ran into this distinction while thinking through rejected orders. The dangerous implementation is easy to write: submit an order, catch an exception, wait, and submit again. The code looks resilient. The state machine is not.
Rejection is not failure
There are at least two broad classes of unsuccessful submission.
The first is transport uncertainty. The client timed out after sending the request, so the system does not know whether the broker accepted it. Retrying immediately may create a duplicate order. The correct next action is reconciliation: query the broker using a client order ID, inspect the order book, and only then decide whether another submission is possible.
The second is a known rejection. The broker or the local risk layer returned a reason: market closed, buying power insufficient, quantity invalid, symbol halted, price outside a band, or the strategy's own limit refused the order. A retry of the same intent is not recovery. It is repetition without new information.
Those paths often share one exception handler because both produce a non-success response. That is a classification bug. The system is treating unknown state and known refusal as the same event.
The state that was missing
An order intent should have a durable identity before it reaches the network. Mine needs more than symbol, side, and quantity. It needs an intent ID, strategy signal ID, created timestamp, limit price, risk snapshot, submission attempt, and a terminal reason when the workflow stops.
The important field is not attempt count. It is the transition reason.
"risk_rejected -> terminal"
"transport_unknown -> reconcile"
"broker_accepted -> monitor"
"broker_rejected_retryable -> retry under policy"
The distinction prevents an operational mechanism from silently creating a new market hypothesis. If the risk layer rejected an order because exposure was already at its cap, a retry does not make the exposure lower. If the broker rejected a stale limit price, a retry might be valid only after the quote or pricing policy changes. The changed input must be explicit.
This is the same principle I use for signals: a decision should be reproducible from the state that produced it. "Try again" is not reproducible. "Retry once after a transport timeout, using the same client order ID, after broker reconciliation" is a rule.
Idempotency has a market meaning
In ordinary software, idempotency is often framed as avoiding duplicate API effects. In a trading engine, it also preserves the meaning of the strategy's action.
Suppose one signal creates an intent to buy 100 shares. The first request times out. A naive retry submits another 100 shares. If both requests filled, the strategy did not buy 100 shares with uncertain plumbing. It bought 200 shares. The second fill is an unintended position change, even if every individual API call was valid.
That makes the client order ID part of the trading model, not just a networking detail. The identifier should be deterministic for the intent and stable across process restarts. A restarted worker must recover the same pending intent from durable storage, not reconstruct a new one from the latest signal.
The practical test is simple: kill the worker after each external boundary. After restart, can it prove whether the intent is pending, accepted, rejected, or unknown? If not, the retry policy is making a portfolio decision out of missing state.
What I would measure
I would not start with "did retries improve success rate?" That metric rewards duplicate submissions unless fills are joined back to intent IDs.
The first dashboard would show:
- intents by terminal state: filled, canceled, rejected, expired, and unknown
- retry count by rejection reason
- fills per intent ID, with duplicates isolated
- time spent in transport-unknown before reconciliation
- signals rejected before submission versus orders rejected by the broker
The last two lines matter because they locate the boundary. A strategy can have fewer trades because its rules are selective, because risk controls are active, or because the order path is broken. Total trade count cannot tell those stories apart.
The design conclusion is narrow. Retry transient infrastructure uncertainty, subject to reconciliation and an idempotency key. Do not retry a known trading refusal unless a named input changed and the new attempt is a new, auditable transition.
Reliability is not measured by how often the system tries again. It is measured by whether the system can explain why the portfolio changed once, and not twice.
Share this post
You Might Also Like
The Market Is Closed Is Not a Trading Rule
A backtest can know the exchange hours and still schedule a trade into a holiday, an early close, or a stale session. Calendar state is market data.
Quantitative TradingEvery Trade in My Backtest Filled
Every trade in my options backtest filled. All of them. There is no line in that file where an order fails, because there is no line where an order exists.
Agentic AIThe Log Is Part of the Agent's Interface
An agent that can act but cannot leave a useful decision record is not autonomous. It is an opaque process with write access.
Agentic AIThe Agent Did Not Need More Context
When an agent edits a shared checkout, the dangerous variable is not context length. It is the boundary around what the run is allowed to write.
Latest Blog Posts
The Log Is Part of the Agent's Interface
An agent that can act but cannot leave a useful decision record is not autonomous. It is an opaque process with write access.
The Market Is Closed Is Not a Trading Rule
A backtest can know the exchange hours and still schedule a trade into a holiday, an early close, or a stale session. Calendar state is market data.
The Agent Did Not Need More Context
When an agent edits a shared checkout, the dangerous variable is not context length. It is the boundary around what the run is allowed to write.
Related Tools & Demos
The QA Field Manual to Language Models
A free 24-chapter book. Start at βwhat is AI, really?β and finish with a small language model you built yourself β one that reads a failing Playwright test and proposes a fix you can run. Read it in your browser, or download the PDF or the Mac app.
View Source Code βMulti-Model LLM Harness
One interface to call any AI model β capability routing, fallback chains, budgets, circuit breakers, and a quality feedback loop. A practical architecture pattern write-up.
Automated Trading System
Multi-engine trading platform with real-time risk management, regime-based strategy selection, and automated order execution.
View Source Code β
Stay in the Loop
Get weekly insights on AI-driven QA, engineering leadership, and automation strategies.
No spam, ever. Unsubscribe anytime.