James McCool commited on
Commit
b3b3746
·
1 Parent(s): 1210272

Enhance NBA player prop simulation interface by restructuring layout and adding new settings container. Introduced 'Imp Over' and 'Imp Under' metrics for improved analysis, and refined data handling for prop categories. Updated DataFrame calculations to streamline simulation processes and ensure accurate projections.

Browse files
Files changed (1) hide show
  1. app.py +327 -324
app.py CHANGED
@@ -65,6 +65,7 @@ gcservice_account, gcservice_account2, db, prop_db, NBA_Data = init_conn()
65
  game_format = {'Paydirt Win%': '{:.2%}', 'Vegas Win%': '{:.2%}'}
66
  prop_format = {'L5 Success': '{:.2%}', 'L10_Success': '{:.2%}', 'L20_success': '{:.2%}', 'Matchup Boost': '{:.2%}', 'Trending Over': '{:.2%}', 'Trending Under': '{:.2%}',
67
  'Implied Over': '{:.2%}', 'Implied Under': '{:.2%}', 'Over Edge': '{:.2%}', 'Under Edge': '{:.2%}'}
 
68
  prop_table_options = ['NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']
69
  all_sim_vars = ['NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']
70
  pick6_sim_vars = ['Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds']
@@ -461,332 +462,334 @@ with tab6:
461
  st.cache_data.clear()
462
  game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()
463
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
464
- col1, col2 = st.columns([1, 5])
465
-
466
- with col2:
467
- df_hold_container = st.empty()
468
- info_hold_container = st.empty()
469
- plot_hold_container = st.empty()
470
- export_container = st.empty()
471
 
472
- with col1:
473
- game_select_var = st.selectbox('Select prop source', options = ['Aggregate', 'Pick6'])
474
- book_select_var = st.selectbox('Select book', options = ['ALL', 'BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL'])
475
- if book_select_var == 'ALL':
476
- book_selections = ['BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL']
477
- else:
478
- book_selections = [book_select_var]
479
- if game_select_var == 'Aggregate':
480
- prop_df = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
481
- elif game_select_var == 'Pick6':
482
- prop_df = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
483
- book_selections = ['Pick6']
484
- st.download_button(
485
- label="Download Prop Source",
486
- data=convert_df_to_csv(prop_df),
487
- file_name='Nba_prop_source.csv',
488
- mime='text/csv',
489
- key='prop_source',
490
- )
491
- if game_select_var == 'Aggregate':
492
- prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS',
493
- 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_3_POINTERS_MADE'])
494
- elif game_select_var == 'Pick6':
495
- prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds', '3-Pointers Made'])
496
-
497
- if st.button('Simulate Prop Category'):
498
- with col2:
 
 
 
499
 
