Ishan Gupta
Data Science & Sports
headshot of ishgup
FAR Analyst @ LPL Financial
June 2024 - Present
• Data Analytics for First Line Risk Management
Tableau
Power BI
Microsoft Excel
Snowflake
Alteryx
SQL
Python
Former Student @ University of Pittsburgh
August 2020 - May 2024
Finance
Computer Science
Business Analytics
My Interests
Stats and AI uncover insights beyond human bias, transforming industries. I apply this to sports, creating models that align with my goals, and aim to bring similar impact to business optimization.
Current Power Rankings
Team
Rank
W
L
Rating
PF
PA
Joey111312.002028.481929.30
Ian28610.132023.801986.04
Savan3869.752032.381992.52
Prad4.5777.251879.241863.00
Sam4.5777.251874.281963.88
Mike6687.002033.681931.26
Ishan7595.631871.982026.08
Neil84105.001881.721933.48
Latest Project

Fantasy Football Power Rankings Algorithm


[Photo by Raj Mehta-USA TODAY Sports]

Introduction

In the history of our Stonks Fantasy League, I have been known to rank teams based on who I think is the best and has the most likely chance to win the rest of the season. It started with simply looking at every team, their schedule, and ranking them in my notes app. I would send the screenshot in our groupchat and the trash talk would commence. I started having less time to manually do all the work and started getting more into analytics in college, utilizing a model that was used to calculate spreads of professional sports games and implementing it with our fantasy football league. However, after a year or two of using that method we found that it was just a glorified method and was really just ranking us by how much of a difference there was in our Points For and Points Against. I wanted to make a rating system that would logically rank our teams, based on both past performance and what their upcoming schedule looked like.

What did I use?

ToolsFunctions
Pythonnumpypandasmathjson

How does it work?

I had originally been scraping scores directly from ESPN. However, scraping was only working once the season was over and I couldn’t find a fix that would work mid-season. I ended up inputting scores manually in the table below. The full script will be uploaded on github at a later date.

WeekHomeHScoreAwayAScore
1Sam136.54Prad106.14
1Mike123.84Joey86.06
1Savan161.6Neil104.68
1Ian131.64Ishan132.16
2Savan167.92Prad137.9
2Joey142.88Ian139.44
2Ishan142.6Neil152.58
2Mike118.04Sam127.16
3Sam149.42Joey160.78
3Ian150.92Neil154.78
3Prad136.08Ishan211.6
3Mike162.56Savan88.08
4Ian127.8Sam201
4Ishan110.58Mike83.78
4Neil190.94Prad102.52
4Joey130.04Savan173.96
5Sam163.26Savan153.92
5Mike91.5Neil112.96
5Ishan139.78Joey181.64
5Prad203.04Ian113.52
6Ishan169.38Sam92.36
6Prad154.34Mike119.84
6Neil133.44Joey150.62
6Savan104.9Ian132.12
7Savan96.16Ishan126.96
7Neil149.48Sam164.7
7Joey143.18Prad167.16
7Mike116.56Ian128.8
8Prad121.24Sam163.36
8Joey147.98Mike106.78
8Neil157.36Savan159.86
8Ishan123.72Ian180.8
9Prad103.1Savan158.4
9Ian164Joey116.58
9Neil144.86Ishan107.94
9Sam118.92Mike133.22
10Joey149.82Sam110.08
10Neil172.26Ian140.34
10Ishan127.82Prad118.48
10Savan124.12Mike119.48
11Sam129.2Ian162.34
11Mike93.64Ishan160.6
11Prad103.98Neil123.56
11Savan146.2Joey134.86
12Savan181.2Sam128.96
12Neil148.14Mike147.24
12Joey146.08Ishan158.78
12Ian130.58Prad177.32
13Sam167Ishan146.48
13Mike124.4Prad86.4
13Joey165.54Neil166.56
13Ian126.46Savan163.82
14Ishan108.74Savan115.28
14Sam169.12Neil156.84
14Prad159.44Joey137.74
14Ian142.02Mike140.22

