Nori V1 — Replaces XGBoost

AI & Machine LearningResearch5 min read

Predicting NFL Passing Yards with Nori: A 24% Backtest Return

We used Nori to predict NFL passing yards and price Kalshi bets. A 2025 quote-based backtest returned 24.1% after fees and modeled execution costs.

#Probabilistic Forecasting#Sports Analytics#Prediction Markets#Tabular Foundation Models#Calibration
Predicting NFL Passing Yards with Nori: A 24% Backtest Return

NFL passing-yard markets list a threshold, such as 250+ yards, and let traders buy a YES contract on whether the quarterback reaches it. If that contract costs 31 cents, it pays $1 when the quarterback throws for at least 250 yards and $0 when he does not.

We asked Nori to estimate the chance of a quarterback reaching each yardage threshold, then compared that estimate with the price to buy the contract. When the gap was large enough to cover costs and leave a margin, the strategy placed a bet. Here's how we built it.

What data helps predict NFL passing yards?

We built the historical features from free nflverse data. The target was the starting quarterback’s final official passing yards. Each decision row combined historical averages with the game so far:

  • recent quarterback attempts, yards, yards per attempt, expected points added (EPA) per dropback, completion percentage over expected (CPOE), air yards, and sack rate;
  • the QB’s average yards, attempts, yards per attempt, and remaining yards at Q1 and halftime over the previous three and eight games;
  • offensive pace, pass rate, efficiency, and available personnel;
  • the opposing defense's passing efficiency, pressure, sacks, and explosive passes allowed;
  • home field, rest, roof, week of season, entering team and opponent records, conference and division position, spread, and game total;
  • current-game passing yards, attempts, sacks, air yards, receiver usage, score differential, and time remaining.
From Football Data to a Nori-Ready Table
Quarterback form
How has the quarterback played?
Attempts, yards, YPA, EPA/dropback, CPOE, air yards, sack rate
Checkpoint history
What is usual at Q1 and halftime?
Prior 3/8-game yards, attempts, YPA, remaining yards, and history count
Offense + availability
What opportunity will the offense create?
Pace, neutral pass rate, offensive EPA, offensive-line and receiver status
Opposing defense
What does this matchup allow?
EPA/dropback allowed, pressure and sack rate, explosive passes allowed
Game context + market
What environment will shape volume?
Home/away, rest, roof, week, standings, spread, game total
Quarterback-gameQuarterback form + checkpoint historyOffenseOpposing defenseContext + marketPostgame label
QBGameYards
L3
YPA
L3
EPA/DB
L3
Q1 yards
L3
Halftime yards
L3
Plays/game
L3
Neutral
pass rate
EPA/DB
allowed
Sack
rate
VenueRestTeam
spread
Game
total
Final pass
yards
Justin HerbertW8 · LAC vs MIN2836.97+0.09542.3110.367.062.2%+0.2598.1%Home4d+3.045.5227
Josh AllenW8 · BUF at CAR2148.13+0.09676.0104.356.356.0%+0.1177.6%Away13d+7.047.5163
Caleb WilliamsW8 · CHI at BAL2126.91+0.04448.793.362.760.0%+0.3674.8%Away7d-2.545.5285
Drake MayeW8 · NE vs CLE2529.57+0.41948.7128.058.063.4%-0.0676.5%Home7d+7.040.5282
Four real Week 8 rows and a representative subset of columns are shown. Q1 and halftime columns show prior three-game averages.

Figure 1Quarterback form, checkpoint history, offense, opposing defense, and game context become columns in the quarterback-game table.

Turning passing-yard predictions into betting probabilities

Nori learns from examples supplied in a table. We gave it historical games and their outcomes, then asked it to predict how many more yards a quarterback would throw from the current point in the game. As games finished, we added them to the historical context for the following week.

Python
1import numpy as np
2from synthefy_nori import NoriRegressor
3
4model = NoriRegressor(model="nori-6m")
5remaining_yards = past_final_yards - past_checkpoint_yards
6model.fit(X_history, remaining_yards)
7prediction = model.predict(X_current, output_type="full")
8final_quantiles = prediction["quantiles"][0] + yards_so_far
9p_200_plus = 1 - np.interp(199.5, final_quantiles, prediction["taus"], left=0, right=1)

