Multichem commited on
Commit
58d7c0c
·
1 Parent(s): f4dfe5f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +278 -0
app.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pulp
2
+ import numpy as np
3
+ import pandas as pd
4
+ import streamlit as st
5
+ import gspread
6
+ from itertools import combinations
7
+
8
+ scope = ['https://www.googleapis.com/auth/spreadsheets',
9
+ "https://www.googleapis.com/auth/drive"]
10
+
11
+ credentials = {
12
+ "type": "service_account",
13
+ "project_id": "sheets-api-connect-378620",
14
+ "private_key_id": "1005124050c80d085e2c5b344345715978dd9cc9",
15
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtKa01beXwc88R\nnPZVQTNPVQuBnbwoOfc66gW3547ja/UEyIGAF112dt/VqHprRafkKGmlg55jqJNt\na4zceLKV+wTm7vBu7lDISTJfGzCf2TrxQYNqwMKE2LOjI69dBM8u4Dcb4k0wcp9v\ntW1ZzLVVuwTvmrg7JBHjiSaB+x5wxm/r3FOiJDXdlAgFlytzqgcyeZMJVKKBQHyJ\njEGg/1720A0numuOCt71w/2G0bDmijuj1e6tH32MwRWcvRNZ19K9ssyDz2S9p68s\nYDhIxX69OWxwScTIHLY6J2t8txf/XMivL/636fPlDADvBEVTdlT606n8CcKUVQeq\npUVdG+lfAgMBAAECggEAP38SUA7B69eTfRpo658ycOs3Amr0JW4H/bb1rNeAul0K\nZhwd/HnU4E07y81xQmey5kN5ZeNrD5EvqkZvSyMJHV0EEahZStwhjCfnDB/cxyix\nZ+kFhv4y9eK+kFpUAhBy5nX6T0O+2T6WvzAwbmbVsZ+X8kJyPuF9m8ldcPlD0sce\ntj8NwVq1ys52eosqs7zi2vjt+eMcaY393l4ls+vNq8Yf27cfyFw45W45CH/97/Nu\n5AmuzlCOAfFF+z4OC5g4rei4E/Qgpxa7/uom+BVfv9G0DIGW/tU6Sne0+37uoGKt\nW6DzhgtebUtoYkG7ZJ05BTXGp2lwgVcNRoPwnKJDxQKBgQDT5wYPUBDW+FHbvZSp\nd1m1UQuXyerqOTA9smFaM8sr/UraeH85DJPEIEk8qsntMBVMhvD3Pw8uIUeFNMYj\naLmZFObsL+WctepXrVo5NB6RtLB/jZYxiKMatMLUJIYtcKIp+2z/YtKiWcLnwotB\nWdCjVnPTxpkurmF2fWP/eewZ+wKBgQDRMtJg7etjvKyjYNQ5fARnCc+XsI3gkBe1\nX9oeXfhyfZFeBXWnZzN1ITgFHplDznmBdxAyYGiQdbbkdKQSghviUQ0igBvoDMYy\n1rWcy+a17Mj98uyNEfmb3X2cC6WpvOZaGHwg9+GY67BThwI3FqHIbyk6Ko09WlTX\nQpRQjMzU7QKBgAfi1iflu+q0LR+3a3vvFCiaToskmZiD7latd9AKk2ocsBd3Woy9\n+hXXecJHPOKV4oUJlJgvAZqe5HGBqEoTEK0wyPNLSQlO/9ypd+0fEnArwFHO7CMF\nycQprAKHJXM1eOOFFuZeQCaInqdPZy1UcV5Szla4UmUZWkk1m24blHzXAoGBAMcA\nyH4qdbxX9AYrC1dvsSRvgcnzytMvX05LU0uF6tzGtG0zVlub4ahvpEHCfNuy44UT\nxRWW/oFFaWjjyFxO5sWggpUqNuHEnRopg3QXx22SRRTGbN45li/+QAocTkgsiRh1\nqEcYZsO4mPCsQqAy6E2p6RcK+Xa+omxvSnVhq0x1AoGAKr8GdkCl4CF6rieLMAQ7\nLNBuuoYGaHoh8l5E2uOQpzwxVy/nMBcAv+2+KqHEzHryUv1owOi6pMLv7A9mTFoS\n18B0QRLuz5fSOsVnmldfC9fpUc6H8cH1SINZpzajqQA74bPwELJjnzrCnH79TnHG\nJuElxA33rFEjbgbzdyrE768=\n-----END PRIVATE KEY-----\n",
16
+ "client_email": "gspread-connection@sheets-api-connect-378620.iam.gserviceaccount.com",
17
+ "client_id": "106625872877651920064",
18
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
19
+ "token_uri": "https://oauth2.googleapis.com/token",
20
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
21
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/gspread-connection%40sheets-api-connect-378620.iam.gserviceaccount.com"
22
+ }
23
+
24
+ gc = gspread.service_account_from_dict(credentials)
25
+
26
+ st.set_page_config(layout="wide")
27
+
28
+ wrong_acro = ['WSH', 'AZ']
29
+ right_acro = ['WAS', 'ARI']
30
+
31
+ game_format = {'Win Percentage': '{:.2%}','First Inning Lead Percentage': '{:.2%}',
32
+ 'Fifth Inning Lead Percentage': '{:.2%}', '8+ runs': '{:.2%}', 'DK LevX': '{:.2%}', 'FD LevX': '{:.2%}'}
33
+
34
+ team_roo_format = {'Top Score%': '{:.2%}','0 Runs': '{:.2%}', '1 Run': '{:.2%}', '2 Runs': '{:.2%}', '3 Runs': '{:.2%}', '4 Runs': '{:.2%}',
35
+ '5 Runs': '{:.2%}','6 Runs': '{:.2%}', '7 Runs': '{:.2%}', '8 Runs': '{:.2%}', '9 Runs': '{:.2%}', '10 Runs': '{:.2%}'}
36
+
37
+ player_roo_format = {'Top_finish': '{:.2%}','Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}',
38
+ '4x%': '{:.2%}','GPP%': '{:.2%}'}
39
+
40
+ all_dk_player_projections = 'https://docs.google.com/spreadsheets/d/1I_1Ve3F4tftgfLQQoRKOJ351XfEG48s36OxXUKxmgS8/edit#gid=1391856348'
41
+
42
+ @st.cache_data
43
+ def set_slate_teams():
44
+ sh = gc.open_by_url(all_dk_player_projections)
45
+ worksheet = sh.worksheet('Site_Info')
46
+ raw_display = pd.DataFrame(worksheet.get_all_records())
47
+
48
+ return raw_display
49
+
50
+ @st.cache_data
51
+ def player_stat_table():
52
+ sh = gc.open_by_url(all_dk_player_projections)
53
+ worksheet = sh.worksheet('Player_Projections')
54
+ raw_display = pd.DataFrame(worksheet.get_all_records())
55
+
56
+ return raw_display
57
+
58
+ @st.cache_data
59
+ def load_dk_player_projections():
60
+ sh = gc.open_by_url(all_dk_player_projections)
61
+ worksheet = sh.worksheet('DK_ROO')
62
+ load_display = pd.DataFrame(worksheet.get_all_records())
63
+ load_display.replace('', np.nan, inplace=True)
64
+ raw_display = load_display.dropna(subset=['Median'])
65
+
66
+ return raw_display
67
+
68
+ @st.cache_data
69
+ def load_fd_player_projections():
70
+ sh = gc.open_by_url(all_dk_player_projections)
71
+ worksheet = sh.worksheet('FD_ROO')
72
+ load_display = pd.DataFrame(worksheet.get_all_records())
73
+ load_display.replace('', np.nan, inplace=True)
74
+ raw_display = load_display.dropna(subset=['Median'])
75
+
76
+ return raw_display
77
+
78
+ @st.cache_data
79
+ def load_dk_stacks():
80
+ sh = gc.open_by_url(all_dk_player_projections)
81
+ worksheet = sh.worksheet('DK_Stacks')
82
+ load_display = pd.DataFrame(worksheet.get_all_records())
83
+ raw_display = load_display
84
+ raw_display = raw_display.sort_values(by='Own', ascending=False)
85
+
86
+ return raw_display
87
+
88
+ @st.cache_data
89
+ def load_fd_stacks():
90
+ sh = gc.open_by_url(all_dk_player_projections)
91
+ worksheet = sh.worksheet('FD_Stacks')
92
+ load_display = pd.DataFrame(worksheet.get_all_records())
93
+ raw_display = load_display
94
+ raw_display = raw_display.sort_values(by='Own', ascending=False)
95
+
96
+ return raw_display
97
+
98
+ @st.cache_data
99
+ def convert_df_to_csv(df):
100
+ return df.to_csv().encode('utf-8')
101
+
102
+ player_stats = player_stat_table()
103
+ dk_stacks_raw = load_fd_stacks()
104
+ fd_stacks_raw = load_fd_stacks()
105
+ dk_roo_raw = load_dk_player_projections()
106
+ fd_roo_raw = load_fd_player_projections()
107
+ t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
108
+ site_slates = set_slate_teams()
109
+ opp_dict = dict(zip(dk_roo_raw.Team, dk_roo_raw.Opp))
110
+
111
+ tab1, tab2 = st.tabs(['Uploads and Info', 'Pivot Finder'])
112
+
113
+ with tab1:
114
+ st.info("The Projections file can have any columns in any order, but must contain columns explicitly named: 'Player', 'Salary', 'Position', 'Team', 'Opp', 'Median', and 'Own'.")
115
+ col1, col2 = st.columns([1, 5])
116
+
117
+ with col1:
118
+ proj_file = st.file_uploader("Upload Projections File", key = 'proj_uploader')
119
+
120
+ if proj_file is not None:
121
+ try:
122
+ proj_dataframe = pd.read_csv(proj_file)
123
+ except:
124
+ proj_dataframe = pd.read_excel(proj_file)
125
+ with col2:
126
+ if proj_file is not None:
127
+ st.dataframe(proj_dataframe.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
128
+
129
+ with tab2:
130
+ col1, col2 = st.columns([1, 5])
131
+ with col1:
132
+ st.info(t_stamp)
133
+ if st.button("Load/Reset Data", key='reset1'):
134
+ st.cache_data.clear()
135
+ player_stats = player_stat_table()
136
+ dk_stacks_raw = load_fd_stacks()
137
+ fd_stacks_raw = load_fd_stacks()
138
+ dk_roo_raw = load_dk_player_projections()
139
+ fd_roo_raw = load_fd_player_projections()
140
+ t_stamp = f"Last Update: " + str(dk_roo_raw['timestamp'][0]) + f" CST"
141
+ site_slates = set_slate_teams()
142
+ data_var1 = st.radio("Which data are you loading?", ('Paydirt', 'User'), key='data_var1')
143
+ site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='site_var1')
144
+ if site_var1 == 'Draftkings':
145
+ if data_var1 == 'User':
146
+ raw_baselines = proj_dataframe
147
+ elif data_var1 != 'User':
148
+ raw_baselines = dk_roo_raw[dk_roo_raw['slate'] == 'Main Slate']
149
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
150
+ elif site_var1 == 'Fanduel':
151
+ if data_var1 == 'User':
152
+ raw_baselines = proj_dataframe
153
+ elif data_var1 != 'User':
154
+ raw_baselines = fd_roo_raw[fd_roo_raw['slate'] == 'Main Slate']
155
+ raw_baselines = raw_baselines[raw_baselines['version'] == 'overall']
156
+ player_check = st.selectbox('Select player to create comps', options = dk_roo_raw['Player'].unique(), key='dk_player')
157
+ Salary_var = st.number_input('Acceptable +/- Salary range', min_value = 0, max_value = 1000, value = 300, step = 100)
158
+ Median_var = st.number_input('Acceptable +/- Median range', min_value = 0, max_value = 10, value = 3, step = 1)
159
+ pos_var1 = st.radio("Compare to all positions or specific positions?", ('All Positions', 'Specific Positions'), key='pos_var1')
160
+ if pos_var1 == 'Specific Positions':
161
+ pos_var_list = st.multiselect('Which positions would you like to include?', options = raw_baselines['Position'].unique(), key='pos_var_list')
162
+ elif pos_var1 == 'All Positions':
163
+ pos_var_list = raw_baselines.Position.values.tolist()
164
+ split_var1 = st.radio("Are you running the full slate or certain games?", ('Full Slate Run', 'Specific Games'), key='split_var1')
165
+ if split_var1 == 'Specific Games':
166
+ team_var1 = st.multiselect('Which teams would you like to include?', options = raw_baselines['Team'].unique(), key='team_var1')
167
+ elif split_var1 == 'Full Slate Run':
168
+ team_var1 = raw_baselines.Team.values.tolist()
169
+
170
+ with col2:
171
+ hold_container = st.empty()
172
+ if st.button('Simulate appropriate pivots'):
173
+ with hold_container:
174
+ if site_var1 == 'Draftkings':
175
+ working_roo = raw_baselines
176
+ working_roo.replace('', 0, inplace=True)
177
+ if site_var1 == 'Fanduel':
178
+ working_roo = raw_baselines
179
+ working_roo.replace('', 0, inplace=True)
180
+
181
+
182
+ own_dict = dict(zip(working_roo.Player, working_roo.Own))
183
+ team_dict = dict(zip(working_roo.Player, working_roo.Team))
184
+ opp_dict = dict(zip(working_roo.Player, working_roo.Opp))
185
+ total_sims = 1000
186
+
187
+ player_var = working_roo.loc[working_roo['Player'] == player_check]
188
+ player_var = player_var.reset_index()
189
+
190
+ working_roo = working_roo[working_roo['Position'].isin(pos_var_list)]
191
+ working_roo = working_roo[working_roo['Team'].isin(team_var1)]
192
+ working_roo = working_roo.loc[(working_roo['Salary'] >= player_var['Salary'][0] - Salary_var) & (working_roo['Salary'] <= player_var['Salary'][0] + Salary_var)]
193
+ working_roo = working_roo.loc[(working_roo['Fantasy'] >= player_var['Fantasy'][0] - Median_var) & (working_roo['Fantasy'] <= player_var['Fantasy'][0] + Median_var)]
194
+
195
+ flex_file = working_roo[['Player', 'Position', 'Salary', 'Fantasy', 'Rush Yards', 'Receptions']]
196
+ flex_file.rename(columns={"Fantasy": "Median", "Pos": "Position"}, inplace = True)
197
+ flex_file['Floor'] = np.where(flex_file['Position'] == 'QB',(flex_file['Median']*.25) + (flex_file['Rush Yards']*.01),flex_file['Median']*.25)
198
+ flex_file['Ceiling'] = np.where(flex_file['Position'] == 'QB',(flex_file['Median'] + flex_file['Floor']) + (flex_file['Rush Yards']*.01), flex_file['Median'] + flex_file['Floor'] + flex_file['Receptions'])
199
+ flex_file['STD'] = (flex_file['Median']/4) + flex_file['Receptions']
200
+ flex_file = flex_file[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD']]
201
+ hold_file = flex_file
202
+ overall_file = flex_file
203
+ salary_file = flex_file
204
+
205
+ overall_players = overall_file[['Player']]
206
+
207
+ for x in range(0,total_sims):
208
+ salary_file[x] = salary_file['Salary']
209
+
210
+ salary_file=salary_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
211
+ salary_file.astype('int').dtypes
212
+
213
+ salary_file = salary_file.div(1000)
214
+
215
+ for x in range(0,total_sims):
216
+ overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
217
+
218
+ overall_file=overall_file.drop(['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
219
+ overall_file.astype('int').dtypes
220
+
221
+ players_only = hold_file[['Player']]
222
+ raw_lineups_file = players_only
223
+
224
+ for x in range(0,total_sims):
225
+ maps_dict = {'proj_map':dict(zip(hold_file.Player,hold_file[x]))}
226
+ raw_lineups_file[x] = sum([raw_lineups_file['Player'].map(maps_dict['proj_map'])])
227
+ players_only[x] = raw_lineups_file[x].rank(ascending=False)
228
+
229
+ players_only=players_only.drop(['Player'], axis=1)
230
+ players_only.astype('int').dtypes
231
+
232
+ salary_2x_check = (overall_file - (salary_file*2))
233
+ salary_3x_check = (overall_file - (salary_file*3))
234
+ salary_4x_check = (overall_file - (salary_file*4))
235
+
236
+ players_only['Average_Rank'] = players_only.mean(axis=1)
237
+ players_only['Top_finish'] = players_only[players_only == 1].count(axis=1)/total_sims
238
+ players_only['Top_5_finish'] = players_only[players_only <= 5].count(axis=1)/total_sims
239
+ players_only['Top_10_finish'] = players_only[players_only <= 10].count(axis=1)/total_sims
240
+ players_only['20+%'] = overall_file[overall_file >= 20].count(axis=1)/float(total_sims)
241
+ players_only['2x%'] = salary_2x_check[salary_2x_check >= 1].count(axis=1)/float(total_sims)
242
+ players_only['3x%'] = salary_3x_check[salary_3x_check >= 1].count(axis=1)/float(total_sims)
243
+ players_only['4x%'] = salary_4x_check[salary_4x_check >= 1].count(axis=1)/float(total_sims)
244
+
245
+ players_only['Player'] = hold_file[['Player']]
246
+
247
+ final_outcomes = players_only[['Player', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
248
+
249
+ final_Proj = pd.merge(hold_file, final_outcomes, on="Player")
250
+ final_Proj = final_Proj[['Player', 'Position', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%']]
251
+ final_Proj['Own'] = final_Proj['Player'].map(own_dict)
252
+ final_Proj['Team'] = final_Proj['Player'].map(team_dict)
253
+ final_Proj['Opp'] = final_Proj['Player'].map(opp_dict)
254
+ final_Proj = final_Proj[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own']]
255
+ final_Proj['Projection Rank'] = final_Proj.Median.rank(pct = True)
256
+ final_Proj['Own Rank'] = final_Proj.Own.rank(pct = True)
257
+ final_Proj['LevX'] = 0
258
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'QB', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
259
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'TE', final_Proj[['Projection Rank', '2x%']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
260
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'RB', final_Proj[['Projection Rank', 'Top_5_finish']].mean(axis=1) + final_Proj['20+%'] - final_Proj['Own Rank'], final_Proj['LevX'])
261
+ final_Proj['LevX'] = np.where(final_Proj['Position'] == 'WR', final_Proj[['Projection Rank', 'Top_10_finish']].mean(axis=1) + final_Proj['4x%'] - final_Proj['Own Rank'], final_Proj['LevX'])
262
+ final_Proj['CPT_Own'] = final_Proj['Own'] / 4
263
+
264
+ final_Proj = final_Proj[['Player', 'Position', 'Team', 'Opp', 'Salary', 'Floor', 'Median', 'Ceiling', 'Top_finish', 'Top_5_finish', 'Top_10_finish', '20+%', '2x%', '3x%', '4x%', 'Own', 'LevX']]
265
+ final_Proj = final_Proj.set_index('Player')
266
+ final_Proj = final_Proj.sort_values(by='Top_finish', ascending=False)
267
+
268
+ with hold_container:
269
+ hold_container = st.empty()
270
+ final_Proj = final_Proj
271
+ st.dataframe(final_Proj.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(player_roo_format, precision=2), use_container_width = True)
272
+
273
+ st.download_button(
274
+ label="Export Tables",
275
+ data=convert_df_to_csv(final_Proj),
276
+ file_name='NFL_pivot_export.csv',
277
+ mime='text/csv',
278
+ )