500
- with df_hold_container.container():
501
- if prop_type_var == 'All Props':
502
- if game_select_var == 'Aggregate':
503
- prop_df_raw = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
504
- sim_vars = ['NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS',
505
- 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_3_POINTERS_MADE']
506
- elif game_select_var == 'Pick6':
507
- prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
508
- sim_vars = ['Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds', '3-Pointers Made']
509
-
510
- player_df = player_stats.copy()
511
-
512
- for prop in sim_vars:
513
-
514
- for books in book_selections:
515
- prop_df = prop_df_raw[prop_df_raw['prop_type'] == prop]
516
- prop_df = prop_df[prop_df['book'] == books]
517
- prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
518
- prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
519
- prop_df['Over'] = 1 / prop_df['over_line']
520
- prop_df['Under'] = 1 / prop_df['under_line']
521
-
522
- prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
523
- prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
524
- book_dict = dict(zip(prop_df.Player, prop_df.book))
525
- over_dict = dict(zip(prop_df.Player, prop_df.Over))
526
- under_dict = dict(zip(prop_df.Player, prop_df.Under))
527
- trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
528
- trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
529
-
530
- player_df['book'] = player_df['Player'].map(book_dict)
531
- player_df['Prop'] = player_df['Player'].map(prop_dict)
532
- player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
533
- player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
534
- player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
535
-
536
- df = player_df.reset_index(drop=True)
537
-
538
- team_dict = dict(zip(df.Player, df.Team))
539
-
540
- total_sims = 1000
541
-
542
- df.replace("", 0, inplace=True)
543
-
544
- if prop == "NBA_GAME_PLAYER_POINTS" or prop == "Points":
545
- df['Median'] = df['Points']
546
- elif prop == "NBA_GAME_PLAYER_REBOUNDS" or prop == "Rebounds":
547
- df['Median'] = df['Rebounds']
548
- elif prop == "NBA_GAME_PLAYER_ASSISTS" or prop == "Assists":
549
- df['Median'] = df['Assists']
550
- elif prop == "NBA_GAME_PLAYER_3_POINTERS_MADE" or prop == "3-Pointers Made":
551
- df['Median'] = df['3P']
552
- elif prop == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS" or prop == "Points + Assists + Rebounds":
553
- df['Median'] = df['Points'] + df['Rebounds'] + df['Assists']
554
- elif prop == "NBA_GAME_PLAYER_POINTS_REBOUNDS" or prop == "Points + Rebounds":
555
- df['Median'] = df['Points'] + df['Rebounds']
556
- elif prop == "NBA_GAME_PLAYER_POINTS_ASSISTS" or prop == "Points + Assists":
557
- df['Median'] = df['Points'] + df['Assists']
558
- elif prop == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS" or prop == "Assists + Rebounds":
559
- df['Median'] = df['Rebounds'] + df['Assists']
560
-
561
- flex_file = df.copy()
562
- flex_file['Floor'] = flex_file['Median'] * .25
563
- flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1.75)
564
- flex_file['STD'] = flex_file['Median'] / 4
565
- flex_file['Prop'] = flex_file['Player'].map(prop_dict)
566
- flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
567
-
568
- hold_file = flex_file.copy()
569
- overall_file = flex_file.copy()
570
- prop_file = flex_file.copy()
571
-
572
- overall_players = overall_file[['Player']]
573
-
574
- for x in range(0,total_sims):
575
- prop_file[x] = prop_file['Prop']
576
-
577
- prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
578
-
579
- for x in range(0,total_sims):
580
- overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
581
-
582
- overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
583
-
584
- players_only = hold_file[['Player']]
585
-
586
- player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
587
-
588
- prop_check = (overall_file - prop_file)
589
-
590
- players_only['Mean_Outcome'] = overall_file.mean(axis=1)
591
- players_only['Book'] = players_only['Player'].map(book_dict)
592
- players_only['Prop'] = players_only['Player'].map(prop_dict)
593
- players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
594
- players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
595
- players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
596
- players_only['10%'] = overall_file.quantile(0.1, axis=1)
597
- players_only['90%'] = overall_file.quantile(0.9, axis=1)
598
- players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
599
- players_only['Imp Over'] = players_only['Player'].map(over_dict)
600
- players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
601
- 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))
602
- players_only['Imp Under'] = players_only['Player'].map(under_dict)
603
- players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
604
- players_only['Prop_avg'] = players_only['Prop'].mean() / 100
605
- players_only['prop_threshold'] = .10
606
- players_only = players_only[players_only['Mean_Outcome'] > 0]
607
- players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
608
- players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
609
- players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
610
- players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
611
- players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
612
- players_only['Edge'] = players_only['Bet_check']
613
- players_only['Prop Type'] = prop
614
-
615
- players_only['Player'] = hold_file[['Player']]
616
- players_only['Team'] = players_only['Player'].map(team_dict)
617
-
618
- leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
619
- sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
620
-
621
- final_outcomes = sim_all_hold
622
- st.write(f'finished {prop} for {books}')
623
-
624
- elif prop_type_var != 'All Props':
625
-
626
- player_df = player_stats.copy()
627
 
