DEV Community

Cover image for PolyTutor Is Open Source: Research-Driven Trading Bots for Polymarket
Teraus
Teraus

Posted on

PolyTutor Is Open Source: Research-Driven Trading Bots for Polymarket


description: "Black-Scholes binary pricing, Avellaneda-Stoikov market making, TWAP-aware Up/Down models, and a 39-strategy handbook, now open on GitHub."
PolyTutor builds trading infrastructure for Polymarket, the prediction market where every contract is a binary option paying $1 or $0. We just opened our GitHub org, github.com/polytutor-ai, with the bots, models, and research we use.

Smart trading. Real edge. That second part has to be measured, not assumed. So every repo below starts in paper or dry-run mode, prints its assumptions, and treats the market's own price as a strong baseline to beat.

This post walks through the math and the code.

Why prediction markets are a good engineering playground

A Polymarket share is a binary contract. A "BTC Up or Down, 5 minutes" market pays $1 if BTC finishes the window at or above where it started. That gives you:

  • a price that is literally a probability (0.57 ≈ 57%),
  • a public CLOB order book you can quote into,
  • fast settlement, so you get feedback on a model within minutes,
  • real frictions: taker fees, thin books, latency, and oracle rules.

The work is to estimate a fair probability, compare it with the executable price, and act only when the gap covers fees, slippage, and model error.

1. Pricing a binary: Black-Scholes N(d2)

For a contract paying 1 if the price S finishes above strike K at time T, the risk-neutral probability is the classic cash-or-nothing result:

from math import log, sqrt
from scipy.stats import norm

def binary_up_prob(S, K, sigma, T, r=0.0):
    """P(S_T > K) under GBM; T in years, sigma annualised."""
    d2 = (log(S / K) + (r - 0.5 * sigma**2) * T) / (sigma * sqrt(T))
    return norm.cdf(d2)
Enter fullscreen mode Exit fullscreen mode

Feed it live spot, a short-horizon realized volatility, and time left, and you get a fair value to compare with the Polymarket ask. Subtract fees and a safety haircut, and you have an expected-value filter:

edge = fair_prob - ask_price - taker_fee - haircut
if edge > min_edge:
    place_order(...)
Enter fullscreen mode Exit fullscreen mode

2. The catch: TWAP resolution

Here is the detail that trips up most first bots. Polymarket's short crypto Up/Down markets don't settle on one terminal tick. They resolve on a Chainlink price averaged over the final 60 seconds (a TWAP).

An average moves less than a point price. Its variance over the averaging window is roughly a third of the terminal variance, and part of it is already "locked in" once the window starts. A plain N(d2) with terminal volatility will be overconfident near the end of the window.

Our HFT bot handles this with a separate model: prob_up_twap in bot/updown.py models the distribution of the 60-second TWAP directly, using volatility per √second and the part of the window already observed. Black-Scholes is used only for optional long-dated strike markets (ENABLE_LONG_MARKETS=true). Using the right model for the settlement rule matters more than any extra feature.

3. Market making: Avellaneda-Stoikov quoting

Taking liquidity pays the spread and the fee. Making liquidity earns them, but you carry inventory risk. The Avellaneda-Stoikov framework gives a principled answer: centre your quotes on fair value, widen them for risk, and skew them against your inventory.

Our market maker uses an "AS-lite" form, centred on the Black-Scholes fair value rather than the noisy Polymarket mid:

bid = FV - half_spread - skew(inventory)
ask = FV + half_spread - skew(inventory)
Enter fullscreen mode Exit fullscreen mode

When you're long, both quotes shift down, so you're more likely to sell and less likely to buy more. The half-spread widens with order-book imbalance, momentum, and VPIN (a toxicity measure) to avoid being picked off. Directional BTC exposure is then delta-hedged on Hyperliquid perpetuals, using the binary's delta, n(d2) / (S·σ·√T).

The repo also includes a PPO reinforcement-learning quoting policy trained on the same backtest data, so you can compare a learned policy with the closed-form one.

The repos

⚡ polymarket-black-scholes-hft-bot

High-frequency bot for crypto Up/Down markets. It combines Polymarket CLOB data, Chainlink feeds, multi-exchange prices, a 60-second TWAP probability model, fee-aware EV, and position and portfolio risk limits. Includes a backtest lab, a calibration journal, and a paper-trading engine.

📈 polymarket-avellaneda-stoikov-market-maker

Black-Scholes fair value, AS quoting, microstructure features, Hyperliquid delta hedging, simulation and backtests, plus the PPO variant.

🤖 polymarket-adaptive-trading-desk

Four competing bots on BTC 5-minute markets: momentum, mean reversion (z-score and RSI), sentiment, and a hybrid ensemble. They share one decision engine and set of risk filters. Each bot tracks win rate by market condition (price bucket, momentum, time of day) and adapts from resolved trades. Comes with a live dashboard and paper mode.

📚 polymarket-strategy-handbook

39 strategies across 14 families, covering mechanics, signal architecture, execution, worked examples, backtesting methodology, and especially failure modes. Our motto there: Never trust the strategy. Test the strategy.

🛠️ polymarket-trading-bot

The PolyTutor hub: strategy case studies and custom bot requests. If you want a strategy automated, an existing bot improved, or help with execution and risk architecture, start here.

Also in the org

  • polymarket-btc-5min-black-scholes-bot: a live edge finder with an A/B paper-trading framework. Its README reports an honest negative result: the market price predicted settlement better than the model. Negative results are research too.
  • polymarket-5min-btc-Jev-trading-bot: a terminal agent that asks an LLM for an UP/DOWN call, abstains or buys once, and holds to resolution. Dry-run by default.

We also host forks of two community projects for reference, with original authorship and licenses kept: polymarket-mcp-agent (from demwick/polymarket-agent-mcp, MIT) and polymarket-ai-trading-bot (from skharchikov/polymarket-bot). All credit goes to their authors.

Try it in two minutes

git clone https://github.com/polytutor-ai/polymarket-black-scholes-hft-bot.git
cd polymarket-black-scholes-hft-bot
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# keep it in paper mode
echo "TRADING_MODE=paper" >> .env
python main.py
Enter fullscreen mode Exit fullscreen mode

Run backtest_lab.py and calibration.py before you think about live mode. If your model's calibrated probabilities don't beat the market's own price after fees, you don't have an edge yet.

Lessons we keep relearning

  1. Model the settlement rule, not the textbook. TWAP vs terminal price changes the answer.
  2. The market is a strong prior. Benchmark every model against the quoted price.
  3. Fees and haircuts belong in the signal, not in a post-mortem.
  4. Paper-trade until the sample size is meaningful. Five-minute markets make that cheap.
  5. Document the failures. The handbook spends as much time on failure modes as on setups.

Get involved


Risk disclaimer: This code and article are for education and research only, not financial advice. Prediction-market trading can lose money. Backtests and historical or simulated results don't guarantee future performance. Markets, fees, oracle rules, and APIs change. Check that trading on Polymarket is legal where you live, start in paper mode, and never risk money you can't afford to lose.

Top comments (0)