Back to Blog

Fantasy Football Is Mostly Luck (Or So I Thought): Building an AI-Assisted Fantasy Football Assistant

October 16, 2026

Featured image for Fantasy Football Is Mostly Luck (Or So I Thought): Building an AI-Assisted Fantasy Football Assistant

I've been playing fantasy football for almost 20 years. Casually. Very casually. I set my lineup every week, even if "setting it" usually meant accepting whatever ESPN recommended, and I made the occasional waiver pickup.

I knew which NFL teams were good, mostly. What I didn't know was anything underneath that. Which defenses were tough against the pass but soft against the run? Which offenses leaned on the ground game, and which ones threw it 40 times a week? No idea. And that's exactly the kind of thing that decides whether your receiver has a big week or a quiet one.

For most of those years, I had a theory I was pretty comfortable with: fantasy football is mostly luck. My proof? I'd won a championship without really knowing what I was doing. If it were a game of skill, the people who actually follow the players and the teams would be winning most of the time, right?

Turns out that's a testable claim. So I tested it.

This is the first post in a series about the Fantasy Football Assistant, an app I built to help me stop guessing. It's part fantasy football, part software, and part lesson in what AI is (and isn't) good at when you're trying to make real decisions.

I Looked at the Results

Our league has a long history, so I went back and looked at who actually won. Here's how it shakes out (names withheld to protect the gloating):

Manager Championships
Player A 5
Player B 4
Player C 3
Me 1

Three managers account for twelve titles. And those three are exactly the people I would have named as "the ones who actually know football." They read the news, they know the depth charts, they know which teams are trending up and which are falling apart.

So my theory was wrong. Luck is real (injuries happen, someone always drops 40 on you in the playoffs), but it's a small part of it. The people who make better decisions win more often. Over a long enough timeline, it isn't close.

That left me with an uncomfortable conclusion: if I wanted to win more, I had to make better decisions. And I didn't have the time or the interest to become a guy who reads injury reports every morning.

Plan A: Use AI to Increase My Luck

My first idea was pretty simple. If I don't know the players, let the AI know them for me.

So going into this year's draft, I used Copilot as my draft advisor. I talked through my league settings, asked who I should target, and built my pre-draft queue from its recommendations. Then I'd run my picks back by it for feedback.

The feedback was great. Every pick was a smart value. Every positional choice was well balanced. By the end of those conversations I was pretty sure I had the trophy in my hands already.

Then draft day came, and something felt off. Nobody was taking my guys. Pick after pick, the players in my queue were still sitting there when it was my turn. At the time I took that as a sign I'd found the hidden value everyone else missed.

It wasn't. It was the rest of the league (including A, B and C) telling me they didn't want those players.

After the draft, ESPN sent out its draft grades. I was at the bottom of the list.

What Went Wrong

There wasn't one catastrophic pick. The problem was the whole approach, and once I looked at it honestly it came down to a few things:

  • The AI had no real data. It was reasoning from whatever it learned in training, which is a season (or more) behind. It didn't know about this year's camp battles, injuries, or role changes. It also didn't know my league's actual scoring settings or roster rules unless I typed them in, and even then it was guessing at how they mattered.
  • There was nothing to check. When it said a player was a great value, I had no number to look at. No ranking, no comparison, no "great value compared to what." Just a confident paragraph.
  • It agreed with me. This is the big one. LLMs are very good at telling you your plan sounds great. I wasn't getting analysis, I was getting encouragement. And encouragement feels exactly like analysis when you don't know enough to tell the difference.
  • I ignored the one real signal I had. The draft room itself was giving me live market data, and I read it backwards.

None of that is really a knock on Copilot. I was using a general-purpose chat assistant as if it were a fantasy football analyst with access to current data. It's not, and asking it to "pick my team" was the wrong question.

Plan B: Build Something That Helps Me Decide

So I changed the goal. Instead of an AI that makes picks for me, I wanted a tool that helps me make better decisions, the same way A, B and C do: with current information, a consistent way to value players, and an honest look back at how my calls turned out.

That shifted the design in a few important ways.

Numbers first, words second

The app does the math itself, deterministically, before an LLM ever sees anything. It pulls my league's rosters, scoring settings, and roster limits straight from ESPN, pulls current player values from two ranking sites (KeepTradeCut for long-term dynasty value and FantasyCalc for this season), and blends them into a single score per player that I can actually look at and compare.

