Methodology
By Kenny Hyder · Last reviewed 2026-05-15
This page documents exactly how SportsBookISH computes every edge, probability, and recommendation surfaced across the site. Goal: full transparency, no hidden assumptions, citable formulas.
Data sources
- Kalshi REST API (free, public) — primary price source. Ingested every 5 minutes via cron.
- The Odds API (Starter tier, $30/mo) — sportsbook lines for NBA, NFL, MLB, NHL, EPL, MLS, UCL, World Cup. Pulled every 15-30 minutes. h2h, spreads, totals markets.
- DataGolf Scratch+ ($30/mo) — golf modeling baselines (win/top-N probabilities) + 11+ book aggregation. Pulled every 10 minutes during active tournaments.
- Polymarket Gamma API (free, public) — peer-to-peer prediction-market comparison for select sports markets. Pulled every 15 minutes.
Kalshi implied probability
For each Kalshi market we receive yes_bid, yes_ask, and last_price. The implied probability is computed:
- If both yes_bid > 0 and yes_ask > yes_bid AND (yes_ask - yes_bid) ≤ 0.10 AND yes_ask < 1.00: implied = (yes_bid + yes_ask) / 2 — bid/ask midpoint.
- Else if last_price is between 0 and 1: implied = last_price.
- Else if bid and ask both exist but the spread is wide: implied = (yes_bid + yes_ask) / 2.
- Otherwise: null (no actionable price).
This logic prevents dust quotes (e.g., yes_bid=0, yes_ask=1¢ on a quiet market) from being read as a 0.5% midpoint when the actual market traded at 50%.
Sportsbook de-vig
We use multiplicative normalizationper-market: for each book's set of outcomes within a single market, sum the raw implied probabilities and divide each side by the total. The result sums to exactly 100% (or to the appropriate target for multi-winner markets like top-5 or top-10).
Books median
For each side of each market, we take the median of de-vigged probabilities across all books we have a quote from in the last 30 minutes. Median (not mean) because individual books occasionally post stale or outlier lines; median is robust to one or two outliers.
Edge calculation
Buy edge = Reference probability − Kalshi implied probability.
- Positive edge = Kalshi is priced cheaper than the reference. Buy YES on Kalshi.
- Negative edge = Kalshi is priced more expensively than the reference. Either sell YES on Kalshi or bet that side at the books.
The reference is, in order of preference:
- The Pro+ user's home book (de-vigged), if they've set one
- Books median with their excluded books removed (Pro+ user preference)
- Books median across all tracked books (default for free + signed-out users)
Net-of-fee edge (Pro+)
Pro and Elite subscribers see edges afterKalshi's per-contract trading fee. Formula:
fee_per_contract_cents = max(1, ceil(0.07 × p × (1-p) × 100)) fee_per_contract_cents = min(fee_per_contract_cents, 7) net_buy_edge = gross_buy_edge - (fee_per_contract_cents / 100)
The fee is symmetric for buys and sells. The formula peaks at 2¢ per contract near 50% probability, dropping to 1¢ at the extremes and capped at 7¢.
Stale reference filtering
Any quote (Kalshi, books, DataGolf model, Polymarket) older than 30 minutes is filtered out before edge calculation. This prevents stale book lines from creating phantom edges during live events when prices move every few minutes.
DataGolf model (golf only)
DataGolf publishes a baseline win/top-N probability for each player at each tournament, computed from their proprietary strokes-gained model with adjustments for course fit, recent form, and field strength. We treat this as a third reference point alongside the books median.
DataGolf closes some markets mid-tournament (e.g., make_cut after R2). We handle this gracefully by returning empty data for those markets rather than crashing.
Movement detection
Every 5 minutes, the movement detector compares Kalshi's current implied probability for each market against the rolling baseline (15 minutes prior). When the absolute change exceeds 2% (configurable), we record a movement event used for:
- League-page “Recent moves” widget
- Per-event “Recent moves on this event” section
- Email + SMS alert dispatch for Elite subscribers with custom rules
Closed-event archive
When an event passes its grace period (12 hours for games, 1-3 weeks for futures, depending on type), the cron snapshots its final Kalshi + books state and transitions it to status=closed. Archive snapshots preserve the closing prices forever so historical edge analysis remains possible.
Limitations + caveats
- We don't track every sportsbook — coverage focuses on US legal books plus Pinnacle (offshore reference). Niche books may have better prices we're not surfacing.
- The Odds API has its own data quality — occasional stale lines or missing outcomes. We try to detect + filter these.
- For low-volume Kalshi markets, bid/ask spreads can be wide enough that the “implied probability” is more theoretical than executable. The bet tracker logs the price you actually got, not the displayed midpoint.
- Past performance ≠ future results. Edge math is a probability framework, not a prediction. Bet responsibly.
Open methodology
The full ingest + edge code is hosted in a public repository (the application is closed-source but core math is published). Browse the glossary for plain-English definitions of every term used above.
Questions or corrections? Use the contact form.