TrueDFS/NBA_Betting_Models_Origin
0
1import streamlit as st2st.set_page_config(layout="wide")3 4for name in dir():5 if not name.startswith('_'):6 del globals()[name]7 8import numpy as np9from numpy import where as np_where10import pandas as pd11import pymongo12import random13import gc14import streamlit as st15import scipy.stats as stats16from datetime import datetime17 18@st.cache_resource19def init_conn():20 21 uri = st.secrets['mongo_uri']22 client = pymongo.MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=100000)23 db = client["NBA_DFS"]24 prop_db = client["Props_DB"]25 26 return db, prop_db27 28db, prop_db = init_conn()29 30game_format = {'Paydirt Win%': '{:.2%}', 'Vegas Win%': '{:.2%}'}31prop_format = {'L5 Success': '{:.2%}', 'L10_Success': '{:.2%}', 'L20_success': '{:.2%}', 'Matchup Boost': '{:.2%}', 'Trending Over': '{:.2%}', 'Trending Under': '{:.2%}',32 'Implied Over': '{:.2%}', 'Implied Under': '{:.2%}', 'Over Edge': '{:.2%}', 'Under Edge': '{:.2%}'}33sim_format = {'Trending Over': '{:.2%}', 'Trending Under': '{:.2%}', 'Imp Over': '{:.2%}', 'Imp Under': '{:.2%}', 'Over%': '{:.2%}', 'Under%': '{:.2%}', 'Edge': '{:.2%}'}34prop_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']35all_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']36pick6_sim_vars = ['Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds']37sim_all_hold = pd.DataFrame(columns=['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge'])38 39def calculate_poisson(row):40 mean_val = row['Mean_Outcome']41 threshold = row['Prop']42 cdf_value = stats.poisson.cdf(threshold, mean_val)43 probability = 1 - cdf_value44 return probability45 46def add_column(df):47 return_df = df48 return_df['2P'] = return_df["Minutes"] * return_df["FG2M"]49 return_df['3P'] = return_df["Minutes"] * return_df["Threes"]50 return_df['FT'] = return_df["Minutes"] * return_df["FTM"]51 return_df['Points'] = (return_df["2P"] * 2) + (return_df["3P"] * 3) + return_df['FT']52 return_df['Rebounds'] = return_df["Minutes"] * return_df["TRB"]53 return_df['Assists'] = return_df["Minutes"] * return_df["AST"]54 return_df['PRA'] = return_df['Points'] + return_df['Rebounds'] + return_df['Assists']55 return_df['PR'] = return_df['Points'] + return_df['Rebounds']56 return_df['PA'] = return_df['Points'] + return_df['Assists']57 return_df['RA'] = return_df['Rebounds'] + return_df['Assists']58 return_df['Steals'] = return_df["Minutes"] * return_df["STL"]59 return_df['Blocks'] = return_df["Minutes"] * return_df["BLK"]60 return_df['Turnovers'] = return_df["Minutes"] * return_df["TOV"]61 return_df['Fantasy'] = (return_df["2P"] * 3) + (return_df["3P"] * 3.5) + return_df['FT'] + (return_df["Rebounds"] * 1.25) + (return_df["Assists"] * 1.5) + (return_df["Steals"] * 2) + (return_df["Blocks"] * 2) + (return_df["Turnovers"] * -.5)62 63 export_df = return_df[['Player', 'Position', 'Team', 'Opp', 'Minutes', '2P', '3P', 'FT', 'Points', 'Rebounds', 'Assists', 'PRA', 'PR', 'PA', 'RA', 'Steals', 'Blocks', 'Turnovers', 'Fantasy']]64 65 return export_df66 67@st.cache_resource(ttl = 300)68def init_baselines():69 collection = db["Game_Betting_Model"] 70 cursor = collection.find()71 72 raw_display = pd.DataFrame(list(cursor))73 raw_display = raw_display[['Team', 'Opp', 'PD Team Points', 'PD Opp Points', 'VEG Team Points', 'VEG Opp Points', 'PD Proj Total', 'VEG Proj Total', 'PD Over%', 'PD Over Odds', 'PD Under%', 'PD Under Odds',74 'PD Proj Winner', 'PD Proj Spread', 'PD W Spread', 'VEG W Spread', 'PD Win%', 'PD Odds']]75 raw_display.replace('#DIV/0!', np.nan, inplace=True)76 game_model = raw_display.dropna()77 78 collection = db["Player_Stats"] 79 cursor = collection.find()80 81 raw_display = pd.DataFrame(list(cursor))82 raw_display.replace('', np.nan, inplace=True)83 raw_display = raw_display.rename(columns={"Name": "Player"})84 raw_baselines = raw_display[['Player', 'Position', 'Team', 'Opp', 'Minutes', 'FGM', 'FGA', 'FG2M', 'FG2A', 'Threes', 'FG3A', 'FTM', 'FTA', 'TRB', 'AST', 'STL', 'BLK', 'TOV', 'PRA', 'PR', 'PA', 'RA']]85 raw_baselines = raw_baselines[raw_baselines['Minutes'] > 0]86 raw_baselines['Player'].replace(['Jaren Jackson', 'Nic Claxton', 'Jabari Smith', 'Lu Dort', 'Moe Wagner', 'Kyle Kuzma', 'Trey Murphy', 'Cameron Thomas'],87 ['Jaren Jackson Jr.', 'Nicolas Claxton', 'Jabari Smith Jr.', 'Luguentz Dort', 'Moritz Wagner', 'Kyle Kuzma Jr.',88 'Trey Murphy III', 'Cam Thomas'], inplace=True)89 90 player_stats = raw_display[['Player', 'Position', 'Team', 'Opp', 'Minutes', '3P', 'Points', 'Rebounds', 'Assists', 'Steals', 'Blocks', 'Turnovers', 'Fantasy']]91 player_stats = player_stats[player_stats['Minutes'] > 0]92 93 player_stats['Player'].replace(['Jaren Jackson', 'Nic Claxton', 'Jabari Smith', 'Lu Dort', 'Moe Wagner', 'Kyle Kuzma', 'Trey Murphy', 'Cameron Thomas'],94 ['Jaren Jackson Jr.', 'Nicolas Claxton', 'Jabari Smith Jr.', 'Luguentz Dort', 'Moritz Wagner', 'Kyle Kuzma Jr.',95 'Trey Murphy III', 'Cam Thomas'], inplace=True)96 97 98 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")99 100 collection = db["Prop_Trends"] 101 cursor = collection.find()102 103 raw_display = pd.DataFrame(list(cursor))104 raw_display.replace('', np.nan, inplace=True)105 raw_display = raw_display[['Name', 'over_prop', 'over_line', 'under_prop', 'under_line', 'OddsType', 'PropType', 'No Vig', 'Team', 'L5 Success', 'L10_Success', 'L20_success', 'L10 Avg', 'Projection',106 'Proj Diff', 'Matchup Boost', 'Implied Over', 'Trending Over', 'Over Edge', 'Implied Under', 'Trending Under', 'Under Edge']]107 raw_display = raw_display.rename(columns={"Name": "Player", "OddsType": "book", "PropType": "prop_type"})108 prop_frame = raw_display.dropna(subset='Player')109 110 collection = db["Pick6_Trends"] 111 cursor = collection.find()112 113 raw_display = pd.DataFrame(list(cursor))114 raw_display = raw_display[['Player', 'over_prop', 'over_line', 'under_prop', 'under_line', 'book', 'prop_type', 'No Vig', 'Team', 'L5 Success', 'L10_Success', 'L20_success', 'L10 Avg', 'Projection',115 'Proj Diff', 'Matchup Boost', 'Implied Over', 'Trending Over', 'Over Edge', 'Implied Under', 'Trending Under', 'Under Edge']]116 pick_frame = raw_display.drop_duplicates(subset=['Player', 'prop_type'], keep='first')117 pick_frame = pick_frame.reset_index(drop=True)118 119 prop_frame['Player'].replace(['Jaren Jackson', 'Nic Claxton', 'Jabari Smith', 'Lu Dort', 'Moe Wagner', 'Kyle Kuzma', 'Trey Murphy', 'Cameron Thomas'],120 ['Jaren Jackson Jr.', 'Nicolas Claxton', 'Jabari Smith Jr.', 'Luguentz Dort', 'Moritz Wagner', 'Kyle Kuzma Jr.',121 'Trey Murphy III', 'Cam Thomas'], inplace=True)122 pick_frame['Player'].replace(['Jaren Jackson', 'Nic Claxton', 'Jabari Smith', 'Lu Dort', 'Moe Wagner', 'Kyle Kuzma', 'Trey Murphy', 'Cameron Thomas'],123 ['Jaren Jackson Jr.', 'Nicolas Claxton', 'Jabari Smith Jr.', 'Luguentz Dort', 'Moritz Wagner', 'Kyle Kuzma Jr.',124 'Trey Murphy III', 'Cam Thomas'], inplace=True)125 126 collection = prop_db["NBA_Props"] 127 cursor = collection.find()128 129 raw_display = pd.DataFrame(list(cursor))130 market_props = raw_display[['Name', 'Position', 'Projection', 'PropType', 'OddsType', 'over_pay', 'under_pay']]131 market_props['over_prop'] = market_props['Projection']132 market_props['over_line'] = market_props['over_pay'].apply(lambda x: (x - 1) * 100 if x >= 2.0 else -100 / (x - 1))133 market_props['under_prop'] = market_props['Projection']134 market_props['under_line'] = market_props['under_pay'].apply(lambda x: (x - 1) * 100 if x >= 2.0 else -100 / (x - 1))135 136 return game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp137 138def calculate_no_vig(row):139 def implied_probability(american_odds):140 if american_odds < 0:141 return (-american_odds) / ((-american_odds) + 100)142 else:143 return 100 / (american_odds + 100)144 145 over_line = row['over_line']146 under_line = row['under_line']147 over_prop = row['over_prop']148 149 over_prob = implied_probability(over_line)150 under_prob = implied_probability(under_line)151 152 total_prob = over_prob + under_prob153 no_vig_prob = (over_prob / total_prob + 0.5) * over_prop154 155 return no_vig_prob156 157def convert_df_to_csv(df):158 return df.to_csv().encode('utf-8')159 160game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()161t_stamp = f"Last Update: " + str(timestamp) + f" CST"162 163tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs(["Game Betting Model", 'Prop Market', "Player Projections", "Prop Trend Table", "Player Prop Simulations", "Stat Specific Simulations"])164 165with tab1:166 st.info(t_stamp)167 if st.button("Reset Data", key='reset1'):168 st.cache_data.clear()169 game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()170 t_stamp = f"Last Update: " + str(timestamp) + f" CST"171 line_var1 = st.radio('How would you like to display odds?', options = ['Percentage', 'American'], key='line_var1')172 team_frame = game_model173 if line_var1 == 'Percentage':174 team_frame = team_frame[['Team', 'Opp', 'PD Team Points', 'PD Opp Points', 'VEG Team Points', 'VEG Opp Points', 'PD Proj Total', 'VEG Proj Total', 'PD Over%', 'PD Under%', 'PD Proj Winner', 'PD Proj Spread', 'PD W Spread', 'VEG W Spread', 'PD Win%']]175 team_frame = team_frame.set_index('Team')176 st.dataframe(team_frame.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(game_format, precision=2), use_container_width = True)177 if line_var1 == 'American':178 team_frame = team_frame[['Team', 'Opp', 'PD Team Points', 'PD Opp Points', 'VEG Team Points', 'VEG Opp Points', 'PD Proj Total', 'VEG Proj Total', 'PD Over Odds', 'PD Under Odds', 'PD Proj Winner', 'PD Proj Spread', 'PD W Spread', 'VEG W Spread', 'PD Odds']]179 team_frame = team_frame.set_index('Team')180 st.dataframe(team_frame.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(game_format, precision=2), use_container_width = True)181 182 st.download_button(183 label="Export Team Model",184 data=convert_df_to_csv(team_frame),185 file_name='NBA_team_betting_export.csv',186 mime='text/csv',187 key='team_export',188 )189 190with tab2:191 st.info(t_stamp)192 if st.button("Reset Data", key='reset2'):193 st.cache_data.clear()194 game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()195 t_stamp = f"Last Update: " + str(timestamp) + f" CST"196 market_type = st.selectbox('Select type of prop are you wanting to view', options = prop_table_options, key = 'market_type_key')197 disp_market = market_props.copy()198 disp_market = disp_market[disp_market['PropType'] == market_type]199 disp_market['No_Vig_Prop'] = disp_market.apply(calculate_no_vig, axis=1)200 fanduel_frame = disp_market[disp_market['OddsType'] == 'FANDUEL']201 fanduel_dict = dict(zip(fanduel_frame['Name'], fanduel_frame['No_Vig_Prop']))202 draftkings_frame = disp_market[disp_market['OddsType'] == 'DRAFTKINGS']203 draftkings_dict = dict(zip(draftkings_frame['Name'], draftkings_frame['No_Vig_Prop']))204 mgm_frame = disp_market[disp_market['OddsType'] == 'MGM']205 mgm_dict = dict(zip(mgm_frame['Name'], mgm_frame['No_Vig_Prop']))206 bet365_frame = disp_market[disp_market['OddsType'] == 'BET_365']207 bet365_dict = dict(zip(bet365_frame['Name'], bet365_frame['No_Vig_Prop']))208 209 disp_market['FANDUEL'] = disp_market['Name'].map(fanduel_dict)210 disp_market['DRAFTKINGS'] = disp_market['Name'].map(draftkings_dict)211 disp_market['MGM'] = disp_market['Name'].map(mgm_dict)212 disp_market['BET365'] = disp_market['Name'].map(bet365_dict)213 214 disp_market = disp_market[['Name', 'Position','FANDUEL', 'DRAFTKINGS', 'MGM', 'BET365']]215 disp_market = disp_market.drop_duplicates(subset=['Name'], keep='first', ignore_index=True)216 217 st.dataframe(disp_market.style.background_gradient(axis=1, subset=['FANDUEL', 'DRAFTKINGS', 'MGM', 'BET365'], cmap='RdYlGn').format(prop_format, precision=2), height = 1000, use_container_width = True)218 st.download_button(219 label="Export Market Props",220 data=convert_df_to_csv(disp_market),221 file_name='NFL_market_props_export.csv',222 mime='text/csv',223 )224 225with tab3:226 st.info(t_stamp)227 if st.button("Reset Data", key='reset3'):228 st.cache_data.clear()229 game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()230 t_stamp = f"Last Update: " + str(timestamp) + f" CST"231 split_var1 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var1')232 if split_var1 == 'Specific Teams':233 team_var1 = st.multiselect('Which teams would you like to include in the tables?', options = player_stats['Team'].unique(), key='team_var1')234 elif split_var1 == 'All':235 team_var1 = player_stats.Team.values.tolist()236 player_stats = player_stats[player_stats['Team'].isin(team_var1)]237 player_stats_disp = player_stats.set_index('Player')238 player_stats_disp = player_stats_disp.sort_values(by='Fantasy', ascending=False)239 st.dataframe(player_stats_disp.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)240 st.download_button(241 label="Export Prop Model",242 data=convert_df_to_csv(player_stats),243 file_name='NBA_stats_export.csv',244 mime='text/csv',245 )246 247with tab4:248 st.info(t_stamp)249 if st.button("Reset Data", key='reset4'):250 st.cache_data.clear()251 game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()252 t_stamp = f"Last Update: " + str(timestamp) + f" CST"253 split_var5 = st.radio("Would you like to view all teams or specific ones?", ('All', 'Specific Teams'), key='split_var5')254 if split_var5 == 'Specific Teams':255 team_var5 = st.multiselect('Which teams would you like to include in the tables?', options = player_stats['Team'].unique(), key='team_var5')256 elif split_var5 == 'All':257 team_var5 = player_stats.Team.values.tolist()258 book_split5 = st.radio("Would you like to view all books or specific ones?", ('All', 'Specific Books'), key='book_split5')259 if book_split5 == 'Specific Books':260 book_var5 = st.multiselect('Which books would you like to include in the tables?', options = ['BET_365', 'DRAFTKINGS', 'CONSENSUS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL'], key='book_var5')261 elif book_split5 == 'All':262 book_var5 = ['BET_365', 'DRAFTKINGS', 'CONSENSUS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL']263 prop_type_var2 = st.selectbox('Select type of prop are you wanting to view', options = prop_table_options)264 prop_frame_disp = prop_frame[prop_frame['Team'].isin(team_var5)]265 prop_frame_disp = prop_frame_disp[prop_frame_disp['book'].isin(book_var5)]266 prop_frame_disp = prop_frame_disp[prop_frame_disp['prop_type'] == prop_type_var2]267 prop_frame_disp = prop_frame_disp.sort_values(by='Trending Over', ascending=False)268 st.dataframe(prop_frame_disp.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(prop_format, precision=2), use_container_width = True)269 st.download_button(270 label="Export Prop Trends Model",271 data=convert_df_to_csv(prop_frame),272 file_name='NBA_prop_trends_export.csv',273 mime='text/csv',274 )275 276with tab5:277 st.info(t_stamp)278 if st.button("Reset Data", key='reset5'):279 st.cache_data.clear()280 game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()281 t_stamp = f"Last Update: " + str(timestamp) + f" CST"282 col1, col2 = st.columns([1, 5])283 284 with col2:285 df_hold_container = st.empty()286 info_hold_container = st.empty()287 plot_hold_container = st.empty()288 289 with col1:290 player_check = st.selectbox('Select player to simulate props', options = player_stats['Player'].unique())291 prop_type_var = st.selectbox('Select type of prop to simulate', options = ['points', 'threes', 'rebounds', 'assists', 'blocks', 'steals',292 'PRA', 'points+rebounds', 'points+assists', 'rebounds+assists'])293 294 ou_var = st.selectbox('Select wether it is an over or under', options = ['Over', 'Under'])295 if prop_type_var == 'points':296 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 50.5, value = 15.5, step = .5)297 elif prop_type_var == 'threes':298 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 5.5, value = 1.5, step = .5)299 elif prop_type_var == 'rebounds':300 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 25.5, value = 5.5, step = .5)301 elif prop_type_var == 'assists':302 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 25.5, value = 5.5, step = .5)303 elif prop_type_var == 'blocks':304 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 5.5, value = 1.5, step = .5)305 elif prop_type_var == 'steals':306 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 5.5, value = 1.5, step = .5)307 elif prop_type_var == 'PRA':308 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 65.5, value = 20.5, step = .5)309 elif prop_type_var == 'points+rebounds':310 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 45.5, value = 10.5, step = .5)311 elif prop_type_var == 'points+assists':312 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 45.5, value = 10.5, step = .5)313 elif prop_type_var == 'rebounds+assists':314 prop_var = st.number_input('Type in the prop offered (i.e 5.5)', min_value = 0.0, max_value = 45.5, value = 10.5, step = .5)315 line_var = st.number_input('Type in the line on the prop (i.e. -120)', min_value = -1500, max_value = 1500, value = -150, step = 1)316 line_var = line_var + 1317 318 if st.button('Simulate Prop'):319 with col2:320 321 with df_hold_container.container():322 323 df = player_stats324 st.write("sim started")325 326 total_sims = 1000327 328 df.replace("", 0, inplace=True)329 330 player_var = df[df['Player'] == player_check]331 player_var = player_var.reset_index()332 333 if prop_type_var == 'points':334 df['Median'] = pd.to_numeric(df['Points'], errors='coerce')335 elif prop_type_var == 'threes':336 df['Median'] = pd.to_numeric(df['3P'], errors='coerce')337 elif prop_type_var == 'rebounds':338 df['Median'] = pd.to_numeric(df['Rebounds'], errors='coerce')339 elif prop_type_var == 'assists':340 df['Median'] = pd.to_numeric(df['Assists'], errors='coerce')341 elif prop_type_var == 'blocks':342 df['Median'] = pd.to_numeric(df['Blocks'], errors='coerce')343 elif prop_type_var == 'steals':344 df['Median'] = pd.to_numeric(df['Steals'], errors='coerce')345 elif prop_type_var == 'PRA':346 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')347 elif prop_type_var == 'points+rebounds':348 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce')349 elif prop_type_var == 'points+assists':350 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')351 elif prop_type_var == 'rebounds+assists':352 df['Median'] = pd.to_numeric(df['Assists'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce')353 354 flex_file = df355 flex_file['Floor'] = (flex_file['Median'] * .25) + (flex_file['Minutes'] * .25)356 flex_file['Ceiling'] = flex_file['Median'] + 10 + (flex_file['Minutes'] * .25)357 flex_file['STD'] = (flex_file['Median']/4)358 flex_file = flex_file[['Player', 'Floor', 'Median', 'Ceiling', 'STD']]359 360 hold_file = flex_file361 overall_file = flex_file362 salary_file = flex_file363 364 overall_players = overall_file[['Player']]365 366 for x in range(0,total_sims):367 overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])368 369 overall_file=overall_file.drop(['Player', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)370 371 players_only = hold_file[['Player']]372 373 player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)374 st.write("sim finished, calculating outcomes")375 376 players_only['Mean_Outcome'] = overall_file.mean(axis=1)377 players_only['Prop'] = prop_var378 players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)379 players_only['10%'] = overall_file.quantile(0.1, axis=1)380 players_only['90%'] = overall_file.quantile(0.9, axis=1)381 if ou_var == 'Over':382 players_only['beat_prop'] = np.where(players_only['Prop'] <= 3, players_only['poisson_var'], overall_file[overall_file > prop_var].count(axis=1)/float(total_sims))383 elif ou_var == 'Under':384 players_only['beat_prop'] = np.where(players_only['Prop'] <= 3, 1 - players_only['poisson_var'], (overall_file[overall_file < prop_var].count(axis=1)/float(total_sims)))385 386 players_only['implied_odds'] = np.where(line_var <= 0, (-(line_var)/((-(line_var))+100)), 100/(line_var+100))387 388 players_only['Player'] = hold_file[['Player']]389 390 final_outcomes = players_only[['Player', '10%', 'Mean_Outcome', '90%', 'implied_odds', 'beat_prop']]391 final_outcomes['Bet?'] = np.where(final_outcomes['beat_prop'] - final_outcomes['implied_odds'] >= .10, "Bet", "No Bet")392 final_outcomes = final_outcomes[final_outcomes['Player'] == player_check]393 player_outcomes = player_outcomes[player_outcomes['Player'] == player_check]394 player_outcomes = player_outcomes.drop(columns=['Player']).transpose()395 player_outcomes = player_outcomes.reset_index()396 player_outcomes.columns = ['Instance', 'Outcome']397 398 x1 = player_outcomes.Outcome.to_numpy()399 400 print(x1)401 402 hist_data = [x1]403 404 group_labels = ['player outcomes']405 406 fig = px.histogram(407 player_outcomes, x='Outcome')408 fig.add_vline(x=prop_var, line_dash="dash", line_color="green")409 410 with df_hold_container:411 df_hold_container = st.empty()412 format_dict = {'10%': '{:.2f}', 'Mean_Outcome': '{:.2f}','90%': '{:.2f}', 'beat_prop': '{:.2%}','implied_odds': '{:.2%}'}413 st.dataframe(final_outcomes.style.format(format_dict), use_container_width = True)414 415 with info_hold_container:416 st.info('The Y-axis is the percent of times in simulations that the player reaches certain thresholds, while the X-axis is the threshold to be met. The Green dotted line is the prop you entered. You can hover over any spot and see the percent to reach that mark.')417 418 with plot_hold_container:419 st.dataframe(player_outcomes, use_container_width = True)420 plot_hold_container = st.empty()421 st.plotly_chart(fig, use_container_width=True)422 423with tab6:424 st.info(t_stamp)425 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.')426 if st.button("Reset Data/Load Data", key='reset6'):427 st.cache_data.clear()428 game_model, raw_baselines, player_stats, prop_frame, pick_frame, market_props, timestamp = init_baselines()429 t_stamp = f"Last Update: " + str(timestamp) + f" CST"430 431 settings_container = st.empty()432 df_hold_container = st.empty()433 export_container = st.empty()434 435 with settings_container.container():436 col1, col2, col3, col4 = st.columns([3, 3, 3, 3])437 with col1:438 game_select_var = st.selectbox('Select prop source', options = ['Aggregate', 'Pick6'])439 with col2:440 book_select_var = st.selectbox('Select book', options = ['ALL', 'BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL'])441 if book_select_var == 'ALL':442 book_selections = ['BET_365', 'DRAFTKINGS', 'FANDUEL', 'MGM', 'UNIBET', 'WILLIAM_HILL']443 else:444 book_selections = [book_select_var]445 if game_select_var == 'Aggregate':446 prop_df = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]447 elif game_select_var == 'Pick6':448 prop_df = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]449 book_selections = ['Pick6']450 with col3:451 if game_select_var == 'Aggregate':452 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',453 'NBA_GAME_PLAYER_POINTS_REBOUNDS', 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_3_POINTERS_MADE'])454 elif game_select_var == 'Pick6':455 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'])456 with col4:457 st.download_button(458 label="Download Prop Source",459 data=convert_df_to_csv(prop_df),460 file_name='Nba_prop_source.csv',461 mime='text/csv',462 key='prop_source',463 )464 465 if st.button('Simulate Prop Category'):466 467 with df_hold_container.container():468 if prop_type_var == 'All Props':469 if game_select_var == 'Aggregate':470 prop_df_raw = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]471 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',472 'NBA_GAME_PLAYER_POINTS_ASSISTS', 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS', 'NBA_GAME_PLAYER_3_POINTERS_MADE']473 elif game_select_var == 'Pick6':474 prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]475 sim_vars = ['Points', 'Rebounds', 'Assists', 'Points + Assists + Rebounds', 'Points + Assists', 'Points + Rebounds', 'Assists + Rebounds', '3-Pointers Made']476 477 player_df = player_stats.copy()478 479 for prop in sim_vars:480 481 for books in book_selections:482 prop_df = prop_df_raw[prop_df_raw['prop_type'] == prop]483 prop_df = prop_df[prop_df['book'] == books]484 prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]485 prop_df.rename(columns={"over_prop": "Prop"}, inplace = True)486 prop_df['Over'] = 1 / prop_df['over_line']487 prop_df['Under'] = 1 / prop_df['under_line']488 489 prop_dict = dict(zip(prop_df.Player, prop_df.Prop))490 prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))491 book_dict = dict(zip(prop_df.Player, prop_df.book))492 over_dict = dict(zip(prop_df.Player, prop_df.Over))493 under_dict = dict(zip(prop_df.Player, prop_df.Under))494 trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))495 trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))496 497 player_df['book'] = player_df['Player'].map(book_dict)498 player_df['Prop'] = player_df['Player'].map(prop_dict)499 player_df['prop_type'] = player_df['Player'].map(prop_type_dict)500 player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)501 player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)502 503 df = player_df.reset_index(drop=True)504 505 team_dict = dict(zip(df.Player, df.Team))506 507 total_sims = 1000508 509 df.replace("", 0, inplace=True)510 511 if prop == "NBA_GAME_PLAYER_POINTS" or prop == "Points":512 df['Median'] = pd.to_numeric(df['Points'], errors='coerce')513 elif prop == "NBA_GAME_PLAYER_REBOUNDS" or prop == "Rebounds":514 df['Median'] = pd.to_numeric(df['Rebounds'], errors='coerce')515 elif prop == "NBA_GAME_PLAYER_ASSISTS" or prop == "Assists":516 df['Median'] = pd.to_numeric(df['Assists'], errors='coerce')517 elif prop == "NBA_GAME_PLAYER_3_POINTERS_MADE" or prop == "3-Pointers Made":518 df['Median'] = pd.to_numeric(df['3P'], errors='coerce')519 elif prop == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS" or prop == "Points + Assists + Rebounds":520 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')521 elif prop == "NBA_GAME_PLAYER_POINTS_REBOUNDS" or prop == "Points + Rebounds":522 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce')523 elif prop == "NBA_GAME_PLAYER_POINTS_ASSISTS" or prop == "Points + Assists":524 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')525 elif prop == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS" or prop == "Assists + Rebounds":526 df['Median'] = pd.to_numeric(df['Rebounds'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')527 528 flex_file = df.copy()529 flex_file['Floor'] = flex_file['Median'] * .25530 flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1.75)531 flex_file['STD'] = flex_file['Median'] / 4532 flex_file['Prop'] = flex_file['Player'].map(prop_dict)533 flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]534 535 hold_file = flex_file.copy()536 overall_file = flex_file.copy()537 prop_file = flex_file.copy()538 539 overall_players = overall_file[['Player']]540 541 for x in range(0,total_sims): 542 prop_file[x] = prop_file['Prop']543 544 prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)545 546 for x in range(0,total_sims):547 overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])548 549 overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)550 551 players_only = hold_file[['Player']]552 553 player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)554 555 prop_check = (overall_file - prop_file)556 557 players_only['Mean_Outcome'] = overall_file.mean(axis=1)558 players_only['Book'] = players_only['Player'].map(book_dict)559 players_only['Prop'] = players_only['Player'].map(prop_dict)560 players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)561 players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)562 players_only['over_adj'] = np_where((players_only['Mean_Outcome'] - players_only['Prop']) > 0, 1, (players_only['Mean_Outcome'] / players_only['Prop']))563 players_only['under_adj'] = np_where((players_only['Prop'] - players_only['Mean_Outcome']) > 0, 1, (players_only['Prop'] / players_only['Mean_Outcome']))564 players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)565 players_only['10%'] = overall_file.quantile(0.1, axis=1)566 players_only['90%'] = overall_file.quantile(0.9, axis=1)567 players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))568 players_only['Imp Over'] = players_only['Player'].map(over_dict)569 players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)570 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))571 players_only['Imp Under'] = players_only['Player'].map(under_dict)572 players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)573 players_only['Prop_avg'] = players_only['Prop'].mean() / 100574 players_only['prop_threshold'] = .10575 players_only = players_only[players_only['Mean_Outcome'] > 0]576 players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']577 players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']578 players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] * players_only['over_adj'], players_only['Under_diff'] * players_only['under_adj'])579 players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")580 players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")581 players_only['Edge'] = players_only['Bet_check']582 players_only['Prop Type'] = prop583 584 players_only['Player'] = hold_file[['Player']]585 players_only['Team'] = players_only['Player'].map(team_dict)586 587 leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]588 sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)589 590 final_outcomes = sim_all_hold591 st.write(f'finished {prop} for {books}')592 593 elif prop_type_var != 'All Props':594 595 player_df = player_stats.copy()596 597 if game_select_var == 'Aggregate':598 prop_df_raw = prop_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]599 elif game_select_var == 'Pick6':600 prop_df_raw = pick_frame[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]601 602 for books in book_selections:603 prop_df = prop_df_raw[prop_df_raw['book'] == books]604 605 if prop_type_var == "NBA_GAME_PLAYER_POINTS":606 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS']607 elif prop_type_var == "Points":608 prop_df = prop_df[prop_df['prop_type'] == 'Points']609 elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS":610 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_REBOUNDS']611 elif prop_type_var == "Rebounds":612 prop_df = prop_df[prop_df['prop_type'] == 'Rebounds']613 elif prop_type_var == "NBA_GAME_PLAYER_ASSISTS":614 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_ASSISTS']615 elif prop_type_var == "Assists":616 prop_df = prop_df[prop_df['prop_type'] == 'Assists']617 elif prop_type_var == "NBA_GAME_PLAYER_3_POINTERS_MADE":618 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_3_POINTERS_MADE']619 elif prop_type_var == "3-Pointers Made":620 prop_df = prop_df[prop_df['prop_type'] == '3-Pointers Made']621 elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS":622 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS']623 elif prop_type_var == "Points + Assists + Rebounds":624 prop_df = prop_df[prop_df['prop_type'] == 'Points + Assists + Rebounds']625 elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS":626 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_REBOUNDS']627 elif prop_type_var == "Points + Rebounds":628 prop_df = prop_df[prop_df['prop_type'] == 'Points + Rebounds']629 elif prop_type_var == "NBA_GAME_PLAYER_POINTS_ASSISTS":630 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_POINTS_ASSISTS']631 elif prop_type_var == "Points + Assists":632 prop_df = prop_df[prop_df['prop_type'] == 'Points + Assists']633 elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS":634 prop_df = prop_df[prop_df['prop_type'] == 'NBA_GAME_PLAYER_REBOUNDS_ASSISTS']635 elif prop_type_var == "Assists + Rebounds":636 prop_df = prop_df[prop_df['prop_type'] == 'Assists + Rebounds']637 638 prop_df = prop_df[['Player', 'book', 'over_prop', 'over_line', 'under_line', 'prop_type', 'Trending Over', 'Trending Under']]639 prop_df = prop_df.rename(columns={"over_prop": "Prop"})640 prop_df['Over'] = 1 / prop_df['over_line']641 prop_df['Under'] = 1 / prop_df['under_line']642 643 prop_dict = dict(zip(prop_df.Player, prop_df.Prop))644 prop_type_dict = dict(zip(prop_df.Player, prop_df.prop_type))645 book_dict = dict(zip(prop_df.Player, prop_df.book))646 over_dict = dict(zip(prop_df.Player, prop_df.Over))647 under_dict = dict(zip(prop_df.Player, prop_df.Under))648 trending_over_dict = dict(zip(prop_df.Player, prop_df['Trending Over']))649 trending_under_dict = dict(zip(prop_df.Player, prop_df['Trending Under']))650 651 player_df['book'] = player_df['Player'].map(book_dict)652 player_df['Prop'] = player_df['Player'].map(prop_dict)653 player_df['prop_type'] = player_df['Player'].map(prop_type_dict)654 player_df['Trending Over'] = player_df['Player'].map(trending_over_dict)655 player_df['Trending Under'] = player_df['Player'].map(trending_under_dict)656 657 df = player_df.reset_index(drop=True)658 659 team_dict = dict(zip(df.Player, df.Team))660 661 total_sims = 1000662 663 df.replace("", 0, inplace=True)664 665 if prop_type_var == "NBA_GAME_PLAYER_POINTS" or prop_type_var == "Points":666 df['Median'] = pd.to_numeric(df['Points'], errors='coerce')667 elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS" or prop_type_var == "Rebounds":668 df['Median'] = pd.to_numeric(df['Rebounds'], errors='coerce')669 elif prop_type_var == "NBA_GAME_PLAYER_ASSISTS" or prop_type_var == "Assists":670 df['Median'] = pd.to_numeric(df['Assists'], errors='coerce')671 elif prop_type_var == "NBA_GAME_PLAYER_3_POINTERS_MADE" or prop_type_var == "3-Pointers Made":672 df['Median'] = pd.to_numeric(df['3P'], errors='coerce')673 elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS_ASSISTS" or prop_type_var == "Points + Assists + Rebounds":674 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')675 elif prop_type_var == "NBA_GAME_PLAYER_POINTS_REBOUNDS" or prop_type_var == "Points + Rebounds":676 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Rebounds'], errors='coerce')677 elif prop_type_var == "NBA_GAME_PLAYER_POINTS_ASSISTS" or prop_type_var == "Points + Assists":678 df['Median'] = pd.to_numeric(df['Points'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')679 elif prop_type_var == "NBA_GAME_PLAYER_REBOUNDS_ASSISTS" or prop_type_var == "Assists + Rebounds":680 df['Median'] = pd.to_numeric(df['Rebounds'], errors='coerce') + pd.to_numeric(df['Assists'], errors='coerce')681 682 flex_file = df.copy()683 flex_file['Floor'] = flex_file['Median'] * .25684 flex_file['Ceiling'] = flex_file['Median'] + (flex_file['Median'] * 1.75)685 flex_file['STD'] = flex_file['Median'] / 4686 flex_file['Prop'] = flex_file['Player'].map(prop_dict)687 flex_file = flex_file[['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD']]688 689 hold_file = flex_file.copy()690 overall_file = flex_file.copy()691 prop_file = flex_file.copy()692 693 overall_players = overall_file[['Player']]694 695 for x in range(0,total_sims): 696 prop_file[x] = prop_file['Prop']697 698 prop_file = prop_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)699 700 for x in range(0,total_sims):701 overall_file[x] = np.random.normal(overall_file['Median'],overall_file['STD'])702 703 overall_file=overall_file.drop(['Player', 'book', 'Prop', 'Floor', 'Median', 'Ceiling', 'STD'], axis=1)704 705 players_only = hold_file[['Player']]706 707 player_outcomes = pd.merge(players_only, overall_file, left_index=True, right_index=True)708 709 prop_check = (overall_file - prop_file)710 711 players_only['Mean_Outcome'] = overall_file.mean(axis=1)712 players_only['Book'] = players_only['Player'].map(book_dict)713 players_only['Prop'] = players_only['Player'].map(prop_dict)714 players_only['Trending Over'] = players_only['Player'].map(trending_over_dict)715 players_only['Trending Under'] = players_only['Player'].map(trending_under_dict)716 players_only['over_adj'] = np_where((players_only['Mean_Outcome'] - players_only['Prop']) > 0, 1, (players_only['Mean_Outcome'] / players_only['Prop']))717 players_only['under_adj'] = np_where((players_only['Prop'] - players_only['Mean_Outcome']) > 0, 1, (players_only['Prop'] / players_only['Mean_Outcome']))718 players_only['poisson_var'] = players_only.apply(calculate_poisson, axis=1)719 players_only['10%'] = overall_file.quantile(0.1, axis=1)720 players_only['90%'] = overall_file.quantile(0.9, axis=1)721 players_only['Over'] = np_where(players_only['Prop'] <= 3, players_only['poisson_var'], prop_check[prop_check > 0].count(axis=1)/float(total_sims))722 players_only['Imp Over'] = players_only['Player'].map(over_dict)723 players_only['Over%'] = players_only[["Over", "Imp Over", "Trending Over"]].mean(axis=1)724 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))725 players_only['Imp Under'] = players_only['Player'].map(under_dict)726 players_only['Under%'] = players_only[["Under", "Imp Under", "Trending Under"]].mean(axis=1)727 players_only['Prop_avg'] = players_only['Prop'].mean() / 100728 players_only['prop_threshold'] = .10729 players_only = players_only[players_only['Mean_Outcome'] > 0]730 players_only['Over_diff'] = players_only['Over%'] - players_only['Imp Over']731 players_only['Under_diff'] = players_only['Under%'] - players_only['Imp Under']732 players_only['Bet_check'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], players_only['Over_diff'] * players_only['over_adj'], players_only['Under_diff'] * players_only['under_adj'])733 players_only['Bet_suggest'] = np.where(players_only['Over_diff'] > players_only['Under_diff'], "Over" , "Under")734 players_only['Bet?'] = np.where(players_only['Bet_check'] >= players_only['prop_threshold'], players_only['Bet_suggest'], "No Bet")735 players_only['Edge'] = players_only['Bet_check']736 players_only['Prop Type'] = prop_type_var737 738 players_only['Player'] = hold_file[['Player']]739 players_only['Team'] = players_only['Player'].map(team_dict)740 741 leg_outcomes = players_only[['Player', 'Team', 'Book', 'Prop Type', 'Prop', 'Mean_Outcome', 'Imp Over', 'Trending Over', 'Over%', 'Imp Under', 'Trending Under', 'Under%', 'Bet?', 'Edge']]742 sim_all_hold = pd.concat([sim_all_hold, leg_outcomes], ignore_index=True)743 744 final_outcomes = sim_all_hold745 st.write(f'finished {prop_type_var} for {books}')746 747 final_outcomes = final_outcomes.dropna()748 if game_select_var == 'Pick6':749 final_outcomes = final_outcomes.drop_duplicates(subset=['Player', 'Prop Type'])750 final_outcomes = final_outcomes.sort_values(by='Edge', ascending=False)751 752 with df_hold_container:753 df_hold_container = st.empty()754 st.dataframe(final_outcomes.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(sim_format, precision=2), height=500, use_container_width = True)755 with export_container:756 export_container = st.empty()757 st.download_button(758 label="Export Projections",759 data=convert_df_to_csv(final_outcomes),760 file_name='NBA_prop_proj.csv',761 mime='text/csv',762 key='prop_proj',763 )