James McCool commited on
Commit
42503f5
·
1 Parent(s): c527886

Refactor app.py to improve UI layout and enhance prop simulation functionality. Introduced a settings container for better organization of selection options, including prop source, book, and prop category. Streamlined the simulation process for player props, ensuring accurate calculations and improved data handling. Updated download functionality for prop sources and projections, enhancing user experience and data accessibility.

Browse files
Files changed (1) hide show
  1. app.py +282 -279
app.py CHANGED
@@ -165,17 +165,19 @@ with tab3:
165
  st.cache_data.clear()
166
  prop_display, prop_trends, pick_frame, timestamp, team_dict = pull_baselines()
167
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
168
- col1, col2 = st.columns([1, 5])
169
-
170
- with col2:
171
- df_hold_container = st.empty()
172
- info_hold_container = st.empty()
173
- plot_hold_container = st.empty()
174
- export_container = st.empty()
175
-
176
- with col1:
177
- game_select_var = st.selectbox('Select prop source', options = ['Aggregate', 'Pick6'])
178
- book_select_var = st.selectbox('Select book', options = ['ALL', 'BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL'])
 
 
179
  if book_select_var == 'ALL':
180
  book_selections = ['BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL']
181
  else:
@@ -185,278 +187,279 @@ with tab3:
185
  elif game_select_var == 'Pick6':
186
  prop_df = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
187
  book_selections = ['Pick6']
188
- st.download_button(
189
- label="Download Prop Source",
190
- data=convert_df_to_csv(prop_df),
191
- file_name='NHL_prop_source.csv',
192
- mime='text/csv',
193
- key='prop_source',
194
- )
195
  if game_select_var == 'Aggregate':
196
  prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'NHL_GAME_PLAYER_POINTS', 'NHL_GAME_PLAYER_SHOTS_ON_GOAL', 'NHL_GAME_PLAYER_ASSISTS', 'NHL_GAME_PLAYER_BLOCKED_SHOTS'])
197
  elif game_select_var == 'Pick6':
198
  prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'Points', 'Shots on Goal', 'Assists', 'Blocks'])