This gives us a probability for every listed line. The strategy uses those probabilities to decide whether to buy at one of two checkpoints.

When does the strategy place a bet?

Edge = (Nori probability × $1) − (price + fee)
After Q1Edge ≥ 10¢?At halftimeEdge ≥ 10¢ ANDprobability ≥ Q1?Buy 1 contractHold to game endBuy 1 contractHold to game endNo betYesYesNoNo

Figure 2The strategy makes one choice per quarterback-game: bet after Q1, bet at halftime, or do not bet. It never opens both positions.

Example: Joe Burrow’s 200+ passing-yard contract

The histogram below shows one 2025 decision. After the first quarter, Joe Burrow had 43 passing yards and Cincinnati trailed Baltimore 7–3. Nori estimated a median of 219 passing yards, with the middle 80% of its predicted outcomes between 131 and 310 yards. It assigned a 61.3% chance of reaching 200 yards. Because a winning YES contract pays $1, a 61.3% chance is equivalent to a 61.3¢ fair value.

Kalshi’s recorded YES asking price was 21¢. Adding our modeled 2¢ fee gave a 23¢ cost for a possible $1 payout. Nori estimated a 61.3% chance of winning, leaving a 38.3¢ edge, so the backtest selected the bet.

From Nori's Distribution to a Bet
Week 13 · Joe Burrow vs. Baltimore · Q1 · trailing 7–3 · 43 passing yards so far
Predicted final passing yards · 5-yard intervalsNori P(200+) = 61.3%1%2%3%0–4 yards: 0.00%5–9 yards: 0.00%10–14 yards: 0.00%15–19 yards: 0.11%20–24 yards: 0.04%25–29 yards: 0.04%30–34 yards: 0.06%35–39 yards: 0.08%40–44 yards: 0.10%45–49 yards: 0.13%50–54 yards: 0.17%55–59 yards: 0.21%60–64 yards: 0.25%65–69 yards: 0.30%70–74 yards: 0.36%75–79 yards: 0.42%80–84 yards: 0.48%85–89 yards: 0.54%90–94 yards: 0.61%95–99 yards: 0.65%100–104 yards: 0.68%105–109 yards: 0.72%110–114 yards: 0.78%115–119 yards: 0.87%120–124 yards: 0.94%125–129 yards: 1.06%130–134 yards: 1.18%135–139 yards: 1.31%140–144 yards: 1.44%145–149 yards: 1.61%150–154 yards: 1.72%155–159 yards: 1.90%160–164 yards: 2.04%165–169 yards: 2.19%170–174 yards: 2.37%175–179 yards: 2.45%180–184 yards: 2.50%185–189 yards: 2.70%190–194 yards: 2.78%195–199 yards: 2.89%200–204 yards: 2.94%205–209 yards: 2.99%210–214 yards: 2.99%215–219 yards: 2.94%220–224 yards: 3.02%225–229 yards: 2.94%230–234 yards: 2.82%235–239 yards: 2.82%240–244 yards: 2.72%245–249 yards: 2.63%250–254 yards: 2.51%255–259 yards: 2.43%260–264 yards: 2.28%265–269 yards: 2.16%270–274 yards: 2.02%275–279 yards: 1.95%280–284 yards: 1.79%285–289 yards: 1.70%290–294 yards: 1.51%295–299 yards: 1.42%300–304 yards: 1.35%305–309 yards: 1.19%310–314 yards: 1.09%315–319 yards: 1.02%320–324 yards: 0.97%325–329 yards: 0.84%330–334 yards: 0.80%335–339 yards: 0.71%340–344 yards: 0.64%345–349 yards: 0.56%350–354 yards: 0.50%355–359 yards: 0.42%360–364 yards: 0.38%365–369 yards: 0.32%370–374 yards: 0.28%375–379 yards: 0.24%380–384 yards: 0.21%385–389 yards: 0.18%390–394 yards: 0.15%395–399 yards: 0.13%400–404 yards: 0.12%405–409 yards: 0.10%410–414 yards: 0.08%415–419 yards: 0.07%420–424 yards: 0.06%425–429 yards: 0.05%430–434 yards: 0.04%435–439 yards: 0.04%440–444 yards: 0.03%445–449 yards: 0.02%450–454 yards: 0.02%455–459 yards: 0.02%460–464 yards: 0.12%465–469 yards: 0.00%470–474 yards: 0.00%200+ line050100150200250300350400450Final passing yards
How one $1 YES contract was priced
Nori fair value
61.3¢
61.3% chance × $1 payout
Quoted cost
− 23¢
21¢ Kalshi YES ask + 2¢ fee
Decision edge
= 38.3¢
Fair value left before fill cushion
38.3¢ decision edge>10¢ minimumBUY 1 YES CONTRACT
For conservative reporting, we then subtract a 5¢ fill cushion: 28¢ assumed cost and 33.3¢ remaining edge.

