James McCool commited on
Commit
578f64b
·
1 Parent(s): 0d91a05

Refactor app.py to streamline data retrieval and processing for 'prop_frame', 'betsheet_frame', and 'pick_frame' by re-enabling MongoDB queries and enhancing data cleaning steps. Update user interface elements for improved clarity and functionality.

Browse files
Files changed (1) hide show
  1. app.py +267 -267
app.py CHANGED
@@ -93,27 +93,27 @@ def init_baselines():
93
  raw_display = pd.DataFrame(cursor)
94
  team_frame = raw_display.drop_duplicates(subset='Names')
95
 
96
- # collection = db['Prop_Trends']
97
- # cursor = collection.find()
98
- # raw_display = pd.DataFrame(cursor)
99
- # raw_display.replace('', np.nan, inplace=True)
100
- # prop_frame = raw_display.dropna(subset='Team')
101
 
102
- # sh = gc.open_by_url(master_hold)
103
- # worksheet = sh.worksheet('Prop_results')
104
- # raw_display = pd.DataFrame(worksheet.get_all_records())
105
- # raw_display.replace('', np.nan, inplace=True)
106
- # betsheet_frame = raw_display.dropna(subset='proj')
107
 
108
- # collection = db['Pick6_Trends']
109
- # cursor = collection.find()
110
- # raw_display = pd.DataFrame(cursor)
111
- # raw_display.replace('', np.nan, inplace=True)
112
- # pick_frame = raw_display.dropna(subset='Player')
113
-
114
- prop_frame = pd.DataFrame()
115
- betsheet_frame = pd.DataFrame()
116
- pick_frame = pd.DataFrame()
117
 
118
  return pitcher_stats, hitter_stats, team_frame, prop_frame, betsheet_frame, pick_frame
119
 
@@ -353,277 +353,277 @@ with tab4:
353
  st.plotly_chart(fig, use_container_width=True)
354
 
355
  with tab5:
356
- st.warning("The prop frame source is currently down, apologies for the inconvenience")
357
- # st.info('The Over and Under percentages are a compositve percentage based on simulations, historical performance, and implied probabilities, and may be different than you would expect based purely on the median projection. Likewise, the Edge of a bet is not the only indicator of if you should make the bet or not as the suggestion is using a base acceptable threshold to determine how much edge you should have for each stat category.')
358
- # if st.button("Reset Data/Load Data", key='reset5'):
359
- # st.cache_data.clear()
360
- # pitcher_stats, hitter_stats, team_frame, prop_frame, pick_frame = init_baselines()
361
- # col1, col2 = st.columns([1, 5])
362
 
363
- # with col2:
364
- # df_hold_container = st.empty()
365
- # info_hold_container = st.empty()
366
- # plot_hold_container = st.empty()
367
- # export_container = st.empty()
368
 
369
- # with col1:
370
- # game_select_var = st.selectbox('Select prop source', options = ['Draftkings', 'Pick6'])
371
- # if game_select_var == 'Draftkings':
372
- # prop_df = prop_frame[['Player', 'over_prop', 'over_line', 'under_line', 'prop_type']]
373
- # working_source = prop_frame.copy
374
- # elif game_select_var == 'Pick6':
375
- # prop_df = pick_frame[['Player', 'over_prop', 'over_line', 'under_line', 'prop_type']]
376
- # working_source = pick_frame.copy()
377
- # st.download_button(
378
- # label="Download Prop Source",
379
- # data=convert_df_to_csv(prop_df),
380
- # file_name='MLB_prop_source.csv',
381
- # mime='text/csv',
382
- # key='prop_source',
383
- # )
384
- # prop_type_var = st.selectbox('Select prop category', options = ['Strikeouts (Pitchers)', 'Total Outs (Pitchers)', 'Earned Runs (Pitchers)', 'Hits Against (Pitchers)',
385
- # 'Walks Allowed (Pitchers)', 'Total Bases (Hitters)', 'Stolen Bases (Hitters)', 'Walks (Hitters)'])
386
-
387
- # if st.button('Simulate Prop Category'):
388
- # with col2:
389
 
