James McCool commited on
Commit
9594423
·
1 Parent(s): f32fab3

added poisson math to stat sims

Browse files
Files changed (1) hide show
  1. app.py +35 -10
app.py CHANGED
@@ -1,8 +1,10 @@
1
  import streamlit as st
2
  import numpy as np
 
3
  import pandas as pd
4
  import gspread
5
  import plotly.express as px
 
6
  st.set_page_config(layout="wide")
7
 
8
  @st.cache_resource
@@ -47,6 +49,13 @@ gcservice_account, gcservice_account2, NFL_Data = init_conn()
47
  game_format = {'Win%': '{:.2%}', 'Vegas': '{:.2%}', 'Win% Diff': '{:.2%}'}
48
  american_format = {'First Inning Lead Percentage': '{:.2%}', 'Fifth Inning Lead Percentage': '{:.2%}'}
49
 
 
 
 
 
 
 
 
50
  @st.cache_resource(ttl=600)
51
  def init_baselines():
52
  sh = gcservice_account.open_by_url(NFL_Data)
@@ -83,7 +92,9 @@ def init_baselines():
83
 
84
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
85
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
 
86
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
 
87
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
88
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
89
 
@@ -107,7 +118,9 @@ with tab1:
107
  st.cache_data.clear()
108
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
109
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
 
110
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
 
111
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
112
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
113
  line_var1 = st.radio('How would you like to display odds?', options = ['Percentage', 'American'], key='line_var1')
@@ -166,7 +179,9 @@ with tab3:
166
  st.cache_data.clear()
167
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
168
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
 
169
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
 
170
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
171
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
172
  split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
@@ -192,7 +207,9 @@ with tab4:
192
  st.cache_data.clear()
193
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
194
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
 
195
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
 
196
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
197
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
198
  split_var5 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var5')
@@ -221,7 +238,9 @@ with tab5:
221
  st.cache_data.clear()
222
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
223
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
 
224
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
 
225
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
226
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
227
  col1, col2 = st.columns([1, 5])
@@ -317,12 +336,14 @@ with tab5:
317
  player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
318
 
319
  players_only['Mean_Outcome'] = overall_file.mean(axis=1)
 
 
320
  players_only['10%'] = overall_file.quantile(0.1, axis=1)
321
  players_only['90%'] = overall_file.quantile(0.9, axis=1)
322
  if ou_var == 'Over':
323
- players_only['beat_prop'] = overall_file[overall_file > prop_var].count(axis=1)/float(total_sims)
324
  elif ou_var == 'Under':
325
- players_only['beat_prop'] = (overall_file[overall_file < prop_var].count(axis=1)/float(total_sims))
326
 
327
  players_only['implied_odds'] = np.where(line_var <= 0, (-(line_var)/((-(line_var))+100)), 100/(line_var+100))
328
 
@@ -368,7 +389,9 @@ with tab6:
368
  st.cache_data.clear()
369
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
370
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
 
371
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
 
372
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
373
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
374
  col1, col2 = st.columns([1, 5])
@@ -499,16 +522,17 @@ with tab6:
499
  prop_check = (overall_file - prop_file)
500
 
501
  players_only['Mean_Outcome'] = overall_file.mean(axis=1)
 
 
 
502
  players_only['10%'] = overall_file.quantile(0.1, axis=1)
503
  players_only['90%'] = overall_file.quantile(0.9, axis=1)
504
- players_only['Over'] = prop_check[prop_check > 0].count(axis=1)/float(total_sims)
505
  players_only['Imp Over'] = players_only['Player'].map(over_dict)
506
  players_only['Over%'] = players_only[["Over", "Imp Over"]].mean(axis=1)
507
- players_only['Under'] = prop_check[prop_check < 0].count(axis=1)/float(total_sims)
508
  players_only['Imp Under'] = players_only['Player'].map(under_dict)