199
-
200
- if st.button('Simulate Prop Category'):
201
- with col2:
202
- with df_hold_container.container():
203
- if prop_type_var == 'All Props':
204
-
205
- if game_select_var == 'Aggregate':
206
- prop_df_raw = prop_trends[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
207
- sim_vars = ['NHL_GAME_PLAYER_POINTS', 'NHL_GAME_PLAYER_SHOTS_ON_GOAL', 'NHL_GAME_PLAYER_ASSISTS', 'NHL_GAME_PLAYER_BLOCKED_SHOTS']
208
- elif game_select_var == 'Pick6':
209
- prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
210
- sim_vars = ['Points', 'Shots on Goal', 'Assists', 'Blocks']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
 
212
- player_df = prop_display.copy()
213
-
214
- for prop in sim_vars:
215
-
216
- for books in book_selections:
217
- prop_df = prop_df_raw[prop_df_raw['prop_type'] == prop]
218
- prop_df = prop_df[prop_df['book'] == books]
219
- prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
220
- prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
221
- prop_df['Over'] = 1 / prop_df['over_line']
222
- prop_df['Under'] = 1 / prop_df['under_line']
223
-
224
- prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
225
- prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
226
- book_dict = dict(zip(prop_df.Player, prop_df.book))
227
- over_dict = dict(zip(prop_df.Player, prop_df.Over))
228
- under_dict = dict(zip(prop_df.Player, prop_df.Under))
229
- trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
230
- trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
231
-
232
- player_df['book'] = player_df['Player'].map(book_dict)
233
- player_df['Prop'] = player_df['Player'].map(prop_dict)
234
- player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
235
- player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
236
- player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
237
-
238
- df = player_df.reset_index(drop=True)
239
-
240
- team_dict = dict(zip(df.Player, df.Team))
241
-
242
- total_sims = 1000
243
-
244
- df.replace("", 0, inplace=True)
245
-
246
- if prop == 'NHL_GAME_PLAYER_POINTS' or prop == 'Points':
247
- df['Median'] = df['Player TP']
248
- elif prop == 'NHL_GAME_PLAYER_SHOTS_ON_GOAL' or prop == 'Shots on Goal':
249
- df['Median'] = df['Player SOG']
250
- elif prop == 'NHL_GAME_PLAYER_ASSISTS' or prop == 'Assists':
251
- df['Median'] = df['Player Assists']
252
- elif prop == 'NHL_GAME_PLAYER_BLOCKED_SHOTS' or prop == 'Blocks':
253
- df['Median'] = df['Player Blocks']
254
-
255
- flex_file = df.copy()
256
- flex_file['Floor'] = (flex_file['Median'] * .15)
257
- flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1)
258
- flex_file['STD'] = (flex_file['Median']/3)
259
- flex_file['Prop'] = flex_file['Player'].map(prop_dict)
260
- flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
261
-
262
- hold_file = flex_file.copy()
263
- overall_file = flex_file.copy()
264
- prop_file = flex_file.copy()
265
-
266
- overall_players = overall_file[['Player']]
267
-
268
- for x in range(0,total_sims):
269
- prop_file[x] = prop_file['Prop']
270
-
271
- prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
272
-
273
- for x in range(0,total_sims):
274
- overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
275
-
276
- overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
277
-
278
- players_only = hold_file[['Player']]
279
-
280
- player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
281
-
282
- prop_check = (overall_file - prop_file)
283
-
284
- players_only['Mean_Outcome'] = overall_file.mean(axis=1)
285
- players_only['Prop'] = players_only['Player'].map(prop_dict)
286
- players_only['Book'] = players_only['Player'].map(book_dict)
287
- players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
288
- players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
289
- players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
290
- players_only['10%'] = overall_file.quantile(0.1, axis=1)
291
- players_only['90%'] = overall_file.quantile(0.9, axis=1)
292
- players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
293
- players_only['Imp Over'] = players_only['Player'].map(over_dict)
294
- players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
295
- 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))
296
- players_only['Imp Under'] = players_only['Player'].map(under_dict)
297
- players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
298
- players_only['Prop_avg'] = players_only['Prop'].mean() / 100
299
- players_only['prop_threshold'] = .10
300
- players_only = players_only[players_only['Mean_Outcome'] > 0]
301
- players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
302
- players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
303
- players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
304
- players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
305
- players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
306
- players_only['Edge'] = players_only['Bet_check']
307
- players_only['Prop Type'] = prop
308
 