390
- # with df_hold_container.container():
391
-
392
- # if prop_type_var == "Strikeouts (Pitchers)":
393
- # player_df = pitcher_stats
394
- # prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_strikeouts']
395
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
396
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
397
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
398
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
399
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
400
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
401
- # elif prop_type_var == "Total Outs (Pitchers)":
402
- # player_df = pitcher_stats
403
- # prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_outs']
404
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
405
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
406
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
407
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
408
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
409
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
410
- # elif prop_type_var == "Earned Runs (Pitchers)":
411
- # player_df = pitcher_stats
412
- # prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_earned_runs']
413
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
414
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
415
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
416
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
417
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
418
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
419
- # elif prop_type_var == "Hits Against (Pitchers)":
420
- # player_df = pitcher_stats
421
- # prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_hits_allowed']
422
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
423
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
424
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
425
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
426
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
427
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
428
- # elif prop_type_var == "Walks Allowed (Pitchers)":
429
- # player_df = pitcher_stats
430
- # prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_walks']
431
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
432
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
433
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
434
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
435
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
436
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
437
- # elif prop_type_var == "Total Bases (Hitters)":
438
- # player_df = hitter_stats
439
- # prop_df = prop_frame[prop_frame['prop_type'] == 'batter_total_bases']
440
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
441
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
442
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
443
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
444
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
445
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
446
- # elif prop_type_var == "Stolen Bases (Hitters)":
447
- # player_df = hitter_stats
448
- # prop_df = prop_frame[prop_frame['prop_type'] == 'batter_stolen_bases']
449
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
450
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
451
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
452
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
453
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
454
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
455
- # elif prop_type_var == "Hits (Hitters)":
456
- # player_df = hitter_stats
457
- # prop_df = prop_frame[prop_frame['prop_type'] == 'batter_hits']
458
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
459
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
460
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
461
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
462
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
463
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
464
- # elif prop_type_var == "Walks (Hitters)":
465
- # player_df = hitter_stats
466
- # prop_df = prop_frame[prop_frame['prop_type'] == 'batter_walks']
467
- # prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
468
- # prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
469
- # prop_df = prop_df.loc[prop_df['Prop'] != 0]
470
- # prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
471
- # prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
472
- # df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
473
 
474
- # prop_dict = dict(zip(df.Player, df.Prop))
475
- # over_dict = dict(zip(df.Player, df.Over))
476
- # under_dict = dict(zip(df.Player, df.Under))
477
 
478
- # total_sims = 1000
479
-
480
- # df.replace("", 0, inplace=True)
481
-
482
- # if prop_type_var == "Strikeouts (Pitchers)":
483
- # df['Median'] = df['Ks']
484
- # elif prop_type_var == "Earned Runs (Pitchers)":
485
- # df['Median'] = df['ERs']
486
- # elif prop_type_var == "Total Outs (Pitchers)":
487
- # df['Median'] = df['Outs']
488
- # elif prop_type_var == "Hits Against (Pitchers)":
489
- # df['Median'] = df['Hits']
490
- # elif prop_type_var == "Walks Allowed (Pitchers)":
491
- # df['Median'] = df['BB']
492
- # elif prop_type_var == "Total Bases (Hitters)":
493
- # df['Median'] = df['Total Bases']
494
- # elif prop_type_var == "Stolen Bases (Hitters)":
495
- # df['Median'] = df['Steals']
496
- # elif prop_type_var == "Hits (Hitters)":
497
- # df['Median'] = df['Hits']
498
- # elif prop_type_var == "Walks (Hitters)":
499
- # df['Median'] = df['Walks']
500
-
501
- # flex_file = df
502
- # if prop_type_var == 'Strikeouts (Pitchers)':
503
- # flex_file['Floor'] = flex_file['Median'] * .20
504
- # flex_file['Ceiling'] = flex_file['Median'] * 1.8
505
- # flex_file['STD'] = flex_file['Median'] / 4
506
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
507
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
508
-
509
- # elif prop_type_var == 'Total Outs (Pitchers)':
510
- # flex_file['Floor'] = flex_file['Median'] * .20
511
- # flex_file['Ceiling'] = flex_file['Median'] * 1.8
512
- # flex_file['STD'] = flex_file['Median'] / 4
513
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
514
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
515
 
516
- # elif prop_type_var == 'Earned Runs (Pitchers)':
517
- # flex_file['Floor'] = flex_file['Median'] * .20
518
- # flex_file['Ceiling'] = flex_file['Median'] * 1.8
519
- # flex_file['STD'] = flex_file['Median'] / 4
520
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
521
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
522
 
