Engineering case study

PropEdge

A player-prop forecasting system: it prices every PrizePicks line from official game logs, calibrates against its own graded record, checks the result against sportsbook prices at the same line where they exist, and publishes every graded pick, losses included.

Live · last refresh Oct 29, 2026, 12:00 AM PT · 15-min cycle

Hit rate61.2%233W–148L · BE 62.4%
Graded381graded Apr 5–Oct 27, 2026
Paper ROI−5.5%−$853 · Kelly-sized paper sim
Realized edge−1.2pts vs break-even · claimed +8.7 at pick time

The hit rate is judged against 62.4%, the average break-even of the graded picks: goblins need 66.7%, standards 57.7%, demons 44.7%. Demons are recorded separately: 82W–79L, 50.9% against their 44.7% break-even. Every graded pick is listed on the board.

On Oct 2, 2026 we corrected the record after a grading bug: 5 picks that had been voided are now graded: 4 wins, 1 loss. Their stat could not be read from the box score when they were voided; it can now, so each is graded on its game.

On Oct 2, 2026 we corrected the record after a grading bug: 23 picks that had been voided are now graded: 11 wins, 12 losses. They were filed under the wrong date or a team code the schedule did not recognise, or had a stat the grader could not read yet; each is now graded against the game it was made for.

The problem

Forecasting in adversarially-priced markets

Player prop markets are priced by professional bookmakers and re-priced intra-day as injuries, lineups, and money movement shift. Most retail prediction tools rely on raw model probabilities and quickly drift overconfident — predicted probabilities cluster around 70%+, actual hit rates land at 55%, and naïve users lose money on what looks like a winning model.

PropEdge attacks this with a layered statistical pipeline: calibrate, gate, scale, track. Every prediction is calibrated against the graded record, gated against break-even floors, its segment’s own graded record and the sportsbook market, sized via fractional Kelly, and resolved against official box scores. The record above is the same one the board prints — wins, losses, return — because real edges show up over hundreds of resolutions, not in cherry-picked screenshots, and a record under break-even says so.

Architecture

Pipeline

  1. Board

    Every PrizePicks line, re-downloaded every 15-minute cycle and matched to official schedules and player ids

  2. Game logs and context

    Official game logs and injury reports, team defense, market game lines and weather; handedness and batted-ball quality for baseball, power-play time for hockey

  3. Projection

    A recency-weighted mean and spread, adjusted for minutes trend, opponent defense and home/away, then blended with how often the line actually cleared

  4. Probability

    35% empirical distribution, 30% recency-weighted hit rate, 35% a 5,000-draw simulation from the player’s own games; shrunk for small samples and role volatility

  5. Calibration

    Each prop type (goblin, standard, demon) pulled toward what its own graded picks actually hit, on its own curve; every model pick and every line on the props page is priced on it

  6. Market check

    Where sportsbooks price our exact line, their average no-vig probability for our side must clear break-even, or the prop is dropped

  7. Filters

    A probability floor 2 to 3 points above each prop type’s break-even (picks priced off a sharp sportsbook line are exempt), per-sport direction rules, hit-rate floors, one pick per player and three per game, cooldowns, and a rolling 30-day auto-disable

  8. Paper trade

    Logged before the game starts, at a quarter-Kelly stake scaled by tier¼ · (p·b − (1−p)) / b

  9. Grade

    Official box scores, about 40 minutes after a game goes final; a player who did not play is a void

  10. Feedback

    Grades refit the calibration and drive the auto-disable and cooldowns. A sport, prop type and side, demons included, is switched off once 20 graded picks (50 in football) put its hit rate confidently below break-even, and stays off until reviewed. A whole prop type is switched off the same way once 50 graded picks across every sport put it confidently below break-even (standards, today); a part of it publishes again only by proving itself on its own record. Any sport with fewer than 50 graded picks (football: until 100, hitting 2 points over break-even) is on probation: at most three model picks a day, goblin overs and up to two demons (picks priced off a sharp sportsbook line are exempt)

Methods

What’s actually under the hood

Probability modeling

Hybrid probability: 35% empirical CDF of the player’s own game log, 30% recency-weighted hit rate at the line, 35% simulation (5,000 draws from the player’s real games), shrunk for small samples and role volatility. Under it, a recency-weighted mean and stddev adjusted for minutes trend, opponent defense and home/away; football adds blowout risk from the market spread and weather, baseball the opposing pitcher and handedness, hockey power-play time. A parametric Normal/Poisson curve covers the fallback paths.

Calibration

Isotonic regression, fitted on the graded record: goblins, standards and demons each get their own curve, because they hit at very different rates, and every pick the board publishes and every line on the props page is priced on its prop type’s curve. The curves refit every 10 graded picks and take effect at once. Platt scaling and the all-picks curves remain only as the fallback for a prop type with fewer than 30 graded picks. So far the model’s probability has not separated winners from losers within a prop type, which is why each sport, prop type and side also answers to its graded record: one that falls confidently below break-even stops publishing. Per-bin Brier diagnostics (50–95%, 5pp buckets) surface where the model is most miscalibrated, and the gap between what the model said and what actually hit is published bin by bin on the board — including where it still runs hot.

Joint probability

The slip prices an entry from its legs’ probabilities multiplied together, and flags legs from the same team: their outcomes move together, so the product would overstate the chance of hitting them all. A Gaussian copula Monte Carlo over historical co-occurrence (Cholesky decomposition, inverse normal CDF) is written but feeds nothing published yet.

Validation

Every published pick is paper-traded and graded against the final box score, and the reliability chart on the board compares predicted and actual hit rates by probability bin. The ML model stays in shadow: its first validation split let the same pick appear in both training and validation, so its reported gain is not trusted until it is retrained on a split grouped by date and graded on forward picks.

Sizing & risk

Paper stakes only: fractional quarter-Kelly on the published probability capped at its sport, prop type and side’s graded hit rate (pulled toward break-even on a thin record), scaled by tier (50% goblin / 75% demon / 100% standard) and capped per pick. Exposure is held by the filters, not by stake size: one pick per player, three per game, two per stat. No money is wagered.

Self-tuning

Auto-disable rule engine: scans 30-day resolved outcomes per (sport, stat, direction, prop_type), mutes combinations below tier-aware break-even with margin. Catastrophic small-sample trip-wire (≤20% WR on 5+ picks) catches 0/5 disasters before they become 0/8.

Stack

Tech

  • TypeScript
  • Node.js
  • Native HTTP
  • Railway
  • Postgres (backup copy)
  • Official stats feeds
  • PrizePicks board
  • Sportsbook prices
  • Weather forecasts
  • Hand-rolled stats
  • No external ML libs

Receipts

Live track record

The system publishes its paper-traded record, every graded pick, at propedge.today/board. The tiles at the top of this page are that record, computed by the same code from the same log, over every graded pick — no cherry-picked window, no marketing math. When the system loses money, the page shows it. When it wins, that shows too.

Why publish losses? Because the only way to prove a probabilistic model is honest is to show it converging to its predicted hit rate over hundreds of resolutions. A 14-day positive window doesn’t prove edge; a 1,000-pick rolling Brier score does.

Built and operated solo in TypeScript. One Node process refreshes the board every 15 minutes and grades each pick against the official box score about 40 minutes after its game goes final.