Spaces:
Running
Running
James McCool
commited on
Commit
·
227c35b
1
Parent(s):
d9a30f7
Add Bet Sheet functionality to streamlit_app.py, including data retrieval, filtering options, and export capabilities for improved user experience.
Browse files- src/streamlit_app.py +42 -9
src/streamlit_app.py
CHANGED
|
@@ -9,6 +9,7 @@ st.set_page_config(layout="wide")
|
|
| 9 |
from database import props_db, dfs_db
|
| 10 |
|
| 11 |
game_format = {'Win%': '{:.2%}', 'Vegas': '{:.2%}', 'Win% Diff': '{:.2%}'}
|
|
|
|
| 12 |
american_format = {'First Inning Lead Percentage': '{:.2%}', 'Fifth Inning Lead Percentage': '{:.2%}'}
|
| 13 |
|
| 14 |
st.markdown("""
|
|
@@ -81,6 +82,20 @@ def init_baselines():
|
|
| 81 |
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_ID', 'site']]
|
| 82 |
load_display = raw_display[raw_display['Position'] != 'K']
|
| 83 |
timestamp = load_display['timestamp'][0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
collection = dfs_db["Prop_Trends"]
|
| 86 |
cursor = collection.find()
|
|
@@ -104,7 +119,7 @@ def init_baselines():
|
|
| 104 |
market_props['under_prop'] = market_props['Projection']
|
| 105 |
market_props['under_line'] = market_props['under_pay'].apply(lambda x: (x - 1) * 100 if x >= 2.0 else -100 / (x - 1))
|
| 106 |
|
| 107 |
-
return game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props
|
| 108 |
|
| 109 |
def calculate_no_vig(row):
|
| 110 |
def implied_probability(american_odds):
|
|
@@ -147,19 +162,37 @@ sim_all_hold = pd.DataFrame(columns=['Player', 'Team', 'Book', 'Prop Type', 'Pro
|
|
| 147 |
|
| 148 |
selected_tab = st.segmented_control(
|
| 149 |
"Select Tab",
|
| 150 |
-
options=["Game Betting Model", 'Prop Market', "QB Projections", "RB/WR/TE Projections", "Player Prop Trends", "Player Prop Simulations", "Stat Specific Simulations"],
|
| 151 |
selection_mode='single',
|
| 152 |
-
default='
|
| 153 |
width='stretch',
|
| 154 |
label_visibility='collapsed',
|
| 155 |
key='tab_selector'
|
| 156 |
)
|
| 157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
if selected_tab == 'Game Betting Model':
|
| 159 |
st.info(t_stamp)
|
| 160 |
if st.button("Reset Data", key='reset1'):
|
| 161 |
st.cache_data.clear()
|
| 162 |
-
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props = init_baselines()
|
| 163 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 164 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 165 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
@@ -192,7 +225,7 @@ if selected_tab == 'Prop Market':
|
|
| 192 |
st.info(t_stamp)
|
| 193 |
if st.button("Reset Data", key='reset4'):
|
| 194 |
st.cache_data.clear()
|
| 195 |
-
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props = init_baselines()
|
| 196 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 197 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 198 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
@@ -232,7 +265,7 @@ if selected_tab == 'QB Projections':
|
|
| 232 |
st.info(t_stamp)
|
| 233 |
if st.button("Reset Data", key='reset2'):
|
| 234 |
st.cache_data.clear()
|
| 235 |
-
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props = init_baselines()
|
| 236 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 237 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 238 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
@@ -260,7 +293,7 @@ if selected_tab == 'RB/WR/TE Projections':
|
|
| 260 |
st.info(t_stamp)
|
| 261 |
if st.button("Reset Data", key='reset3'):
|
| 262 |
st.cache_data.clear()
|
| 263 |
-
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props = init_baselines()
|
| 264 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 265 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 266 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
@@ -288,7 +321,7 @@ if selected_tab == 'Player Prop Trends':
|
|
| 288 |
st.info(t_stamp)
|
| 289 |
if st.button("Reset Data", key='reset5'):
|
| 290 |
st.cache_data.clear()
|
| 291 |
-
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props = init_baselines()
|
| 292 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 293 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 294 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
@@ -319,7 +352,7 @@ if selected_tab == 'Player Prop Simulations':
|
|
| 319 |
st.info(t_stamp)
|
| 320 |
if st.button("Reset Data", key='reset6'):
|
| 321 |
st.cache_data.clear()
|
| 322 |
-
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props = init_baselines()
|
| 323 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 324 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 325 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
|
|
| 9 |
from database import props_db, dfs_db
|
| 10 |
|
| 11 |
game_format = {'Win%': '{:.2%}', 'Vegas': '{:.2%}', 'Win% Diff': '{:.2%}'}
|
| 12 |
+
bet_format = {'Edge': '{:.2%}'}
|
| 13 |
american_format = {'First Inning Lead Percentage': '{:.2%}', 'Fifth Inning Lead Percentage': '{:.2%}'}
|
| 14 |
|
| 15 |
st.markdown("""
|
|
|
|
| 82 |
'Own', 'Small_Field_Own', 'Large_Field_Own', 'Cash_Field_Own', 'CPT_Own', 'LevX', 'version', 'slate', 'timestamp', 'player_ID', 'site']]
|
| 83 |
load_display = raw_display[raw_display['Position'] != 'K']
|
| 84 |
timestamp = load_display['timestamp'][0]
|
| 85 |
+
|
| 86 |
+
collection = dfs_db["Bet_Sheet"]
|
| 87 |
+
cursor = collection.find()
|
| 88 |
+
|
| 89 |
+
raw_display = pd.DataFrame(list(cursor))
|
| 90 |
+
raw_display.replace('', np.nan, inplace=True)
|
| 91 |
+
raw_display = raw_display[['Name', 'PropType', 'No Vig', 'Projection', 'Edge']]
|
| 92 |
+
raw_display = raw_display.rename(columns={"Name": "Player", "PropType": "prop_type"})
|
| 93 |
+
raw_display = raw_display.dropna(subset='Player')
|
| 94 |
+
raw_display = raw_display.drop_duplicates(subset=['Player', 'prop_type'], keep='first')
|
| 95 |
+
raw_display = raw_display.sort_values(by='Edge', ascending=False)
|
| 96 |
+
raw_display = raw_display.reset_index(drop=True)
|
| 97 |
+
raw_display['O/U'] = np.where(raw_display['No Vig'] > raw_display['Projection'], 'Under', 'Over')
|
| 98 |
+
bet_sheet = raw_display[['Player', 'prop_type', 'O/U', 'No Vig', 'Projection', 'Edge']]
|
| 99 |
|
| 100 |
collection = dfs_db["Prop_Trends"]
|
| 101 |
cursor = collection.find()
|
|
|
|
| 119 |
market_props['under_prop'] = market_props['Projection']
|
| 120 |
market_props['under_line'] = market_props['under_pay'].apply(lambda x: (x - 1) * 100 if x >= 2.0 else -100 / (x - 1))
|
| 121 |
|
| 122 |
+
return game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet
|
| 123 |
|
| 124 |
def calculate_no_vig(row):
|
| 125 |
def implied_probability(american_odds):
|
|
|
|
| 162 |
|
| 163 |
selected_tab = st.segmented_control(
|
| 164 |
"Select Tab",
|
| 165 |
+
options=["Bet Sheet", "Game Betting Model", 'Prop Market', "QB Projections", "RB/WR/TE Projections", "Player Prop Trends", "Player Prop Simulations", "Stat Specific Simulations"],
|
| 166 |
selection_mode='single',
|
| 167 |
+
default='Bet Sheet',
|
| 168 |
width='stretch',
|
| 169 |
label_visibility='collapsed',
|
| 170 |
key='tab_selector'
|
| 171 |
)
|
| 172 |
|
| 173 |
+
if selected_tab == 'Bet Sheet':
|
| 174 |
+
with st.expander("Info and Filters"):
|
| 175 |
+
st.info(t_stamp)
|
| 176 |
+
if st.button("Reset Data", key='reset_bet_sheet'):
|
| 177 |
+
st.cache_data.clear()
|
| 178 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 179 |
+
t_stamp = f"Last Update: " + str(timestamp) + f" CST"
|
| 180 |
+
prop_selection = st.multiselect('Select prop type to view', default = bet_sheet['prop_type'].unique(), options = bet_sheet['prop_type'].unique(), key='prop_selection')
|
| 181 |
+
bet_sheet = bet_sheet[bet_sheet['prop_type'].isin(prop_selection)]
|
| 182 |
+
st.dataframe(bet_sheet.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(bet_format, precision=2), use_container_width = True)
|
| 183 |
+
st.download_button(
|
| 184 |
+
label="Export Bet Sheet",
|
| 185 |
+
data=convert_df_to_csv(bet_sheet),
|
| 186 |
+
file_name='NFL_bet_sheet_export.csv',
|
| 187 |
+
mime='text/csv',
|
| 188 |
+
key='bet_sheet_export',
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
if selected_tab == 'Game Betting Model':
|
| 192 |
st.info(t_stamp)
|
| 193 |
if st.button("Reset Data", key='reset1'):
|
| 194 |
st.cache_data.clear()
|
| 195 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 196 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 197 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 198 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
|
|
| 225 |
st.info(t_stamp)
|
| 226 |
if st.button("Reset Data", key='reset4'):
|
| 227 |
st.cache_data.clear()
|
| 228 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 229 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 230 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 231 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
|
|
| 265 |
st.info(t_stamp)
|
| 266 |
if st.button("Reset Data", key='reset2'):
|
| 267 |
st.cache_data.clear()
|
| 268 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 269 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 270 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 271 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
|
|
| 293 |
st.info(t_stamp)
|
| 294 |
if st.button("Reset Data", key='reset3'):
|
| 295 |
st.cache_data.clear()
|
| 296 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 297 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 298 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 299 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
|
|
| 321 |
st.info(t_stamp)
|
| 322 |
if st.button("Reset Data", key='reset5'):
|
| 323 |
st.cache_data.clear()
|
| 324 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 325 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 326 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 327 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|
|
|
|
| 352 |
st.info(t_stamp)
|
| 353 |
if st.button("Reset Data", key='reset6'):
|
| 354 |
st.cache_data.clear()
|
| 355 |
+
game_model, overall_stats, timestamp, prop_frame, prop_trends, pick_frame, market_props, bet_sheet = init_baselines()
|
| 356 |
qb_stats = overall_stats[overall_stats['Position'] == 'QB']
|
| 357 |
qb_stats = qb_stats.drop_duplicates(subset=['Player', 'Position'])
|
| 358 |
non_qb_stats = overall_stats[overall_stats['Position'] != 'QB']
|