4 min read

Inside My Fantasy Baseball Analyzer

Table of Contents

Most fantasy seasons, I’d have a dozen tabs open. ESPN for rosters, FanGraphs for projections, spreadsheets for tracking my own rankings. It was tedious, easy to screw up, and full of guesswork. I figured I could save time (and maybe win more often) by building something that pulled it all together.

The result is a tool that connects directly to ESPN, scrapes FanGraphs, runs some scoring models, and gives me data-driven recommendations during the draft, weekly waivers, and season-long roster moves.

What It Does

  • Pulls league and player data from ESPN
  • Merges it with FanGraphs projections and recent stats
  • Normalizes stats using z-scores
  • Lets you tweak the balance between projections and recent performance
  • Accounts for positional scarcity
  • Highlights draft value based on tiers and ADP gaps
  • Suggests adds and drops based on your current roster

screenshot: Main dashboard with navigation and metrics

How It Works

Data Pipeline

The pipeline pulls from ESPN and FanGraphs, merges everything, and calculates scores.

from espn_data import get_all_players, get_league_info
from fangraphs_api import get_fangraphs_merged_data
from analysis import calculate_composite_scores, rank_players
  • Extract: ESPN cookies for league info and player pools
  • Transform: Scrape Steamer projections and live stats from FanGraphs
  • Load: Merge, normalize names, align positions
  • Analyze: Z-score everything and apply weighted scoring

screenshot: Update process with feedback messages

Scoring Model

The main scoring engine combines projections with current stats. The weighting is adjustable.

def calculate_composite_scores(df, weights=None):
    if weights is None:
        weights = {'proj': 0.8, 'curr': 0.2}
    ...

Metrics used:

  • Hitters: wOBA, wRC+, ISO, wBsR
  • Pitchers: FIP, WHIP, K-BB%, SV
  • Delta: Tracks performance vs projection
  • Composite score: Weighted blend for ranking

screenshot: Comparison tool showing projection vs current

Draft Logic

Draft rankings adjust based on value and positional depth. There’s also tiering and ADP comparison.

def analyze_and_adjust_rankings(file_path):
    ...

Core logic:

  • Bumps for thin positions
  • Penalizes deep ones
  • VADP: value vs average draft position
  • Tiering: clusters players by value
  • Caps: avoids overreaction to ADP

screenshot: Draft board with tiers and tracking

Interface

Streamlit handles the frontend with modular pages.

from app_pages.draft_strategy import show_draft_strategy
from app_pages.add_drop_recommendations import show_add_drop_recommendations
from app_pages.player_comparison import show_player_comparison

It includes:

  • Mobile-friendly layout
  • Filters by team, position, or stat
  • Draft board with click-to-draft
  • Player comparison view
  • Excel export for offline review

screenshot: Add/drop page with comparison layout

Features

Roster Suggestions

Compares your team against the free agent pool, highlighting weak spots and better options. Accounts for matchups and playing time.

screenshot: Roster summary with replacement suggestions

Draft Preparation

Pre-draft rankings by position, tier, and VADP. Tracks your picks and adjusts live.

League Analysis

Shows team strength across the league, trade targets, and where positions are thin.

Technical Notes

Data

  • Handles broken/missing data gracefully
  • Cleans up inconsistent player names
  • Uses Streamlit caching to avoid slow reloads
  • Modularized for easier debugging

Performance

  • Vectorized with Pandas
  • File-based caching with modification checks
  • Lazy loading for responsiveness

UI

  • Sidebar nav
  • Loading and error feedback
  • Responsive design
  • Light CSS for readability

Running It

# Standard Python
python run_new_app.py

# Or via Streamlit
streamlit run src/main_app.py

Why I Built It

This started as a weekend project to stop juggling spreadsheets. Over time, it became a tool that actually helped me make better calls during drafts and weekly lineup decisions. It’s not perfect, but it saves time and gives me more confidence in the moves I make.

Skills Used

  • API interaction with ESPN
  • Web scraping from FanGraphs
  • ETL and data cleanup
  • Statistical modeling with z-scores and weights
  • Streamlit UI

GitHub repo