PolymarketPolymarketDeveloper20 min read2025-12-11

How to Build a Polymarket Arbitrage Bot: $40M Opportunity Guide

AL - Founder of PolyTrack, Polymarket trader & analyst

AL

Founder of PolyTrack, Polymarket trader & analyst

How to Build a Polymarket Arbitrage Bot: $40M Opportunity Guide - Developer Guide for Polymarket Traders | PolyTrack Blog

Arbitrage traders have extracted over $40 million in profits from Polymarket between April 2024 and April 2025. This guide reveals exactly how they do it—from detecting opportunities to building automated bots that capture risk-free profits in seconds.

What is Polymarket Arbitrage?

Arbitrage exploits price inefficiencies to lock in guaranteed profits regardless of outcome. On prediction markets like Polymarket, this happens when:

  • YES + NO prices don't sum to $1.00 (intra-market)
  • Multiple outcomes don't sum to $1.00 (multi-outcome)
  • Same event priced differently across platforms (cross-platform)

Types of Arbitrage Opportunities

1. Market Rebalancing (Intra-Market)

The simplest form. In a binary market, YES + NO should always equal $1.00.

Example:

  • YES price: $0.45
  • NO price: $0.50
  • Combined cost: $0.95
  • Guaranteed payout: $1.00
  • Risk-free profit: $0.05 (5.3% return)

2. Combinatorial (Multi-Outcome)

In markets with multiple outcomes (e.g., "Who will win the election?"), all outcome prices should sum to $1.00.

Example:

  • Candidate A: $0.25
  • Candidate B: $0.24
  • Candidate C: $0.26
  • Candidate D: $0.245
  • Total cost: $0.995
  • Profit: $0.005 per share (0.5% return)

3. Cross-Platform Arbitrage

Exploiting price differences between Polymarket and other platforms like Kalshi, Robinhood, or PredictIt.

Example (Bitcoin > $100k):

  • Polymarket YES: $0.55
  • Kalshi YES: $0.62
  • Buy Polymarket, sell Kalshi
  • Locked profit: $0.07 (12.7% on capital)

4. Endgame Arbitrage

Buying near-certain outcomes (95-99% probability) close to market resolution. Lower margins but extremely high annualized returns.

Example:

  • Market resolves in 2 days
  • Current price: $0.97
  • Buy and hold until $1.00
  • 3% profit in 2 days
  • Annualized: 548% return

Real Data: How Much Can You Make?

MetricValue
Total arbitrage profits (Apr 2024-2025)$40 million+
Top 3 wallets combined profits$4.2 million
Average arbitrage margin2-3%
Typical opportunity windowSeconds (not minutes)
Profitable users (>$1k)Only 0.51%

Key Insight

One documented trader turned $10,000 into $100,000 over 6 months by participating in 10,000+ markets with pure arbitrage strategies—no gambling or insider information.

See What Whales Are Trading Right Now

Get instant alerts when top traders make moves. Track P&L, win rates, and copy winning strategies.

Track Whales Free

Free forever. No credit card required.

Building an Arbitrage Detection Bot

Basic Intra-Market Detector

from py_clob_client.client import ClobClient

client = ClobClient("https://clob.polymarket.com")

def detect_binary_arbitrage(market):
    """Detect arbitrage in YES/NO markets."""
    tokens = market.get("tokens", [])
    if len(tokens) != 2:
        return None

    yes_token = next((t for t in tokens if t["outcome"] == "Yes"), None)
    no_token = next((t for t in tokens if t["outcome"] == "No"), None)

    if not yes_token or not no_token:
        return None

    yes_price = float(yes_token.get("price", 0.5))
    no_price = float(no_token.get("price", 0.5))
    combined = yes_price + no_price

    # Arbitrage exists if combined < 1.0
    if combined < 0.995:  # Account for fees
        profit_margin = 1.0 - combined
        profit_pct = (profit_margin / combined) * 100

        return {
            "type": "BUY_BOTH",
            "market": market.get("question"),
            "yes_price": yes_price,
            "no_price": no_price,
            "cost": combined,
            "profit": profit_margin,
            "profit_pct": profit_pct
        }

    return None

# Scan all markets
def scan_markets():
    markets = client.get_markets()
    opportunities = []

    for market in markets.get("data", []):
        arb = detect_binary_arbitrage(market)
        if arb:
            opportunities.append(arb)
            print(f"ARBITRAGE FOUND: " + str(arb['market']))
            print(f"  Cost: $" + format(arb['cost'], '.4f') + ", Profit: " + format(arb['profit_pct'], '.2f') + "%")

    return opportunities

if __name__ == "__main__":
    scan_markets()

Multi-Outcome Arbitrage Detector

