Sports.
$5M+/month in liquidity rewards. Almost nobody is collecting.
Polymarket pays market makers to quote both sides of sports markets under a quadratic scoring function. EPL, NBA, UCL, CS2, IPL, NFL. You don't pick winners; you ship tight quotes and uptime. SimpleFunctions runs the pre-game and live engines, handles circuit breakers, and skews sizes when a thesis edge appears.

Calcio Fiorentino · 1530 Piazza Santa Croce — sport, crowd, and the scribe at the bookmaker's table all in one frame.
What the runtime optimizes
Tight is exponentially better. Two-sided is 3x.
Polymarket sports MM optimizes a fixed reward pool through a quadratic function — different objective from spread capture, different constraints. Seven fields per market drive every quoting decision.
quadraticScoreS(v, s) = ((v − s)/v)² — the formula Polymarket uses to allocate the daily reward pool.
tickFromMidDistance from midpoint, in cents. Default 1¢ both sides for max score on a 3¢-cap market.
twoSidedDepthBid + ask both at top-of-book, equal size. Single-sided scores ~⅓ of two-sided.
rewardShareYour score ÷ total qualifying score in that pool. ~20% target share is achievable for top-3 makers.
adverseSelection~$50/EPL-game from 2.5 avg goals × 20¢ impact × 100 contracts. <3% of revenue at scale.
circuitBreakerPull all quotes on a sudden mid jump (±5¢ in <2s default), cool 10s, recompute, requote.
skewBiasWhen a thesis edge says one side is mispriced, skew sizes — score near-max, inventory leans.
Per-game reward pools
At ~20% market-share for a top-3 maker, most leagues clear $300-$3,500/game. Live mode is ~72% of the pool; the engine handles both modes from one config.
| League | Per game | Pre | Live |
|---|---|---|---|
| UCL | $4,800 | $1,344 | $3,456 |
| EPL | $2,000 | $560 | $1,440 |
| NBA (regular) | $1,800 | $504 | $1,296 |
| NFL | $1,500 | $420 | $1,080 |
| CS2 (major) | $1,100 | $308 | $792 |
| La Liga | $660 | $185 | $475 |
| IPL | $450 | $126 | $324 |
| Serie A | $660 | $185 | $475 |
Estimates assume top-3 reward share. Source: Polymarket liquidity-rewards docs.
Why a purpose-built sports engine
Hand-quoting on Polymarket UI
You see the market with full context
No quadratic-score optimization, no circuit breakers, no two-sided depth automation
Generic MM bot
Familiar tooling for equities / perps
Wrong objective function — reward pool ≠ spread capture; no event-aware circuit breaks
DIY Python script
Total flexibility, no vendor lock-in
Months of work to handle goals, halftime, lineup, scoring, circuit, polling cadence
SimpleFunctions sfmm + QuoteEngine
Pre + live, all leagues, BYOK on Polymarket
Quadratic-score optimal, sub-100ms requoting, edge-aware skew, full circuit handling
Who runs sports MM
Six recurring shapes. Capital scales sub-linearly with reward share — most operators run multi-league for coverage, not single-league for size.
Sports MM firms
Multi-stream operation across EPL/UCL/NBA — coverage capacity matters more than per-game bias.
Quant prop desks
Sports as low-correlation alpha; reward pool capture independent of equities P&L.
Esports specialists
CS2 / LoL — discrete-round structure, $5,500/match pools, digital-native flow underserved.
Cricket-focused makers
IPL is the largest unrebated cricket pool; clear cadence, light competition for top-3 share.
Underwriting models
Run sfmm + your model: thesis-skewed quotes that earn the pool AND lean toward conviction side.
Discretionary punters
Use sf scan + sf book to find edge, hand-quote with the engine handling tick-distance + circuit.
Run it from anywhere
The bot is open source. The data feed is the same one the rest of the runtime uses. Wire it into your ops Slack, your IC pack, or your agent.
Live sports markets
GET /api/public/markets?keyword=epl+nba+ucl&venue=polymarketopenPer-game orderbook
GET /v1/orderbook/{polymarket-condition-id}openEdges (sports lens)
GET /api/public/edges?theme=sportsopenRun the bot
sfmm run --leagues epl,ucl,nba --mode liveopenMCP — sf.book (agent)
mcp call simplefunctions.book { ticker: "..." }openPre and live, side by side
Two different operational modes. Same engine, different polling cadence, different circuit-breaker thresholds, different reward economics.
$ sfmm run --mode pre --leagues epl,ucl
PRE Liverpool vs Arsenal (3 markets)
Match Result YES bid 0.54×100 ask 0.56×100
Over 2.5 Goals bid 0.61×100 ask 0.63×100
Both Teams Score bid 0.58×100 ask 0.60×100
Score: 44.4/min · est reward $560/game
Polling: 5s · Status: quoting
Risk window: lineup announcement (~5 min)
Circuit: ±5¢ in <30s$ sfmm run --mode live --leagues epl
LIVE Liverpool vs Arsenal — 67'
Match Result YES bid 0.71×100 ask 0.73×100
Score: 44.4/min · est reward $1,440/game
[72'] ⚠ GOAL — Liverpool 2-1
[72'] CIRCUIT BREAK — quotes pulled
[72'] cooldown 10s ...
[72'] ✓ requoted at new mid 0.78
bid 0.77×100 ask 0.79×100S(v, s) = ((v - s) / v)²
v = 3¢ (max qualifying spread)
s = 1¢ → score = 0.444 per contract
s = 2¢ → score = 0.111 per contract ← 4x worse
s = 3¢ → score = 0 (cap reached)
Two-sided quoting (bid + ask) ≈ 3x score
Tighter is exponentially better.$ sf quote create LIVERPOOL-ARSENAL-MATCH \
--thesis-id liverpool-vs-injuries \
--skew-from-edge
✓ active · auto-skew from edge feed
default: bid 100 / ask 100 (symmetric)
thesis edge says +5¢ Liverpool YES
→ bid 130 / ask 70 (favored side leans)
score stays 0.43/min · inventory tiltsFAQ
What is Polymarket sports market making?
Polymarket pays market makers to quote both sides of sports markets through a quadratic scoring function. Every minute the platform samples your resting orders; the closer your bid/ask sit to the midpoint and the more two-sided depth you provide, the more of the daily reward pool you receive. About $5M+/month flows through the EPL/NBA/UCL/CS2/IPL pools combined.
How does quadratic scoring actually work?
Score(v, s) = ((v − s)/v)² where v is the maximum qualifying spread (3¢ on most sports markets) and s is your distance from midpoint. At s=1¢ you score 0.444 per contract; at s=2¢ only 0.111. Two-sided quoting (bid + ask) scores ~3x single-sided. Tighter is exponentially better — you can not just brute-force volume.
Pre-game vs live mode — what changes?
Pre-game ~28% of the pool, slow price moves, 5-second polling, low adverse selection (only lineup announcements really move the book). Live ~72% of the pool, sub-second polling required, circuit-breaker on midpoint jumps, 2.5-3x more reward but you absorb adverse selection on every goal/score change. The runtime ships both modes; sfmm run --mode pre|live picks one.
Adverse-selection math for soccer?
EPL average: 2.5 goals per game, ~20¢ price impact per goal, ~100 contract exposure → ~$50 cost per game. Reward at 20% pool share is ~$2,000 per game live, ~$560 pre-game. Adverse selection is roughly 2.5% of revenue. The numbers work because soccer is "96% safe time" — long stretches of stable quoting between rare high-impact events.
Which leagues does the runtime cover?
Soccer: EPL, La Liga, Bundesliga, Serie A, UCL, UEL, Conference, MLS, J-League. Basketball: NBA, EuroLeague, college (NCAAM/NCAAW). Esports: CS2 majors, LoL, Valorant. Cricket: IPL, T20I, Test. American football: NFL, college bowls. New leagues are wired by configuring contract patterns; the engine is league-agnostic.
Capital requirement to start?
Soccer-only single-stream: $3,000-$5,000 USDC, depending on league mix. Multi-sport: $10,000-$25,000 to spread inventory across overlapping windows. Capital scales sub-linearly with reward share — once you are top-3 on a market, more inventory mostly buys depth not score, so you cap inventory and add markets instead.
How does the runtime decide quote sizes?
The default is symmetric (no view): bid 100×, ask 100×. When a thesis or edge feed gives you a side-bias (e.g., your model says +5¢ on Liverpool YES), the bot skews sizes — more on the favored side, score stays near-maximum, inventory leans toward your edge. This is QuoteEngine v2 in the CLI.
What about circuit breakers?
On any sudden midpoint jump (configurable: default ±5¢ in <2s on live), the engine pulls all quotes, cools down for 10s, recomputes fair from new mid, and requotes. This is the difference between a +$1,440 live game and a -$300 ride after a goal you did not see coming.
How is this different from a standard MM bot?
Standard MMs optimize for spread capture on equities/perps where the spread is wide and volume is volatile. Polymarket sports MM optimizes a fixed reward pool through a quadratic function — different objective, different constraints. The runtime is purpose-built for the Polymarket scoring rules and the sports-specific event structure (kickoff, lineup, halftime, goal, period end).
Open source?
sfmm (the Python sports MM bot) is public on GitHub. QuoteEngine v2 lives in the supported @spfunctions/cli npm package and uses the same BYOK execution path as the rest of sf.
Related surfaces
Maker strategy
General two-sided quoting beyond sports — same primitives, different objective.
Quant trading
Microstructure, depth-adjusted edge, regime detection.
Edge discovery
Find which side to skew on; thesis-vs-market in one feed.
For funds
Cross-venue tools, audit trail, BYOK execution for fund desks.
Portfolio Autopilot
Wrap sfmm output into a portfolio agent that allocates across leagues.
Prediction market API
CLI, REST/Data API, real-time WebSocket streams, MCP adapter.
Heartbeat engine
24/7 monitoring + thesis re-evaluation across markets and leagues.