BDL LAB Documentation

Complete guide to building betting models

Overview

What is BDL Lab?

BDL Lab is a betting model builder by BALLDONTLIE. It allows you to create prediction models by combining pre-built factors, backtest against 6+ years of historical data, and track live predictions for upcoming games.

Key Features

  • Factor-based modeling - Combine 15-18 pre-built factors per sport
  • Historical backtesting - Test models against data from 2020 to present
  • Multiple sports - NBA, NFL, NHL, and MLB supported
  • Live predictions - Generate predictions for upcoming games
  • API access - Programmatic access for automation and AI agents

Who is it for?

BDL Lab is designed for sports bettors who want a data-driven approach to their betting strategy. Whether you're a casual bettor looking to make more informed decisions or a serious bettor building systematic models, Lab provides the tools you need.

Subscription Tiers

Free
$0
  • UI access only
  • 1 model limit
  • 1 week backtest limit
  • No API access
ALL-ACCESS
$299.99/mo
  • Everything in LAB PRO
  • BALLDONTLIE Sports API
  • Real-time data for 20+ leagues

Getting Started

1. Create an Account

Sign up for free at lab-app.balldontlie.io/signup. You can explore the UI and create models immediately with the free tier.

2. Choose Your Sport

Select from NBA, NFL, NHL, or MLB. Each sport has its own set of factors tailored to that league's unique characteristics.

3. Create Your First Model

  1. Click Create Model on the Models page
  2. Select a bet type (Spread, Moneyline, or Over/Under)
  3. Choose your mode (Simple or Weighted)
  4. Add factors and assign importance levels
  5. Click Run Preview to see historical performance
  6. Save your model when satisfied

4. Evaluate and Generate Predictions

After saving, run Evaluate Performance to get a full historical analysis. Then use Generate Predictions to create predictions for upcoming games.

Core Concepts

Factors

Factors are metrics that predict game outcomes. Each factor has a raw value (the actual metric) and a normalized score (0-100 scale) for comparison across different factors.

There are 5 factor categories:

  • Team Performance - Scoring averages, defensive ratings, home/away splits
  • Matchup - Head-to-head history, pace differentials
  • Situational - Rest days, travel, schedule density
  • Player - Star player availability and impact
  • Market - Line movement, public betting percentages

Models

Models combine multiple factors with assigned weights to generate predictions. There are two modes:

  • Simple Mode - Assign Low/Medium/High importance to each factor. The system converts these to weights automatically.
  • Weighted Mode - Assign precise percentage weights that must sum to 100%.

Bet Types

  • Point Spread - Predict which team covers the spread
  • Moneyline - Predict the outright winner
  • Over/Under - Predict whether total score goes over or under the line

Evaluation Pipeline

The workflow for using a model:

  1. Preview - Test configuration before saving (results not persisted)
  2. Save - Persist the model configuration
  3. Evaluate - Run full historical analysis (results persisted)
  4. Generate Predictions - Create predictions for upcoming games

Complete Walkthrough

This section walks through a complete example: creating an NBA spread model, running a backtest, interpreting results, and generating predictions. We'll explain every configuration choice along the way.

Step 1: Create the Model

Let's build a model called "NBA Rest & Defense" that focuses on situational advantages and defensive performance—two factors that tend to be undervalued by casual bettors.

Choosing the Sport and Bet Type

Our choice: NBA, Point Spread

We're choosing NBA because basketball has the most games (82 per team) giving us the largest sample size for backtesting. Point spread is ideal because:

  • Spreads require a more nuanced edge than moneyline (where heavy favorites offer little value)
  • The vig on spreads (-110) is lower than moneyline underdogs
  • Our factors (rest, defense) directly impact margin of victory, not just win/loss

Choosing the Mode

Our choice: Simple Mode

We'll use Simple Mode with Low/Medium/High importance levels. This is recommended when:

  • You're still learning which factors work best
  • You want the system to normalize weights automatically
  • You prefer faster iteration over precise control

Weighted Mode (precise percentages) is better once you've identified your core factors through backtesting.

Selecting Factors

We'll select 5 factors, chosen to complement each other without overlap:

team_last_n_pts_allowed_avgHigh Importance
Points Allowed Average

Why: Defense travels. Teams allowing fewer points tend to keep games close, which matters for spread betting. This is our primary signal.

rest_daysHigh Importance
Rest Days Advantage

Why: Rest is one of the most predictive factors in the NBA. Teams on 0 rest (back-to-back) underperform by 2-3 points on average. This is especially valuable because oddsmakers sometimes underadjust.

