Skip to content
CURRENT
-7 → -6 (+1) over 24 captures ATL @ GB spread -7 → -6 house House backtest last 10: 6–4 · 90-day all-market 55.3% (n=8163) · 21h ago Wire Sources: Colts' Pierce out weeks; hoping for return midseason Wire Giants QB Jaxson Dart exits MNF game vs. Rams with knee injury Wire Seahawks plan to have Sam Darnold back at practice Wednesday
Access: Anonymous access. Content follows.
how-the-sausage-is-made

Pre-Snap Formation Features: A Bettable Walkthrough

Read the price, role, and market first Engineer pre-snap formation features that move WR yardage props. Receiver alignment, motion-at-snap, RB depth, and the Brier-lift math.

11 sections

Shark Snip Editorial

House byline of the Shark Snip analytics desk — numbers sourced from the data pipeline, not vibes.

Key takeaways (from article sections)

  • What counts as “pre-snap”
  • Feature 1: receiver alignment width
  • Feature 2: motion-at-snap binary flag
  • Feature 3: RB depth and backfield structure
  • Wiring the three features into TF.js
  • Validating the lift
  • Watch-outs you’ll hit on real data
  • Where to use these features
  • From feature to backtest in a real workflow
  • How these features interact with coverage shells
  • Bottom line

The pre-snap formation is the cheapest tracking-data feature you can compute. The football hasn’t moved yet, the play hasn’t happened, and the books haven’t fully priced what the offense is signaling. Every other tracking feature — separation, route trees, YAC — depends on the snap firing first. Pre-snap features just need x, y positions and the ball_snap event. This walkthrough shows the three formation features that lift WR prop Brier the most, the exact tracking-CSV columns they ride on, and how to wire them into a TF.js model running in Studio.

What counts as “pre-snap”

In a Big Data Bowl tracking_week_.csv frame, the event column flags major moments. The pre-snap window for a single play is the contiguous block of frames between event == "line_set" and event == "ball_snap" minus one frame. The line_set marker fires when officials reset the chains and the play clock starts; ball_snap fires the instant the center’s hand begins moving the ball. Anything before line_set is dead time. Anything at or after ball_snap is post-snap and must be excluded from pre-snap features.

At 10 Hz that window is roughly 30 to 80 frames, averaging about 5 seconds of live setup. That’s plenty of data to fingerprint formation, detect motion, and compute alignment, but you do not need all of it. The most useful pre-snap features collapse to just two moments: line_set (the static setup) and ball_snap minus 1 (the dynamic moment-of-snap state).

Feature 1: receiver alignment width

The simplest, hardest-to-beat formation feature is just measuring how wide the offense lines up. Procedure:

  1. Filter the tracking frames to event == "ball_snap".
  2. Join players.csv on nflId to get position.
  3. Subset to offensive skill players (WR, TE, RB, FB) on the possession team.
  4. Find the football position (nflId is NaN, displayName "football") to anchor the y axis.
  5. For each skill player, compute abs(player.y minus football.y). Take the mean across players in the WR/TE subset only — that’s the alignment width feature.

Interpretation: a 4WR empty set tends to land at width 14 to 18 yards. A 2WR/2TE set lands closer to 8 to 11. The continuous version of this feature outperforms the categorical "SHOTGUN/EMPTY/PISTOL" indicator because it captures within-formation variation — an empty set with the slots 6 yards inside the numbers behaves very differently from an empty set with everyone splitting to the sideline.

One trap: the football’s y is not always centered on the field. Hashmark plays push the snap point left or right by about 6 yards. Always anchor on the football, never on the geometric field center.

Feature 2: motion-at-snap binary flag

The single most underpriced formation cue. Procedure:

  1. Find the frameId where event == "ball_snap" for the play.
  2. Filter all offensive non-OL players in that one frame.
  3. Check whether any player has s (speed in yards/sec) greater than 1.5.
  4. Set motion_at_snap = 1 if yes, 0 otherwise.

About 28% of NFL plays in the 2023 BDB sample had motion-at-snap on offense. On those plays the in-motion receiver gained an average of 0.4 yards of additional separation at pass_arrived versus a static baseline. Books understand this in the aggregate — the team’s pass-EPA over-expected baked into the spread captures most of it — but they consistently underprice the player-level impact on WR yardage props, especially for slot WRs against zone coverage.

Per our BDB cornerstone, the motion-flag alone lifts a WR-yards-prop Brier from 0.245 to 0.243 on a 2,000-player-week sample. Combined with the alignment feature it goes to 0.240. The features stack.

Why the 1.5 yards/sec threshold

You could use any cutoff between 1.0 and 2.0 yards/sec. We landed on 1.5 because:

  • Below 1.0: you catch noise frames where a WR is shuffling or recovering from a fake motion.
  • Above 2.0: you miss tight-end orbit motion that fires the moment the snap is called.
  • At 1.5 you’re selecting for players who are actually moving across the formation, not adjusting depth.

If you’re tuning the threshold per position, use 1.2 for TEs and 1.7 for WRs — TE motion tends to be slower (often glide motion) and WR motion tends to be at-speed.