628
- if game_select_var == 'Aggregate':
629
- prop_df_raw = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
630
- elif game_select_var == 'Pick6':
631
- prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
632
-
633
- for books in book_selections:
634
- prop_df = prop_df_raw[prop_df_raw['book'] == books]
635
-
636
- if prop_type_var == "NBA_GAME_PLAYER_POINTS":
637
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS']
638
- elif prop_type_var == "Points":
639
- prop_df = prop_df[prop_df['prop_type'] == 'Points']
640
- elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS":
641
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_REBOUNDS']
642
- elif prop_type_var == "Rebounds":
643
- prop_df = prop_df[prop_df['prop_type'] == 'Rebounds']
644
- elif prop_type_var == "NBA_GAME_PLAYER_ASSISTS":
645
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_ASSISTS']
646
- elif prop_type_var == "Assists":
647
- prop_df = prop_df[prop_df['prop_type'] == 'Assists']
648
- elif prop_type_var == "NBA_GAME_PLAYER_3_POINTERS_MADE":
649
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_3_POINTERS_MADE']
650
- elif prop_type_var == "3-Pointers Made":
651
- prop_df = prop_df[prop_df['prop_type'] == '3-Pointers Made']
652
- elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS":
653
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS']
654
- elif prop_type_var == "Points + Assists + Rebounds":
655
- prop_df = prop_df[prop_df['prop_type'] == 'Points + Assists + Rebounds']
656
- elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS":
657
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_REBOUNDS']
658
- elif prop_type_var == "Points + Rebounds":
659
- prop_df = prop_df[prop_df['prop_type'] == 'Points + Rebounds']
660
- elif prop_type_var == "NBA_GAME_PLAYER_POINTS_ASSISTS":
661
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_ASSISTS']
662
- elif prop_type_var == "Points + Assists":
663
- prop_df = prop_df[prop_df['prop_type'] == 'Points + Assists']
664
- elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS":
665
- prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']
666
- elif prop_type_var == "Assists + Rebounds":
667
- prop_df = prop_df[prop_df['prop_type'] == 'Assists + Rebounds']
668
-
669
- prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
670
- prop_df = prop_df.rename(columns={"over_prop": "Prop"})
671
- prop_df['Over'] = 1 / prop_df['over_line']
672
- prop_df['Under'] = 1 / prop_df['under_line']
673
-
674
- prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
675
- prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
676
- book_dict = dict(zip(prop_df.Player, prop_df.book))
677
- over_dict = dict(zip(prop_df.Player, prop_df.Over))
678
- under_dict = dict(zip(prop_df.Player, prop_df.Under))
679
- trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
680
- trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
681
-
682
- player_df['book'] = player_df['Player'].map(book_dict)
683
- player_df['Prop'] = player_df['Player'].map(prop_dict)
684
- player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
685
- player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
686
- player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
687
-
688
- df = player_df.reset_index(drop=True)
689
-
690
- team_dict = dict(zip(df.Player, df.Team))
691
-
692
- total_sims = 1000
693
-
694
- df.replace("", 0, inplace=True)
695
-
696
- if prop_type_var == "NBA_GAME_PLAYER_POINTS" or prop_type_var == "Points":
697
- df['Median'] = df['Points']
698
- elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS" or prop_type_var == "Rebounds":
699
- df['Median'] = df['Rebounds']
700
- elif prop_type_var == "NBA_GAME_PLAYER_ASSISTS" or prop_type_var == "Assists":
701
- df['Median'] = df['Assists']
702
- elif prop_type_var == "NBA_GAME_PLAYER_3_POINTERS_MADE" or prop_type_var == "3-Pointers Made":
703
- df['Median'] = df['3P']
704
- elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS" or prop_type_var == "Points + Assists + Rebounds":
705
- df['Median'] = df['Points'] + df['Rebounds'] + df['Assists']
706
- elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS" or prop_type_var == "Points + Rebounds":
707
- df['Median'] = df['Points'] + df['Rebounds']
708
- elif prop_type_var == "NBA_GAME_PLAYER_POINTS_ASSISTS" or prop_type_var == "Points + Assists":
709
- df['Median'] = df['Points'] + df['Assists']
710
- elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS" or prop_type_var == "Assists + Rebounds":
711
- df['Median'] = df['Rebounds'] + df['Assists']
712
-
713
- flex_file = df.copy()
714
- flex_file['Floor'] = flex_file['Median'] * .25
715
- flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1.75)
716
- flex_file['STD'] = flex_file['Median'] / 4
717
- flex_file['Prop'] = flex_file['Player'].map(prop_dict)
718
- flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
719
-
720
- hold_file = flex_file.copy()
721
- overall_file = flex_file.copy()
722
- prop_file = flex_file.copy()
723
-
724
- overall_players = overall_file[['Player']]
725
-
726
- for x in range(0,total_sims):
727
- prop_file[x] = prop_file['Prop']
728
-
729
- prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
730
-
731
- for x in range(0,total_sims):
732
- overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
733
-
734
- overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
735
-
736
- players_only = hold_file[['Player']]
737
-
738
- player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
739
-
740
- prop_check = (overall_file - prop_file)
741
-
742
- players_only['Mean_Outcome'] = overall_file.mean(axis=1)
743
- players_only['Book'] = players_only['Player'].map(book_dict)
744
- players_only['Prop'] = players_only['Player'].map(prop_dict)
745
- players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
746
- players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
747
- players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
748
- players_only['10%'] = overall_file.quantile(0.1, axis=1)
749
- players_only['90%'] = overall_file.quantile(0.9, axis=1)
750
- players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
751
- players_only['Imp Over'] = players_only['Player'].map(over_dict)
752
- players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
753
- 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))
754
- players_only['Imp Under'] = players_only['Player'].map(under_dict)
755
- players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
756
- players_only['Prop_avg'] = players_only['Prop'].mean() / 100
757
- players_only['prop_threshold'] = .10
758
- players_only = players_only[players_only['Mean_Outcome'] > 0]
759
- players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
760
- players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
761
- players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
762
- players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
763
- players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
764
- players_only['Edge'] = players_only['Bet_check']
765
- players_only['Prop Type'] = prop_type_var
766
-
767
- players_only['Player'] = hold_file[['Player']]
768
- players_only['Team'] = players_only['Player'].map(team_dict)
769
-
770
- leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
771
- sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
772
 