523
- # elif prop_type_var == 'Hits Against (Pitchers)':
524
- # flex_file['Floor'] = flex_file['Median'] * .20
525
- # flex_file['Ceiling'] = flex_file['Median'] * 1.8
526
- # flex_file['STD'] = flex_file['Median'] / 4
527
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
528
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
529
 
530
- # elif prop_type_var == 'Walks Allowed (Pitchers)':
531
- # flex_file['Floor'] = flex_file['Median'] * .20
532
- # flex_file['Ceiling'] = flex_file['Median'] * 1.8
533
- # flex_file['STD'] = flex_file['Median'] / 4
534
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
535
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
536
-
537
- # elif prop_type_var == 'Total Bases (Hitters)':
538
- # flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
539
- # flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
540
- # flex_file['STD'] = flex_file['Median'] / 1.5
541
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
542
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
543
-
544
- # elif prop_type_var == 'Stolen Bases (Hitters)':
545
- # flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
546
- # flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
547
- # flex_file['STD'] = flex_file['Median'] / 1.5
548
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
549
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
550
 
551
- # elif prop_type_var == 'Hits (Hitters)':
552
- # flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
553
- # flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
554
- # flex_file['STD'] = flex_file['Median'] / 1.5
555
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
556
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
557
 
558
- # elif prop_type_var == 'Walks (Hitters)':
559
- # flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
560
- # flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
561
- # flex_file['STD'] = flex_file['Median'] / 1.5
562
- # flex_file['Prop'] = flex_file['Player'].map(prop_dict)
563
- # flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
564
-
565
- # hold_file = flex_file
566
- # overall_file = flex_file
567
- # prop_file = flex_file
568
 
569
- # overall_players = overall_file[['Player']]
570
 
571
- # for x in range(0,total_sims):
572
- # prop_file[x] = prop_file['Prop']
573
 
574
- # prop_file = prop_file.drop(['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
575
 
576
- # for x in range(0,total_sims):
577
- # overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
578
 
579
- # overall_file=overall_file.drop(['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
580
 
581
- # players_only = hold_file[['Player']]
582
 
583
- # player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
584
 
585
- # prop_check = (overall_file - prop_file)
586
 
587
- # players_only['Mean_Outcome'] = overall_file.mean(axis=1)
588
- # players_only['10%'] = overall_file.quantile(0.1, axis=1)
589
- # players_only['90%'] = overall_file.quantile(0.9, axis=1)
590
- # players_only['Over'] = prop_check[prop_check > 0].count(axis=1)/float(total_sims)
591
- # players_only['Imp Over'] = players_only['Player'].map(over_dict)
592
- # players_only['Over%'] = players_only[["Over", "Imp Over"]].mean(axis=1)
593
- # players_only['Under'] = prop_check[prop_check < 0].count(axis=1)/float(total_sims)
594
- # players_only['Imp Under'] = players_only['Player'].map(under_dict)
595
- # players_only['Under%'] = players_only[["Under", "Imp Under"]].mean(axis=1)
596
- # players_only['Prop'] = players_only['Player'].map(prop_dict)
597
- # players_only['Prop_avg'] = players_only['Prop'].mean() / 100
598
- # players_only['prop_threshold'] = .10
599
- # players_only = players_only.loc[players_only['Mean_Outcome'] > 0]
600
- # players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
601
- # players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
602
- # players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
603
- # players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
604
- # players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
605
- # players_only['Edge'] = players_only['Bet_check']
606
 
607
- # players_only['Player'] = hold_file[['Player']]
608
 
609
- # final_outcomes = players_only[['Player', 'Prop', 'Mean_Outcome', 'Imp Over', 'Over%', 'Imp Under', 'Under%', 'Bet?', 'Edge']]
610
 
611
- # final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)
612
 
613
- # final_outcomes = final_outcomes.set_index('Player')
614
-
615
- # with df_hold_container:
616
- # df_hold_container = st.empty()
617
- # st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
618
- # with export_container:
619
- # export_container = st.empty()
620
- # st.download_button(
621
- # label="Export Projections",
622
- # data=convert_df_to_csv(final_outcomes),
623
- # file_name='MLB_DFS_prop_proj.csv',
624
- # mime='text/csv',
625
- # key='prop_proj',
626
- # )
627
 
628
  with tab6:
629
  st.info("This sheet is currently under reconstruction, it'll be back soon!")
 
93
  raw_display = pd.DataFrame(cursor)
94
  team_frame = raw_display.drop_duplicates(subset='Names')