back_to_backMedium Importance
Back-to-Back Game

Why: While rest_days captures the general rest advantage, this factor specifically penalizes the second game of a back-to-back. It complements rest_days by adding extra weight to the worst-case scenario.

team_ats_recordMedium Importance
Against The Spread Record

Why: Teams that consistently cover the spread may have qualities (depth, coaching, clutch performance) not captured by other metrics. This is a "meta" factor that captures market inefficiency.

travel_contextLow Importance
Travel Context

Why: Extended road trips cause fatigue. We set this to Low because it's a secondary situational factor— important but less impactful than rest days.

Configuration Summary

Model Configuration
Model Name: NBA Rest & Defense
Sport: NBA
Bet Type: Point Spread
Mode: Simple

Factors:
  - team_last_n_pts_allowed_avg: HIGH (50)
  - rest_days:                   HIGH (50)
  - back_to_back:                MEDIUM (30)
  - team_ats_record:             MEDIUM (30)
  - travel_context:              LOW (10)

Total multiplier sum: 170
Effective weights:
  - team_last_n_pts_allowed_avg: 29.4%
  - rest_days:                   29.4%
  - back_to_back:                17.6%
  - team_ats_record:             17.6%
  - travel_context:              5.9%

Step 2: Run Preview

Before saving, click Run Preview to see how this model would have performed. The preview runs against all historical games with available odds.

Sample Preview Results

Preview Output
Historical Performance (2020-2024)
══════════════════════════════════
Total Games Analyzed: 4,892
Games with Predictions: 3,156 (64.5%)

Record: 1,672 - 1,412 - 72 (W-L-P)
Win Rate: 54.2%
ROI: +3.8%

Results by Confidence:
  Low (0-33):    512-498   (50.7%, +0.2% ROI)
  Medium (34-66): 724-612   (54.2%, +3.1% ROI)
  High (67-100):  436-302   (59.1%, +8.4% ROI)

How to Interpret Preview Results

Win Rate (54.2%):

  • Against the spread, you need ~52.4% to break even (due to -110 vig)
  • 54.2% is a solid edge—approximately +3.8% ROI assuming flat betting
  • This means for every $100 wagered, you'd profit $3.80 on average

Results by Confidence:

  • Low confidence (0-33): 50.7% is near break-even. These are games where the model has weak signal—consider skipping these.
  • Medium confidence (34-66): 54.2% with +3.1% ROI. Decent edge but not overwhelming.
  • High confidence (67-100): 59.1% with +8.4% ROI. This is where the model shines. The higher the confidence, the stronger the signal.

Games with Predictions (64.5%):

The model only predicts when the score differential exceeds the betting threshold (default: 5). 35.5% of games didn't meet this threshold—that's intentional. It's better to skip marginal games.

Key Insight: Focus on High Confidence

The data shows a clear pattern: higher confidence = better results. Consider only betting when confidence is 50+, which would give you ~57% win rate but fewer total bets.

Step 3: Save and Evaluate

If the preview looks good, click Save Model. Then run Evaluate Performanceto persist the results.

Evaluation provides the same metrics as preview, but the results are saved so you can track them over time. It also provides additional breakdowns:

  • Monthly performance - See how the model performs in different months (playoffs vs regular season)
  • Per-game details - Review individual predictions and outcomes

Sample Evaluation Detail View

Per-Game Breakdown (Sample)
Date       | Matchup              | Line  | Prediction | Confidence | Result
───────────┼──────────────────────┼───────┼────────────┼────────────┼────────
2024-01-15 | BOS @ MIA            | -4.5  | BOS -4.5   | 72         | WIN
2024-01-15 | LAL @ DEN            | +7    | DEN -7     | 58         | LOSS
2024-01-14 | PHX @ GSW (B2B)      | +3    | GSW -3     | 81         | WIN
2024-01-14 | MIL @ CLE            | +2.5  | CLE -2.5   | 45         | PUSH
2024-01-13 | NYK @ BKN            | -6    | NYK -6     | 63         | WIN