309
- players_only['Player'] = hold_file[['Player']]
310
- players_only['Team'] = players_only['Player'].map(team_dict)
311
-
312
- leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
313
- sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
314
-
315
- final_outcomes = sim_all_hold
316
- st.write(f'finished {prop} for {books}')
317
-
318
- elif prop_type_var != 'All Props':
319
-
320
- player_df = prop_display.copy()
321
-
322
- if game_select_var == 'Aggregate':
323
- prop_df_raw = prop_trends[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
324
- elif game_select_var == 'Pick6':
325
- prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
- for books in book_selections:
328
- prop_df = prop_df_raw[prop_df_raw['book'] == books]
329
-
330
- if prop_type_var == "NHL_GAME_PLAYER_SHOTS_ON_GOAL":
331
- prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_SHOTS_ON_GOAL']
332
- elif prop_type_var == 'Shots on Goal':
333
- prop_df = prop_df[prop_df['prop_type'] == 'Player SOG']
334
- elif prop_type_var == "NHL_GAME_PLAYER_POINTS":
335
- prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_POINTS']
336
- elif prop_type_var == "Points":
337
- prop_df = prop_df[prop_df['prop_type'] == 'Player TP']
338
- elif prop_type_var == "NHL_GAME_PLAYER_ASSISTS":
339
- prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_ASSISTS']
340
- elif prop_type_var == "Assists":
341
- prop_df = prop_df[prop_df['prop_type'] == 'Player Assists']
342
- elif prop_type_var == "NHL_GAME_PLAYER_BLOCKED_SHOTS":
343
- prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_BLOCKED_SHOTS']
344
- elif prop_type_var == "Blocks":
345
- prop_df = prop_df[prop_df['prop_type'] == 'Player Blocks']
346
-
347
- prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line']]
348
- prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
349
- prop_df['Over'] = 1 / prop_df['over_line']
350
- prop_df['Under'] = 1 / prop_df['under_line']
351
-
352
- prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
353
- prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
354
- book_dict = dict(zip(prop_df.Player, prop_df.book))
355
- over_dict = dict(zip(prop_df.Player, prop_df.Over))
356
- under_dict = dict(zip(prop_df.Player, prop_df.Under))
357
- trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
358
- trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
359
-
360
- player_df['book'] = player_df['Player'].map(book_dict)
361
- player_df['Prop'] = player_df['Player'].map(prop_dict)
362
- player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
363
- player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
364
- player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
365
-
366
- df = player_df.reset_index(drop=True)
367
-
368
- team_dict = dict(zip(df.Player, df.Team))
369
-
370
- total_sims = 1000
371
-
372
- df.replace("", 0, inplace=True)
373
-
374
- if prop_type_var == 'NHL_GAME_PLAYER_POINTS' or prop_type_var == 'Points':
375
- df['Median'] = df['Player TP']
376
- elif prop_type_var == 'NHL_GAME_PLAYER_SHOTS_ON_GOAL' or prop_type_var == 'Shots on Goal':
377
- df['Median'] = df['Player SOG']
378
- elif prop_type_var == 'NHL_GAME_PLAYER_ASSISTS' or prop_type_var == 'Assists':
379
- df['Median'] = df['Player Assists']
380
- elif prop_type_var == 'NHL_GAME_PLAYER_BLOCKED_SHOTS' or prop_type_var == 'Blocks':
381
- df['Median'] = df['Player Blocks']
382
-
383
- flex_file = df.copy()
384
- flex_file['Floor'] = (flex_file['Median'] * .15)
385
- flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1)
386
- flex_file['STD'] = (flex_file['Median']/3)
387
- flex_file['Prop'] = flex_file['Player'].map(prop_dict)
388
- flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
389
-
390
- hold_file = flex_file.copy()
391
- overall_file = flex_file.copy()
392
- prop_file = flex_file.copy()
393
-
394
- overall_players = overall_file[['Player']]
395
-
396
- for x in range(0,total_sims):
397
- prop_file[x] = prop_file['Prop']
398
-
399
- prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
400
-
401
- for x in range(0,total_sims):
402
- overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
403
-
404
- overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
405
-
406
- players_only = hold_file[['Player']]
407
-
408
- player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
409
-
410
- prop_check = (overall_file - prop_file)
411
-
412
- players_only['Mean_Outcome'] = overall_file.mean(axis=1)
413
- players_only['Prop'] = players_only['Player'].map(prop_dict)
414
- players_only['Book'] = players_only['Player'].map(book_dict)
415
- players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
416
- players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
417
- players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
418
- players_only['10%'] = overall_file.quantile(0.1, axis=1)
419
- players_only['90%'] = overall_file.quantile(0.9, axis=1)
420
- players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
421
- players_only['Imp Over'] = players_only['Player'].map(over_dict)
422
- players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
423
- 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))
424
- players_only['Imp Under'] = players_only['Player'].map(under_dict)
425
- players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
426
- players_only['Prop_avg'] = players_only['Prop'].mean() / 100
427
- players_only['prop_threshold'] = .10
428
- players_only = players_only[players_only['Mean_Outcome'] > 0]
429
- players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
430
- players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
431
- players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
432
- players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
433
- players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
434
- players_only['Edge'] = players_only['Bet_check']
435
- players_only['Prop Type'] = prop_type_var
436
-
437
- players_only['Player'] = hold_file[['Player']]
438
- players_only['Team'] = players_only['Player'].map(team_dict)
439
-
440
- leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop', 'Prop Type', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
441
- sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
442
-
443
- final_outcomes = sim_all_hold
444
- st.write(f'finished {prop_type_var} for {books}')
445
-
446
- final_outcomes = final_outcomes[final_outcomes['Prop'] > 0]
447
- if game_select_var == 'Pick6':
448
- final_outcomes = final_outcomes.drop_duplicates(subset=['Player', 'Prop Type'])
449
- final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)
450
-
451
- with df_hold_container:
452
- df_hold_container = st.empty()
453
- st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
454
- with export_container:
455
- export_container = st.empty()
456
- st.download_button(
457
- label="Export Projections",
458
- data=convert_df_to_csv(final_outcomes),
459
- file_name='NHL_prop_proj.csv',
460
- mime='text/csv',
461
- key='prop_proj',
462
- )
 
165
  st.cache_data.clear()