509
  players_only['Under%'] = players_only[["Under", "Imp Under"]].mean(axis=1)
510
- players_only['Prop'] = players_only['Player'].map(prop_dict)
511
- players_only['Book'] = players_only['Player'].map(book_dict)
512
  players_only['Prop_avg'] = players_only['Prop'].mean() / 100
513
  players_only['prop_threshold'] = .10
514
  players_only = players_only[players_only['Mean_Outcome'] > 0]
@@ -652,16 +676,17 @@ with tab6:
652
  prop_check = (overall_file - prop_file)
653
 
654
  players_only['Mean_Outcome'] = overall_file.mean(axis=1)
 
 
 
655
  players_only['10%'] = overall_file.quantile(0.1, axis=1)
656
  players_only['90%'] = overall_file.quantile(0.9, axis=1)
657
- players_only['Over'] = prop_check[prop_check > 0].count(axis=1)/float(total_sims)
658
  players_only['Imp Over'] = players_only['Player'].map(over_dict)
659
  players_only['Over%'] = players_only[["Over", "Imp Over"]].mean(axis=1)
660
- players_only['Under'] = prop_check[prop_check < 0].count(axis=1)/float(total_sims)
661
  players_only['Imp Under'] = players_only['Player'].map(under_dict)
662
  players_only['Under%'] = players_only[["Under", "Imp Under"]].mean(axis=1)
663
- players_only['Book'] = players_only['Player'].map(book_dict)
664
- players_only['Prop'] = players_only['Player'].map(prop_dict)
665
  players_only['Prop_avg'] = players_only['Prop'].mean() / 100
666
  players_only['prop_threshold'] = .10
667
  players_only = players_only[players_only['Mean_Outcome'] > 0]
 
1
  import streamlit as st
2
  import numpy as np
3
+ from numpy import where as np_where
4
  import pandas as pd
5
  import gspread
6
  import plotly.express as px
7
+ import scipy.stats as stats
8
  st.set_page_config(layout="wide")
9
 
10
  @st.cache_resource
 
49
  game_format = {'Win%': '{:.2%}', 'Vegas': '{:.2%}', 'Win% Diff': '{:.2%}'}
50
  american_format = {'First Inning Lead Percentage': '{:.2%}', 'Fifth Inning Lead Percentage': '{:.2%}'}
51
 
52
+ def calculate_poisson(row):
53
+ mean_val = row['Mean_Outcome']
54
+ threshold = row['Prop']
55
+ cdf_value = stats.poisson.cdf(threshold, mean_val)
56
+ probability = 1 - cdf_value
57
+ return probability
58
+
59
  @st.cache_resource(ttl=600)
60
  def init_baselines():
61
  sh = gcservice_account.open_by_url(NFL_Data)
 
92
 
93
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
94
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
95
+ qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
96
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
97
+ non_qb_stats = non_qb_stats.drop_duplicates(subset=['Player', 'Position'])
98
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
99
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
100
 
 
118
  st.cache_data.clear()
119
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
120
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
121
+ qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
122
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
123
+ non_qb_stats = non_qb_stats.drop_duplicates(subset=['Player', 'Position'])
124
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
125
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
126
  line_var1 = st.radio('How would you like to display odds?', options = ['Percentage', 'American'], key='line_var1')
 
179
  st.cache_data.clear()
180
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
181
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
182
+ qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
183
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
184
+ non_qb_stats = non_qb_stats.drop_duplicates(subset=['Player', 'Position'])
185
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
186
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
187
  split_var2 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var2')
 
207
  st.cache_data.clear()
208
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
209
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
210
+ qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
211
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
212
+ non_qb_stats = non_qb_stats.drop_duplicates(subset=['Player', 'Position'])
213
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
214
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
215
  split_var5 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var5')
 
238
  st.cache_data.clear()