Trade candidates and waiver add/drop pairs are computed by code too. The LLM's job is to explain those numbers in plain English, not invent them. Here's a small piece of the rules the model gets for waiver suggestions:

_WAIVER_ADD_DROP_RULES = """\
Assume the user's roster is full: every pickup requires dropping one of
their current players. For each waiver recommendation, name exactly one
player to ADD (from waiver_candidates) and one to DROP (from the user's
roster), and only recommend a swap that improves the team:
- The pickup's pvs must be higher than the dropped player's pvs. Free-agent
  and roster pvs are on the same scale. Skip any free agent whose pvs is
  null, there's no basis to call it an upgrade.
...
If no swap meets these rules, say plainly that no add/drop would improve
the roster right now instead of padding the list.
"""

That last line matters. "Nothing here is worth doing" is a valid answer, and it's one my draft advisor never gave me.

Current information, not training data

The model is explicitly told that its own knowledge of players is out of date and not to use it. Every claim it makes has to come from data I hand it: dated ESPN player news, recent weekly points, injury status, and the player's score. If it can't cite something, it has to say so instead of making up a storyline. (How I got there, and what the AI was doing before I added those rules, is a big part of Part 2.)

A record of every decision

This is the feature I'm most excited about, and the one that ties back to how this whole thing started. The Decision Log imports every trade, waiver claim, add, and drop from ESPN and freezes a snapshot of each player's value at the moment the move happened. Later it shows "then vs. now" next to it, both in value and in real fantasy points scored.

I can grade each move myself (A through F, with a note on why) while the reasoning is still fresh. Then, at any point in the season, an AI retrospective reads the whole log and tells me where my grades matched what actually happened, where they didn't, and what patterns show up in my decisions.

Here's my actual Decision Log, and it's already keeping me honest.

My Decision Log in the Fantasy Football Assistant

Look at the waiver claim in the top right: I dropped Michael Pittman Jr. to claim Roman Wilson, with a confident note about Wilson being "the clear target." Since then, Pittman's value has gone up 6.7 and Wilson's has gone up 4.6. Not a disaster, but the guy I let go has gained more than the guy I picked up. Before this app, I never would have noticed.

In other words, it's the same thing I did with the league's championship history, just applied to my own decisions every week instead of once every 20 years.

What the App Does Today

Here's a quick tour of where it landed:

  • League Overview. Every team in the league, with roster value, positional strengths and weaknesses, and who's contending vs. rebuilding.
  • Waiver Targets. The free-agent pool next to my roster, scored on the same scale, with AI-suggested add/drop pairs grounded in current news.
  • Trade Simulator and trade matching. Evaluate any trade, or let the app find trades where both teams fill a real need with what the other side can actually spare.
  • AI Report. A written recommendation covering keepers, waiver moves, and trade options, built from the numbers above.
  • Decision Log. My moves, my grades, and hindsight on all of them.
  • Rankings. A full player pool cheat sheet for draft prep. (Yes, I'll be using this one next year.)

It supports multiple ESPN leagues, both keeper and redraft formats, and it reads each league's own settings so a superflex PPR league isn't valued like a standard one.

The Stack (Briefly)

This series is mostly about the decision-making side, but for the developers reading:

  • Backend: Python and FastAPI, with SQLAlchemy and Alembic for the data layer.
  • Frontend: React with TypeScript (it started life as a Streamlit app, which lasted about three days).
  • AI: OpenAI, with all scoring done in code before the model is involved.
  • Hosting: Azure. App Service for the app, a Function App for a nightly sync of rosters, transactions, player value history, and news, and Azure Database for PostgreSQL in production (SQLite locally).

I also built it with an AI coding assistant, which is its own kind of irony: the AI I asked to draft my team let me down, and the AI I asked to help me build a tool for drafting my team was great. The difference, again, was the question I asked and the data it had to work with.

What's Next

In Part 2, I'll get into the math: how the app turns two ranking sites, a player's age, and whether my team is contending or rebuilding into a single score, and how I stopped the AI from confidently recommending moves that the actual news contradicted.

In Part 3, I'll dig into the Decision Log: grading myself against hindsight, what "then vs. now" really measures, and what the AI retrospective has told me about my own habits so far.

My draft grade this year says I still have a lot to learn. The difference now is that I have a way to track whether I'm actually learning it.


Profile picture

Written by Shannon Stewart I am a software architect and engineer focused on Azure, C#, and AI. I write about real-world projects, cloud-native patterns, and building smarter systems with modern tools.