95
 
96
+ collection = db['Prop_Trends']
97
+ cursor = collection.find()
98
+ raw_display = pd.DataFrame(cursor)
99
+ raw_display.replace('', np.nan, inplace=True)
100
+ prop_frame = raw_display.dropna(subset='Team')
101
 
102
+ sh = gc.open_by_url(master_hold)
103
+ worksheet = sh.worksheet('Prop_results')
104
+ raw_display = pd.DataFrame(worksheet.get_all_records())
105
+ raw_display.replace('', np.nan, inplace=True)
106
+ betsheet_frame = raw_display.dropna(subset='proj')
107
 
108
+ collection = db['Pick6_Trends']
109
+ cursor = collection.find()
110
+ raw_display = pd.DataFrame(cursor)
111
+ raw_display.replace('', np.nan, inplace=True)
112
+ pick_frame = raw_display.dropna(subset='Player')
113
+
114
+ # prop_frame = pd.DataFrame()
115
+ # betsheet_frame = pd.DataFrame()
116
+ # pick_frame = pd.DataFrame()
117
 
118
  return pitcher_stats, hitter_stats, team_frame, prop_frame, betsheet_frame, pick_frame
119
 
 
353
  st.plotly_chart(fig, use_container_width=True)
354
 
355
  with tab5:
356
+ # st.warning("The prop frame source is currently down, apologies for the inconvenience")
357
+ st.info('The Over and Under percentages are a compositve percentage based on simulations, historical performance, and implied probabilities, and may be different than you would expect based purely on the median projection. Likewise, the Edge of a bet is not the only indicator of if you should make the bet or not as the suggestion is using a base acceptable threshold to determine how much edge you should have for each stat category.')
358
+ if st.button("Reset Data/Load Data", key='reset5'):
359
+ st.cache_data.clear()
360
+ pitcher_stats, hitter_stats, team_frame, prop_frame, pick_frame = init_baselines()
361
+ col1, col2 = st.columns([1, 5])
362
 
363
+ with col2:
364
+ df_hold_container = st.empty()
365
+ info_hold_container = st.empty()
366
+ plot_hold_container = st.empty()
367
+ export_container = st.empty()
368
 
369
+ with col1:
370
+ game_select_var = st.selectbox('Select prop source', options = ['Draftkings', 'Pick6'])
371
+ if game_select_var == 'Draftkings':
372
+ prop_df = prop_frame[['Player', 'over_prop', 'over_line', 'under_line', 'prop_type']]
373
+ working_source = prop_frame.copy
374
+ elif game_select_var == 'Pick6':
375
+ prop_df = pick_frame[['Player', 'over_prop', 'over_line', 'under_line', 'prop_type']]
376
+ working_source = pick_frame.copy()
377
+ st.download_button(
378
+ label="Download Prop Source",
379
+ data=convert_df_to_csv(prop_df),
380
+ file_name='MLB_prop_source.csv',
381
+ mime='text/csv',
382
+ key='prop_source',
383
+ )
384
+ prop_type_var = st.selectbox('Select prop category', options = ['Strikeouts (Pitchers)', 'Total Outs (Pitchers)', 'Earned Runs (Pitchers)', 'Hits Against (Pitchers)',
385
+ 'Walks Allowed (Pitchers)', 'Total Bases (Hitters)', 'Stolen Bases (Hitters)', 'Walks (Hitters)'])
386
+
387
+ if st.button('Simulate Prop Category'):
388
+ with col2:
389
 
