Your Polymarket trading bot says:
Position: +100
But the account actually holds:
Position: +40
Which one should the trading system trust?
This is a position reconciliation problem.
For an automated Polymarket trading bot, local state can become different from actual account state after:
- partial fills
- WebSocket disconnects
- missed events
- application restarts
- delayed events
- unexpected API responses
My approach is to treat reconciliation as a first-class part of the trading system rather than something added after execution fails.
The basic idea is:
Local State
↓
Remote State
↓
Compare
↓
Repair
↓
Verified State
This is one of the core ideas behind the Polymarket Trading Control Plane I'm building.
Why position state can become wrong
A simple trading bot often assumes that every event arrives correctly and that its local state always represents the account.
In reality, there are several places where state can diverge.
For example:
WebSocket disconnect
↓
Execution event missed
↓
Local state not updated
↓
Position becomes stale
The system may still be running.
The process may still be healthy.
The strategy may still be producing signals.
But its understanding of the current position can already be wrong.
The Control Plane is designed around making those conditions visible and controllable.
Local position vs actual position
Consider this simple example:
Local position:
+100
Remote position:
+40
The difference is:
-60
If the strategy uses the local value for its next decision, it is now calculating from incorrect state.
That can affect:
Position sizing
Exposure
Hedging
Risk limits
Available capital
Next orders
So the trading system needs to know not just:
“What does my local state say?”
but:
“Does my local state agree with the account?”
Position reconciliation is not just a database comparison
It is tempting to think of reconciliation as:
SELECT local_position
SELECT remote_position
if different:
update
The problem is that a trading system has multiple related state domains.
A useful model is:
Orders
↓
Trades / Fills
↓
Positions
↓
Exposure
↓
Risk
The Control Plane explicitly keeps these concepts separate.
An order is what the strategy requested.
A fill is what actually executed.
A position is what the account holds.
Exposure is the risk created by that position.
If one of those layers is wrong, the downstream state can also become wrong.
The real problem: events can be missed
Real-time event streams are useful because automated trading systems need low-latency updates.
But an event-driven system cannot assume that every event will always arrive exactly when expected.
Imagine:
Order submitted
↓
Partial fill
↓
WebSocket disconnect
↓
Fill event missed
↓
WebSocket reconnect
The connection is back.
But the local position may still be wrong.
The system should not treat:
RECONNECTED
as equivalent to:
STATE VERIFIED
Those are different conditions.
Reconnect is not reconciliation
This distinction is central to the architecture.
A reconnect answers:
“Can I connect again?”
A reconciliation answers:
“Does my local state match the current remote state?”
The recovery flow should therefore look like:
WebSocket disconnect
↓
Trading = PAUSED
↓
Reconnect
↓
Read remote state
↓
Compare local state
↓
Repair discrepancies
↓
Verify position
↓
Verify risk
↓
Resume trading
The Control Plane's current recovery model explicitly includes reconnects, restarts, suspected event gaps, unexpected API responses, and state mismatches as reconciliation triggers.
A concrete position mismatch
Suppose the local system contains:
Market: BTC Up/Down
Local position:
+100
The remote account reports:
Remote position:
+40
A reconciliation report could become:
POSITION MISMATCH
Market: BTC Up/Down
Local:
+100
Remote:
+40
Difference:
-60
Status:
REQUIRES_RECONCILIATION
At this point, I don't want the strategy to continue creating more positions.
The system first needs to establish a verified state.
That is the purpose of the reconciliation layer.
What should trigger reconciliation?
A trading system doesn't need to reconcile only after something obviously breaks.
Useful triggers include:
WebSocket reconnect
Application restart
Suspected event gap
Unexpected API response
State mismatch
These are already part of the Control Plane's planned reconciliation model.
Conceptually:
Normal operation
↓
Real-time events
↓
Local state
Failure / uncertainty
↓
Reconciliation
↓
Verified state
That gives the system both speed and a recovery mechanism.
Reconciliation should compare more than positions
Suppose the position is correct, but an order is still unexpectedly open.
Or the fills are correct, but the local exposure calculation is wrong.
So a reconciliation process should eventually compare multiple dimensions:
Orders
↓
Fills
↓
Positions
↓
Exposure
↓
Risk
This is why the Control Plane's state model includes orders, trades, positions, exposure, PnL, and health as separate observable areas.
The goal is not merely:
“Position matches.”
It is:
“The trading state is internally consistent and verified.”
What should happen during a mismatch?
I would not allow the system to continue trading normally while critical state is unresolved.
A simplified control flow is:
Position mismatch
↓
Trading = PAUSED
↓
Reconcile
↓
Repair
↓
Verify
↓
Risk check
↓
Resume
This is consistent with the broader control-plane principle of making critical state visible and controllable before allowing additional risk.
Why pausing matters
Imagine the system believes:
Position = +40
but the real position is:
Position = +100
The strategy might see enough available capacity to add another 40.
The real account would then become:
+140
even though the trading system thought it would become:
+80
A state mismatch therefore isn't only a display problem.
It can become a risk problem.
That's why stale or inconsistent state should be able to block new trading.
Position reconciliation after a partial fill
Partial fills are a good example of why reconciliation matters.
Suppose:
Requested:
100
Filled:
40
Remaining:
60
The strategy intended 100.
The execution layer actually filled 40.
The remote position should reflect the actual fill, not the original intention.
The state flow becomes:
Order
↓
40 Fill
↓
Position +40
↓
Exposure calculation
↓
Risk check
If the local system instead assumes:
Position +100
then every downstream control is working from the wrong state.
This is why yesterday's partial-fill work connects directly to today's reconciliation problem.
Reconciliation after an application restart
Another common case is restarting the trading process.
Before the restart:
Local State
Orders: ...
Positions: ...
Exposure: ...
After restarting, the application may only know what was persisted locally.
It should not blindly assume that the persisted state is still current.
A safer startup sequence is:
Application starts
↓
Load local state
↓
Read remote state
↓
Compare
↓
Repair discrepancies
↓
Verify risk
↓
Allow trading
This makes startup a recovery operation rather than simply:
“The process has started, so trading can start.”
Reconciliation after a WebSocket gap
Another example:
WebSocket
↓
Event A
↓
Disconnect
↓
Events B, C, D
↓
Reconnect
The application may know about A but not B, C, or D.
The system should have a way to establish the current state after reconnecting.
Conceptually:
Last known state
↓
Reconnect
↓
Remote state
↓
Compare
↓
Repair
↓
Verified state
This is one reason the project treats real-time events and reconciliation as complementary mechanisms rather than alternatives.
A state machine makes this easier to reason about
One useful way to express the operational state is:
HEALTHY
↓
DEGRADED
↓
PAUSED
↓
RECOVERING
↓
HEALTHY
For example:
WebSocket disconnect
↓
HEALTHY → DEGRADED
↓
Trading → PAUSED
↓
Reconnect
↓
Reconcile
↓
Verify
↓
RECOVERING
↓
HEALTHY
The Control Plane currently defines explicit health states including HEALTHY, DEGRADED, PAUSED, RECOVERING, and FAILED.
Reconciliation should be observable
A good reconciliation process should not silently modify state.
It should produce observable events.
For example:
RECONCILIATION_STARTED
RECONCILIATION_COMPLETED
STATE_MISMATCH
TRADING_PAUSED
TRADING_RESUMED
The broader Control Plane event model also includes:
ORDER_FAILURE
PARTIAL_FILL
MARKET_DATA_STALE
WEBSOCKET_DISCONNECTED
RISK_LIMIT_BREACHED
KILL_SWITCH_TRIGGERED
These events can feed dashboards, logs, alerts, and webhooks.
That makes reconciliation part of the system's operational history rather than a hidden database operation.
What happens when state cannot be verified?
This is an important case.
Sometimes reconciliation cannot immediately determine the correct state.
For example:
Local:
+100
Remote:
unknown
The system should be able to represent uncertainty.
Instead of assuming:
REMOTE = LOCAL
it can move into a controlled state:
UNKNOWN
↓
PAUSED
↓
RETRY / RECONCILE
The principle is:
Unverified state should not be treated as verified state.
That is especially important for systems that can place additional orders automatically.
The control plane around the trading bot
This is where the broader architecture comes together:
POLYMARKET
│
▼
Trading Bot
│
Strategy
│
Execution
│
▼
Execution State
│
▼
┌─────────────────┐
│ CONTROL PLANE │
│ │
│ State │
│ Risk │
│ Health │
│ Reconciliation │
│ Alerts │
│ Recovery │
└────────┬────────┘
│
▼
Verified State
The Control Plane is not another trading strategy.
It is the operational layer around the trading system.
That is the purpose of the project.
A practical reconciliation checklist
Before allowing a trading bot to resume, the system should eventually be able to answer:
[✓] Market data is fresh
[✓] WebSocket is healthy
[✓] Orders are known
[✓] Fills are known
[✓] Positions match
[✓] Exposure is correct
[✓] Risk limits are satisfied
[✓] No unresolved critical mismatch
[✓] Trading can resume
This turns recovery from a vague concept into a sequence of verifiable conditions.
Testing position reconciliation
I would test reconciliation against explicit failure scenarios:
| Scenario | Expected behavior |
|---|---|
| Position matches | Continue |
| Position mismatch | Pause and reconcile |
| Missed event | Detect and reconcile |
| Duplicate event | Avoid double-counting |
| Partial fill | Update actual quantity |
| Unknown order state | Reconcile |
| WebSocket disconnect | Degrade and recover |
| Application restart | Reload and reconcile |
| Stale data | Pause affected trading |
| Risk breach | Pause or kill |
The Control Plane's planned failure scenarios already follow this kind of model.
Why this matters
A trading bot should not be considered healthy just because:
Process = running
A more useful definition is:
Process
+
Connections
+
State
+
Risk
+
Execution
+
Verified Position
The system needs to know whether those pieces are consistent.
That is what makes position reconciliation an important part of automated trading infrastructure.
Final takeaway
The question isn't only:
“Is my bot running?”
It is:
“Does my bot know what the account actually looks like?”
A local position can become stale.
A WebSocket can disconnect.
An event can be missed.
An order can partially fill.
An application can restart.
When those things happen, the trading system needs a reliable path back to a verified state.
For me, that path is:
Local State
↓
Remote State
↓
Compare
↓
Repair
↓
Verify
↓
Risk Check
↓
Resume
That is the core idea behind the Polymarket Trading Control Plane I'm building.
Not another strategy.
An operational layer that helps an automated Polymarket trading system know when its state can be trusted—and when it should stop trading until it can.
Top comments (0)