← All guides

Find Breakouts & Busts with Deviation Analytics

Projections tell you what's expected. Deviation analytics tell you who keeps beating expectations — your buy-low breakouts — and who keeps falling short. It's the edge your leaguemates don't have.

What you'll build: a script that scores a watchlist by average deviation and splits it into "riding hot" (sell-high / start with confidence) and "fading" (buy-low or bench) buckets.

Endpoints used

1. What a deviation looks like

For each player we track how far their actual fantasy points landed from the projection, every week. A positive avg_deviation means they routinely outscore the number.

curl -H "x-api-key: YOUR_KEY" \
  "https://api.gridirondata.com/api/v1/deviations/CeeDee%20Lamb%23WR"
{
  "player_id": "CeeDee Lamb#WR",
  "player_name": "CeeDee Lamb",
  "position": "WR",
  "season": "2025",
  "avg_deviation": 2.7,
  "weeks_analyzed": 17,
  "weekly_deviations": { "1": -0.3, "2": 4.1, "3": 1.8, ... }
}
🔑 Player IDs are First Last#POSITION (e.g. CeeDee Lamb#WR). URL-encode the space (%20) and the # (%23) — the script below does it for you.

2. The full script

import requests
from urllib.parse import quote

API = "https://api.gridirondata.com/api/v1"
H = {"x-api-key": "YOUR_KEY"}

WATCHLIST = [
    "CeeDee Lamb#WR", "Jaxon Smith-Njigba#WR", "Drake London#WR",
    "Trey McBride#TE", "Chuba Hubbard#RB", "DK Metcalf#WR",
]

scored = []
for pid in WATCHLIST:
    r = requests.get(f"{API}/deviations/{quote(pid, safe='')}", headers=H)
    if r.status_code != 200:
        continue
    d = r.json()
    scored.append((d["player_name"], d.get("avg_deviation", 0), d.get("weeks_analyzed", 0)))

scored.sort(key=lambda x: -x[1])

print("RIDING HOT (beating projections):")
for name, dev, wks in scored:
    if dev > 0:
        print(f"  +{dev:4.1f}  {name}  ({wks} wks)")

print("\nFADING (missing projections):")
for name, dev, wks in scored:
    if dev <= 0:
        print(f"  {dev:5.1f}  {name}  ({wks} wks)")

3. Turn it into signal

Next steps