High-frequency market making engine for Polymarket binary options on BTC, with fair value pricing via Black-Scholes, quoting via Avellaneda-Stoikov, and delta hedging on Hyperliquid perpetuals. Includes a second variant where the quoting policy is a PPO RL agent trained on the same backtest data.
Research-and-deployment project that goes the full loop: live connectors, microstructure features, risk management, simulation, backtesting, and offline RL comparison.
avellaneda_stoikov.py— AS-lite quoting formula:bid = FV - half_spread - skew(inventory),ask = FV + half_spread - skew(inventory). Skew clamps inventory back to a target, half-spread compensates the risk of being picked off by adverse flow.pricing.py— Black-Scholes fair value for binary options:FV = N(d2)whered2 = (ln(S/K) + (r - σ²/2)·T) / (σ·√T). Used as the centre of the AS quote (rather than the mid, which is noisy on Polymarket).microstructure.py— order-book imbalance, momentum, VPIN, spread shape. Used to adjust the AS half-spread and detect adverse selection regimes.binary_delta.py— binary option delta:Δ = e^(-rT) · φ(d2) / (σ · S · √T). Drives the size of the BTC hedge on Hyperliquid.realized_vol.py— Kalman-smoothed realised volatility (fallback when Deribit IV is unavailable).risk_manager.py— inventory caps, exposure caps, daily loss circuit breaker, volatility-spike halt, time-to-expiry phases (WIND_DOWN / STOP / FAK).state.py,fill_model.py— shared state + simulated fills for backtest.
poly_ws.py— Polymarket CLOB WebSocket consumer (order book, ticks).hyperliquid_client.py— Hyperliquid REST + WebSocket: market BTC perpetual hedge orders, position polling.deribit_ws.py— Deribit BTC options WebSocket (used to fetch live implied volatility for the Black-Scholes pricing).binance_ws.py— Binance BTC spot WebSocket (used as the underlying for the binary option pricing).cf_bypass.py— utility to handle Cloudflare-protected endpoints.
trader.py— main loop: pulls live data → computes FV → AS quote → places orders via Polymarket CLOB → polls fills → triggers hedge.quote_manager.py— maintains live two-sided quotes, cancel-and-replace on drift, GTD expiry buffer, hybrid maker/taker behaviour above an edge threshold.hedge_manager.py— delta hedging on Hyperliquid: aggregates option deltas into a target BTC position, rebalances when drift exceeds tolerance.
backtest_AB.py/backtest_B_fulltick.py/backtest_comparison.py— tick-level backtest engines comparing AS-lite heuristic vs RL PPO policy on identical historical CSVs.rl_ppo_train.py— PPO training (stable-baselines3) on a custom Gym env derived from the live data. Action = spread tier + skew tier.rl_quick_test.py— sanity check / eval helper for trained models.build_rl_dataset.py— builds train/eval splits from raw market CSVs.poly_iv_analysis.py— implied vol surface analysis on Polymarket data.param_optimizer.py— grid search for AS-lite hyperparameters (half-spread, max inventory, skew max).
Production entry point: loads config, starts connectors, spins up the quote/hedge managers, handles graceful shutdown.
All trading parameters in one place: inventory caps, spread / skew, hedge
tolerance, RL toggles, momentum filter, circuit breakers. Secrets live in
a .env (never committed) and are loaded via os.getenv.
- Fair value, not mid — Polymarket binary options often have wide / stale mids, so the centre of the AS quote is the Black-Scholes fair value computed from live BTC spot + Deribit IV, not the order-book mid.
- Skew that clamps inventory — half-spread sets the rebate, skew brings inventory back to zero. Both are bounded explicitly so a tail event can't blow up the book.
- Delta-neutral via Hyperliquid — each open option position contributes a delta; the hedge manager keeps the net BTC exposure inside a tolerance band on the Hyperliquid perpetual.
- Time-aware phases — as expiry approaches, the bot transitions
NORMAL → WIND_DOWN → STOP, cancelling the riskier side first and finishing with fill-and-kill takers if a flat position is still preferable. - RL as a comparison baseline — the AS-lite heuristic is the production policy. The PPO agent is trained on the same data and compared on identical out-of-sample slices, so we know whether the added complexity buys anything.
Historical data, in-sample, ~5 USDC quote size, 10 max inventory per market:
| Strategy | Avg PnL / day | Avg Sharpe | Notes |
|---|---|---|---|
| AS-lite heuristic | ~+44 USDC | (in-sample) | Baseline production policy |
| PPO RL agent | ~+54 USDC | (in-sample) | +22% vs heuristic, in-sample |
These are simulated, in-sample numbers — the goal of the tools/backtest_*
scripts is to repeat on strict out-of-sample windows and quantify the
RL advantage (or lack thereof). Honest expectation: gap should narrow OOS.
data/— recorded market data and trades journal, including transaction hashes that can be traced back to a real wallet on-chain.results/— backtest outputs from real strategy runs..env— Polymarket / Hyperliquid private key, exchange API keys.*.pem— SSH key for the production VM.rl_models/— trained model weights.
If you want to reproduce: record your own market data via data/recorder.py,
fill in your own .env, and run a backtest with tools/backtest_comparison.py.
Python 3.11+ · py-clob-client · web3 / eth_account · websockets · curl_cffi · stable-baselines3 · gymnasium · numpy · pandas · scipy · matplotlib
Built as a personal research project on market making in binary-options-meets-crypto. The live version ran on AWS for several weeks in early 2026; the local copy in this repo is the backtesting / iteration sandbox.
Antoine Krychowski — M1 Quantitative Finance @ ESILV LinkedIn: antoine-krychowski
MIT — see LICENSE.