166
  prop_display, prop_trends, pick_frame, timestamp, team_dict = pull_baselines()
167
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
168
+
169
+ settings_container = st.container()
170
+ df_hold_container = st.empty()
171
+ export_container = st.empty()
172
+
173
+ with settings_container.container():
174
+ col1, col2, col3, col4 = st.columns([3, 3, 3, 3])
175
+ with col1:
176
+ game_select_var = st.selectbox('Select prop source', options = ['Aggregate', 'Pick6'])
177
+ with col2:
178
+ book_select_var = st.selectbox('Select book', options = ['ALL', 'BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL'])
179
+ with col3:
180
+ prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'NHL_GAME_PLAYER_POINTS', 'NHL_GAME_PLAYER_SHOTS_ON_GOAL', 'NHL_GAME_PLAYER_ASSISTS', 'NHL_GAME_PLAYER_BLOCKED_SHOTS'])
181
  if book_select_var == 'ALL':
182
  book_selections = ['BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL']
183
  else:
 
187
  elif game_select_var == 'Pick6':
188
  prop_df = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
189
  book_selections = ['Pick6']
190
+
 
 
 
 
 
 
191
  if game_select_var == 'Aggregate':
192
  prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'NHL_GAME_PLAYER_POINTS', 'NHL_GAME_PLAYER_SHOTS_ON_GOAL', 'NHL_GAME_PLAYER_ASSISTS', 'NHL_GAME_PLAYER_BLOCKED_SHOTS'])
193
  elif game_select_var == 'Pick6':
194
  prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'Points', 'Shots on Goal', 'Assists', 'Blocks'])
195
+ with col4:
196
+ st.download_button(
197
+ label="Download Prop Source",
198
+ data=convert_df_to_csv(prop_df),
199
+ file_name='NHL_prop_source.csv',
200
+ mime='text/csv',
201
+ key='prop_source',
202
+ )
203
+
204
+ if st.button('Simulate Prop Category'):
205
+ with df_hold_container.container():
206
+ if prop_type_var == 'All Props':
207
+
208
+ if game_select_var == 'Aggregate':
209
+ prop_df_raw = prop_trends[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
210
+ sim_vars = ['NHL_GAME_PLAYER_POINTS', 'NHL_GAME_PLAYER_SHOTS_ON_GOAL', 'NHL_GAME_PLAYER_ASSISTS', 'NHL_GAME_PLAYER_BLOCKED_SHOTS']
211
+ elif game_select_var == 'Pick6':
212
+ prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
213
+ sim_vars = ['Points', 'Shots on Goal', 'Assists', 'Blocks']
214
+
215
+ player_df = prop_display.copy()
216
+
217
+ for prop in sim_vars:
218
+
219
+ for books in book_selections:
220
+ prop_df = prop_df_raw[prop_df_raw['prop_type'] == prop]
221
+ prop_df = prop_df[prop_df['book'] == books]
222
+ prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
223
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
224
+ prop_df['Over'] = 1 / prop_df['over_line']
225
+ prop_df['Under'] = 1 / prop_df['under_line']
226
+
227
+ prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
228
+ prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
229
+ book_dict = dict(zip(prop_df.Player, prop_df.book))
230
+ over_dict = dict(zip(prop_df.Player, prop_df.Over))
231
+ under_dict = dict(zip(prop_df.Player, prop_df.Under))
232
+ trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
233
+ trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
234
+
235
+ player_df['book'] = player_df['Player'].map(book_dict)
236
+ player_df['Prop'] = player_df['Player'].map(prop_dict)
237
+ player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
238
+ player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
239
+ player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
240
+
241
+ df = player_df.reset_index(drop=True)
242
+
243
+ team_dict = dict(zip(df.Player, df.Team))
244
+
245
+ total_sims = 1000
246
+
247
+ df.replace("", 0, inplace=True)
248
+
249
+ if prop == 'NHL_GAME_PLAYER_POINTS' or prop == 'Points':
250
+ df['Median'] = df['Player TP']
251
+ elif prop == 'NHL_GAME_PLAYER_SHOTS_ON_GOAL' or prop == 'Shots on Goal':
252
+ df['Median'] = df['Player SOG']
253
+ elif prop == 'NHL_GAME_PLAYER_ASSISTS' or prop == 'Assists':
254
+ df['Median'] = df['Player Assists']
255
+ elif prop == 'NHL_GAME_PLAYER_BLOCKED_SHOTS' or prop == 'Blocks':
256
+ df['Median'] = df['Player Blocks']
257
+
258
+ flex_file = df.copy()
259
+ flex_file['Floor'] = (flex_file['Median'] * .15)
260
+ flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1)
261
+ flex_file['STD'] = (flex_file['Median']/3)
262
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
263
+ flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
264
+
265
+ hold_file = flex_file.copy()
266
+ overall_file = flex_file.copy()
267
+ prop_file = flex_file.copy()
268
 