Reading the breakdown:

  • Line - The opening spread. Negative = home favorite.
  • Prediction - Which side the model recommends.
  • Confidence - Score from 0-100. Higher = stronger signal.
  • Result - WIN (covered), LOSS (didn't cover), or PUSH (exactly on the number).

Notice the PHX @ GSW game: Phoenix was on a back-to-back, GSW was well-rested, and our model correctly predicted Golden State to cover at home. The 81 confidence reflects the strong situational advantage.

Step 4: Generate Predictions

Click Generate Predictions to create predictions for upcoming games. The system calculates current factor values and applies your model weights.

Sample Predictions Output

Today's Predictions
Upcoming Games - January 20, 2025
═════════════════════════════════

Game: Boston Celtics @ Miami Heat
  Line: BOS -3.5
  Prediction: BOSTON -3.5
  Confidence: 67 (HIGH)

  Factor Breakdown:
    pts_allowed_avg: BOS 106.2 (score: 78) vs MIA 112.4 (score: 45)
    rest_days:       BOS 2 days (score: 70) vs MIA 1 day (score: 50)
    back_to_back:    Neither team
    ats_record:      BOS 58% (score: 58) vs MIA 48% (score: 48)
    travel_context:  BOS road trip game 2 (score: 45) vs MIA home (score: 65)

  Model Scores: BOS 65.2, MIA 51.4 (diff: +13.8)

─────────────────────────────────

Game: Los Angeles Lakers @ Denver Nuggets
  Line: LAL +6.5
  Prediction: DENVER -6.5
  Confidence: 74 (HIGH)

  Factor Breakdown:
    pts_allowed_avg: LAL 115.8 (score: 32) vs DEN 108.4 (score: 68)
    rest_days:       LAL 0 days (score: 20) vs DEN 2 days (score: 70)
    back_to_back:    LAL is B2B (score: 40 vs 60)
    ats_record:      LAL 45% (score: 45) vs DEN 55% (score: 55)
    travel_context:  LAL road trip game 4 (score: 35) vs DEN home (score: 65)

  Model Scores: DEN 63.8, LAL 34.4 (diff: +29.4)

─────────────────────────────────

Game: Phoenix Suns @ Golden State Warriors
  Line: PHX -1.5
  Prediction: NO BET
  Confidence: 12 (LOW)

  Note: Score differential (3.2) below threshold (5).
  Model doesn't have strong conviction on this game.

How to Interpret Predictions

Factor Breakdown:

Each factor shows the raw value and normalized score (0-100) for both teams. This helps you understand why the model is making a recommendation.

Model Scores:

The weighted sum of all factor scores for each team. The team with the higher score is predicted to cover. The difference determines confidence:

  • Difference of 5-15: Low-Medium confidence
  • Difference of 15-25: Medium-High confidence
  • Difference of 25+: High confidence

NO BET Recommendations:

When the score differential is below your threshold (default: 5), the model outputs "NO BET". This is a feature, not a bug—it prevents you from betting on games with marginal edge.

Taking Action

Based on these predictions, here's a reasonable approach:

  1. Denver -6.5 (Confidence: 74) - Strong play. Lakers on B2B, extended road trip, weak defense. Denver well-rested at home.
  2. Boston -3.5 (Confidence: 67) - Good play. Celtics' elite defense and rest advantage offset road game.
  3. PHX/GSW (Confidence: 12) - Skip. No edge identified.

Step 5: Track Results

After games complete, return to your model to see updated results. The predictions page will show:

  • Pending - Game hasn't started
  • Win - Your prediction covered
  • Loss - Your prediction didn't cover
  • Push - Landed exactly on the number
Remember: Results don't update automatically. Click Evaluate Performanceto refresh your model's historical record after games complete.

Refining Your Model

After tracking results for a few weeks:

  • If high-confidence picks outperform: Consider raising the betting threshold to only bet on 60+ confidence games
  • If a factor isn't contributing: Try removing it or reducing its importance
  • If you want more bets: Lower the threshold, but expect lower win rate
  • To try new factors: Use Preview to test changes before saving

Advanced: Switching to Weighted Mode

Once you've validated your factor selection through backtesting, consider switching to Weighted Mode for precise control:

Weighted Mode Example
Based on our backtest, rest factors outperformed.
Adjusted weights:

  team_last_n_pts_allowed_avg: 25%
  rest_days:                   35%  (↑ from 29.4%)
  back_to_back:                20%  (↑ from 17.6%)
  team_ats_record:             15%  (↓ from 17.6%)
  travel_context:              5%   (unchanged)
                              ─────
                              100%

This gives you surgical precision over how the model weighs different inputs, allowing you to fine-tune based on what the backtest data reveals.

Factors System

Factor Categories

Each sport has factors organized into 5 categories, though the specific factors differ based on the sport's characteristics.

Team Performance

Measures how well a team has been playing recently. Examples include scoring averages, points allowed, and home/away performance splits.

Matchup

Analyzes the specific matchup between two teams. Includes head-to-head history and style matchups.

Situational

External factors that affect performance. Rest days, travel distance, back-to-back games, and schedule density all fall into this category.

Player

Accounts for individual player impact. Focuses on star player availability and their effect on team performance.

Score Calculation Methods

Raw factor values are converted to normalized scores (0-100) using one of these methods:

  • League Percentile - Score based on ranking vs. all teams in the league (100 = best, 0 = worst)
  • Linear Scale - Direct mapping from a defined range to 0-100
  • Inverse Linear Scale - For factors where lower is better (e.g., points allowed)
  • Boolean Scale - Binary factors converted to advantage/disadvantage scores

Configurable Parameters

Many factors have configurable parameters:

  • n_games - Number of recent games to consider (typically 3-30)
  • home_only - Only include home games in calculation
  • away_only - Only include away games in calculation
  • as_favorite / as_underdog - Filter by betting role
  • include_playoffs - Include playoff games in history

Factor Summary by Sport

SportTeam PerfMatchupSituationalPlayerTotal
NBA545317
NFL644418
NHL634215
MLB535518

NBA Factors (17)

Team Performance (5)

team_last_n_pts_avgTeam Performance
Team Last N Games Scoring Average

Average points scored by team in their last N games. Higher scoring indicates stronger offense.

Score: League percentile (100 = best)Params: n_games (default: 10), home_only, away_only
team_last_n_pts_allowed_avgTeam Performance
Team Last N Games Points Allowed Average

Average points allowed by team in their last N games. Lower indicates better defense.

Score: Inverse percentile (lower allowed = higher score)Params: n_games (default: 10)
team_home_away_splitTeam Performance
Team Home/Away Performance Split

Difference in scoring margin between home and away games. Positive = better at home.

Score: +10 split = 80, 0 = 50, -10 = 20 (range: -15 to +15)Params: n_games (default: 20)
team_ats_recordTeam Performance
Team Against The Spread Record

Win percentage against the spread in recent games. 60%+ indicates consistent value.

Score: Direct percentage (60% ATS = 60 score)Params: n_games (default: 20), as_favorite, as_underdog
team_over_under_trendTeam Performance
Team Over/Under Trend

Percentage of games that went over the total. High = team tends to play high-scoring games.

Score: Direct percentage (70% over = 70 score)Params: n_games (default: 20)

Matchup (4)

head_to_head_recordMatchup
Head-to-Head Record

Win percentage in recent matchups between the two teams. Historical dominance can persist.

Score: Win percentage (75% H2H = 75 score)Params: n_games (default: 10), include_playoffs (default: true)
head_to_head_atsMatchup
Head-to-Head ATS Record

Against the spread record in recent matchups between the two teams.

Score: ATS percentage (historical spread patterns can persist)Params: n_games (default: 10)
offensive_vs_defensive_ratingMatchup
Offensive vs Defensive Rating Matchup

Compares team's offensive rating against opponent's defensive rating. Positive = favorable matchup.

Score: +10 diff = 75, 0 = 50, -10 = 25 (range: -15 to +15)Params: n_games (default: 15)
pace_differentialMatchup
Pace Differential

Difference in pace between the two teams. Large difference can affect total prediction.

Score: 10 diff = 80, 0 diff = 50 (higher = more volatile total)Params: n_games (default: 15)

Situational (5)

rest_daysSituational
Rest Days Advantage

Days of rest before the game. More rest generally correlates with better performance.

Score: 0 days (B2B) = 20, 1 day = 50, 2 days = 70, 3+ days = 80Params: None
back_to_backSituational
Back-to-Back Game

Whether this is the second game of a back-to-back. B2B teams typically underperform.

Score: Not B2B = 60, B2B = 40Params: None
travel_contextSituational
Travel Context

Whether team is on a road trip, home stand, or transitioning. Extended road trips can cause fatigue.

Score: Home stand = 70, first road game = 50, 3+ road = 35Params: None
season_segmentSituational
Season Segment

Early, mid, or late season. Teams may perform differently at different points.

Score: Based on team's historical segment performanceParams: segment_split (default: "thirds", options: thirds/quarters/halves)
division_gameSituational
Division Game

Whether this is a division matchup. Division games are often more competitive and unpredictable.

Score: Division = 55 (slightly unpredictable), Non-division = 50Params: None

Player (3)

star_player_availabilityPlayer
Star Player Availability

Whether key players are available. Injuries to stars significantly impact team performance.

Score: 100% stars = 70, missing 1 star = 50, missing 2+ = 30Params: star_threshold (default: 25 usage rate)
player_last_n_avgPlayer
Player Recent Performance

A player's performance in their last N games vs season average. Hot/cold streaks matter.

Score: 120% of avg = 70 (hot), 100% = 50, 80% = 30 (cold)Params: n_games (default: 5), stat_type (pts/reb/ast/pts_reb_ast/3pm)
player_vs_teamPlayer
Player vs Opponent History

A player's historical performance against this specific opponent.

Score: 130% vs team = 75 (great matchup), 100% = 50, 70% = 25Params: n_games (default: 10), stat_type (pts/reb/ast/pts_reb_ast/3pm)

NFL Factors (18)

Team Performance (6)

team_last_n_pts_avgTeam Performance
Team Last N Games Scoring Average

Average points scored by team in their last N games. Reflects recent offensive production.

Score: League percentile (100 = top scoring)Params: n_games (default: 5, max: 10), home_only, away_only
team_last_n_pts_allowed_avgTeam Performance
Team Last N Games Points Allowed Average

Average points allowed by team in their last N games. Lower indicates better defense.

Score: Inverse percentile (lower allowed = higher score)Params: n_games (default: 5)
team_home_away_splitTeam Performance
Team Home/Away Performance Split

Difference in point differential between home and away games. Home field is significant in NFL.

Score: +7 split = 75, 0 = 50, -7 = 25 (range: -14 to +14)Params: n_games (default: 8)
team_ats_recordTeam Performance
Team Against The Spread Record

Win percentage against the spread in recent games. Consistent ATS teams offer value.

Score: Direct percentage (65% ATS = 65 score)Params: n_games (default: 8), as_favorite, as_underdog
team_over_under_trendTeam Performance
Team Over/Under Trend

Percentage of games that went over the total. Indicates team's game script tendencies.

Score: Direct percentage (70% over = 70 score)Params: n_games (default: 8)
yards_per_playTeam Performance
Yards Per Play Efficiency

Team's offensive yards per play vs league average. Key efficiency metric.

Score: 6.0 YPP = 75, 5.5 = 50, 5.0 = 25 (elite offenses avg 6+)Params: None

Matchup (4)

head_to_head_recordMatchup
Head-to-Head Record

Win percentage in recent matchups between the two teams. Rivalry games have patterns.

Score: Win percentage (75% H2H = 75 score)Params: n_games (default: 6), include_playoffs (default: true)
rush_vs_run_defenseMatchup
Rush Offense vs Run Defense

Compares team's rushing yards per carry against opponent's rush defense.

Score: +1.0 YPC advantage = 75, 0 = 50, -1.0 = 25Params: None
pass_vs_pass_defenseMatchup
Pass Offense vs Pass Defense

Compares team's passing yards per attempt against opponent's pass defense.

Score: +1.5 YPA advantage = 75, 0 = 50, -1.5 = 25Params: None
turnover_differential_matchupMatchup
Turnover Differential Matchup

Compares both teams' turnover differentials. Turnovers are the best predictor of outcomes.

Score: +1 TO diff/game = 75, 0 = 50, -1 = 25Params: n_games (default: 5)

Situational (4)

rest_daysSituational
Rest Days Advantage

Days of rest before the game. Short weeks (Thursday games) hurt teams significantly.

Score: 3-4 days (short week) = 35, 6-7 days = 50, 10+ (bye) = 65Params: None
bye_week_advantageSituational
Bye Week Advantage

Whether team is coming off a bye week. Extra rest and preparation helps.

Score: Coming off bye = 65, not off bye = 50Params: None
division_gameSituational
Division Game

Whether this is a division matchup. Division games are often closer and more physical.

Score: Division = 45 (expect closer game), Non-division = 50Params: None
prime_time_performanceSituational
Prime Time Performance

Team's record in prime time games (SNF, MNF, TNF). Some teams thrive under the lights.

Score: Win percentage in prime time (65% = 65 score)Params: n_games (default: 8)

Player (4)

qb_efficiencyPlayer
Quarterback Efficiency

Starting QB's recent passer rating vs season average. QB play drives NFL outcomes.

Score: 100+ rating = 75, 90 = 50, 80 = 25Params: n_games (default: 4)
key_player_availabilityPlayer
Key Player Availability

Availability of key players (QB, top RB, top WR, edge rushers). Injuries swing lines.

Score: 100% healthy = 65, missing 1 key = 50, missing 2+ = 35Params: None
red_zone_efficiencyPlayer
Red Zone Efficiency

Team's touchdown rate when inside the opponent's 20. Converts drives into points.

Score: 65% TD rate = 75, 55% = 50, 45% = 25Params: None
third_down_efficiencyPlayer
Third Down Efficiency

Team's third down conversion rate. Sustaining drives is crucial for controlling the game.

Score: 45% conversion = 75, 38% = 50, 30% = 25Params: None

NHL Factors (15)

Team Performance (6)

team_last_n_goals_avgTeam Performance
Team Last N Games Goals Average

Average goals scored by team in their last N games. Higher scoring indicates stronger offense.

Score: League percentile (100 = best scoring)Params: n_games (default: 10), home_only, away_only
team_last_n_goals_allowed_avgTeam Performance
Team Last N Games Goals Allowed Average

Average goals allowed by team. Lower indicates better defense and goaltending.

Score: Inverse percentile (lower goals = higher score)Params: n_games (default: 10)
team_home_away_splitTeam Performance
Team Home/Away Performance Split

Difference in goal differential between home and away. Home ice advantage is significant.

Score: +1 split = 75, 0 = 50, -1 = 25 (range: -2 to +2)Params: n_games (default: 15)
team_ats_recordTeam Performance
Team Against The Spread Record

Win percentage against the puckline in recent games.

Score: Direct percentage (60% ATS = 60 score)Params: n_games (default: 15)
team_over_under_trendTeam Performance
Team Over/Under Trend

Percentage of games that went over the total. Useful for total predictions.

Score: Direct percentage (70% over = 70 score)Params: n_games (default: 15)
shots_on_goal_trendTeam Performance
Shots on Goal Trend

Team's recent shots on goal vs season average. Higher SOG creates more scoring chances.

Score: 110% of avg = 70, 100% = 50, 90% = 30Params: n_games (default: 5)

Matchup (3)

head_to_head_recordMatchup
Head-to-Head Record

Win percentage in recent matchups. Historical dominance matters in rivalry games.

Score: Win percentage (75% H2H = 75 score)Params: n_games (default: 10), include_playoffs (default: true)
special_teams_matchupMatchup
Special Teams Matchup

Compares team's power play efficiency against opponent's penalty kill.

Score: PP% - opp PK% differential: +10% = 75, 0 = 50, -10% = 25Params: None
goal_differential_matchupMatchup
Goal Differential Matchup

Compares both teams' recent goal differentials. Strong indicator of team quality.

Score: +1 GD/game = 70, 0 = 50, -1 = 30Params: n_games (default: 10)

Situational (4)

rest_daysSituational
Rest Days Advantage

Days of rest before the game. NHL teams often play back-to-backs with travel.

Score: 0 days (B2B) = 25, 1 day = 50, 2+ days = 70Params: None
back_to_backSituational
Back-to-Back Game

Whether this is the second game of a B2B. B2B teams, especially goalies, often struggle.

Score: Not B2B = 60, B2B = 35 (greater impact due to goalie workload)Params: None
travel_contextSituational
Travel Context

Road trip length and travel distance. Extended road trips cause fatigue.

Score: Home stand = 65, first road = 50, 4+ road = 30Params: None
division_gameSituational
Division Game

Whether this is a division matchup. Division games are chippy and often low-scoring.

Score: Division = 45 (favors under), Non-division = 50Params: None

Player (2)

goalie_save_pct_trendPlayer
Goalie Save Percentage Trend

Starting goalie's recent save percentage vs season average. Hot goalies can steal games.

Score: +2% above avg = 75, at avg = 50, -2% below = 25Params: n_games (default: 5)
goalie_fatiguePlayer
Goalie Fatigue

Days since goalie's last start and recent workload. Tired goalies have lower save percentages.

Score: 0-1 days = 35 (tired), 2-3 days = 60 (rested), 4+ = 45 (rust)Params: None

MLB Factors (18)

Team Performance (5)

team_last_n_runs_avgTeam Performance
Team Last N Games Runs Average

Average runs scored by team in their last N games. Reflects recent offensive production.

Score: League percentile (100 = top scoring)Params: n_games (default: 10), home_only, away_only
team_last_n_runs_allowed_avgTeam Performance
Team Last N Games Runs Allowed Average

Average runs allowed. Reflects pitching and defense quality.

Score: Inverse percentile (lower runs = higher score)Params: n_games (default: 10)
team_home_away_splitTeam Performance
Team Home/Away Performance Split

Difference in run differential between home and away games.

Score: +1 run = 70, 0 = 50, -1 run = 30 (range: -2 to +2)Params: n_games (default: 20)
team_ats_recordTeam Performance
Team Against The Spread (Runline) Record

Win percentage against the runline in recent games. MLB runline is typically -1.5.

Score: Direct percentage (55% = 55 score)Params: n_games (default: 20)
team_over_under_trendTeam Performance
Team Over/Under Trend

Percentage of games that went over the total.

Score: Direct percentage (60% over = 60 score)Params: n_games (default: 20)

Matchup (3)

head_to_head_recordMatchup
Head-to-Head Record

Win percentage in recent matchups between the two teams (current season).

Score: Win percentage (65% H2H = 65 score)Params: n_games (default: 10), include_playoffs (default: false)
batting_vs_pitcher_handednessMatchup
Lineup vs Pitcher Handedness

Team's batting average against the starting pitcher's handedness (LHP/RHP).

Score: .280+ vs hand = 75, .250 = 50, .220 = 25Params: None
bullpen_matchupMatchup
Bullpen Quality Matchup

Compares both teams' bullpen ERA and usage. Critical for close games and totals.

Score: -1.0 ERA advantage = 70, 0 = 50, +1.0 = 30Params: None

Situational (5)

rest_daysSituational
Rest Days

Days since team's last game. Back-to-back games are normal in MLB.

Score: 0 days = 50 (normal), 1 day = 55, 2+ days = 45 (rust)Params: None
back_to_backSituational
Back-to-Back Game

Whether this is the second consecutive day playing. Normal in MLB but affects bullpen.

Score: B2B = 48 (slight disadvantage from bullpen use), not B2B = 52Params: None
series_positionSituational
Series Position

Whether this is game 1, 2, or 3+ of a series. Game 1 starters are typically aces.

Score: Game 1 = 55 (ace starts), Game 2 = 50, Game 3+ = 45Params: None
division_gameSituational
Division Game

Whether this is a division matchup. Division games are more competitive.

Score: Division = 45 (expect closer), Non-division = 50Params: None
day_night_performanceSituational
Day/Night Performance

Team's record in day games vs night games. Some teams perform differently.

Score: Win percentage for relevant time slot (55% = 55 score)Params: None

Player (5)

starter_eraPlayer
Starting Pitcher ERA

Starting pitcher's ERA. The single most important factor in MLB betting.

Score: 3.0 ERA = 75, 4.0 = 50, 5.0 = 25 (ace starters dominate)Params: None
starter_fipPlayer
Starting Pitcher FIP

Starting pitcher's FIP (Fielding Independent Pitching). More predictive than ERA.

Score: 3.2 FIP = 75, 4.0 = 50, 4.8 = 25 (isolates pitcher skill)Params: None
starter_recent_formPlayer
Starting Pitcher Recent Form

Starter's ERA in last N starts vs season ERA. Recent form matters.

Score: -1.0 ERA (improving) = 70, 0 = 50, +1.0 (regressing) = 30Params: n_starts (default: 3)
starter_strikeout_ratePlayer
Starting Pitcher Strikeout Rate

Starter's K/9 rate. High strikeout pitchers are less dependent on defense.

Score: 10+ K/9 = 75, 8 = 50, 6 = 25Params: None
bullpen_availabilityPlayer
Bullpen Availability

Key relievers' availability based on recent usage. Tired bullpens blow leads.

Score: 100% available = 65, 75% = 50, 50% = 35Params: None

Building Models

Model Creation Flow

  1. Navigate to the Models page
  2. Click Create Model
  3. Enter a name for your model
  4. Select the sport (NBA, NFL, NHL, MLB)
  5. Choose the bet type (Spread, Moneyline, Over/Under)
  6. Select the mode (Simple or Weighted)
  7. Add factors from the available list
  8. Assign importance/weights to each factor
  9. Run a preview to test performance
  10. Save when satisfied

Simple Mode vs Weighted Mode

Simple Mode

Assign importance levels (Low, Medium, High) to each factor. The system converts these to weights using configurable multipliers:

  • Low - Default multiplier: 10
  • Medium - Default multiplier: 30
  • High - Default multiplier: 50

The final weight is calculated as: factor_multiplier / sum_of_all_multipliers

Weighted Mode

Assign precise percentage weights to each factor. Weights must sum to exactly 100%. This mode gives you full control over how much each factor contributes to the final score.

Factor Selection Strategy

Tips for choosing factors:

  • Diversify categories - Include factors from multiple categories to capture different aspects
  • Consider the bet type - For Over/Under, focus on scoring and pace factors
  • Start simple - Begin with 3-5 factors and add more as you understand their impact
  • Use backtesting - Test different factor combinations to find what works

Backtesting

What is Backtesting?

Backtesting runs your model against historical games to see how it would have performed. The system calculates factor values using only data available before each game, simulating real-world conditions.

Data Availability

Historical data available from 2020 to present (6+ years). Backtests use historical opening lines from DraftKings.

Free Tier Limitations

The free tier limits you to 1 model and 1 week of backtest data. Subscribe to LAB PRO or ALL-ACCESS for unlimited models and full historical access.

Backtest Configuration

  • Date range - Start and end dates for the backtest period
  • Team filters - Optionally limit to specific teams
  • Confidence threshold - Minimum signal strength to place a bet

Understanding Results

  • Record - Wins, losses, and pushes
  • Win Rate - Percentage of bets won (excluding pushes)
  • ROI - Return on investment assuming flat betting
  • Results by Confidence - Performance broken down by signal strength

Performance Evaluation

Preview vs Evaluate

FeaturePreviewEvaluate
PurposeTest before savingFull analysis after saving
Results PersistedNo (ephemeral)Yes (stored in database)
Upcoming PredictionsYes (preview only)No (use Generate Predictions)

What Evaluation Calculates

  • Overall record (W/L/P)
  • Win rate and ROI
  • Average signal strength (confidence)
  • Results by confidence bucket (Low/Medium/High)
  • Results over time (monthly breakdown)
  • Per-game breakdown with predictions

Invalidation

Important: Performance data is automatically cleared when you edit a model's factors, mode, bet type, or advanced config. You must re-run Evaluate Performance after making changes.

Manual Refresh Required

Backtests and evaluations do not update automatically. When new games are played or odds change, you need to manually re-run the evaluation to include the latest data.

Live Predictions

How Predictions Work

Predictions apply your model's factor weights to upcoming games. For each game, the system:

  1. Calculates factor values for both teams
  2. Computes weighted scores based on your model configuration
  3. Determines the predicted side (home, away, over, under)
  4. Assigns a confidence level based on score differential

Prediction Lifecycle

  • Pending - Game has not started
  • Win - Prediction was correct
  • Loss - Prediction was incorrect
  • Push - Result matched the line exactly

Manual Refresh Required

Important: Predictions do not update automatically. You must click Generate Predictions to refresh predictions when:
  • You edit the model
  • New games become available
  • Opening lines are published

When to Regenerate

Run Generate Predictions:

  • After editing model factors or weights
  • When the schedule updates (new games added)
  • Periodically to capture the latest factor values

Advanced Settings

Importance Multipliers (Simple Mode)

Customize how importance levels translate to weights. Default values:

LevelDefault Multiplier
Low10
Medium30
High50

Adjusting these changes the relative contribution of each importance level. For example, setting High to 100 makes high-importance factors contribute twice as much relative to the default.

Betting Thresholds

Control when to place a bet based on the model's score differential:

SettingDefaultDescription
spread_score_diff5Bet home if home_score - away_score > threshold
moneyline_score_diff5Same as spread threshold
over_under_combined55Bet over if average combined score > threshold

Tuning Strategies

  • Lower thresholds - More bets, potentially lower edge per bet
  • Higher thresholds - Fewer bets, higher conviction required
  • Backtest different settings - Use preview to compare threshold configurations

Using with AI Agents

AI Agent Compatibility

The LAB API works great with AI agents like ChatGPT, Claude, and other LLM-powered tools. By providing the OpenAPI specification, AI agents can automatically understand and call the API.

Use Cases

  • "Create a model focused on home team performance"
  • "Run a backtest for my model and summarize the results"
  • "Generate predictions for tonight's games"
  • "Compare my models' performance over the last month"
  • "Suggest factor combinations for NFL spread betting"

Getting Started with AI Agents

  1. Get your API key from the Settings page (requires LAB PRO or ALL-ACCESS)
  2. Share the OpenAPI spec URL with your AI agent: https://lab.balldontlie.io/openapi.yaml
  3. Describe what you want to do in natural language

Example Prompts

Example prompt for ChatGPT/Claude
"Using the BDL LAB API, create a new NBA spread model
with factors for scoring average and rest days.
Set scoring average to high importance and rest days
to medium importance."
Example prompt for analysis
"Run a backtest on my model 'NFL Sharp' for the
2024 season. Summarize the results including win rate,
ROI, and performance by confidence level."

Tips for AI Agent Usage

  • Be specific about sport, bet type, and factors
  • Ask for summaries after running operations
  • Use the agent to compare multiple configurations
  • Have the agent explain factor choices and their impact