Skip to content

cengizmandros/polymarket-arb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Polymarket Cross-Market Arbitrage Scanner

A Python scanner that hunts for pricing inefficiencies between Polymarket (on-chain prediction market) and traditional Web2 sportsbooks. Finds hedged positions across 1X2 soccer markets, computes optimal stake splits including Polymarket fees and bookmaker cashback bonuses, and can alert via Telegram.

Features

  • Multi-source odds aggregation — pulls live markets from Polymarket Gamma API + 30+ leagues via the-odds-api
  • Fuzzy team-name matching — handles naming variants across platforms (e.g. "Brondby IF" ↔ "Brøndby IF", "Qingdao West Coast" ↔ "Qingdao Xihaian")
  • Optimal stake calculation — closed-form equalization formula for hedged profit, accounting for Polymarket's 2% fee and bookmaker-specific loss rebates
  • Microstructure scanner — detects ask orders priced below best bid on low-liquidity markets (instant-arb opportunities) via direct CLOB API queries
  • Interactive promo calculator — computes optimal hedge when a user enters a boosted odds offer from a Turkish legal betting site
  • CLOB + Betfair trading modules — automated order placement with --live flag, dry-run by default, safety guards on position size and covered profit floor
  • Telegram alerts — sends formatted opportunity notifications with deduplication

Architecture

polymarket-arb/
├── src/
│   ├── polymarket.py        # Gamma API client — parses 1X2 match events
│   ├── web2_odds.py         # the-odds-api client + team name normalization
│   ├── arbitrage.py         # Cross-position engine (6 combos per match)
│   ├── loss_bonus.py        # Turkish bookmaker cashback modeling
│   ├── promo_calculator.py  # Interactive boosted-odds hedge CLI
│   ├── microstructure.py    # CLOB orderbook scanner for discount orders
│   ├── poly_trader.py       # Polymarket CLOB order placement
│   ├── betfair_trader.py    # Betfair Exchange API integration
│   ├── executor.py          # Trade coordination + safety checks
│   ├── telegram_alert.py    # Alert dispatcher
│   ├── display.py           # Rich terminal formatting
│   └── main.py              # CLI entry point
├── requirements.txt
└── .env.example

Tech Stack

  • Python 3.10+ (async/await, dataclasses, type hints)
  • httpx — async HTTP client
  • Rich — terminal UI
  • py-clob-client — Polymarket on-chain order signing (Polygon)
  • betfairlightweight — Betfair Exchange API
  • python-dotenv — environment management

Installation

python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env        # edit and add API keys

Usage

# Scan mode (continuous, 60s refresh)
python -m src.main

# Interactive boosted-odds calculator
python -m src.main --promo

# Microstructure scan (find discount sell orders)
python -m src.main --micro --min-discount 3

# Trade mode — dry run simulates order placement
python -m src.main --trade

# Live trading (requires confirmation, real money)
python -m src.main --trade --live

Environment

Required:

  • ODDS_API_KEY — free tier at the-odds-api.com (500 req/month)

Optional:

  • TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID — alerts
  • POLY_API_KEY, POLY_API_SECRET, POLY_API_PASSPHRASE, POLY_FUNDER, POLY_PRIVATE_KEY — CLOB trading
  • BETFAIR_USERNAME, BETFAIR_PASSWORD, BETFAIR_APP_KEY — Betfair trading
  • BOOKMAKER_WHITELIST — comma-separated list to filter results by accessible bookmakers

Key Design Decisions

  • Polymarket CLOB orderbook ordering: The API returns bids in ascending order and asks in descending order. Best bid is bids[-1], best ask is asks[-1]. Missing this subtlety silently invalidates every downstream calculation.
  • Equalized-profit stake split: s_poly = budget * web2_odds / ((1 - poly_fee) / poly_price + web2_odds) — closed form, accounts for 2% Polymarket fee on winnings.
  • Loss rebate integration: Turkish bookmakers offer 8-20% cashback on weekly losses. The optimizer treats this as effective web2 odds of actual_odds - bonus_rate, which shifts allocation toward the web2 leg.
  • Concurrency: Orderbook fetches use asyncio.Semaphore(10) to avoid rate limits while scanning thousands of markets.
  • Safety for trading: Dry-run is default. Live mode requires --live flag + typed confirmation. Max position size and minimum covered-profit floor prevent tail-risk plays.

What the Numbers Actually Say

In the tested time window, the scanner found 6 matched markets and 36 cross-hedge positions. Most had negative expected value once Polymarket's 2% fee was included — consistent with the thesis that simple 1X2 cross-arb is a marginal strategy at retail scale. The real edge surfaces with:

  • Boosted-odds promotions from Turkish bookmakers (3-15% edge, size-capped)
  • Loss-rebate compounding (tilts EV meaningfully positive)
  • Microstructure discount orders on thin markets (rare, transient, HFT-adjacent)

Disclaimer

This is a research and scanning tool. No financial advice. Gambling carries risk of total loss. --live trading is off by default and requires explicit opt-in.

License

MIT

About

Python async scanner for pricing inefficiencies between Polymarket and traditional sportsbooks. Multi-source odds aggregation, fuzzy team matching, CLOB orderbook microstructure analysis, Betfair/Polymarket trading modules.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages