Skip to content

agreenberg18/arbitrage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Arbitrage Scanner (Polymarket x Kalshi)

This project discovers overlapping markets between Polymarket and Kalshi, matches them conservatively, and logs potential arbitrage spreads to CSV. It is read-only by default and does not place any trades.

What It Does

  • Fetches market lists from Polymarket (Gamma API) and Kalshi (REST API).
  • Matches events using structural rules (e.g., Fed decisions) plus tight generic matching.
  • Subscribes to live quotes via WebSockets and polls Kalshi REST for fresh prices.
  • Writes opportunities to opportunities.csv and near-misses to skipped_opportunities.csv.

Requirements

  • Windows 10/11
  • Python 3.11+ (tested with 3.14)
  • Git (optional, for version control)
  • WSL + Redis or Windows Redis
  • Optional: Ollama (only used for future enrichment, not required for core scanning)

Quick Start

  1. Create and activate a virtual environment

    cd "C:\Users\andre\OneDrive\Documents\Arbitrage"
    python -m venv .venv
    .\.venv\Scripts\Activate.ps1
  2. Install dependencies

    python -m pip install -r requirements.txt
  3. Create your .env

    • Copy the template below into a new file named .env at the repo root.
    • Fill in your Kalshi and Polymarket credentials.
  4. Start Redis (WSL example below)

  5. Run the scanner

    python -m src.main
  6. Stop with Ctrl+C.

.env Template

Create a .env file in the repo root:

# === KALSHI CONFIG ===
KALSHI_API_KEY_ID=your-kalshi-key-id
KALSHI_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n"
# demo or prod
KALSHI_ENVIRONMENT=demo

# === POLYMARKET CONFIG ===
POLY_PRIVATE_KEY=0x...
POLY_API_KEY=...
POLY_API_SECRET=...
POLY_API_PASSPHRASE=...

# === SYSTEM CONFIG ===
REDIS_HOST=localhost
REDIS_PORT=6379
DRY_RUN=True
MIN_SPREAD_PCT=1.5
MAX_POSITION_SIZE=10.0

# === DISCOVERY CONFIG ===
POLY_INCLUDE_POPULAR=True
POLY_SEARCH_TERMS=fed,cpi,inflation,jobs,bitcoin,ethereum,election,rates,oil,gold,treasury,interest,sp500,nasdaq,crypto,sports,nfl,nba,mlb,nhl,wnba,ufc,boxing,tennis,golf,soccer,champions league,europa,conference league,world cup,super bowl,stanley cup,world series,mls,premier league,la liga,bundesliga,serie a,march madness,college football,playoff,playoffs,championship,olympics,f1,nascar,pga,cricket,rugby,esports,league of legends,valorant,cs2,dota,overwatch,apex,rocket league,call of duty,fortnite,formula 1,grand slam,atp,wta,college basketball,ncaa,ncaab

KALSHI_SERIES_TICKERS=KXFEDDECISION,KXCPI,KXBTC,KXETH,KXJOBS,KXINX,KXSPY,KXOIL,KXGOLD,KXNFL,KXNBA,KXMLB,KXNHL,KXNCAAF,KXWNBA,KXUFC,KXBOXING,KXF1,KXNASCAR,KXSB,KXEPL,KXEPLGAME,KXEPLSPREAD,KXEPLTOTAL,KXPREMIERLEAGUE,KXUCL,KXUCLGAME,KXUCLSPREAD,KXUCLTOTAL,KXUEL,KXUELGAME,KXUELSPREAD,KXUELTOTAL,KXUECL,KXUECLGAME,KXUEFAGAME,KXSOCCERBTTS,KXSOCCERSPREAD,KXSOCCERTOTAL,KXATPGAME,KXATPMATCH,KXWTAGAME,KXWTAMATCH,KXPGA,KXTHEOPEN,KXGENESISINVITATIONAL,KXPGAMAJORWIN,KXMLSGAME,KXMLS,KXNFLSPREAD,KXNFLTOTAL,KXNFLTEAMTOTAL,KXNFLPLAYOFF,KXNFLWINS,KXNHLGAME,KXNHLSPREAD,KXNHLTOTAL,KXNHLWINS,KXNBA1QWINNER,KXNBA1HWINNER,KXNBA1HSPREAD,KXNBA1HTOTAL,KXNBA2HWINNER,KXNBA2HSPREAD,KXNBA2HTOTAL,KXNBA3QWINNER,KXNBA4QWINNER,KXMLBGAME,KXMLBSPREAD,KXMLBTOTAL,KXMLBPLAYOFFS,KXMARMAD,KXMARMADSEED,KXLEAGUE,KXLEAGUEWORLDS,KXLOLGAME,KXVALORANT,KXVALORANTGAME,KXCS2,KXDOTA2,KXOVERWATCH,KXR6,KXPUBG

# Optional filter to include only Kalshi markets containing specific words
KALSHI_SEARCH_FILTER=

# Optional: Ollama (not required)
OLLAMA_HOST=http://localhost:11434
OLLAMA_MODEL=qwen3:8b

Redis (WSL Ubuntu)

If you already have Redis in WSL:

sudo service redis-server start
# or
sudo systemctl start redis-server

To verify:

redis-cli ping
# PONG

If you are not using WSL, you can install Redis on Windows or run it in Docker. Just set REDIS_HOST and REDIS_PORT in .env accordingly.

Ollama (Optional)

Ollama isn’t required for the scanner to run. If you want it for future enrichment:

  1. Install Ollama from the official site.
  2. Start it and pull a model:
    ollama run qwen3:8b
  3. Set OLLAMA_HOST and OLLAMA_MODEL in .env.

How the Matching Works

  • Structural matching: Fed decision markets are matched by month/year and action.
  • Generic matching: Strict token overlap, sport/competition labels, and market type checks.
  • Series hints: Kalshi series tickers supply sport/competition context to reduce mismatches.

The matcher is intentionally conservative to minimize false positives.

Outputs

  • opportunities.csv — only rows where net spread exceeds MIN_SPREAD_PCT.
  • skipped_opportunities.csv — near misses and reasons for rejection.

Both CSVs are ignored by git by default.

Common Issues

  • 429 rate limits: The scanner automatically retries with backoff.
  • No matches: Expand POLY_SEARCH_TERMS and KALSHI_SERIES_TICKERS.
  • Duplicate rows: Dedupe uses CSV_DEDUPE_SECONDS in .env.

Safety

This project is read-only and runs in DRY_RUN=True by default. It does not place any trades.

Frontend (Optional)

Set FRONTEND_ENABLED=True in .env, then run the scanner and open http://127.0.0.1:8765. The UI lets you view recent opportunities and update key .env settings. After saving, restart the scanner to apply changes.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages