DEV Community

Cover image for Polymarket Paper Trading Bot: Build One in Python

Polymarket Paper Trading Bot: Build One in Python

Polymarket Paper Trading Bot: Build One in Python

A real-money trading bot is the wrong place to discover that your signal logic, order-book handling, or position accounting is broken.

A Polymarket paper trading bot gives you a safer engineering environment: consume real market data, generate real signals, simulate orders and fills, and measure hypothetical performance before connecting execution credentials.

The important distinction is that paper trading should simulate the execution layer, not fabricate market data. Polymarket currently exposes public market data without authentication, while its public WebSocket market channel provides real-time order-book and price updates.

This article builds that architecture in Python.

What You'll Learn

  • How a paper-trading architecture differs from a live bot
  • How to discover markets through the public API
  • How to consume CLOB order-book data
  • How to simulate limit-order fills
  • How to track positions and P&L
  • How to test arbitrage, market-making, and directional strategies
  • How to graduate from paper trading to production safely

About the Author

Soulcrancerdev

Contact:
X: @soulcrancerdev
Telegram: soulcrancerdev
YouTube: YouTube channel

The Architecture

A useful design separates data, strategy, simulation, and accounting:

flowchart LR
    A[Gamma Market Discovery] --> B[Market Metadata]
    C[CLOB REST / WebSocket] --> D[Market Data Engine]
    B --> D
    D --> E[Strategy Engine]
    E --> F[Paper Execution Engine]
    F --> G[Virtual Portfolio]
    G --> H[P&L / Risk Metrics]
    D --> I[Logger / Metrics]
Enter fullscreen mode Exit fullscreen mode

The key design decision is that PaperExecutionEngine should implement the same interface your live execution engine eventually uses.

That means the strategy does not know whether an order is simulated or real.

1. Discover Markets

Polymarket's Gamma API provides public market discovery. The current documentation exposes keyset pagination through:

https://gamma-api.polymarket.com/markets/keyset

Markets include fields such as conditionId, clobTokenIds, outcomes, outcomePrices, enableOrderBook, and market status information.

A minimal scanner:

import requests

GAMMA_URL = "https://gamma-api.polymarket.com/markets/keyset"

def get_markets(limit=20):
    response = requests.get(
        GAMMA_URL,
        params={"limit": limit, "closed": False},
        timeout=10,
    )
    response.raise_for_status()
    return response.json()["markets"]

for market in get_markets():
    if not market.get("enableOrderBook"):
        continue

    print(market["question"])
    print(market["clobTokenIds"])
Enter fullscreen mode Exit fullscreen mode

For a production scanner, use the documented next_cursor rather than repeatedly requesting the same first page.

2. Read the Order Book

The CLOB exposes an order-book endpoint for a token ID. The response contains bids, asks, minimum order size, tick size, and last trade price.

import requests

def get_book(token_id):
    response = requests.get(
        "https://clob.polymarket.com/book",
        params={"token_id": token_id},
        timeout=5,
    )
    response.raise_for_status()
    return response.json()
Enter fullscreen mode Exit fullscreen mode

For a simple paper bot, this REST approach is enough to validate the accounting and strategy layers.

For event-driven systems, use the public market WebSocket. Its market channel provides book snapshots and price-change events, allowing your local book to react to updates instead of relying entirely on polling.

3. Simulate Execution

The biggest mistake in paper trading is assuming:

signal → order → immediate fill

That produces meaningless results.

Your simulator should answer:

  • Was the order price executable?
  • Was enough displayed liquidity available?
  • Was the order partially filled?
  • What price did the simulated fill receive?
  • What happened to the remaining quantity?

A simple simulator can start with top-of-book execution:

from dataclasses import dataclass

@dataclass
class PaperOrder:
    side: str
    price: float
    size: float

class PaperBroker:
    def __init__(self, cash=10_000):
        self.cash = cash
        self.position = 0.0
        self.orders = []

    def submit(self, order):
        self.orders.append(order)

    def process(self, book):
        if not book["bids"] or not book["asks"]:
            return

        best_bid = float(book["bids"][0]["price"])
        best_ask = float(book["asks"][0]["price"])

        for order in self.orders[:]:
            if order.side == "BUY" and best_ask <= order.price:
                self.position += order.size
                self.cash -= order.size * best_ask
                self.orders.remove(order)

            elif order.side == "SELL" and best_bid >= order.price:
                self.position -= order.size
                self.cash += order.size * best_bid
                self.orders.remove(order)
