Note · 2026-05-15

Steam detection: what a steam move looks like

Same-direction moneyline and spread moves at two operators inside a 5-minute window. What an event looks like, how a spread move is weighted by the key numbers, and what we filter out as noise.

Updated 2026-10-02: the examples are illustrations.

Every minute while NFL games are inside the next seven days we pull current moneylines and spreads from the operators we watch: Pinnacle and BetOnline today (LowVig is BetOnline's reduced-juice skin, so the two count as one operator). When two of them move the same game the same way by ≥2pp inside a 5-minute window, that's a steam event. We log it, dispatch it to a Slack webhook, and surface it on /trust/steam: the public view lists moves that settled more than two hours ago, and a Pro account sees them live (pricing). On a spread the size of a move is not its number of points but what those points are worth. Measured from 2,939 regular-season games against one league-wide margin distribution, the same for every game, a half-point is worth about 4.8pp onto the key number 3, about 2.2pp onto 6, about 2.8pp onto 7 and about 0.5pp from 8.5 to 9: what the margin table measures at that number, not a prediction of any one alert's size. A half-point onto 3, 6 or 7 clears the 2pp bar on its own; onto 4, 10 or 14 does not; most half-points away from the key numbers are not.

What steam actually looks like

An illustration, not a log excerpt. The two moves that make up one steam event:

11:42 ET  KC@LAR  h2h/away  +3.2pp  Pinnacle
11:43 ET  KC@LAR  h2h/away  +2.8pp  BetOnline

Two operators moved the Chiefs' moneyline higher within 90 seconds. Pinnacle moved first; BetOnline followed within a minute. That's the pattern we detect: the same move at two operators inside the window. The alert records that the prices moved, not why they moved. Nothing we run measures the cause.

What we deliberately filter out

Single-operator moves

If only Pinnacle moves and BetOnline sits still, no alert fires. We require two operators before we call it steam, and BetOnline and LowVig count as one: both of them moving is one operator moving twice.

Sub-2pp jitter

Prices retick constantly. A 0.5pp move on Pinnacle that drifts back within 90 seconds is jitter, not a steam move. The 2pp floor filters this.

Moves outside the 5-minute window

A move at 11:42 and another at 11:55 might be related but most often isn't. The 5-minute window catches moves that land together; longer windows pull in unrelated moves.

Two illustrations

Worked scenarios, not entries from our log.

Example 1: Late injury news

Say it's a Sunday morning at 11:42 ET and the starting quarterback for the home team is ruled out. Pinnacle and BetOnline both move the home team's moneyline by 2-4pp inside the next two minutes. Steam fires. In this scenario we know about the injury; the alert does not. It sees two prices move.

Pro accounts with our watchlist set on that game get the alert at /me/alerts. Whether they act on it is their call: we don't tell users what to bet, just when the prices moved.

Example 2: A move with no news

A Friday afternoon, no injury news, no weather change, no public coverage. Pinnacle and BetOnline both move the same team's moneyline by 2.5pp inside 4 minutes.

Steam fires the same way. We don't know who moved the price or why, and the alert doesn't pretend to.

Why the dispatch is best-effort, not authoritative

We dispatch to a Slack webhook for our own alerting and fan out per-user alerts to anyone watchlisting the game. The authoritative surface is the in-product /trust/steam feed, which reads the stored alerts. The loop polls every 60 seconds; the public view lists moves that settled more than two hours ago, and a Pro account sees them live. Slack can drop messages; the feed does not depend on it.

The honest caveats

Methodology details: /methodology#signal-steam_detection.