Remote MCP server for backtesting Polymarket BTC Up/Down 5-minute markets on 100ms tick data. Add it to Claude as a custom connector

Polymarket BTC Backtester (hosted MCP server)

A public MCP server for backtesting simple limit-order strategies onPolymarket's "BTC Up or Down" 5-minute markets. You paste one URL intoClaude as a custom connector and then ask things like:

Backtest buying Up at 40 cents with a 5 cent take-profit across all marketsand show me the win rate, the skew breakdown, and the date range tested.

Connector URL (replace with your deployment):

https://<your-app>.onrender.com/mcp

No login, no API key. The server is read-only and serves a static historicaldataset, so there is nothing to protect. A small per-IP rate limit keeps itpolite.

How it works

 Kaggle datasets (downloaded once, at image build time)
 ┌─────────────────────────────┐  ┌──────────────────────────┐
 │ 100ms ticks + outcomes      │  │ 2s snapshots (metadata)  │
 │ namz8888, ~14k markets      │  │ debayan31415, 1,191 mkts │
 └─────────────┬───────────────┘  └────────────┬─────────────┘
               │   pmbt/ingest.py              │
               │   - in-window quotes only     │
               │   - dedup to quote changes    │
               │   - prices -> integer 1/10c   │
               │   - winners from outcomes     │
               │   - price_to_beat + x-check   │
               ▼                               ▼
         ┌───────────────────────────────────────────┐
         │ data/store.db (SQLite, read-only, ~700MB) │
         │ markets / quotes / meta                   │
         └─────────────────────┬─────────────────────┘
                               │
         ┌─────────────────────┴─────────────────────┐
         │ pmbt/server.py (FastMCP, streamable HTTP) │
         │  /mcp     5 tools                         │
         │  /        landing page                    │
         │  /health  liveness                        │
         └─────────────────────┬─────────────────────┘
                               │ HTTPS (Render)
                               ▼
                  Claude custom connector

The backtest engine (pmbt/engine.py) is pure functions over integer prices.It knows nothing about BTC reference prices or price_to_beat, so display datacan never leak into PnL.

Tools

tool what it does
data_coverage date range, market counts, list of missing or partial days
list_markets browse markets with winner, price_to_beat, tradeability
get_price_series bid/ask series for both sides plus BTC reference, resampled
backtest the strategy simulator, see below
market_context one market in full: window, strike, winner, tick coverage

The strategy that gets backtested

For each market in the chosen date range:

  1. Rest a limit buy on the chosen side at your entry price. It fills at thefirst tick where that side's best ask is at or below the entry price,always at the entry price exactly. One trade per market, full size.
  2. On entry, rest a limit sell at entry plus the take-profit. It fills at thefirst later tick where the best bid reaches the target, always at the limitprice, even when the bid gaps through it.
  3. If the take-profit never fills, the position rides to resolution: $1.00 ifthe held side won, $0.00 if it lost.

Stated assumptions (also returned by every backtest call):

  • Touch-fill: resting orders fill when the opposing best quote reaches theirlevel. No queue position or book depth model. Empirically reasonable inthese very liquid markets, still an approximation.
  • Both legs are maker orders and Polymarket makers pay zero fees here, so thedefault fee is 0. A taker_fee override exists for simulating market orders.
  • Redemption at $1/$0 is free.
  • Static dataset. Past quotes, not live ones.

The results make the skew of this strategy very visible: win rates above 70%with negative expectancy, because the upside is capped at the take-profitwhile a forced loss costs the whole entry price.

Resolution rules

"Up" wins when the Chainlink BTC/USD price at window end is at or above theprice at window start. Ties resolve Up. The engine takes winners only from theoutcomes file of the 100ms dataset, never from the Binance/Coinbase/Krakenreference prices in the data, because those prints differ from Chainlinkenough to flip close markets.

Data