The only thing needed is the scores for the weeks that have been played, any games that are upcoming can leave scores blank. The algorithm will look through the game logs and calculate each team’s record, points for, points against, average weekly score, and standard devation of those scores. It will also calculate the median score for each week to be compared to each team later in the code. You can view the results of these calculations below.

alt text

The goal of calculating the average weekly score and the deviation is to account for owner performance. It’s almost impossible for me to know which individual players are injured or on bye and who the owners would sub in for them. It’s also impossible for me to analyze each of these player’s schedules and figure out if they’re likely to boom or bust from week-to-week. The average score and deviation gives me a good idea of how well a team is scoring and how much variance is occuring, regardless of the context of that variance. So if owners are experiencing injuries, extreme boom or bust swings, or just bad team management, it will most likely reflect in these calculations.

I then parse the game log and go through each game, comparing the home and away scores to the median. These games are then marked as tough wins/losses, neutral wins/losses, and easy wins/losses. A tough game is when both teams are above the weekly median, an easy game is when both teams are below the median, and a neutral game means opponents are both above and below the median.

The level of toughness of the game is marked accordingly by a 1 within the table indicating both the home and away team’s win/loss status. During this process, the home and away teams also go through a simulation of 1 million games using their average score and devation data. This produces the win probability that is seen next to the marked wins and losses shown below.

Cool. That’s a lot of yapping, how is the Rating calulated?

The rating is calculated using all of the math discussed previously. To simplify it, it first rates the difficulty of the games you’ve already played and uses the formula shown below to add up your score. If your game was considered neutral, a win is a win and you get 1 point. Otherwise you lost, so you get 0 points. If your game was tough, a win gives you a little extra boost in the rankings with 1.375 points, but your loss shouldn’t be penalized completely so we still award 0.375 for doing better than the median. Now the same applies for easy wins, you won… but you did worse than the league so why should you be rewarded? You’ll get a partial win with 0.625 points and you really suck if you lose an easy game so you lose 0.375 in rating, which makes it very possible to go negative on the season.

Now, what about the games that still haven’t been played? Well, that’s why we calculated win probabilities. We can use those probabilities to give us a rough estimate for how many games you’re expected to win the rest of the season. It’s as simple as just summing all the probabilities of the remaining games.

So, lets say we finished week 10 and I am 6-4. I have 3 neutral wins, 2 tough wins, 1 easy win, 1 neutral loss, 1 tough loss, and 2 easy losses. My rating is calculated as follows: 3(NW)*1 + 2(TW)*1.375 + 1(EW)*0.625 + 1(NL)*0 + 1(TL)*0.375 - 2(EL)*0.375 = 6.625

Makes sense so far, I have 6 wins and most of them were great games and I was penalized for my 2 bad losses. A 6.625 seems reasonable for my performance. With 4 games left in the season, I have some easier opponents left. Week 11 Mike (All-time most losses), Week 12 Ian (Eternally mid), Week 13 Sam (Went 2-12), and Week 14 Savan (Easy rivalry win, no competition). The model outputs my win probabilities for each of those weeks at about 0.79, 0.58, 0.63, and 0.71 respectively. If we sum those probabilities up, we get my expected wins for the next 4 weeks which is 2.71 wins. If you want to do some analysis, I’m favored in all those games so I could finish the season at 10-4. However, there’s always the chance I lose one or more of those games so if we round up the 2.71 (since there’s no partial wins) to 3 then I’m likely to end the season at 9-5.

Not bad, so lets factor this into our rating: 6.625 + 2.71 = 9.335

Great! So at 6-4 after week 10, our rating is 9.335. We can likely expect that the model sees us as an above average team that can finish off the season around 9 wins. That’s what I like about the new method I created, it’s very interpretable and gives you an idea of where you’ll stack up by the end of the season compared to the rest of the league.

The equation can simply be looked at as: Final Rating = [Past Performance Rating] + [Expected Wins]

It’s not perfect, but from my understanding it takes into account the most important factors that determine your standing amongst the league. Your scoring consistency, how you compare to the rest of the league every week even if you won an easy game or lost a hard game, and does the rest of your schedule allow for you to make a comeback in the rankings.

You can take a look at our league’s current rankings at the top of the home page.