DEV Community

Cover image for Building a Polymarket TWAP State Machine for Trading Bots

Building a Polymarket TWAP State Machine for Trading Bots

Learn why a Polymarket TWAP state machine should model resolution, oracle observations, market time, and execution as separate states.

Building a Polymarket TWAP State Machine

A short-duration trading bot can receive every price update correctly and still make a structurally wrong decision.

The reason is simple: a stream of prices is not the same thing as a market state.

For TWAP-resolved Polymarket markets, the strategy is not merely predicting where an exchange price will move next. It is attempting to estimate whether an oracle-defined measurement will satisfy a specific resolution rule. Current Polymarket markets can explicitly define a Chainlink TWAP stream as the resolution source rather than another exchange's spot price. ([Polymarket][1])

That changes the architecture.


About the Author

Soulcrancerdev specializes in the engineering and quantitative research behind automated prediction-market trading.

Get in touch:

Github: github.com/thesoulcrancerdev/poly-trading-strategies
X: x.com/soulcrancerdev
Telegram: t.me/soulcrancerdev
Youtube: youtube.com/@soulcrancerdev

The Core Question

How should a Polymarket TWAP state machine represent a market when price, oracle data, time remaining, order-book conditions, and resolution status can all change independently?

The answer is not a single if price > threshold statement.

A useful system needs to model transitions.


The Important Distinction: Events vs State

An event-driven trading system receives observations:

oracle price update
exchange price update
order book update
market metadata update
timer update
market resolution event
Enter fullscreen mode Exit fullscreen mode

But strategy logic should not directly treat every event as a trade signal.

Instead:

Events
   ↓
State transition
   ↓
Current market state
   ↓
Strategy evaluation
   ↓
Execution decision
Enter fullscreen mode Exit fullscreen mode

This is the core purpose of a Polymarket TWAP state machine.

A market can receive a new Binance observation while its oracle data is stale. It can have a valid oracle price while the order book becomes too wide. It can have a favorable model probability while entering a period where the remaining time no longer supports new risk.

Those are different states, not merely different prices.

A Practical TWAP State Model

I would model a market with states such as:

DISCOVERED
    ↓
RULES_VALIDATED
    ↓
DATA_SYNCHRONIZED
    ↓
ACTIVE
    ↓
RISK_REDUCED
    ↓
EXECUTION_DISABLED
    ↓
RESOLUTION_PENDING
    ↓
RESOLVED
Enter fullscreen mode Exit fullscreen mode

The transition should depend on explicit conditions.

For example:

DISCOVERED
    → RULES_VALIDATED
    when resolution metadata is understood

RULES_VALIDATED
    → DATA_SYNCHRONIZED
    when required data sources are healthy

DATA_SYNCHRONIZED
    → ACTIVE
    when the market is tradable and observations are fresh

ACTIVE
    → RISK_REDUCED
    when uncertainty or market conditions deteriorate

ANY
    → EXECUTION_DISABLED
    when critical state becomes invalid
Enter fullscreen mode Exit fullscreen mode

This matters because Polymarket exposes real-time market lifecycle and order-book events through its market WebSocket channel, including order-book snapshots, price changes, best bid/ask updates, new markets, and market resolution events. ([Polymarket Documentation][2])

A state machine gives those events meaning.


The Resolution State Is More Important Than the Signal

The most common architectural mistake is allowing the signal engine to define the market.

It should be the opposite.

The market definition should constrain the signal engine.

A useful framework is:

Rules → Resolution Model → Observations → State → Probability → Execution

Polymarket documentation emphasizes that market resolution rules define the source and conditions used to determine an outcome. Market metadata can also expose fields such as resolutionSource, making resolution information something software can capture rather than manually hard-code. ([Polymarket Documentation][3])

For a TWAP market, the state might include:

market_id
asset_pair
resolution_source
twap_methodology
window_start
window_end
oracle_price
oracle_timestamp
oracle_age
exchange_reference_price
orderbook_midpoint
spread
time_remaining
Enter fullscreen mode Exit fullscreen mode

The strategy should consume this normalized state.

It should not independently reconstruct market meaning from scattered WebSocket handlers.


TWAP Creates a Time-Dependent State Problem

A spot-price strategy asks:

What is the price now?

A TWAP-oriented strategy needs to ask:

What observations are contributing to the measurement that ultimately matters?

Conceptually:

TWAP = (1 / T) ∫ P(t)dt
Enter fullscreen mode Exit fullscreen mode

The exact implementation and resolution methodology must come from the specific market's rules and designated source.