Feature 3: RB depth and backfield structure

The third feature is RB depth: how far behind the QB the running back is at ball_snap.

  1. Filter to event == "ball_snap".
  2. Find the QB (position == "QB" on possession team).
  3. Find the RBs (position == "RB" or "FB" on possession team).
  4. If there is one RB, compute rb.x minus qb.x (sign flipped if playDirection == "left"). If zero RBs (empty), set to 0 and flag empty_backfield = 1. If multiple RBs, take the deepest.

RB depth correlates with run-game intent. A depth of 5+ yards typically signals downhill running. A depth of 0 to 2 yards (pistol or behind-QB) signals quicker action and often more pass options. A depth of -2 to 1 (offset alongside or in front) signals pass protection or screen action. The continuous variable beats the categorical "I_FORM/SHOTGUN/PISTOL" label because it captures the spectrum, including hybrid sets that are mislabeled in plays.csv.

Wiring the three features into TF.js

Once your feature transformer produces (alignment_width, motion_at_snap, rb_depth) per play, the player-week aggregate is just a mean (alignment, rb_depth) and an exposure rate (motion). Persist the per-player rolling 4-week values in IndexedDB. The training brick in Studio takes them as three input features alongside the Vegas closing line, opponent defensive DVOA, and a base-rate yardage prior. The exact training loop:

  • Architecture: dense 8 → 4 → 1, sigmoid output.
  • Loss: binary cross-entropy for over/under, MSE for continuous yardage.
  • Sample: 1,500 to 2,500 player-weeks across 2 to 3 seasons.
  • Holdout: the most recent season, never random splits.
  • Convergence: 8 to 12 seconds on CPU, 1 to 2 seconds with WebGPU.

The whole training loop fits in the Studio brick walkthrough with these features substituted in.

Validating the lift

Brier score on a holdout is the right primary metric. Two checks before you trust the lift:

  1. Calibration plot — bucket your predictions into deciles and check the realized hit rate. If your 60% prop calls hit 55%, the Brier improvement is calibration drift, not edge. See the CLV explainer for why this matters more than raw win rate.
  2. Permutation importance — shuffle each feature column one at a time and re-score. If permuting the motion flag drops Brier by only 0.0001, that feature isn’t doing real work for you.

The headline result on our internal 2024 holdout: alignment_width contributed 0.0024 Brier, motion_at_snap 0.0019, rb_depth 0.0011. The three together lifted 0.0061 (more than the sum because they interact — motion-with-wide-alignment is much more informative than either alone).

Watch-outs you’ll hit on real data

  • Pre-snap shifts vs motion: a shift is multiple players moving and then settling before the snap, while motion is a single player moving across the snap. Our flag captures motion-at-snap, not shifts that completed before ball_snap. Shifts are useful too but require frame-window analysis, not a single-frame check.
  • Trick formations: Wildcat, Wildcat-direct-snap, and similar plays break the QB anchor. Either set rb_depth to NaN and let the model learn the pattern, or filter these plays out.
  • Field flips: BDB plays move both directions on the field. Normalize x by playDirection: if playDirection == "left", set x = 120 - x and dir = dir - 180 before any of these features are computed.
  • Punt formations and Hail Marys: filter to plays.csv rows where playDescription doesn’t flag punt/kick/Hail Mary. About 8% of total snaps.
  • Season-to-season drift: motion rates in particular drift year over year as offenses copy from each other. Re-fit the feature transformer every season, not just the downstream model.

Where to use these features

Three places they pay off, ranked:

  1. WR yardage / receptions / longest-reception props. Best edge.
  2. Run-pass option (RPO) team total adjustments. Formation cohesion correlates with red-zone scoring efficiency.
  3. RB rushing-attempt props. RB depth + alignment width predicts run-rate within a quarter or two on either side.

The list of where they don’t pay off is just as important: do not use formation features alone for moneylines or spreads — Vegas captures team-level formation tendency in the closing line. Use them for player props, where the slower update cycle gives you room.

From feature to backtest in a real workflow

Engineering the features is half the work. Wiring them into a bet-by-bet workflow that doesn’t lie to you is the other half. The minimum honest backtest:

  1. Build the feature row at the exact moment you would have bet. For WR props this means using the most-recent-completed week’s tracking aggregates, never including data from the game-being-predicted. The temptation to peek at this week’s formation is the most common backtest leak in tracking work.
  2. Pull the actual prop line you could have bet, not the closing line. Edge against closing line tells you whether your model is sharp, but edge you can act on is against the price you actually saw at bet time. Both numbers matter and they answer different questions.
  3. Track CLV per bet in addition to win/loss. A 56% hit rate with -1.2% CLV is variance, not edge. A 51% hit rate with +3% CLV is real and will print over time. The /desk bet log captures both automatically when you log your tracking-data plays.
  4. Size in units, not dollars. Tracking models are fragile to scheme changes mid-season. Keep stake sizing modest until the in-season Brier confirms the holdout Brier.

How these features interact with coverage shells