Enter fullscreen mode Exit fullscreen mode

This is intentionally simplified. It is useful for validating architecture, but it is not a realistic fill simulator.

A stronger simulator consumes book depth and tracks remaining quantity at each price level.

4. Separate Strategy From Execution

Your strategy should produce an instruction, not directly manipulate a wallet.

def strategy(book):
    best_bid = float(book["bids"][0]["price"])
    best_ask = float(book["asks"][0]["price"])

    spread = best_ask - best_bid

    if spread > 0.05:
        return {
            "side": "BUY",
            "price": best_bid,
            "size": 10,
        }

    return None
Enter fullscreen mode Exit fullscreen mode

Then:

signal = strategy(book)

if signal:
    broker.submit(
        PaperOrder(
            side=signal["side"],
            price=signal["price"],
            size=signal["size"],
        )
    )
Enter fullscreen mode Exit fullscreen mode

This separation becomes extremely valuable later:

Strategy
   ↓
Order Intent
   ↓
Paper Broker       Live Broker
   ↓                    ↓
Simulation          CLOB API
Enter fullscreen mode Exit fullscreen mode

The same strategy can therefore be tested without changing its decision logic.

Paper Trading Is More Than Fake P&L

A useful Polymarket trading bot simulator should model at least four states:

  1. Market state — what the book currently shows.
  2. Order state — what your strategy requested.
  3. Execution state — what would have filled.
  4. Portfolio state — cash, positions, exposure, and realized/unrealized P&L.

Do not calculate P&L from the signal price alone.

If your simulated BUY occurs at $0.50 but the executable ask was $0.53, recording a $0.50 fill creates artificial alpha.

Testing Arbitrage and Market Making

A paper environment is particularly useful for experimenting with a Polymarket arbitrage bot, Polymarket market making bot, or directional Polymarket trading strategy.

For arbitrage, simulate both legs independently and include:

  • spread
  • available liquidity
  • partial fills
  • execution timing
  • fees
  • resolution risk
  • leg imbalance

For market making, track:

  • quote placement
  • inventory
  • cancellations
  • adverse selection
  • spread capture
  • inventory skew

The goal is not to produce an impressive backtest. The goal is to determine whether your assumptions survive realistic execution.

WebSocket Upgrade

Once the REST version works, move market-data ingestion to the WebSocket.

The current market channel supports subscriptions by asset ID and sends order-book snapshots and price-change events.

Conceptually:

async def on_market_update(message):
    if message["event_type"] == "book":
        local_book.replace(message)

    elif message["event_type"] == "price_change":
        local_book.apply_delta(message)

    signal = strategy(local_book)
    if signal:
        broker.submit(signal)
Enter fullscreen mode Exit fullscreen mode

Keep the WebSocket consumer, strategy engine, and broker independent. That makes reconnection, testing, and replay much easier.

Production Considerations

A paper bot should eventually become a deterministic replay system.

Persist:

timestamp
market_id
asset_id
book state
strategy signal
simulated order
simulated fill
position
cash
equity
Enter fullscreen mode Exit fullscreen mode

Then you can replay the same market session after changing your strategy.

Also respect API rate limits. Polymarket documents rate limiting across its APIs and states that excessive requests can be throttled rather than immediately rejected.

Common Mistakes

Treating displayed prices as guaranteed fills

A quote can disappear before your hypothetical order would execute.

Ignoring partial fills

A 1,000-share order cannot automatically be treated as filled simply because the top price existed.

Using future information

If your simulator knows the eventual resolution while deciding whether to trade, your results are contaminated.

Ignoring fees and slippage

A strategy with a tiny theoretical edge can disappear after execution costs.

Mixing strategy and execution

Hard-coding client.post_order() inside strategy logic makes paper testing unnecessarily difficult.

Using old SDK examples blindly

Polymarket's documentation has migrated its CLOB integration to V2 SDK packages. The current migration guide specifically identifies py-clob-client-v2 as the Python CLOB client and warns against relying on legacy V1 packages for production.

For paper trading, however, you can avoid credentials entirely because public market data does not require authentication.

Performance and Observability

