DEV Community

Cover image for Polymarket Mean Reversion: Build a Python Trading Bot
Bo$onaX
Bo$onaX

Posted on

Polymarket Mean Reversion: Build a Python Trading Bot

Build a Polymarket mean reversion bot in Python using price history, z-scores, order-book data, execution controls, and production risk management.

Introduction

A Polymarket mean reversion strategy is based on a simple quantitative hypothesis: when an outcome-token price moves unusually far from its recent statistical range, it may eventually move back toward its local mean.

The difficult part is not calculating a moving average.

The difficult part is determining whether the deviation is actually temporary—or whether new information has permanently changed the market's fair probability.

For a trading bot, that means the strategy needs three separate components:

  1. A statistical signal.
  2. An executable market-data layer.
  3. An execution and risk-management system.

Polymarket's current API exposes order-book snapshots and historical price data, making it possible to build the research layer directly from market data. ([Polymarket Documentation][1])


About the Author

Bo$onaX

I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.

Contact:

Github: github.com/n9xdev/poly-alpha-lab
Telegram: t.me/bosonax
Youtube: youtube.com/@bosonax
X: x.com/xxniiinxx
Gmail: mailto:dylandevera91928@gmail.com


What You'll Learn

  • How mean reversion applies to prediction-market prices
  • How to calculate a rolling z-score
  • How to filter false signals
  • How to incorporate the CLOB order book
  • How to structure a Python bot
  • Why fees, spread, liquidity and adverse selection matter
  • How to backtest and paper trade the strategy

1. The Mean-Reversion Model

Let (P_t) represent the price of an outcome token.

Calculate a rolling mean:

{
  mu_t = SMA(P_{t-n+1},...,P_t)
}
Enter fullscreen mode Exit fullscreen mode

and rolling standard deviation:

{
  sigma_t = Std(P_{t-n+1},...,P_t)
}
Enter fullscreen mode Exit fullscreen mode

Then calculate:

{
  Z_t = \frac{P_t-\mu_t}{\sigma_t}
}
Enter fullscreen mode Exit fullscreen mode

A basic strategy might define:

  • Z < -2: unusually low price → investigate a long
  • Z > +2: unusually high price → investigate an exit or short-side opportunity
  • Z near 0: price has returned toward its local mean

The important word is investigate.

A z-score is a signal, not proof of mispricing.

A breaking-news event can legitimately move a token several standard deviations away from its previous distribution.


2. Architecture

A production implementation should separate research from execution:

flowchart LR
    A[Market Discovery] --> B[Historical / Live Data]
    B --> C[Feature Engine]
    C --> D[Mean Reversion Signal]
    D --> E[Risk Manager]
    E --> F[Execution Engine]
    F --> G[Polymarket CLOB]
    G --> H[Order / Fill State]
    H --> I[Monitoring]

This separation is important because changing the strategy should not require rewriting authentication, order management, or portfolio accounting.

Polymarket's official Python SDK is currently available as polymarket-client; Polymarket describes it as a unified Python SDK and currently labels the API beta. ([GitHub][2])


3. Getting Historical Prices

Polymarket documents a /prices-history endpoint for retrieving historical market prices, with supported intervals including 1m, 1h, 1d, and others. ([Polymarket Documentation][3])

For research, your data pipeline should look approximately like:

import requests
import pandas as pd

def get_price_history(token_id: str):
    response = requests.get(
        "https://clob.polymarket.com/prices-history",
        params={
            "market": token_id,
            "interval": "1h",
            "fidelity": 1,
        },
        timeout=10,
    )
    response.raise_for_status()

    history = response.json()["history"]

    df = pd.DataFrame(history)
    df["timestamp"] = pd.to_datetime(df["t"], unit="s")
    df["price"] = df["p"].astype(float)

    return df
Enter fullscreen mode Exit fullscreen mode

This is research code, not a complete live trading engine.


4. Calculate the Signal

A compact implementation is:

def mean_reversion_signal(
    prices,
    window=20,
    entry_z=2.0,
    exit_z=0.5,
):
    mean = prices.rolling(window).mean()
    std = prices.rolling(window).std()

    z = (prices - mean) / std

    latest = z.iloc[-1]

    if latest <= -entry_z:
        return "LONG", latest

    if abs(latest) <= exit_z:
        return "EXIT", latest

    return "HOLD", latest
Enter fullscreen mode Exit fullscreen mode

But a production bot should not trade solely because z <= -2.

Add filters such as:

  • minimum order-book depth
  • maximum spread
  • minimum recent volume
  • stale-data detection
  • market status
  • volatility regime
  • time-to-resolution
  • external information events

5. The Order Book Changes Everything

A model may calculate a fair entry at $0.48, while the actual ask is $0.51.

That difference is your execution problem.

Polymarket's CLOB order-book endpoint returns bids, asks, last trade price, minimum order size and tick size for a token. ([Polymarket Documentation][1])

For example:

Model fair value:     $0.50
Best bid:             $0.46
Best ask:             $0.52
Spread:               $0.06
Enter fullscreen mode Exit fullscreen mode

A naive strategy sees $0.46 and thinks the token is cheap.

An execution-aware strategy asks:

Can I actually acquire enough inventory at a price that leaves positive expected value?

That distinction separates a backtest from a trading system.


6. A Better Entry Rule

Instead of:

Z-score < -2 → BUY
Enter fullscreen mode Exit fullscreen mode

use something closer to:

Z-score < -2
AND spread < maximum_spread
AND liquidity > minimum_liquidity
AND data_age < maximum_age
AND market_is_tradeable
AND expected_edge > estimated_cost
Enter fullscreen mode Exit fullscreen mode

Conceptually:

$$
ExpectedEdge =
FairValue - ExecutablePrice

  • SpreadCost
  • FeeCost
  • Slippage
  • ModelUncertainty $$

Only trade when the remaining edge is sufficiently large.

Polymarket currently charges taker fees on certain markets while makers are not charged fees; fee parameters vary by market and can be queried from market information. ([Polymarket Documentation][4])

Therefore, a mean-reversion model that ignores execution costs can produce attractive but completely artificial signals.


7. Production Failure Modes

1. Trading against a regime change

A price can move far from its historical mean because the underlying probability genuinely changed.

2. Using stale prices

A stale observation can generate a perfect-looking z-score that no longer exists in the live book.

3. Ignoring spread

Mid-price reversion does not necessarily equal executable reversion.

4. Overfitting

Changing window=20 to window=17 because it improves historical results is classic parameter overfitting.

5. Ignoring resolution

A prediction market approaching resolution can behave fundamentally differently from one with substantial time remaining.

6. Treating every market identically

Political, sports, crypto, economic and other markets can have very different liquidity and information dynamics.


8. Risk Management

The strategy should have hard limits independent of the signal engine.

For example:

MAX_POSITION = 100
MAX_ORDER_SIZE = 10
MAX_SPREAD = 0.03

def risk_check(position, order_size, spread):
    if abs(position + order_size) > MAX_POSITION:
        return False

    if order_size > MAX_ORDER_SIZE:
        return False

    if spread > MAX_SPREAD:
        return False

    return True
Enter fullscreen mode Exit fullscreen mode

Real systems should additionally track:

  • per-market exposure
  • portfolio exposure
  • correlated positions
  • daily loss limits
  • order rejection rates
  • outstanding orders
  • partial fills
  • API failures
  • emergency shutdown state

9. Testing Strategy

Do not start with real capital.

Use three stages:

Backtest → Paper Trading → Limited Live Trading

The backtest should simulate executable prices rather than simply using historical midpoints.

A useful simulator should model:

  • spread
  • available depth
  • partial fills
  • fees
  • order latency
  • cancellations
  • position limits
  • resolution
  • rejected orders

Then run the strategy on unseen data.

The most important test is not:

"Did the historical strategy make money?"

It is:

"Does the strategy remain positive after realistic execution assumptions?"


10. Monitoring

A live bot should expose metrics such as:

signal_count
trade_count
fill_rate
average_entry_price
average_exit_price
position_size
realized_pnl
unrealized_pnl
average_spread
data_age
order_rejections
api_errors
Enter fullscreen mode Exit fullscreen mode

Log every signal and every execution decision.

When a strategy loses money, you want to determine whether the problem was:

model → data → execution → liquidity → risk → infrastructure

without guessing.


11. Advanced Improvements

A basic z-score is only the starting point.

More sophisticated systems can use:

Volatility-adjusted thresholds

Increase the entry threshold when volatility expands.

Exponentially weighted means

Give recent observations greater importance than older ones.

Regime detection

Separate stable markets from event-driven markets.

Order-book imbalance

Combine statistical deviation with bid/ask depth.

Cross-market signals

Compare related Polymarket contracts or external reference markets.

Adaptive parameters

Estimate the appropriate lookback window from recent market behavior rather than fixing it permanently.

The strongest architecture is therefore not simply a "z-score bot."

It is a conditional mean-reversion system that asks whether the deviation is statistically unusual and economically tradeable.


Frequently Asked Questions

What is Polymarket mean reversion?

It is a trading approach that attempts to identify outcome-token prices that have moved unusually far from their recent statistical mean and may subsequently move back toward it.

Is mean reversion profitable on Polymarket?

There is no guaranteed profitability. Market selection, execution costs, liquidity, model error and information events can overwhelm a statistical signal.

What indicator should I use?

A rolling z-score is a useful starting point, but it should be combined with market microstructure and risk filters.

Should I trade every ±2 z-score event?

No. A large deviation may represent new information rather than temporary dislocation.

Can Python be used to build the bot?

Yes. Polymarket currently provides an official Python SDK, although its documentation currently identifies the SDK as beta. ([GitHub][2])


Conclusion

A useful Polymarket mean reversion bot is not simply:

price < moving average → buy
Enter fullscreen mode Exit fullscreen mode

The real system is:

Market Data
     ↓
Statistical Model
     ↓
Regime Filter
     ↓
Order-Book Validation
     ↓
Expected-Value Check
     ↓
Risk Manager
     ↓
Execution
     ↓
Fill Reconciliation
     ↓
Monitoring
Enter fullscreen mode Exit fullscreen mode

The statistical signal tells you where a potential opportunity exists. The order book tells you whether you can actually trade it. Risk management determines whether one bad assumption can damage the entire portfolio.

That is the difference between a Python strategy script and production trading infrastructure.

Trading-risk disclaimer: This article is for educational and software-development purposes only. Automated prediction-market trading involves financial risk. No strategy, model, backtest, or implementation guarantees profits.


Related Articles / Internal Linking

Article Suggested anchor Why link it
How to Build a Polymarket Trading Bot in Python build a Polymarket trading bot Broad implementation foundation
Build a Real-Time Polymarket Order Book Monitor real-time Polymarket order book Supports execution-aware signals
Polymarket Market Discovery automated market discovery Explains market selection
Polymarket Paper Trading Bot paper trading system Natural next step before deployment
Polymarket CLOB Explained Polymarket CLOB Explains execution infrastructure
Polymarket Limit Orders vs Market Orders Polymarket order execution Connects signals to fills
Polymarket API Explained for Developers Polymarket API API implementation reference

Useful Resources

Polymarket API Tutorial — Build a Python Trading Bot from Zero

— visual implementation reference, not an authoritative API source.

Top comments (0)