239
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
240
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
241
+ qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
242
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
243
+ non_qb_stats = non_qb_stats.drop_duplicates(subset=['Player', 'Position'])
244
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
245
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
246
  col1, col2 = st.columns([1, 5])
 
336
  player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
337
 
338
  players_only['Mean_Outcome'] = overall_file.mean(axis=1)
339
+ players_only['Prop'] = prop_var
340
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
341
  players_only['10%'] = overall_file.quantile(0.1, axis=1)
342
  players_only['90%'] = overall_file.quantile(0.9, axis=1)
343
  if ou_var == 'Over':
344
+ players_only['beat_prop'] = np.where(players_only['Prop'] <= 3, players_only['poisson_var'], overall_file[overall_file > prop_var].count(axis=1)/float(total_sims))
345
  elif ou_var == 'Under':
346
+ players_only['beat_prop'] = np.where(players_only['Prop'] <= 3, 1 - players_only['poisson_var'], (overall_file[overall_file < prop_var].count(axis=1)/float(total_sims)))
347
 
348
  players_only['implied_odds'] = np.where(line_var <= 0, (-(line_var)/((-(line_var))+100)), 100/(line_var+100))
349
 
 
389
  st.cache_data.clear()
390
  game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame = init_baselines()
391
  qb_stats = overall_stats[overall_stats['Position'] == 'QB']
392
+ qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
393
  non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
394
+ non_qb_stats = non_qb_stats.drop_duplicates(subset=['Player', 'Position'])
395
  team_dict = dict(zip(prop_frame['Player'], prop_frame['Team']))
396
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
397
  col1, col2 = st.columns([1, 5])
 
522
  prop_check = (overall_file - prop_file)
523
 
524
  players_only['Mean_Outcome'] = overall_file.mean(axis=1)
525
+ players_only['Book'] = players_only['Player'].map(book_dict)
526
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
527
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
528
  players_only['10%'] = overall_file.quantile(0.1, axis=1)
529
  players_only['90%'] = overall_file.quantile(0.9, axis=1)
530
+ players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
531
  players_only['Imp Over'] = players_only['Player'].map(over_dict)
532
  players_only['Over%'] = players_only[["Over", "Imp Over"]].mean(axis=1)
533
+ players_only['Under'] = np_where(players_only['Prop'] <= 3, 1 - players_only['poisson_var'], prop_check[prop_check < 0].count(axis=1)/float(total_sims))
534
  players_only['Imp Under'] = players_only['Player'].map(under_dict)
535
  players_only['Under%'] = players_only[["Under", "Imp Under"]].mean(axis=1)
 
 
536
  players_only['Prop_avg'] = players_only['Prop'].mean() / 100
537
  players_only['prop_threshold'] = .10
538
  players_only = players_only[players_only['Mean_Outcome'] > 0]
 
676
  prop_check = (overall_file - prop_file)
677
 
678
  players_only['Mean_Outcome'] = overall_file.mean(axis=1)
679
+ players_only['Book'] = players_only['Player'].map(book_dict)
680
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
681
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
682
  players_only['10%'] = overall_file.quantile(0.1, axis=1)
683
  players_only['90%'] = overall_file.quantile(0.9, axis=1)
684
+ players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
685
  players_only['Imp Over'] = players_only['Player'].map(over_dict)
686
  players_only['Over%'] = players_only[["Over", "Imp Over"]].mean(axis=1)
687
+ players_only['Under'] = np_where(players_only['Prop'] <= 3, 1 - players_only['poisson_var'], prop_check[prop_check < 0].count(axis=1)/float(total_sims))
688
  players_only['Imp Under'] = players_only['Player'].map(under_dict)
689
  players_only['Under%'] = players_only[["Under", "Imp Under"]].mean(axis=1)
 
 
690
  players_only['Prop_avg'] = players_only['Prop'].mean() / 100
691
  players_only['prop_threshold'] = .10
692
  players_only = players_only[players_only['Mean_Outcome'] > 0]