Market Efficiency (Sharp vs. Soft Bookmakers)

Summary

Market efficiency in sports betting refers to how accurately and quickly bookmaker odds reflect the true probabilities of outcomes. An efficient market prices odds such that the sum of implied probabilities equals 100% (after removing vig), leaving no systematic opportunities for profit.

In practice, sports betting markets are not fully efficient. They exist on a spectrum from very efficient (sharp books) to inefficient (soft books). Understanding this hierarchy is crucial for the prediction model: finding value is easier against soft books, but soft book odds may be too slow to react to late information.

Sharp bookmakers (Pinnacle, Betfair, low-margin European books) have:
- Very low vig (2-4%)
- Fast odds adjustment reacting to sharp action
- High limits allowing large stakes
- Odds close to "true" probabilities

Soft bookmakers (DraftKings, FanDuel, BetMGM in the US) have:
- Higher vig (4-8% for major markets)
- Slower odds adjustment
- Lower limits
- Often have biases that can be exploited

The concept of market efficiency is central to the model's strategy: use sharp book odds (Pinnacle) as ground truth for fair probabilities, then find +EV opportunities against soft books.

Key Concepts

  • Efficient market hypothesis: In its strong form, all available information is reflected in prices — no arbitrage possible. In sports betting, this is never fully achieved.
  • Favorite-longshot bias: A well-documented market inefficiency where bettors overbet longshots and underbet favorites. This means odds on underdogs are systematically worse value than odds on favorites.
  • Home bias: Some markets show systematic bias toward the home team in 1X2 odds.
  • Sharp action: Large bets from professional/syndicates that move the line. Following sharp action (steam moves) is a trading strategy.
  • Market efficiency by sport: NFL/NBA are very efficient; lower-profile leagues and props are less efficient.
  • Information efficiency: Late injury news, weather changes, and lineup announcements can create temporary inefficiencies before sharp books adjust.

Market Efficiency Hierarchy

Bookmaker Type Vig Efficiency Betting Limits Example
Sharpest 2-3% ~98% efficient High Pinnacle, Betfair
Sharp 3-5% ~95% efficient Medium-High oddsjam sharp feeds
Soft 5-8% ~90-95% efficient Low DraftKings, FanDuel
Public/Recreational 8-12% <90% efficient Very Low State lottery-style

Implications for the Model

  1. Use Pinnacle as benchmark: Pinnacle closing odds are the closest to "true" market probabilities. De-vigging Pinnacle gives the best fair probability estimates.
  2. Compare soft vs. sharp: The model's edge is most visible when it predicts better than Pinnacle's odds — if Pinnacle agrees with the model, that's confirmation, not alpha.
  3. Soft book arbitrage: When a soft book significantly overprices an outcome vs. Pinnacle, the +EV opportunity may be larger.
  4. Line shopping: Always check multiple bookmakers — the model should identify the best available odds, not just bet at whatever book is available.
  5. World Cup context: World Cup odds are extremely efficient due to global attention and huge betting volume. Finding value requires either very good models or information advantages (injury news, lineup leaks).

Python Implementation

def estimate_market_efficiency(bookie_odds, pinnacle_odds):
    """
    Estimate how efficiently a bookie prices a market vs. Pinnacle.
    Returns efficiency ratio and identifies mispricings.
    """
    # Implied probabilities
    p_bookie = 1 / np.array(bookie_odds)
    p_pinnacle = 1 / np.array(pinnacle_odds)

    # De-vig both
    p_bookie_fair = p_bookie / sum(p_bookie)
    p_pinnacle_fair = p_pinnacle / sum(p_pinnacle)

    efficiency = 1 - np.abs(p_bookie_fair - p_pinnacle_fair).sum() / 2
    return efficiency

def find_soft_book_value(soft_odds, sharp_odds, model_prob):
    """
    Identify value in soft book odds vs. sharp book.
    soft_odds: dict of {outcome: decimal_odds}
    sharp_odds: dict of {outcome: decimal_odds}  
    model_prob: dict of {outcome: probability}
    """
    sharp_fair = {k: 1/v / sum(1/v for v in sharp_odds.values()) 
                  for k, v in sharp_odds.items()}

    opportunities = []
    for outcome in soft_odds:
        implied = 1 / soft_odds[outcome]
        edge_vs_model = model_prob[outcome] / (1/soft_odds[outcome]) - 1
        edge_vs_sharp = sharp_fair[outcome] / (1/soft_odds[outcome]) - 1

        if edge_vs_model > 0.05:  # 5% minimum edge
            opportunities.append({
                'outcome': outcome,
                'soft_odds': soft_odds[outcome],
                'sharp_fair_odds': 1/sharp_fair[outcome],
                'edge_vs_model': edge_vs_model,
                'edge_vs_sharp': edge_vs_sharp
            })

    return sorted(opportunities, key=lambda x: x['edge_vs_sharp'], reverse=True)

Notes

  • The client uses Pinnacle API for sharp odds and The Odds API for multi-bookmaker comparison — this is the correct architecture for finding value
  • Favorite-longshot bias means underdog value is less reliable than favorite value; the model should account for this
  • For World Cup: even Pinnacle can be inefficient in the group stage futures market (who wins the World Cup) due to long time horizons and public bias