The important engineering implication is broader: time becomes a state variable.

A sustained move and a brief spike may produce very different implications for a time-weighted measurement.

This suggests another useful model:

Observation
    ↓
Oracle relevance
    ↓
Time-window position
    ↓
Resolution probability
    ↓
Execution quality
Enter fullscreen mode Exit fullscreen mode

A fast market move is therefore not automatically a strong signal.

The state machine must determine whether that move is relevant to the measurement the market actually resolves against.


Hypothetical State Transition

Imagine a hypothetical market state:

oracle_age_ms = healthy
market_rules = validated
time_remaining = sufficient
spread = acceptable
model_probability = 0.64
Enter fullscreen mode Exit fullscreen mode

The system enters:

ACTIVE
Enter fullscreen mode Exit fullscreen mode

Then an oracle stream becomes unavailable or stale.

The exchange feed may continue updating.

A poorly designed bot remains active because its signal still works.

A state-machine-driven bot transitions:

ACTIVE
    ↓
EXECUTION_DISABLED
Enter fullscreen mode Exit fullscreen mode

That distinction is important.

The question is not whether the model can calculate a probability.

The question is whether the probability is still based on valid market state.


What Most Traders Get Wrong

1. A fresh exchange price means the system is healthy

Not necessarily. Exchange freshness and resolution-data freshness are different conditions.

2. TWAP is just delayed spot

Not necessarily. A time-weighted measurement changes the importance of when observations occur.

3. Market state can be inferred from one feed

A real-time trading system may require separate views of market rules, oracle observations, exchange data, order-book conditions, and lifecycle events.

4. A state machine is only software engineering

It is also model risk management.

The state machine determines when the model is allowed to make decisions.


Failure Modes Worth Testing

The most dangerous failures are often transition failures.

Test for:

  • Oracle data becoming stale while exchange data remains active.
  • Resolution metadata changing or being unavailable.
  • Duplicate or out-of-order events.
  • Market resolution arriving while orders or strategy processes remain active.
  • Restarting the bot and reconstructing an incorrect market state.
  • Order-book data becoming unavailable while the probability model continues running.

Raw events should be stored with both source timestamps and local receive timestamps. Otherwise, debugging later becomes a story about what the system probably saw.


Architecture

flowchart LR
    RULES[Market Rules] --> STATE[Market State Machine]
    ORACLE[Oracle Observations] --> STATE
    EXCHANGE[Exchange Observations] --> STATE
    BOOK[Polymarket Order Book] --> STATE
    CLOCK[Market Clock] --> STATE

    STATE --> MODEL[Probability Model]
    STATE --> RISK[Risk Controls]

    MODEL --> DECISION[Decision Engine]
    RISK --> DECISION

    DECISION --> EXEC[Polymarket CLOB]
    EXEC --> EVENTS[Market Events]
    EVENTS --> STATE

Polymarket's current official SDK ecosystem includes a Rust CLOB client with WebSocket and real-time data features, which makes this separation practical for systems built around typed components and event streams. ([GitHub][4])

What This Means for Polymarket Developers

A production system should measure transitions, not just prices.

Record:

  • current state
  • previous state
  • transition reason
  • triggering event
  • event timestamp
  • local timestamp
  • state duration

The useful metric is not merely:

price_update_count
Enter fullscreen mode Exit fullscreen mode

It is also:

ACTIVE → RISK_REDUCED
ACTIVE → EXECUTION_DISABLED
DATA_SYNCHRONIZED → ACTIVE
ACTIVE → RESOLUTION_PENDING
Enter fullscreen mode Exit fullscreen mode

That creates an auditable model of why the bot traded—or refused to trade.

Advanced Insight

The deeper lesson is that a Polymarket TWAP state machine is really a synchronization engine.

It synchronizes five realities:

  1. What the market says determines the outcome.
  2. What the oracle currently reports.
  3. What other market data suggests.
  4. Where the market is in time.
  5. Whether execution conditions still justify action.

Most trading bots optimize the fourth and fifth steps after building the signal.

For oracle-defined markets, that order should be reversed.

Final Engineering View

The central question is not how to calculate a TWAP signal.

It is how to prevent a strategy from acting when its understanding of the market is incomplete.

The best next step is to build a replayable state machine before optimizing the model: ingest historical or synthetic events, reconstruct every transition, and verify that invalid data states reliably disable execution.

Trading disclaimer: Examples in this article are conceptual or hypothetical. Trading involves substantial risk, and execution quality, liquidity, fees, model error, and changing market conditions can materially affect results.

Top comments (0)