773
- final_outcomes = sim_all_hold
774
- st.write(f'finished {prop_type_var} for {books}')
775
-
776
- final_outcomes = final_outcomes.dropna()
777
- if game_select_var == 'Pick6':
778
- final_outcomes = final_outcomes.drop_duplicates(subset=['Player', 'Prop Type'])
779
- final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)
780
 
781
- with df_hold_container:
782
- df_hold_container = st.empty()
783
- st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
784
- with export_container:
785
- export_container = st.empty()
786
- st.download_button(
787
- label="Export Projections",
788
- data=convert_df_to_csv(final_outcomes),
789
- file_name='NBA_prop_proj.csv',
790
- mime='text/csv',
791
- key='prop_proj',
792
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  game_format = {'Paydirt Win%': '{:.2%}', 'Vegas Win%': '{:.2%}'}
66
  prop_format = {'L5 Success': '{:.2%}', 'L10_Success': '{:.2%}', 'L20_success': '{:.2%}', 'Matchup Boost': '{:.2%}', 'Trending Over': '{:.2%}', 'Trending Under': '{:.2%}',
67
  'Implied Over': '{:.2%}', 'Implied Under': '{:.2%}', 'Over Edge': '{:.2%}', 'Under Edge': '{:.2%}'}
68
+ sim_format = {'Trending Over': '{:.2%}', 'Trending Under': '{:.2%}', 'Imp Over': '{:.2%}', 'Imp Under': '{:.2%}', 'Over%': '{:.2%}', 'Under%': '{:.2%}', 'Edge': '{:.2%}'}
69
  prop_table_options = ['NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']
70
  all_sim_vars = ['NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']
71
  pick6_sim_vars = ['Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds']
 
462
  st.cache_data.clear()
463
  game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()
464
  t_stamp = f"Last Update: " + str(timestamp) + f" CST"
465
+
466
+ df_hold_container = st.empty()
467
+ info_hold_container = st.empty()
468
+ plot_hold_container = st.empty()
469
+ export_container = st.empty()
470
+ settings_container = st.empty()
 
471
 
472
+ with settings_container.container():
473
+ col1, col2, col3, col4 = st.columns([3, 3, 3, 3])
474
+ with col1:
475
+ game_select_var = st.selectbox('Select prop source', options = ['Aggregate', 'Pick6'])
476
+ with col2:
477
+ book_select_var = st.selectbox('Select book', options = ['ALL', 'BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL'])
478
+ if book_select_var == 'ALL':
479
+ book_selections = ['BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL']
480
+ else:
481
+ book_selections = [book_select_var]
482
+ if game_select_var == 'Aggregate':
483
+ prop_df = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
484
+ elif game_select_var == 'Pick6':
485
+ prop_df = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
486
+ book_selections = ['Pick6']
487
+ with col3:
488
+ if game_select_var == 'Aggregate':
489
+ prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS',
490
+ 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_3_POINTERS_MADE'])
491
+ elif game_select_var == 'Pick6':
492
+ prop_type_var = st.selectbox('Select prop category', options = ['All Props', 'Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds', '3-Pointers Made'])
493
+ with col4:
494
+ st.download_button(
495
+ label="Download Prop Source",
496
+ data=convert_df_to_csv(prop_df),
497
+ file_name='Nba_prop_source.csv',
498
+ mime='text/csv',
499
+ key='prop_source',
500
+ )
501
+ if st.button('Simulate Prop Category'):
502
 
503
+ with df_hold_container.container():
504
+ if prop_type_var == 'All Props':
505
+ if game_select_var == 'Aggregate':
506
+ prop_df_raw = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
507
+ sim_vars = ['NBA_GAME_PLAYER_POINTS', 'NBA_GAME_PLAYER_REBOUNDS', 'NBA_GAME_PLAYER_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_POINTS_REBOUNDS',
508
+ 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_3_POINTERS_MADE']
509
+ elif game_select_var == 'Pick6':
510
+ prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
511
+ sim_vars = ['Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds', '3-Pointers Made']
512
+
513
+ player_df = player_stats.copy()
514
+
515
+ for prop in sim_vars:
516
+
517
+ for books in book_selections:
518
+ prop_df = prop_df_raw[prop_df_raw['prop_type'] == prop]
519
+ prop_df = prop_df[prop_df['book'] == books]
520
+ prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
521
+ prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)
522
+ prop_df['Over'] = 1 / prop_df['over_line']
523
+ prop_df['Under'] = 1 / prop_df['under_line']
524
+
525
+ prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
526
+ prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
527
+ book_dict = dict(zip(prop_df.Player, prop_df.book))
528
+ over_dict = dict(zip(prop_df.Player, prop_df.Over))
529
+ under_dict = dict(zip(prop_df.Player, prop_df.Under))
530
+ trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
531
+ trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
532
+
533
+ player_df['book'] = player_df['Player'].map(book_dict)
534
+ player_df['Prop'] = player_df['Player'].map(prop_dict)
535
+ player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
536
+ player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
537
+ player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
538
+
539
+ df = player_df.reset_index(drop=True)
540
+
541
+ team_dict = dict(zip(df.Player, df.Team))
542
+
543
+ total_sims = 1000
544
+
545
+ df.replace("", 0, inplace=True)
546
+
547
+ if prop == "NBA_GAME_PLAYER_POINTS" or prop == "Points":
548
+ df['Median'] = df['Points']
549
+ elif prop == "NBA_GAME_PLAYER_REBOUNDS" or prop == "Rebounds":
550
+ df['Median'] = df['Rebounds']
551
+ elif prop == "NBA_GAME_PLAYER_ASSISTS" or prop == "Assists":
552
+ df['Median'] = df['Assists']
553
+ elif prop == "NBA_GAME_PLAYER_3_POINTERS_MADE" or prop == "3-Pointers Made":
554
+ df['Median'] = df['3P']
555
+ elif prop == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS" or prop == "Points + Assists + Rebounds":
556
+ df['Median'] = df['Points'] + df['Rebounds'] + df['Assists']
557
+ elif prop == "NBA_GAME_PLAYER_POINTS_REBOUNDS" or prop == "Points + Rebounds":
558
+ df['Median'] = df['Points'] + df['Rebounds']
559
+ elif prop == "NBA_GAME_PLAYER_POINTS_ASSISTS" or prop == "Points + Assists":
560
+ df['Median'] = df['Points'] + df['Assists']
561
+ elif prop == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS" or prop == "Assists + Rebounds":
562
+ df['Median'] = df['Rebounds'] + df['Assists']
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
 
564
+ flex_file = df.copy()
565
+ flex_file['Floor'] = flex_file['Median'] * .25
566
+ flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1.75)
567
+ flex_file['STD'] = flex_file['Median'] / 4
568
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
569
+ flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
570
+
571
+ hold_file = flex_file.copy()
572
+ overall_file = flex_file.copy()
573
+ prop_file = flex_file.copy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
 