390
+ with df_hold_container.container():
391
+
392
+ if prop_type_var == "Strikeouts (Pitchers)":
393
+ player_df = pitcher_stats
394
+ prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_strikeouts']
395
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
396
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
397
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
398
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
399
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
400
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
401
+ elif prop_type_var == "Total Outs (Pitchers)":
402
+ player_df = pitcher_stats
403
+ prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_outs']
404
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
405
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
406
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
407
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
408
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
409
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
410
+ elif prop_type_var == "Earned Runs (Pitchers)":
411
+ player_df = pitcher_stats
412
+ prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_earned_runs']
413
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
414
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
415
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
416
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
417
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
418
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
419
+ elif prop_type_var == "Hits Against (Pitchers)":
420
+ player_df = pitcher_stats
421
+ prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_hits_allowed']
422
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
423
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
424
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
425
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
426
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
427
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
428
+ elif prop_type_var == "Walks Allowed (Pitchers)":
429
+ player_df = pitcher_stats
430
+ prop_df = prop_frame[prop_frame['prop_type'] == 'pitcher_walks']
431
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
432
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
433
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
434
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
435
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
436
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
437
+ elif prop_type_var == "Total Bases (Hitters)":
438
+ player_df = hitter_stats
439
+ prop_df = prop_frame[prop_frame['prop_type'] == 'batter_total_bases']
440
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
441
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
442
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
443
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
444
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
445
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
446
+ elif prop_type_var == "Stolen Bases (Hitters)":
447
+ player_df = hitter_stats
448
+ prop_df = prop_frame[prop_frame['prop_type'] == 'batter_stolen_bases']
449
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
450
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
451
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
452
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
453
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
454
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
455
+ elif prop_type_var == "Hits (Hitters)":
456
+ player_df = hitter_stats
457
+ prop_df = prop_frame[prop_frame['prop_type'] == 'batter_hits']
458
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
459
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
460
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
461
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
462
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
463
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
464
+ elif prop_type_var == "Walks (Hitters)":
465
+ player_df = hitter_stats
466
+ prop_df = prop_frame[prop_frame['prop_type'] == 'batter_walks']
467
+ prop_df = prop_df[['Player', 'over_prop', 'over_line', 'under_line']]
468
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
469
+ prop_df = prop_df.loc[prop_df['Prop'] != 0]
470
+ prop_df['Over'] = np.where(prop_df['over_line'] < 0, (-(prop_df['over_line'])/((-(prop_df['over_line']))+100)), 100/(prop_df['over_line']+100))
471
+ prop_df['Under'] = np.where(prop_df['under_line'] < 0, (-(prop_df['under_line'])/((-(prop_df['under_line']))+100)), 100/(prop_df['under_line']+100))
472
+ df = pd.merge(player_df, prop_df, how='left', left_on=['Player'], right_on = ['Player'])
473
 
474
+ prop_dict = dict(zip(df.Player, df.Prop))
475
+ over_dict = dict(zip(df.Player, df.Over))
476
+ under_dict = dict(zip(df.Player, df.Under))
477
 
478
+ total_sims = 1000
479
+
480
+ df.replace("", 0, inplace=True)
481
+
482
+ if prop_type_var == "Strikeouts (Pitchers)":
483
+ df['Median'] = df['Ks']
484
+ elif prop_type_var == "Earned Runs (Pitchers)":
485
+ df['Median'] = df['ERs']
486
+ elif prop_type_var == "Total Outs (Pitchers)":
487
+ df['Median'] = df['Outs']
488
+ elif prop_type_var == "Hits Against (Pitchers)":
489
+ df['Median'] = df['Hits']
490
+ elif prop_type_var == "Walks Allowed (Pitchers)":
491
+ df['Median'] = df['BB']
492
+ elif prop_type_var == "Total Bases (Hitters)":
493
+ df['Median'] = df['Total Bases']
494
+ elif prop_type_var == "Stolen Bases (Hitters)":
495
+ df['Median'] = df['Steals']
496
+ elif prop_type_var == "Hits (Hitters)":
497
+ df['Median'] = df['Hits']
498
+ elif prop_type_var == "Walks (Hitters)":
499
+ df['Median'] = df['Walks']
500
+
501
+ flex_file = df
502
+ if prop_type_var == 'Strikeouts (Pitchers)':
503
+ flex_file['Floor'] = flex_file['Median'] * .20
504
+ flex_file['Ceiling'] = flex_file['Median'] * 1.8
505
+ flex_file['STD'] = flex_file['Median'] / 4
506
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
507
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
508
+
509
+ elif prop_type_var == 'Total Outs (Pitchers)':
510
+ flex_file['Floor'] = flex_file['Median'] * .20
511
+ flex_file['Ceiling'] = flex_file['Median'] * 1.8
512
+ flex_file['STD'] = flex_file['Median'] / 4
513
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
514
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
515
 
516
+ elif prop_type_var == 'Earned Runs (Pitchers)':
517
+ flex_file['Floor'] = flex_file['Median'] * .20
518
+ flex_file['Ceiling'] = flex_file['Median'] * 1.8
519
+ flex_file['STD'] = flex_file['Median'] / 4
520
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
521
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
522
 
