A missed exit on 100 shares at $50 leaves $5,000 of exposure. If the price falls 10% before the agent notices, that is a $500 loss before fees.
Position reconciliation is the control that catches this gap. Most systems get it wrong by comparing a local position total with a broker snapshot, then treating any difference as a number to overwrite.
Broker state and agent state are different records
The agent usually maintains a view assembled from order requests, acknowledgements and fills. The broker maintains positions from executions and adjustments, and may expose orders, fills and positions through separate endpoints. Those records can update at different times.
A timeout after submission does not tell the agent whether an order reached the broker. A partial fill can change the broker position while the agent still has the order marked as pending.
Start with an execution ledger, not a mutable position field. Record each broker execution once, using the broker's execution ID where available.
Derive the agent's position from that ledger, then compare it with the broker's reported position. Keep the broker's position snapshot as an independent check, not as a replacement for the event history.
Define what counts as the same position
Matching on a ticker alone is not enough. Position identity should include the account, instrument identifier, venue where relevant, currency, product type and strategy allocation. For derivatives, include expiry, strike, option right and multiplier.
A futures contract's displayed quantity is not its cash exposure. A 1-lot position with a $50 multiplier represents a different risk from one share.
Netting rules matter too. A netting account may report one signed quantity where the agent tracks strategy-level allocations.
A hedging account may report separate long and short positions. Decide how to map the broker's representation to the agent's, and preserve both the raw broker record and the mapped result for diagnosis.
Do not use timestamps as event order
Wall-clock timestamps can arrive late, repeat or reflect different clock sources. Prefer broker sequence numbers or execution IDs.
If those are unavailable, use a durable cursor with a time overlap: request a small period already processed, deduplicate by execution ID, and advance the cursor only after storing the full response. This costs extra API calls but reduces the chance of skipping a fill at a pagination boundary.
Reconcile the lifecycle, not just the position total
A position match can hide a broken order state. For example, the broker may have filled a buy and a sell while the local ledger missed both, leaving the net quantity unchanged. Compare open orders and executions as well as positions. Track requested, acknowledged, partially filled, filled, cancelled, rejected and unknown states separately.
On each reconciliation cycle, collect data in a defined order: executions since the last safe cursor, open orders, then position snapshots. Broker APIs may not offer an atomic account snapshot, so a fill can land between calls.
If records conflict, repeat the relevant queries after a short delay rather than declaring an error from one mixed-time view. Use execution IDs to merge the repeated results safely.
Polling cadence is a trade-off. Short intervals catch discrepancies sooner but consume rate limits and can amplify outages through retries. Streaming updates reduce detection delay, but disconnects need explicit detection and recovery.
The figures below are typical market ranges, not service guarantees. Exposure examples use 1,000 shares at $50 each; they show notional, not a predicted loss.
| Signal or recovery path | Typical market range | Illustrative exposure at risk |
|---|---|---|
| Streaming disconnect detection | 5 to 30 seconds, depending on heartbeat settings | $50,000 notional; a 1% move is $500 |
| Position polling interval | 1 to 10 seconds, plus API response delay | $50,000 notional; a 1% move is $500 |
| Execution update delivery | Sub-second to several seconds on a healthy feed | $50,000 notional; a 1% move is $500 |
| Overnight adjustment detection | Next scheduled account or instrument check | Depends on the position and adjustment terms |
Set a freshness limit per data source. A stale position snapshot should be marked stale, not treated as a current zero. Keep a separate health state for the connection, order feed, execution feed and account snapshot. That lets the agent distinguish "no position" from "position not verified". For rehearsal, agentic paper trading from $9.99 a month can help exercise reconnect and reconciliation paths without placing live orders.
Make mismatch handling bounded and deliberate
Not every difference means the same thing. A one-share rounding or allocation mismatch may be within a defined tolerance. A growing unexplained difference, an execution with no known order, or an order whose submission outcome is unknown needs containment. Make these rules explicit in code and logs.
A practical response sequence is:
- Mark the affected account and instruments as unverified. Stop new risk-increasing orders for that scope.
- Fetch recent executions and open orders again. Deduplicate executions, and check for pending cancels or amendments before taking action.
- Rebuild the ledger from broker events where possible. Compare the resulting quantity with a fresh broker snapshot and retain the original values.
- If the mismatch remains, alert the operator and apply a defined policy: stay paused, reduce exposure, or use a separately authorised recovery order.
Do not automatically flatten every difference. The apparent mismatch could be a delayed fill, a manual trade, an assignment or an instrument mapping error.
Sending a compensating order before resolving the cause can double the position. If a system permits automated recovery, cap its size, require fresh market data, check buying power, and record the reason and source values for each action.
Thresholds should reflect market value and product risk, not only contract count. One share may be material in a high-priced instrument; ten contracts may be material in a leveraged product.
Use both an absolute quantity tolerance and a notional or risk limit. A short persistence window, such as two consistent checks separated by several seconds, can filter transient races, but it must not delay containment of a known duplicate order or a large exposure.
Test recovery paths before unattended trading
Tests should model the broker's separate feeds and imperfect timing. Inject a fill that arrives before its acknowledgement, a partial fill followed by a cancel, a stream disconnect during an execution, duplicate execution events, and a position snapshot that lags the fill ledger.
Test pagination boundaries and restart the agent with an uncommitted cursor. Confirm that recovery neither loses an execution nor books it twice.
Measure detection time, time to containment, unresolved mismatch duration and the number of unnecessary orders caused by recovery logic. Set limits for each. A useful test also verifies that an agent remains paused when the broker API is unavailable, rather than interpreting an empty response as a flat account. Keep raw responses, normalized events and reconciliation decisions with correlation IDs so an operator can reconstruct the sequence.
Stop doing these things:
- Stop overwriting the agent's position with a single broker snapshot.
- Stop assuming a timed-out order request failed.
- Stop treating matching net quantities as proof that order state is correct.
- Stop sending a corrective trade before checking executions and open orders.
Frequently Asked Questions
How often should a trading agent reconcile positions?
Use streaming updates for prompt changes and periodic snapshots as an independent check. Typical polling intervals range from 1 to 10 seconds, subject to broker rate limits and strategy risk. Reconcile again after reconnects, restarts and order-state uncertainty.
Should broker positions overwrite the agent ledger?
No. Keep an execution ledger and derive the agent position from it, then compare that result with the broker snapshot. A snapshot can reveal a mismatch, but does not explain whether it came from a missed fill, a manual trade or an adjustment.
What should an agent do when broker and local positions disagree?
Mark the affected account or instrument as unverified and pause new risk-increasing orders. Re-fetch executions and open orders, deduplicate events, and compare with a fresh position snapshot. Use an automated recovery order only under a defined, capped policy.
How can position reconciliation handle partial fills?
Record each execution as it arrives and update filled quantity independently from the order's remaining quantity. A cancel request does not undo fills already received. Reconcile the final execution total against the broker position before submitting replacement orders.
Why can a broker position snapshot be stale?
Positions, executions and open orders may come from separate services or update paths. A fill can occur between API calls, and a disconnected stream can delay local updates. Track data freshness and repeat relevant queries when records conflict.