Two Kaggle datasets, credit where due:

  • Polymarket BTC 5-Minute 100ms Market Databy namz8888. The backbone: 100ms quotes and resolved outcomes for ~14,000markets over about 7 weeks (2026-03-05 to 2026-04-25). The tradeableuniverse is exactly the markets here that have both quotes and an outcome.
  • Polymarket 5 minutes BTC UP Down databy debayan31415. 2s snapshots for 1,191 markets (2026-02-23 to 2026-03-05).Used only for the official price_to_beat and for cross-checking winners.Markets that exist only here are never backtested, since 2s sampling missesprice touches.

The two datasets currently share zero markets (they cover adjacent dateranges), so cross-validation had nothing to flag and tradeable markets show anapproximate price_to_beat taken from the first reference tick. That value isdisplay only. See docs/DATA_SCHEMA.md for the full schema and decisions.

Run it locally

pip install -r requirements.txt

# build the data store (~600MB download, a few minutes)
python -m pmbt.ingest --download --raw data_raw --db data/store.db

# tests
python -m pytest tests/ -q

# serve
PORT=8000 python -m pmbt.server
# landing page: http://localhost:8000/
# MCP endpoint: http://localhost:8000/mcp

Deploy to Render

The Dockerfile downloads the datasets and builds the SQLite store during theimage build, so the running container never fetches data. Host disks beingephemeral does not matter; the store ships inside the image.

  1. Push this repo to GitHub.
  2. On render.com: New, then Web Service, then connectthe repo. Render picks up render.yaml and the Dockerfile automatically(runtime: Docker, health check on /health). The starter plan is enough;the image is about 1GB because of the baked store.
  3. Wait for the build (the Kaggle download runs inside it, expect ~10 min).
  4. Your connector URL is https://<app-name>.onrender.com/mcp. HTTPS isautomatic. Open the root URL to see the landing page with the copy button.

Railway and Fly work the same way: deploy the Dockerfile, expose $PORT,done. The server listens on 0.0.0.0:$PORT and defaults to 8000.

Add it to Claude

  1. Settings, then Connectors, then Add custom connector.
  2. Paste the /mcp URL. No auth fields needed; the connector flow probes theOAuth discovery endpoints, gets clean 404s, and falls back to anonymous.
  3. In a chat, open the plus menu and enable the connector.
  4. Ask for a backtest.

Repo layout

pmbt/
  ingest.py    Kaggle files -> SQLite store
  store.py     store schema + connections
  db.py        read-only query layer
  engine.py    backtest engine (pure, integer prices)
  server.py    FastMCP server, tools, rate limiting
  landing.py   the landing page HTML
scripts/
  discover_schema.py   raw-schema dump (run before trusting any column name)
docs/
  DATA_SCHEMA.md             schemas and ingest decisions
  schema_discovery_output.txt captured discovery output
tests/         engine + store tests (22)
Dockerfile     two-stage build, store baked at build time
render.yaml    Render blueprint

Not financial advice. Built as a portfolio project.

MCP Server · Populars

MCP Server · New

    bobmatnyc

    MCP Vector Search

    CLI-first semantic code search with MCP integration. Modern, fast, and intelligent code search powered by ChromaDB and AST parsing.

    Community bobmatnyc
    ptbsare

    MCP Proxy Server

    This server acts as a central hub for Model Context Protocol (MCP) resource servers.

    Community ptbsare
    docling-project

    Docling MCP: making docling agentic

    Making docling agentic through MCP

    Community docling-project
    SouravRoy-ETL

    duckle

    Local-first ETL/ELT studio: a drag-and-drop visual pipeline designer that compiles to SQL and runs on DuckDB. Tiny desktop app, no servers, git-friendly workspaces.

    Community SouravRoy-ETL
    ksylvan

    Fabric MCP Server

    Fabric MCP Server: Seamlessly integrate Fabric AI capabilities into MCP-enabled tools like IDEs and chat interfaces.

    Community ksylvan