def detect_multi_outcome_arbitrage(market):
    """Detect arbitrage in multi-outcome markets."""
    tokens = market.get("tokens", [])
    if len(tokens) < 3:
        return None

    total_cost = sum(float(t.get("price", 0)) for t in tokens)

    # All outcomes should sum to 1.0
    if total_cost < 0.995:  # Account for fees
        profit = 1.0 - total_cost
        profit_pct = (profit / total_cost) * 100

        return {
            "type": "COMBINATORIAL",
            "market": market.get("question"),
            "outcomes": len(tokens),
            "total_cost": total_cost,
            "profit": profit,
            "profit_pct": profit_pct,
            "tokens": [
                {"outcome": t["outcome"], "price": t["price"]}
                for t in tokens
            ]
        }

    return None

Cross-Platform Detector (Polymarket vs Kalshi)

def detect_cross_platform_arbitrage(poly_market, kalshi_market):
    """Compare prices between Polymarket and Kalshi."""
    poly_yes = float(poly_market.get("yes_price", 0.5))
    kalshi_yes = float(kalshi_market.get("yes_price", 0.5))

    # Platform fees
    POLY_FEE = 0.0001   # 0.01%
    KALSHI_FEE = 0.007  # 0.7%

    # Opportunity 1: Poly cheaper
    if poly_yes < kalshi_yes:
        gross_spread = kalshi_yes - poly_yes
        net_spread = gross_spread - POLY_FEE - KALSHI_FEE

        if net_spread > 0.005:  # Minimum 0.5% profit
            return {
                "type": "CROSS_PLATFORM",
                "buy_platform": "Polymarket",
                "sell_platform": "Kalshi",
                "buy_price": poly_yes,
                "sell_price": kalshi_yes,
                "gross_profit": gross_spread,
                "net_profit": net_spread,
                "roi_pct": (net_spread / poly_yes) * 100
            }

    # Opportunity 2: Kalshi cheaper
    elif kalshi_yes < poly_yes:
        gross_spread = poly_yes - kalshi_yes
        net_spread = gross_spread - POLY_FEE - KALSHI_FEE

        if net_spread > 0.005:
            return {
                "type": "CROSS_PLATFORM",
                "buy_platform": "Kalshi",
                "sell_platform": "Polymarket",
                "buy_price": kalshi_yes,
                "sell_price": poly_yes,
                "gross_profit": gross_spread,
                "net_profit": net_spread,
                "roi_pct": (net_spread / kalshi_yes) * 100
            }

    return None

Real-Time Monitoring with WebSockets

REST API polling is too slow for arbitrage. Use WebSocket streaming for real-time detection:

from websocket import WebSocketApp
import json
import time

class ArbitrageMonitor:
    def __init__(self, asset_pairs):
        self.asset_pairs = asset_pairs  # {condition_id: [yes_token, no_token]}
        self.prices = {}
        self.url = "wss://ws-subscriptions-clob.polymarket.com"

    def on_message(self, ws, message):
        data = json.loads(message)

        if data.get("event_type") == "price_change":
            for change in data.get("price_changes", []):
                asset_id = change["asset_id"]
                best_bid = float(change.get("best_bid", 0))
                best_ask = float(change.get("best_ask", 1))
                mid_price = (best_bid + best_ask) / 2

                self.prices[asset_id] = mid_price
                self.check_arbitrage()

    def check_arbitrage(self):
        for condition_id, tokens in self.asset_pairs.items():
            yes_token, no_token = tokens

            if yes_token in self.prices and no_token in self.prices:
                yes_price = self.prices[yes_token]
                no_price = self.prices[no_token]
                combined = yes_price + no_price

                if combined < 0.99:
                    profit = 1.0 - combined
                    print(f"ARBITRAGE: {condition_id}")
                    print(f"  YES: {yes_price}, NO: {no_price}")
                    print(f"  Cost: {combined}, Profit: " + format(profit, '.4f'))
                    self.execute_arbitrage(condition_id, yes_token, no_token)

    def execute_arbitrage(self, condition_id, yes_token, no_token):
        # Implement order execution here
        # See py-clob-client for placing orders
        pass

    def on_open(self, ws):
        all_tokens = []
        for tokens in self.asset_pairs.values():
            all_tokens.extend(tokens)

        subscription = {
            "assets_ids": all_tokens,
            "type": "market"
        }
        ws.send(json.dumps(subscription))
        print(f"Monitoring {len(all_tokens)} tokens for arbitrage...")

    def start(self):
        ws = WebSocketApp(
            self.url + "/ws/market",
            on_open=self.on_open,
            on_message=self.on_message
        )
        ws.run_forever()

Execution Strategy

Atomic Execution

from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY
import os

client = ClobClient(
    "https://clob.polymarket.com",
    key=os.getenv("PK"),
    chain_id=137
)
client.set_api_creds(client.create_or_derive_api_creds())

def execute_binary_arbitrage(yes_token, no_token, size=10):
    """Execute arbitrage by buying both YES and NO."""

    # Get current prices
    yes_price = float(client.get_price(yes_token, side="BUY"))
    no_price = float(client.get_price(no_token, side="BUY"))

    combined = yes_price + no_price
    if combined >= 0.995:
        print("Opportunity no longer exists")
        return None

    try:
        # Buy YES
        yes_order = OrderArgs(
            token_id=yes_token,
            price=yes_price + 0.01,  # Slightly above market
            size=size,
            side=BUY
        )
        yes_signed = client.create_order(yes_order)
        yes_response = client.post_order(yes_signed, OrderType.FOK)

        # Buy NO
        no_order = OrderArgs(
            token_id=no_token,
            price=no_price + 0.01,
            size=size,
            side=BUY
        )
        no_signed = client.create_order(no_order)
        no_response = client.post_order(no_signed, OrderType.FOK)

        actual_cost = (yes_price + no_price) * size
        guaranteed_payout = size
        profit = guaranteed_payout - actual_cost

        print("Arbitrage executed!")
        print("  Cost: $" + format(actual_cost, '.2f'))
        print("  Payout: $" + format(guaranteed_payout, '.2f'))
        print("  Profit: $" + format(profit, '.2f'))

        return {
            "yes_order": yes_response,
            "no_order": no_response,
            "profit": profit
        }

    except Exception as e:
        print(f"Execution failed: {e}")
        return None

Tools and Resources

EventArb Calculator

URL: eventarb.com - Free web-based calculator supporting Polymarket, Kalshi, Robinhood, and Interactive Brokers. Features email alerts and fee-adjusted calculations.

Open Source Bots

  • polymarket-arbitrage-bot - github.com/0xalberto/polymarket-arbitrage-bot - Single and multi-market detection
  • polymarket-kalshi-btc-arbitrage-bot - github.com/CarlosIbCu/polymarket-kalshi-btc-arbitrage-bot - Cross-platform BTC arbitrage
  • event-contract-arbitrage - github.com/akhan280/event-contract-arbitrage - EventArb source code

DeFi Rate Calculators

defirate.com/prediction-markets/calculators/ - Arbitrage, odds converter, hedging, and EV calculators.

Risks and Challenges

Execution Risk: Slippage

Markets move fast. Your planned 3% profit can become 0.5% (or a loss) if prices change before execution.

  • Use limit orders with slight premium over market
  • Check order book depth before trading
  • Start with small positions (1-5% of available liquidity)
  • Avoid thin markets (<$1,000 liquidity)

Speed Competition

Reality Check

"Arbitrage opportunities on Polymarket exist for only a few seconds. Today, they are captured not by people but by bots operating on Polygon nodes."

  • Manual trading is uncompetitive for standard arbitrage
  • Sub-second execution required
  • Consider co-located servers near Polygon nodes
  • Focus on less competitive strategies (endgame, cross-platform)

Black Swan Events

Even 99% probability markets can reverse. Political scandals, health events, and resolution disputes happen.

  • Never assume any position is "guaranteed"
  • Diversify across many markets
  • Limit position size (max 1/10 of portfolio per market)

Fee Considerations

PlatformFee
Polymarket (US)0.01% trading fee
Polymarket (International)2% on net winnings
Kalshi~0.7% trading fee
Polygon gas~$0.007 per transaction

Example: $1,000 cross-platform arbitrage with 3% gross profit:

  • Gross profit: $30
  • Polymarket fee: $0.10
  • Kalshi fee: $7.00
  • Gas: $0.01
  • Net profit: $22.89 (2.29%)

Recommended Strategy by Experience Level

Beginner: Manual Endgame Arbitrage

  • Focus on 95-99% probability markets near resolution
  • Use EventArb calculator for cross-platform opportunities
  • Capital: $1,000-$10,000
  • Expected returns: 10-30% annualized

Intermediate: Semi-Automated Detection

  • Build detection scripts with manual execution
  • Focus on multi-outcome markets
  • Capital: $10,000-$100,000
  • Expected returns: 30-100% annualized

Advanced: Fully Automated Bots

  • Sub-second detection and execution
  • WebSocket streaming for real-time data
  • Co-located infrastructure
  • Capital: $100,000+
  • Expected returns: 100-300%+ annualized (highly competitive)

Key Takeaways

What Works

  • ✅ Automated detection is mandatory for consistent profits
  • ✅ Speed is critical—opportunities last seconds
  • ✅ High-volume events (elections, sports) create more opportunities
  • ✅ Cross-platform and endgame arbitrage more accessible
  • ✅ Market making + arbitrage combination most profitable

What Doesn't Work

  • ❌ Manual monitoring of standard arbitrage (too slow)
  • ❌ Large positions in thin markets (slippage eats profits)
  • ❌ Ignoring fees (can eliminate profits entirely)
  • ❌ Treating 99% as 100% (black swans happen)

Track Arbitrage Opportunities with PolyTrack

PolyTrack helps you monitor market prices, track whale movements, and identify potential arbitrage opportunities. Start your free trial and trade smarter.

Next Steps

Frequently Asked Questions

Over $40 million in arbitrage profits were extracted from Polymarket between April 2024 and April 2025. The top 3 wallets alone generated approximately $4.2 million in profits.

12,400+ TRADERS

Stop Guessing. Start Following Smart Money.

Get instant alerts when whales make $10K+ trades. Track P&L, win rates, and copy winning strategies.

Track Whales FreeNo credit card required