Figure 3Burrow finished with 261 passing yards.

What did the 2025 backtest return?

Across 272 NFL games in the 2025 sample, the strategy selected 42 bets in 39 games. Twenty-four won. Buying one contract per selected bet produced a 24.1% return on money deployed: profit divided by the total cost of those contracts, including fees and an extra 5¢ per contract for execution costs.

We used the same one-contract size for every bet to measure the strategy's selections consistently. The reported return comes from a backtest using historical quotes.

2025 strategyResult
Simulated bets42
Games with a bet39
Winning bets24
Simulated return after fees and modeled execution costs24.1%

We allowed an extra 5¢ per contract for execution costs. Actual costs can differ with market liquidity and the size of the order.

On the selected bets, Nori's probabilities also predicted outcomes more accurately than the purchase prices did. Its Brier score, which measures probability error, was 0.224 versus 0.253 for the entry prices. Lower is better.

These 42 bets give us an encouraging result to build on. The strategy was selected through experimentation on this season, so the next step is to fix the rules and test them on new games, recording actual fills and available size. That will show how the result carries over to live trading.

How can I build my own NFL passing-yard prediction model?

Open in Google Colab or view the executed notebook on GitHub. It downloads public football data and Nori’s weights, builds the features, and reproduces the blog’s Q1-first, halftime-fallback strategy.

Want to try your own features or betting rules? Tell your agent:

text
1Help me build my own NFL passing-yard prediction model with Nori-6M. Use Python and synthefy_nori.NoriRegressor for the model forecasts.
2
3Use this published notebook as the starting point:
4https://github.com/Synthefy/synthefy-nori/blob/main/examples/notebooks/nori-nfl-passing-yards.ipynb
5
6Before writing code, ask me:
7- Do I want predictions, a historical backtest, or both?
8- Which season and quarterbacks do I want predictions for?
9- What other features or football knowledge do I want to include? For example: injuries, receiver availability, coaching changes, offensive line quality, quarterback and defense identity, or different rolling averages.
10
11Build the model
12- Start with the notebook's public nflverse downloads, feature-building helper, and pinned Nori setup. I can provide additional data if I have it.
13- Predict remaining passing yards at each checkpoint, then add yards already thrown to obtain a distribution of final passing yards.
14- Use only information available at the prediction time. Calculate historical averages from earlier games and encode any new categorical inputs using past context only.
15- List the proposed feature columns and confirm them with me. Flag unavailable data instead of inventing it.
16- Show each quarterback's predicted passing yards and P10–P90 interval. If I provide a yardage line, also show the probability of reaching it.
17
18Only if I choose a backtest
19- Ask whether I want to evaluate forecast accuracy, a betting strategy, or both. For betting, ask whether to use the blog's rule or try different entry rules, edge thresholds, or bet sizes.
20- Agree on the evaluation period and rules before running. Report forecast accuracy separately from simulated betting results, including fees and execution costs.
21- Use historical Kalshi quotes for betting evaluation when available. If they are unavailable, report that limitation rather than inventing prices or returns. Recorded quotes do not guarantee fills or available size. Never place real orders.
22- Use earlier data to develop the model and later data to evaluate it where possible. Label results on data used for tuning as exploratory.
23
24Explain each step for someone who knows football but is new to machine learning. Show sample rows, cache downloads, and record the configuration so I can rerun the model.

Build with Nori

Questions? contact@synthefy.com

Backtest note: The 24.1% return is a simulation using recorded quotes, modeled fees, and an extra 5¢ per contract, not actual earnings. Historical quotes do not establish available size or guarantee a fill. We refined the strategy on 2025 data, so these are exploratory results, not independent validation or a guarantee of future returns.