269
+ overall_players = overall_file[['Player']]
270
+
271
+ for x in range(0,total_sims):
272
+ prop_file[x] = prop_file['Prop']
273
+
274
+ prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
275
+
276
+ for x in range(0,total_sims):
277
+ overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
278
+
279
+ overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
280
+
281
+ players_only = hold_file[['Player']]
282
+
283
+ player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
284
+
285
+ prop_check = (overall_file - prop_file)
286
+
287
+ players_only['Mean_Outcome'] = overall_file.mean(axis=1)
288
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
289
+ players_only['Book'] = players_only['Player'].map(book_dict)
290
+ players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
291
+ players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
292
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
293
+ players_only['10%'] = overall_file.quantile(0.1, axis=1)
294
+ players_only['90%'] = overall_file.quantile(0.9, axis=1)
295
+ players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
296
+ players_only['Imp Over'] = players_only['Player'].map(over_dict)
297
+ players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
298
+ 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))
299
+ players_only['Imp Under'] = players_only['Player'].map(under_dict)
300
+ players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
301
+ players_only['Prop_avg'] = players_only['Prop'].mean() / 100
302
+ players_only['prop_threshold'] = .10
303
+ players_only = players_only[players_only['Mean_Outcome'] > 0]
304
+ players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
305
+ players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
306
+ players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
307
+ players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
308
+ players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
309
+ players_only['Edge'] = players_only['Bet_check']
310
+ players_only['Prop Type'] = prop
311
+
312
+ players_only['Player'] = hold_file[['Player']]
313
+ players_only['Team'] = players_only['Player'].map(team_dict)
314
+
315
+ leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
316
+ sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
317
+
318
+ final_outcomes = sim_all_hold
319
+ st.write(f'finished {prop} for {books}')
320
+
321
+ elif prop_type_var != 'All Props':
322
+
323
+ player_df = prop_display.copy()
324
+
325
+ if game_select_var == 'Aggregate':
326
+ prop_df_raw = prop_trends[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
327
+ elif game_select_var == 'Pick6':
328
+ prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
 
330
+ for books in book_selections:
331
+ prop_df = prop_df_raw[prop_df_raw['book'] == books]
332
+
333
+ if prop_type_var == "NHL_GAME_PLAYER_SHOTS_ON_GOAL":
334
+ prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_SHOTS_ON_GOAL']
335
+ elif prop_type_var == 'Shots on Goal':
336
+ prop_df = prop_df[prop_df['prop_type'] == 'Player SOG']
337
+ elif prop_type_var == "NHL_GAME_PLAYER_POINTS":
338
+ prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_POINTS']
339
+ elif prop_type_var == "Points":
340
+ prop_df = prop_df[prop_df['prop_type'] == 'Player TP']
341
+ elif prop_type_var == "NHL_GAME_PLAYER_ASSISTS":
342
+ prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_ASSISTS']
343
+ elif prop_type_var == "Assists":
344
+ prop_df = prop_df[prop_df['prop_type'] == 'Player Assists']
345
+ elif prop_type_var == "NHL_GAME_PLAYER_BLOCKED_SHOTS":
346
+ prop_df = prop_df[prop_df['prop_type'] == 'NHL_GAME_PLAYER_BLOCKED_SHOTS']
347
+ elif prop_type_var == "Blocks":
348
+ prop_df = prop_df[prop_df['prop_type'] == 'Player Blocks']
349
+
350
+ prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line']]
351
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
352
+ prop_df['Over'] = 1 / prop_df['over_line']
353
+ prop_df['Under'] = 1 / prop_df['under_line']
354
+
355
+ prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
356
+ prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
357
+ book_dict = dict(zip(prop_df.Player, prop_df.book))
358
+ over_dict = dict(zip(prop_df.Player, prop_df.Over))
359
+ under_dict = dict(zip(prop_df.Player, prop_df.Under))
360
+ trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
361
+ trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
362
+
363
+ player_df['book'] = player_df['Player'].map(book_dict)
364
+ player_df['Prop'] = player_df['Player'].map(prop_dict)
365
+ player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
366
+ player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
367
+ player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
368
+
369
+ df = player_df.reset_index(drop=True)
370
+
371
+ team_dict = dict(zip(df.Player, df.Team))
372
+
373
+ total_sims = 1000
374
+
375
+ df.replace("", 0, inplace=True)
376
+
377
+ if prop_type_var == 'NHL_GAME_PLAYER_POINTS' or prop_type_var == 'Points':
378
+ df['Median'] = df['Player TP']
379
+ elif prop_type_var == 'NHL_GAME_PLAYER_SHOTS_ON_GOAL' or prop_type_var == 'Shots on Goal':
380
+ df['Median'] = df['Player SOG']
381
+ elif prop_type_var == 'NHL_GAME_PLAYER_ASSISTS' or prop_type_var == 'Assists':
382
+ df['Median'] = df['Player Assists']
383
+ elif prop_type_var == 'NHL_GAME_PLAYER_BLOCKED_SHOTS' or prop_type_var == 'Blocks':
384
+ df['Median'] = df['Player Blocks']
385
+
386
+ flex_file = df.copy()
387
+ flex_file['Floor'] = (flex_file['Median'] * .15)
388
+ flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1)
389
+ flex_file['STD'] = (flex_file['Median']/3)
390
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
391
+ flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
392
+
393
+ hold_file = flex_file.copy()
394
+ overall_file = flex_file.copy()
395
+ prop_file = flex_file.copy()
396
 
