A Polymarket trading bot can receive a successful execution response and still not know enough to safely continue trading.
That sounds like a small implementation detail.
It isn't.
In a production trading system, there is a big difference between:
"I sent the order."
"I received a fill."
"The fill has a transaction."
"The transaction is confirmed."
"The execution is settled."
"My position matches reality."
Those are different states.
If your bot treats them as one state called FILLED, eventually you get a system that believes it owns one position while the account says something else.
This is why execution verification deserves its own layer.
I built a small Polymarket execution-verification project around this idea:
Don't let a trading system assume an execution is complete before the relevant state has been verified.
GitHub: Polymarket Execution Verifier
The problem with treating FILLED as the end
Imagine the strategy decides to buy 100 shares.
The bot submits:
BUY 100
Then it receives an execution update:
FILLED
A naive implementation does:
filled = true
position += 100
continue trading
That is dangerous.
The bot has made several assumptions at once:
- the requested quantity was actually matched
- the execution event was complete
- the settlement transaction is known
- the transaction was successfully processed
- the external position reflects the expected result
- no relevant event was missed
Those assumptions can fail independently.
A safer trading system treats execution as a state transition rather than a boolean.
Order → Fill → Transaction → Confirmation → Settlement → Position
The execution lifecycle I use is:
INTENDED
↓
SUBMITTED
↓
ACCEPTED
↓
MATCHED
↓
FILLED
↓
TX_PENDING
↓
CONFIRMED
↓
SETTLED
↓
POSITION VERIFIED
There are also failure and uncertainty states:
REJECTED
CANCELLED
FAILED
RETRYING
UNKNOWN
INCONSISTENT
The important part is that FILLED is not necessarily the final state your risk engine should trust.
Polymarket's current CLOB tooling also distinguishes trade completion from simply observing a fill: the current client logic considers a trade resolved when it reaches a terminal outcome, such as having a settlement transaction hash or having failed. The client can also expose transaction hashes when available and trade IDs that can be followed while a hash is not yet available.
That distinction is exactly what an execution verifier should make explicit.
Why execution state becomes uncertain
There are several ways a trading bot can end up with incomplete execution information.
1. The order was matched, but transaction information is not available yet
A matching event tells you something important happened.
It does not necessarily mean every downstream piece of information is already available to your application.
For example:
Order
↓
Matched
↓
Fill observed
↓
Transaction information unavailable
The correct state is not:
DONE
It is closer to:
TX_PENDING
or:
UNKNOWN
depending on what the system actually knows.
Your execution layer should preserve that uncertainty instead of hiding it.
2. Partial execution
Suppose you intended:
100 shares
but only 40 were matched.
Your bot now has:
Requested: 100
Matched: 40
Remaining: 60
That remaining quantity cannot simply disappear from your accounting.
The execution system needs to know whether the remaining 60:
- are still active
- were cancelled
- expired
- failed
- were never accepted
- require another verification step
This is why requested quantity and executed quantity should always be separate fields.
For example:
{
"requested_size": 100,
"matched_size": 40,
"remaining_size": 60,
"execution_state": "PARTIAL"
}
The exact data model can vary, but the principle should remain the same.
3. The transaction is confirmed, but the position still isn't verified
This is one of the most important boundaries.
Consider:
FILLED
↓
TX CONFIRMED
A developer may immediately update the internal position:
local_position += executed_size
But the trading system still has another question:
Does the external account state actually match what I expected?
For example:
Expected position: 125.5
Observed position: 100.0
The transaction succeeded.
The internal state is still wrong.
This is where execution verification connects directly to position reconciliation.
A trading bot should not confuse:
transaction verified
with:
position verified
Those are different checks.
4. A WebSocket event can be missed
Real-time trading systems depend heavily on event streams.
That creates another failure mode.
Imagine:
Event 101 received
Event 102 received
[connection drops]
Event 103 happens
Event 104 happens
connection restored
Your application reconnects.
But reconnecting the socket does not magically reconstruct the events that were missed.
You now have:
local state != external state
The correct recovery sequence is:
DISCONNECT
↓
PAUSE
↓
RECONNECT
↓
REBUILD STATE
↓
RECONCILE
↓
VERIFY
↓
RESUME
This is why execution verification cannot be implemented as a single API callback.
It belongs inside a larger state-management system.
Execution verification should be explicit
Instead of:
if order.filled {
update_position();
continue_trading();
}
use an explicit state machine.
For example:
enum ExecutionState {
Intended,
Submitted,
Accepted,
Matched,
Filled,
TxPending,
Confirmed,
Settled,
PositionVerified,
Rejected,
Cancelled,
Failed,
Retrying,
Unknown,
Inconsistent,
}
Now the rest of the system can react to the state.
For example:
FILLED
↓
Does transaction information exist?
↓
No
↓
TX_PENDING
Then:
TX_PENDING
↓
Transaction confirmed?
↓
Yes
↓
CONFIRMED
Then:
CONFIRMED
↓
Position matches expected state?
↓
No
↓
INCONSISTENT
This is much safer than a single filled=true flag.
The verifier should separate facts from assumptions
A useful execution record might contain:
strategy_decision_id
internal_execution_id
polymarket_order_id
trade_id
market_id
token_id
side
requested_quantity
matched_quantity
order_timestamp
fill_timestamp
transaction_hash
confirmation_timestamp
execution_state
position_state
verification_timestamp
The important property is that each value represents something actually observed.
For example:
requested_quantity = 100
matched_quantity = 40
is different from assuming:
matched_quantity = requested_quantity
Likewise:
execution_state = CONFIRMED
should not automatically imply:
position_state = VERIFIED
Good trading infrastructure makes those boundaries visible.
What should happen when verification fails?
This is where execution verification becomes a risk-control problem.
Suppose the verifier reaches:
INCONSISTENT
The strategy layer should not simply continue because it still has a signal.
The control flow should look more like:
Execution uncertain
↓
Pause affected trading
↓
Query authoritative state
↓
Reconcile orders / fills / positions
↓
Verify risk
↓
Healthy?
↙ ↘
YES NO
↓ ↓
RESUME PAUSE
The trading decision is therefore not just:
Should I buy?
It also becomes:
Is the system in a state where buying is safe?
That is a very different engineering problem.
A useful execution verifier architecture
The project I am working on separates verification into layers:
Strategy
│
▼
Execution Request
│
▼
Order Submission
│
▼
┌──────────────────┐
│ Execution │
│ Verifier │
└──────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
Order Fill Transaction
│ │ │
└───────────┼───────────┘
▼
Settlement
│
▼
Position Verification
│
▼
Risk Layer
│
▼
Resume / Pause
This gives the system a clear boundary:
the strategy produces an intention; the infrastructure determines whether reality matches that intention.
Execution verification vs position reconciliation
These two concepts are closely related, but they solve different problems.
Execution verification
Question:
Did the intended trade actually reach a verified terminal execution state?
It follows:
Order
→ Fill
→ Transaction
→ Confirmation
→ Settlement
Position reconciliation
Question:
Does the account's actual position match the position my system believes it has?
It follows:
Expected State
↓
External State
↓
Compare
↓
Match / Mismatch
You need both.
For example:
Execution: VERIFIED
Position: MISMATCH
is completely possible.
Likewise:
Execution: UNKNOWN
Position: temporarily unchanged
is also possible.
The system should retain both pieces of information.
Why this matters for automated trading
A strategy can be statistically correct and still lose control of the system.
The failure may happen after the signal.
For example:
Signal
↓
Order
↓
Partial Fill
↓
WebSocket Gap
↓
Incorrect Local State
↓
Incorrect Position
↓
Incorrect Risk Calculation
↓
New Order
The original strategy wasn't necessarily the problem.
The execution state was.
This is why production trading infrastructure needs more than:
market data
+
strategy
+
order placement
It needs:
market data
+
strategy
+
execution
+
verification
+
reconciliation
+
risk
+
recovery
+
observability
When should the bot resume trading?
This is the final question.
Suppose the bot reconnects after losing its market-data connection.
Should it immediately resume?
No state machine should answer that with:
socket_connected == true
A safer condition is closer to:
connection healthy
AND
market data fresh
AND
orders reconciled
AND
fills reconciled
AND
positions verified
AND
exposure verified
AND
risk limits healthy
Only then should the system move back toward:
TRADING
This is also where an execution verifier connects to a broader trading control plane.
The verifier answers:
What actually happened?
The reconciliation layer answers:
Does my state match reality?
The risk layer answers:
Is continuing safe according to configured limits?
The control plane coordinates the result.
Building the execution verifier
My current project focuses on making these execution states explicit instead of burying them inside strategy code.
Repository:
github.com/casatrickdev/polymarket-execution-verifier
The project is intentionally focused on one problem:
Verify Polymarket execution
across
order → fill → transaction → confirmation → settlement → position
That makes it easier to integrate with the rest of a production trading stack.
The broader architecture connects this with:
- a Polymarket trading bot
- position reconciliation
- trading monitoring
- risk controls
- recovery logic
- operational control
Projects:
Polymarket Trading Control Plane
Practical execution-verification checklist
Before allowing a trading bot to treat an execution as complete, I want to be able to answer:
[ ] Was the order accepted?
[ ] Was it matched?
[ ] How much actually filled?
[ ] Is the remaining quantity known?
[ ] Is the relevant transaction known?
[ ] Has the transaction reached the expected terminal state?
[ ] Is settlement verified?
[ ] Does the external position match expected state?
[ ] Is exposure correct?
[ ] Are risk limits still valid?
[ ] Is there any unresolved execution uncertainty?
If one of those answers is unknown, the system should know that it is unknown.
That sounds obvious.
In production, it is one of the differences between a bot that places trades and a trading system that can actually be trusted.
Final takeaway
A Polymarket trading bot should not think:
FILLED = DONE
A better mental model is:
INTENDED
↓
SUBMITTED
↓
MATCHED
↓
FILLED
↓
TRANSACTION VERIFIED
↓
SETTLED
↓
POSITION VERIFIED
↓
RISK VERIFIED
↓
SAFE TO CONTINUE
The important question is not only whether an order was filled.
It is:
Can the system prove that its current trading state matches reality?
That is the reason for building an execution-verification layer.
Project
Polymarket Execution Verifier
Verify execution across:
ORDER
FILL
TRANSACTION
CONFIRMATION
SETTLEMENT
POSITION
GitHub: https://github.com/casatrickdev/polymarket-execution-verifier
Related reading
- Polymarket Trading Bot: Execution, Risk Management, and Backtesting
- Polymarket Partial Fills: How Automated Trading Bots Should Handle Them
- Polymarket Position Reconciliation: Keeping Trading Bot State in Sync
- Polymarket WebSocket Reconnects: Rebuilding Trading State Safely
- Polymarket Trading Bot Monitoring: State, Risk and Recovery
Top comments (0)