Measure engineering performance separately from trading performance.

Useful metrics include:

  • market-data update rate
  • WebSocket reconnect count
  • strategy evaluation time
  • simulated order count
  • fill ratio
  • partial-fill ratio
  • average simulated slippage
  • gross P&L
  • net P&L
  • maximum drawdown
  • inventory exposure

Log every state transition with a timestamp.

If you cannot explain why the simulator generated a trade, you are not ready to trust its results.

Security

The strongest security feature of a paper trading system is that it does not need trading credentials.

Do not place private keys in the repository. Do not add credentials merely to make paper trading feel more realistic.

When you eventually add live execution, isolate credentials from strategy code and use environment variables or a proper secret-management system.

Polymarket's live CLOB architecture uses signed orders and authenticated trading requests, so the transition from paper to live should be treated as a separate security boundary.

Practical Example

Suppose your model estimates a hypothetical YES probability of 0.62.

The order book shows:

Best bid: 0.57
Best ask: 0.59
Enter fullscreen mode Exit fullscreen mode

Your paper strategy might submit:

BUY YES
Price limit: 0.59
Size: 20
Enter fullscreen mode Exit fullscreen mode

The simulator should then inspect available ask liquidity and determine whether 20 units could actually be filled.

If only 8 units were available at $0.59 and the next 12 were at $0.61, the correct simulation is a partial fill—not an artificial 20-unit fill at $0.59.

That single distinction can radically change how believable a backtest is.

Advanced Improvements

Once the basic system works, add:

  • depth-aware fill simulation
  • queue-position modeling
  • configurable latency
  • cancellation latency
  • market-data recording and replay
  • portfolio-level risk limits
  • strategy versioning
  • Monte Carlo execution assumptions
  • multiple simultaneous markets
  • live-vs-paper divergence monitoring

At that point, your paper trader becomes more than a demo. It becomes an execution research platform.

Frequently Asked Questions

Is there an official Polymarket paper-trading environment?

This article uses a local simulator, not a claim that Polymarket provides a dedicated paper-trading venue. Public market data can be consumed without authentication, allowing developers to build their own simulation layer.

Can I build a Polymarket paper trading bot in Python?

Yes. Python can consume Polymarket's public APIs and WebSocket market data, while your own broker layer simulates orders.

Do I need a private key for paper trading?

Not for the public market-data portion. Authentication is required for live trading operations, not for the public market-data APIs.

Can I test a Polymarket arbitrage strategy with paper trading?

Yes, but your simulator must model both legs, liquidity, fees, timing, and incomplete execution rather than assuming instantaneous fills.

Does paper trading prove a strategy is profitable?

No. It validates implementation and assumptions. Live execution introduces liquidity changes, slippage, latency, fees, adverse selection, and other risks that simulation may not perfectly reproduce.

Conclusion

A serious Polymarket paper trading bot should be treated as an execution simulator, not a toy trading script.

Use real public market data. Keep strategy logic independent from execution. Model the order book rather than assuming fills. Record every decision. Replay historical sessions. Then compare simulated behavior against reality before enabling live execution.

That workflow turns Polymarket trading bot development from “write a script and hope” into an engineering process:

observe → simulate → measure → replay → validate → deploy.

Risk disclaimer: Paper-trading results are hypothetical and do not guarantee live performance. Real trading involves market, liquidity, execution, model, technology, and financial risks. Never treat simulated P&L as a promise of future returns.

Related Articles

  1. Polymarket CLOB: How the Order Book and Trading API Work
    Anchor: Polymarket CLOB and order book
    Why: Explains the execution infrastructure underneath the simulator.

  2. How to Build a Polymarket Trading Bot (50ms Delay Edition)
    Anchor: Polymarket trading bot architecture
    Why: Extends the paper architecture toward latency-sensitive execution.

  3. Build a Real-Time Polymarket Order Book Monitor
    Anchor: real-time Polymarket order book monitoring
    Why: Natural prerequisite for WebSocket-based simulation.

  4. Polymarket API Explained for Developers
    Anchor: Polymarket API
    Why: Establishes the API architecture before implementation.

  5. How to Build a Polymarket Trading Bot in Python
    Anchor: build a Polymarket trading bot in Python
    Why: Moves from paper execution toward live execution.

Useful Resources

Top comments (0)