397
+ overall_players = overall_file[['Player']]
398
+
399
+ for x in range(0,total_sims):
400
+ prop_file[x] = prop_file['Prop']
401
+
402
+ prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
403
+
404
+ for x in range(0,total_sims):
405
+ overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
406
+
407
+ overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
408
+
409
+ players_only = hold_file[['Player']]
410
+
411
+ player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
412
+
413
+ prop_check = (overall_file - prop_file)
414
+
415
+ players_only['Mean_Outcome'] = overall_file.mean(axis=1)
416
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
417
+ players_only['Book'] = players_only['Player'].map(book_dict)
418
+ players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
419
+ players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
420
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
421
+ players_only['10%'] = overall_file.quantile(0.1, axis=1)
422
+ players_only['90%'] = overall_file.quantile(0.9, axis=1)
423
+ players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
424
+ players_only['Imp Over'] = players_only['Player'].map(over_dict)
425
+ players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
426
+ 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))
427
+ players_only['Imp Under'] = players_only['Player'].map(under_dict)
428
+ players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
429
+ players_only['Prop_avg'] = players_only['Prop'].mean() / 100
430
+ players_only['prop_threshold'] = .10
431
+ players_only = players_only[players_only['Mean_Outcome'] > 0]
432
+ players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
433
+ players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
434
+ players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
435
+ players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
436
+ players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
437
+ players_only['Edge'] = players_only['Bet_check']
438
+ players_only['Prop Type'] = prop_type_var
439
+
440
+ players_only['Player'] = hold_file[['Player']]
441
+ players_only['Team'] = players_only['Player'].map(team_dict)
442
+
443
+ leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop', 'Prop Type', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
444
+ sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
445
+
446
+ final_outcomes = sim_all_hold
447
+ st.write(f'finished {prop_type_var} for {books}')
448
+
449
+ final_outcomes = final_outcomes[final_outcomes['Prop'] > 0]
450
+ if game_select_var == 'Pick6':
451
+ final_outcomes = final_outcomes.drop_duplicates(subset=['Player', 'Prop Type'])
452
+ final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)
453
+
454
+ with df_hold_container:
455
+ df_hold_container = st.empty()
456
+ st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
457
+ with export_container:
458
+ export_container = st.empty()
459
+ st.download_button(
460
+ label="Export Projections",
461
+ data=convert_df_to_csv(final_outcomes),
462
+ file_name='NHL_prop_proj.csv',
463
+ mime='text/csv',
464
+ key='prop_proj',
465
+ )