523
+ elif prop_type_var == 'Hits Against (Pitchers)':
524
+ flex_file['Floor'] = flex_file['Median'] * .20
525
+ flex_file['Ceiling'] = flex_file['Median'] * 1.8
526
+ flex_file['STD'] = flex_file['Median'] / 4
527
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
528
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
529
 
530
+ elif prop_type_var == 'Walks Allowed (Pitchers)':
531
+ flex_file['Floor'] = flex_file['Median'] * .20
532
+ flex_file['Ceiling'] = flex_file['Median'] * 1.8
533
+ flex_file['STD'] = flex_file['Median'] / 4
534
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
535
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
536
+
537
+ elif prop_type_var == 'Total Bases (Hitters)':
538
+ flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
539
+ flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
540
+ flex_file['STD'] = flex_file['Median'] / 1.5
541
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
542
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
543
+
544
+ elif prop_type_var == 'Stolen Bases (Hitters)':
545
+ flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
546
+ flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
547
+ flex_file['STD'] = flex_file['Median'] / 1.5
548
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
549
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
550
 
551
+ elif prop_type_var == 'Hits (Hitters)':
552
+ flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
553
+ flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
554
+ flex_file['STD'] = flex_file['Median'] / 1.5
555
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
556
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
557
 
558
+ elif prop_type_var == 'Walks (Hitters)':
559
+ flex_file['Floor'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * .20, 0)
560
+ flex_file['Ceiling'] = np.where((prop_type_var == "Fantasy") | (prop_type_var == "FD_Fantasy") | (prop_type_var == "PrizePicks"), flex_file['Median'] * 1.8, flex_file['Median'] * 4)
561
+ flex_file['STD'] = flex_file['Median'] / 1.5
562
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
563
+ flex_file = flex_file[['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
564
+
565
+ hold_file = flex_file
566
+ overall_file = flex_file
567
+ prop_file = flex_file
568
 
569
+ overall_players = overall_file[['Player']]
570
 
571
+ for x in range(0,total_sims):
572
+ prop_file[x] = prop_file['Prop']
573
 
574
+ prop_file = prop_file.drop(['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
575
 
576
+ for x in range(0,total_sims):
577
+ overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
578
 
579
+ overall_file=overall_file.drop(['Player', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
580
 
581
+ players_only = hold_file[['Player']]
582
 
583
+ player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
584
 
585
+ prop_check = (overall_file - prop_file)
586
 
587
+ players_only['Mean_Outcome'] = overall_file.mean(axis=1)
588
+ players_only['10%'] = overall_file.quantile(0.1, axis=1)
589
+ players_only['90%'] = overall_file.quantile(0.9, axis=1)
590
+ players_only['Over'] = prop_check[prop_check > 0].count(axis=1)/float(total_sims)
591
+ players_only['Imp Over'] = players_only['Player'].map(over_dict)
592
+ players_only['Over%'] = players_only[["Over", "Imp Over"]].mean(axis=1)
593
+ players_only['Under'] = prop_check[prop_check < 0].count(axis=1)/float(total_sims)
594
+ players_only['Imp Under'] = players_only['Player'].map(under_dict)
595
+ players_only['Under%'] = players_only[["Under", "Imp Under"]].mean(axis=1)
596
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
597
+ players_only['Prop_avg'] = players_only['Prop'].mean() / 100
598
+ players_only['prop_threshold'] = .10
599
+ players_only = players_only.loc[players_only['Mean_Outcome'] > 0]
600
+ players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
601
+ players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
602
+ players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
603
+ players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
604
+ players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
605
+ players_only['Edge'] = players_only['Bet_check']
606
 
607
+ players_only['Player'] = hold_file[['Player']]
608
 
609
+ final_outcomes = players_only[['Player', 'Prop', 'Mean_Outcome', 'Imp Over', 'Over%', 'Imp Under', 'Under%', 'Bet?', 'Edge']]
610
 
611
+ final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)
612
 
613
+ final_outcomes = final_outcomes.set_index('Player')
614
+
615
+ with df_hold_container:
616
+ df_hold_container = st.empty()
617
+ st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
618
+ with export_container:
619
+ export_container = st.empty()
620
+ st.download_button(
621
+ label="Export Projections",
622
+ data=convert_df_to_csv(final_outcomes),
623
+ file_name='MLB_DFS_prop_proj.csv',
624
+ mime='text/csv',
625
+ key='prop_proj',
626
+ )
627
 
628
  with tab6:
629
  st.info("This sheet is currently under reconstruction, it'll be back soon!")