575
+ overall_players = overall_file[['Player']]
 
 
 
 
 
 
576
 
577
+ for x in range(0,total_sims):
578
+ prop_file[x] = prop_file['Prop']
579
+
580
+ prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
581
+
582
+ for x in range(0,total_sims):
583
+ overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
584
+
585
+ overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
586
+
587
+ players_only = hold_file[['Player']]
588
+
589
+ player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
590
+
591
+ prop_check = (overall_file - prop_file)
592
+
593
+ players_only['Mean_Outcome'] = overall_file.mean(axis=1)
594
+ players_only['Book'] = players_only['Player'].map(book_dict)
595
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
596
+ players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
597
+ players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
598
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
599
+ players_only['10%'] = overall_file.quantile(0.1, axis=1)
600
+ players_only['90%'] = overall_file.quantile(0.9, axis=1)
601
+ players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
602
+ players_only['Imp Over'] = players_only['Player'].map(over_dict)
603
+ players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
604
+ 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))
605
+ players_only['Imp Under'] = players_only['Player'].map(under_dict)
606
+ players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
607
+ players_only['Prop_avg'] = players_only['Prop'].mean() / 100
608
+ players_only['prop_threshold'] = .10
609
+ players_only = players_only[players_only['Mean_Outcome'] > 0]
610
+ players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
611
+ players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
612
+ players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
613
+ players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
614
+ players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
615
+ players_only['Edge'] = players_only['Bet_check']
616
+ players_only['Prop Type'] = prop
617
+
618
+ players_only['Player'] = hold_file[['Player']]
619
+ players_only['Team'] = players_only['Player'].map(team_dict)
620
+
621
+ leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
622
+ sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
623
+
624
+ final_outcomes = sim_all_hold
625
+ st.write(f'finished {prop} for {books}')
626
+
627
+ elif prop_type_var != 'All Props':
628
+
629
+ player_df = player_stats.copy()
630
+
631
+ if game_select_var == 'Aggregate':
632
+ prop_df_raw = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
633
+ elif game_select_var == 'Pick6':
634
+ prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
635
+
636
+ for books in book_selections:
637
+ prop_df = prop_df_raw[prop_df_raw['book'] == books]
638
+
639
+ if prop_type_var == "NBA_GAME_PLAYER_POINTS":
640
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS']
641
+ elif prop_type_var == "Points":
642
+ prop_df = prop_df[prop_df['prop_type'] == 'Points']
643
+ elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS":
644
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_REBOUNDS']
645
+ elif prop_type_var == "Rebounds":
646
+ prop_df = prop_df[prop_df['prop_type'] == 'Rebounds']
647
+ elif prop_type_var == "NBA_GAME_PLAYER_ASSISTS":
648
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_ASSISTS']
649
+ elif prop_type_var == "Assists":
650
+ prop_df = prop_df[prop_df['prop_type'] == 'Assists']
651
+ elif prop_type_var == "NBA_GAME_PLAYER_3_POINTERS_MADE":
652
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_3_POINTERS_MADE']
653
+ elif prop_type_var == "3-Pointers Made":
654
+ prop_df = prop_df[prop_df['prop_type'] == '3-Pointers Made']
655
+ elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS":
656
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS']
657
+ elif prop_type_var == "Points + Assists + Rebounds":
658
+ prop_df = prop_df[prop_df['prop_type'] == 'Points + Assists + Rebounds']
659
+ elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS":
660
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_REBOUNDS']
661
+ elif prop_type_var == "Points + Rebounds":
662
+ prop_df = prop_df[prop_df['prop_type'] == 'Points + Rebounds']
663
+ elif prop_type_var == "NBA_GAME_PLAYER_POINTS_ASSISTS":
664
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_ASSISTS']
665
+ elif prop_type_var == "Points + Assists":
666
+ prop_df = prop_df[prop_df['prop_type'] == 'Points + Assists']
667
+ elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS":
668
+ prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']
669
+ elif prop_type_var == "Assists + Rebounds":
670
+ prop_df = prop_df[prop_df['prop_type'] == 'Assists + Rebounds']
671
+
672
+ prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]
673
+ prop_df = prop_df.rename(columns={"over_prop": "Prop"})
674
+ prop_df['Over'] = 1 / prop_df['over_line']
675
+ prop_df['Under'] = 1 / prop_df['under_line']
676
+
677
+ prop_dict = dict(zip(prop_df.Player, prop_df.Prop))
678
+ prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))
679
+ book_dict = dict(zip(prop_df.Player, prop_df.book))
680
+ over_dict = dict(zip(prop_df.Player, prop_df.Over))
681
+ under_dict = dict(zip(prop_df.Player, prop_df.Under))
682
+ trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))
683
+ trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))
684
+
685
+ player_df['book'] = player_df['Player'].map(book_dict)
686
+ player_df['Prop'] = player_df['Player'].map(prop_dict)
687
+ player_df['prop_type'] = player_df['Player'].map(prop_type_dict)
688
+ player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)
689
+ player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)
690
+
691
+ df = player_df.reset_index(drop=True)
692
+
693
+ team_dict = dict(zip(df.Player, df.Team))
694
+
695
+ total_sims = 1000
696
+
697
+ df.replace("", 0, inplace=True)
698
+
699
+ if prop_type_var == "NBA_GAME_PLAYER_POINTS" or prop_type_var == "Points":
700
+ df['Median'] = df['Points']
701
+ elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS" or prop_type_var == "Rebounds":
702
+ df['Median'] = df['Rebounds']
703
+ elif prop_type_var == "NBA_GAME_PLAYER_ASSISTS" or prop_type_var == "Assists":
704
+ df['Median'] = df['Assists']
705
+ elif prop_type_var == "NBA_GAME_PLAYER_3_POINTERS_MADE" or prop_type_var == "3-Pointers Made":
706
+ df['Median'] = df['3P']
707
+ elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS" or prop_type_var == "Points + Assists + Rebounds":
708
+ df['Median'] = df['Points'] + df['Rebounds'] + df['Assists']
709
+ elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS" or prop_type_var == "Points + Rebounds":
710
+ df['Median'] = df['Points'] + df['Rebounds']
711
+ elif prop_type_var == "NBA_GAME_PLAYER_POINTS_ASSISTS" or prop_type_var == "Points + Assists":
712
+ df['Median'] = df['Points'] + df['Assists']
713
+ elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS" or prop_type_var == "Assists + Rebounds":
714
+ df['Median'] = df['Rebounds'] + df['Assists']
715
+
716
+ flex_file = df.copy()
717
+ flex_file['Floor'] = flex_file['Median'] * .25
718
+ flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1.75)
719
+ flex_file['STD'] = flex_file['Median'] / 4
720
+ flex_file['Prop'] = flex_file['Player'].map(prop_dict)
721
+ flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]
722
+
723
+ hold_file = flex_file.copy()
724
+ overall_file = flex_file.copy()
725
+ prop_file = flex_file.copy()
726
+
727
+ overall_players = overall_file[['Player']]
728
+
729
+ for x in range(0,total_sims):
730
+ prop_file[x] = prop_file['Prop']
731
+
732
+ prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
733
+
734
+ for x in range(0,total_sims):
735
+ overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])
736
+
737
+ overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)
738
+
739
+ players_only = hold_file[['Player']]
740
+
741
+ player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)
742
+
743
+ prop_check = (overall_file - prop_file)
744
+
745
+ players_only['Mean_Outcome'] = overall_file.mean(axis=1)
746
+ players_only['Book'] = players_only['Player'].map(book_dict)
747
+ players_only['Prop'] = players_only['Player'].map(prop_dict)
748
+ players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)
749
+ players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)
750
+ players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)
751
+ players_only['10%'] = overall_file.quantile(0.1, axis=1)
752
+ players_only['90%'] = overall_file.quantile(0.9, axis=1)
753
+ players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))
754
+ players_only['Imp Over'] = players_only['Player'].map(over_dict)
755
+ players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)
756
+ 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))
757
+ players_only['Imp Under'] = players_only['Player'].map(under_dict)
758
+ players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)
759
+ players_only['Prop_avg'] = players_only['Prop'].mean() / 100
760
+ players_only['prop_threshold'] = .10
761
+ players_only = players_only[players_only['Mean_Outcome'] > 0]
762
+ players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']
763
+ players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']
764
+ players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] , players_only['Under_diff'])
765
+ players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")
766
+ players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")
767
+ players_only['Edge'] = players_only['Bet_check']
768
+ players_only['Prop Type'] = prop_type_var
769
+
770
+ players_only['Player'] = hold_file[['Player']]
771
+ players_only['Team'] = players_only['Player'].map(team_dict)
772
+
773
+ leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]
774
+ sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)
775
+
776
+ final_outcomes = sim_all_hold
777
+ st.write(f'finished {prop_type_var} for {books}')
778
+
779
+ final_outcomes = final_outcomes.dropna()
780
+ if game_select_var == 'Pick6':
781
+ final_outcomes = final_outcomes.drop_duplicates(subset=['Player', 'Prop Type'])
782
+ final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)
783
+
784
+ with df_hold_container:
785
+ df_hold_container = st.empty()
786
+ st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(sim_format, precision=2), height=1000, use_container_width = True)
787
+ with export_container:
788
+ export_container = st.empty()
789
+ st.download_button(
790
+ label="Export Projections",
791
+ data=convert_df_to_csv(final_outcomes),
792
+ file_name='NBA_prop_proj.csv',
793
+ mime='text/csv',
794
+ key='prop_proj',
795
+ )