The interaction between formation and defensive coverage is where the biggest residual edge lives. The presnap features we engineered are pure offense — they don’t know what the defense is showing. A second-stage feature that bins the defensive shell (single high, two high, tight zone, press man) and crosses it with the offensive formation produces multiplicative edge.

Reading the shell from tracking is a separate feature module, but the shortcut: at ball_snap, count safeties (FS, SS) more than 10 yards deep. One safety deep = single-high. Two safeties deep = two-high. Then look at the cornerbacks (CB): if both CB y-distance to nearest WR is under 2 yards at snap, it’s press. Combine the four-way cross-tab with the offensive formation features and the WR yardage Brier drops another 0.003 on the same 2,000-week sample.

This is the cleanest case for the “small, composable features stack” discipline we keep coming back to. Three offensive features alone get you the bulk of the lift. The defensive shell layer adds incremental value but only if your offensive features are already debugged.

Bottom line

Three columns, three features, ~30 lines of code, and a Brier lift big enough to clear vig on the WR prop board. Pre-snap formation features are the easiest first tracking-data win for a bettor, because they don’t require modeling routes or coverage and they run in a browser tab. Train them once, validate against a real Sunday on /picks, and let the model card on the BDB hub tell you whether to keep them or swap them.

Prop hit rate versus recorded line distance

This chart remains empty until a verified source binds a player projection distribution, the offered prop line, and the settled result.

Breakeven win rate at recorded American prices

Breakeven probability is calculated only from American prices that were actually captured in the odds-history table.

Frequently asked questions

Do I have to use the offenseFormation column from plays.csv?
No, and you shouldn't for serious modeling. plays.csv offenseFormation is human-labeled and roughly 4 to 6 percent of rows mismatch what the tracking frames actually show at ball_snap. Compute formation from the tracking x, y positions yourself. The labeled column is fine as a sanity check.
What's the smallest meaningful pre-snap feature set?
Three features: receiver alignment width (mean y-distance from football for WR/TE), motion-at-snap binary flag (any offensive non-OL with speed > 1.5 yards/sec at the ball_snap frame), and RB depth (RB x-distance behind the QB). On 2,000 player-weeks these three lift WR yards-per-route Brier from 0.247 to 0.241.
Why do formation features matter more for WR props than spreads?
Vegas already prices team-level scheme tendency into spreads — the closing line for a 3WR-heavy offense reflects market knowledge. Player-level prop pricing leans more on season aggregates and is slower to react to week-specific formation deployment, especially against new defensive coordinators. That lag is the edge.
How do I avoid leaking post-snap information into a "pre-snap" feature?
Filter strictly to frames where frameId is less than the ball_snap frameId for that gameId+playId. Some BDB seasons have a 0.1-second clock-event ambiguity right at the snap; if in doubt, cut at ball_snap minus 2 frames. Pass result, target, and route labels live in plays.csv and player_play.csv post-snap fields — never join those into a pre-snap feature row.

Build a free model in 60 seconds →

Go →
10m read time
6 players/teams
8 key angles

Angles in this read

  • Edge meter Positive expected value is presented as a meter, not a guarantee.
  • Line arrow Spread, total, and price movement sections get directional cues.
  • Prop ladder Player prop sections use a laddered information rhythm.
  • Route trace A subtle route path calls attention to NFL schedule and route concepts.
  • Football thread The football animation gives NFL pages one controlled kinetic accent.
  • Model sparkline Model output and projection movement get a tiny sparkline rhythm.

This article's context stays anchored to Big Data Bowl, Hail Marys and Hail Mary. About and model, price and team total, all of which appear in the post itself.

Names and terms found in this article
Big Data BowlHail MarysHail Mary. AboutFor WRTrack CLVBrier. Howmodelpriceteam totalfeature engineeringtracking data
Share this guide Help another reader make a sharper decision.

Get picks in your inbox

One email, every slate — ranked edges, no touts. Unsubscribe any time.

Start free — pick a sport

Go →

Continue with evidence

Related reading and source status

Related Reads

players.csv in nflverse-data Is a Flat Lookup Table — Shark Snip
Beginner Guides

players.csv in nflverse-data Is a Flat Lookup Table

A public roster file holds one entry per player, no market data. Our own prop board is built the same way, and two real players prove it.

Sep 3, 2026 4 min read
NFL Big Data Bowl for Bettors: From Tracking CSV to Bet Edge thumbnail art
Data

NFL Big Data Bowl for Bettors: From Tracking CSV to Bet Edge

players.csv and games.csv live in nflverse-data's GitHub releases: the exact columns a bettor opens, the id that joins them, and how we use both.

May 15, 2026 4 min read
NCAA Women's Basketball Totals Model: A Browser Recipe thumbnail art
Modeling

NCAA Women's Basketball Totals Model: A Browser Recipe

Build an NCAA WBB totals model in the browser using pace, eFG%, and conference splits — with UConn, Iowa, LSU, and USC worked examples.

May 15, 2026 9 min read

query: loadMergedBlogPostCards + scoreRelated · n = 3

No data

No graded source picks match this article yet

The public.source_accuracy_scores 90-day query returned no rows for this article's inferred sport.