PMWallets
中文

Backtest copy trading on Polymarket before risking money

A trader's record says what they made. A backtest says what you would have made following them — later, at worse prices, paying fees they may not have paid, and skipping the trades your rules reject. The two numbers are rarely the same.

Start from every fill

A backtest needs each of the trader's fills with its exact time and price, across all of their wallets. A trade-history export gives exactly that, read from the chain. Pick traders worth testing first: positive profit without their best market, a high lower bound on the win rate over many decided markets, and taker style — a maker's fills cannot be reproduced by taking liquidity.

Add your real delay

Your copy happens after the trader's fill reaches you, your bot decides, and your order reaches Polymarket. Use measured numbers: the PMWallets latency page publishes block-to-push p50 and p95, and your own bot's order round trip can be timed in dry-run. Test at the p95, not the median — the fills that matter most are often the ones where the price runs.

Price your entry from the market, not the trader

The trader's price is not available to you a second later. Price each copy from what the market offered at your time: Polymarket's per-market trade history gives the prints around that moment, and for crypto Up or Down markets tick-level order books are available from our partner OutcomeTick. Then apply the rules a live bot would: maximum slippage over the trader's price, a price band, a minimum book depth, no markets about to settle.

python
# for each fill of the trader (from the export), oldest first
for f in trader_fills:
    if f.side != "BUY":            continue                  # the bot copies buys; exits follow the trader's sells
    t_you = f.ts + delay                                     # your reaction: feed latency + decision + order
    ask   = best_ask(f.tokenId, at=t_you)                    # from market data, not from the trader's fill
    if ask is None or ask > f.price + max_slippage:   skip("slipped")
    if not (min_price <= ask <= max_price):           skip("price band")
    shares = floor(order_usdc / ask)
    cost   = shares * ask + taker_fee(shares, ask)
    book(position[f.tokenId], shares, cost)
# then value every position at the market's payout (or exit at the bid when the trader sold)
# and compare your PnL with the trader's on the same markets

Count fees and exits

Add the taker fee on every copy and on every exit that takes liquidity. Exit when the trader sells, at the bid you could have hit, or hold to resolution and value at the payout. Compare your result with the trader's on the same markets: the gap is the cost of following, and if it eats the whole edge, the trader is not worth copying for you.

Then forward-test

A backtest can still flatter. Run the open-source copy-trading bot in dry-run on the traders that passed: it receives every live fill, applies your limits and logs what it would have done and why, without trading. A few weeks of dry-run decisions against what the market then did is the honest test.

Questions

Can I backtest copying a Polymarket trader?

Yes. Take their full fill history, add your real reaction delay, price your entries from market data at that later moment, apply slippage limits and taker fees, and compare your result with theirs on the same markets.

Why does copying a profitable trader lose money?

Because you trade later and at worse prices, pay fees the trader may not pay (especially when they were the maker), and miss or skip some of their best entries. Thin edges disappear under those costs.

Where do I get a Polymarket trader's full history for a backtest?

A PMWallets trade-history export gives every fill of a trader across all their wallets, from on-chain logs, one CSV file per wallet per day.

Related