[polymarket][mm] BTC $1M MM parameterisation w=0.002 d=$200 — PASS (caveats)

active
polymarketmmbtcparameterisationpassadverse-selection   Priority: 5   Source: polymarket-mm   Created: 2026-05-20   Updated: 2026-05-20

Hypothesis

A symmetric MM posting width=0.002 quotes on the BTC-hit-$1M binary market captures positive spread PnL with Sharpe > 0.5 over 30 days, because the market is mean-reverting in a tight range (0.483–0.497) with a real CLOB spread of 0.003.

Data used

Method

Symmetric MM quotes: $b = m_t - 0.001$, $a = m_t + 0.001$ (width $w=0.002$). Depth $d$ USD per side. Fill rule: crossing-price (see harness note). Maker fee = 0%. Inventory limit $5,000 USD.

Width × Depth PnL grid (BTC $1M, 30-day PnL in USD):

width \ depth $50 $200 $1000
0.001 +0.49 +1.97 -15.74
0.002 +4.98 +19.91 +58.35
0.005 +0.39 +1.57 +7.85
0.010 +0.20 +0.78 +3.91
0.020 0.00 0.00 0.00

Width × Depth Sharpe grid (BTC $1M, annualised):

width \ depth $50 $200 $1000
0.001 0.112 0.112 -0.155
0.002 0.971 0.971 0.695
0.005 0.285 0.285 0.285
0.010 0.095 0.095 0.095

Best config (w=0.002, d=$200) detail: - Fills: 120 total (62 bid / 58 ask) — near-balanced, 2.8% of ticks - Gross spread capture (theoretical): $49.01 - Cash: −$750.99 | Inventory MTM: $770.90 - Max |inventory|: $1,751.60 USD - Return on max capital: 19.91 / 1751.60 = 1.14% / 30d → ~13.7% annualised - Sharpe (annualised, time-weighted): 0.971

Adverse selection comparison (PSG Champions League — FAIL): - Market trended 0.165 → 0.585 (directional move, 42pp in 30d) - ALL 21 configs negative; best: w=0.005 → −$47.68 gross, −$238.39 on $1000 depth - Adverse selection mechanism: rising price fills our asks → we go short → pay mark-up at close

Result

Key sensitivity: BTC profits only at widths ≤ 0.01 (market range = 0.014; wider quotes never fill). PSG losses scale linearly with depth.

Reproduction

source ~/.pmvenv/bin/activate
# Single config:
python3 /home/workspace/pm_mm_backtest.py --market btc_1m --width 0.002 --depth 200
# Full sweep:
python3 /home/workspace/pm_mm_backtest.py --sweep
# Results CSV: /tmp/pm_data/sweep_results.csv

Failure mode / next step

  1. Fill model overcount: crossing-price fills ≈ 3× more than real in a mean-reverting market; true Sharpe likely 0.3–0.5 range. Next: validate against Polymarket trade-auth API to get real taker flow.
  2. Inventory cap missing in live trading: the $5,000 max inventory cap is a soft control; without hedging (e.g., correlated NO token), the MM has uncapped binary resolution risk.
  3. Queue position: we assume top-of-book priority; in reality other MMs compete at the same tick. Effective fill rate could be 5–10× lower.
  4. Single 30-day window: n=120 fills for BTC is too small to confirm Sharpe robustly (95% CI spans ~±0.8); need multi-period test or out-of-sample validation.
Edit this Idea