NFL_DFS_Contest_Sims / src /streamlit_app.py
James McCool
Add database connection module and refactor Streamlit app to utilize it, improving code organization and data handling for simulations.
f70d907
raw
history blame
51.7 kB
import streamlit as st
import numpy as np
import pandas as pd
import pymongo
import re
import os
from itertools import combinations
st.set_page_config(layout="wide")
from database import db
from sim_func_hold.regular_functions import *
from sim_func_hold.showdown_functions import *
percentages_format = {'Exposure': '{:.2%}'}
freq_format = {'Exposure': '{:.2%}', 'Proj Own': '{:.2%}', 'Edge': '{:.2%}'}
dk_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
fd_columns = ['QB', 'RB1', 'RB2', 'WR1', 'WR2', 'WR3', 'TE', 'FLEX', 'DST', 'salary', 'proj', 'Team', 'Team_count', 'Secondary', 'Secondary_count', 'Own']
st.markdown("""
<style>
/* Tab styling */
.stElementContainer [data-baseweb="button-group"] {
gap: 8px;
padding: 4px;
}
.stElementContainer [kind="segmented_control"] {
height: 45px;
white-space: pre-wrap;
background-color: #DAA520;
color: white;
border-radius: 10px;
gap: 1px;
padding: 10px 20px;
font-weight: bold;
transition: all 0.3s ease;
}
.stElementContainer [kind="segmented_controlActive"] {
height: 50px;
background-color: #DAA520;
border: 3px solid #FFD700;
color: white;
}
.stElementContainer [kind="segmented_control"]:hover {
background-color: #FFD700;
cursor: pointer;
}
div[data-baseweb="select"] > div {
background-color: #DAA520;
color: white;
}
</style>""", unsafe_allow_html=True)
if st.button("Load/Reset Data", key='reset2'):
st.cache_data.clear()
for key in st.session_state.keys():
del st.session_state[key]
DK_seed = init_DK_seed_frames('Main Slate', 10000)
DK_sd_seed = init_DK_SD_seed_frames('Main Slate', 10000)
FD_seed = init_FD_seed_frames('Main Slate', 10000)
FD_sd_seed = init_FD_SD_seed_frames('Main Slate', 10000)
dk_raw, fd_raw = init_baselines('Main Slate')
dk_sd_raw, fd_sd_raw = init_SD_baselines('Main Slate')
dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
dk_sd_id_dict = dict(zip(dk_sd_raw.Player, dk_sd_raw.player_ID))
fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
fd_sd_id_dict = dict(zip(fd_sd_raw.Player, fd_sd_raw.player_ID))
selected_tab = st.segmented_control(
"Select Tab",
options=["Regular Slate Contest Sims", "Showdown Contest Sims"],
selection_mode='single',
default='Regular Slate Contest Sims',
width='stretch',
label_visibility='collapsed',
key='tab_selector'
)
if selected_tab == "Regular Slate Contest Sims":
dk_raw, fd_raw = init_baselines('Main Slate')
raw_baselines = dk_raw
column_names = dk_columns
with st.expander("Info and Filters"):
site_data_col, slate_data_col, contest_size_col, contest_sharpness_col = st.columns([1, 1, 1, 1])
with site_data_col:
sim_site_var1 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='sim_site_var1')
with slate_data_col:
sim_slate_var1 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='sim_slate_var1')
with contest_size_col:
contest_var1 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large'))
if contest_var1 == 'Small':
Contest_Size = 1000
elif contest_var1 == 'Medium':
Contest_Size = 5000
elif contest_var1 == 'Large':
Contest_Size = 10000
elif contest_var1 == 'Custom':
Contest_Size = st.number_input("Insert contest size", value=100, placeholder="Type a number under 10,000...")
with contest_sharpness_col:
strength_var1 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'))
if strength_var1 == 'Not Very':
sharp_split = 500000
elif strength_var1 == 'Below Average':
sharp_split = 250000
elif strength_var1 == 'Average':
sharp_split = 100000
elif strength_var1 == 'Above Average':
sharp_split = 50000
elif strength_var1 == 'Very':
sharp_split = 10000
if st.button("Run Contest Sim"):
if 'working_seed' not in st.session_state:
if sim_site_var1 == 'Draftkings':
st.session_state.working_seed = init_DK_seed_frames(sim_slate_var1, sharp_split)
dk_raw, fd_raw = init_baselines(sim_slate_var1)
dk_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
raw_baselines = dk_raw
column_names = dk_columns
elif sim_site_var1 == 'Fanduel':
st.session_state.working_seed = init_FD_seed_frames(sim_slate_var1, sharp_split)
dk_raw, fd_raw = init_baselines(sim_slate_var1)
fd_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
raw_baselines = fd_raw
column_names = fd_columns
st.session_state.maps_dict = {
'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
}
Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size)
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
#st.table(Sim_Winner_Frame)
# Initial setup
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
# Type Casting
type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
# Sorting
st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
# Data Copying
st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
if sim_site_var1 == 'Draftkings':
for col in st.session_state.Sim_Winner_Export.iloc[:, 0:9].columns:
st.session_state.Sim_Winner_Export[col] = st.session_state.Sim_Winner_Export[col].map(dk_id_dict)
elif sim_site_var1 == 'Fanduel':
for col in st.session_state.Sim_Winner_Export.iloc[:, 0:9].columns:
st.session_state.Sim_Winner_Export[col] = st.session_state.Sim_Winner_Export[col].map(fd_id_dict)
# Data Copying
st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
st.session_state.freq_copy = st.session_state.Sim_Winner_Display
else:
st.session_state.maps_dict = {
'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev))
}
Sim_Winners = sim_contest(1000, st.session_state.working_seed, st.session_state.maps_dict, Contest_Size)
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
# Initial setup
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
# Type Casting
type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
# Sorting
st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
# Data Copying
st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
# Data Copying
st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
if sim_site_var1 == 'Draftkings':
freq_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:9].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
freq_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:9].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
freq_working['Freq'] = freq_working['Freq'].astype(int)
freq_working['Position'] = freq_working['Player'].map(st.session_state.maps_dict['Pos_map'])
freq_working['Salary'] = freq_working['Player'].map(st.session_state.maps_dict['Salary_map'])
freq_working['Proj Own'] = freq_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
freq_working['Exposure'] = freq_working['Freq']/(1000)
freq_working['Edge'] = freq_working['Exposure'] - freq_working['Proj Own']
freq_working['Team'] = freq_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.player_freq = freq_working.copy()
if sim_site_var1 == 'Draftkings':
qb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:1].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
qb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,0:1].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
qb_working['Freq'] = qb_working['Freq'].astype(int)
qb_working['Position'] = qb_working['Player'].map(st.session_state.maps_dict['Pos_map'])
qb_working['Salary'] = qb_working['Player'].map(st.session_state.maps_dict['Salary_map'])
qb_working['Proj Own'] = qb_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
qb_working['Exposure'] = qb_working['Freq']/(1000)
qb_working['Edge'] = qb_working['Exposure'] - qb_working['Proj Own']
qb_working['Team'] = qb_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.qb_freq = qb_working.copy()
if sim_site_var1 == 'Draftkings':
rbwrte_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:7].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
rbwrte_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:7].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
rbwrte_working['Freq'] = rbwrte_working['Freq'].astype(int)
rbwrte_working['Position'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Pos_map'])
rbwrte_working['Salary'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Salary_map'])
rbwrte_working['Proj Own'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
rbwrte_working['Exposure'] = rbwrte_working['Freq']/(1000)
rbwrte_working['Edge'] = rbwrte_working['Exposure'] - rbwrte_working['Proj Own']
rbwrte_working['Team'] = rbwrte_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.rbwrte_freq = rbwrte_working.copy()
if sim_site_var1 == 'Draftkings':
rb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:3].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
rb_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,1:3].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
rb_working['Freq'] = rb_working['Freq'].astype(int)
rb_working['Position'] = rb_working['Player'].map(st.session_state.maps_dict['Pos_map'])
rb_working['Salary'] = rb_working['Player'].map(st.session_state.maps_dict['Salary_map'])
rb_working['Proj Own'] = rb_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
rb_working['Exposure'] = rb_working['Freq']/(1000)
rb_working['Edge'] = rb_working['Exposure'] - rb_working['Proj Own']
rb_working['Team'] = rb_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.rb_freq = rb_working.copy()
if sim_site_var1 == 'Draftkings':
wr_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,3:6].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
wr_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,3:6].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
wr_working['Freq'] = wr_working['Freq'].astype(int)
wr_working['Position'] = wr_working['Player'].map(st.session_state.maps_dict['Pos_map'])
wr_working['Salary'] = wr_working['Player'].map(st.session_state.maps_dict['Salary_map'])
wr_working['Proj Own'] = wr_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
wr_working['Exposure'] = wr_working['Freq']/(1000)
wr_working['Edge'] = wr_working['Exposure'] - wr_working['Proj Own']
wr_working['Team'] = wr_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.wr_freq = wr_working.copy()
if sim_site_var1 == 'Draftkings':
te_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,6:7].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
te_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,6:7].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
te_working['Freq'] = te_working['Freq'].astype(int)
te_working['Position'] = te_working['Player'].map(st.session_state.maps_dict['Pos_map'])
te_working['Salary'] = te_working['Player'].map(st.session_state.maps_dict['Salary_map'])
te_working['Proj Own'] = te_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
te_working['Exposure'] = te_working['Freq']/(1000)
te_working['Edge'] = te_working['Exposure'] - te_working['Proj Own']
te_working['Team'] = te_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.te_freq = te_working.copy()
if sim_site_var1 == 'Draftkings':
flex_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,7:8].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
flex_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,7:8].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
flex_working['Freq'] = flex_working['Freq'].astype(int)
flex_working['Position'] = flex_working['Player'].map(st.session_state.maps_dict['Pos_map'])
flex_working['Salary'] = flex_working['Player'].map(st.session_state.maps_dict['Salary_map'])
flex_working['Proj Own'] = flex_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
flex_working['Exposure'] = flex_working['Freq']/(1000)
flex_working['Edge'] = flex_working['Exposure'] - flex_working['Proj Own']
flex_working['Team'] = flex_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.flex_freq = flex_working.copy()
if sim_site_var1 == 'Draftkings':
dst_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,8:9].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
dst_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,8:9].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
dst_working['Freq'] = dst_working['Freq'].astype(int)
dst_working['Position'] = dst_working['Player'].map(st.session_state.maps_dict['Pos_map'])
dst_working['Salary'] = dst_working['Player'].map(st.session_state.maps_dict['Salary_map'])
dst_working['Proj Own'] = dst_working['Player'].map(st.session_state.maps_dict['Own_map']) / 100
dst_working['Exposure'] = dst_working['Freq']/(1000)
dst_working['Edge'] = dst_working['Exposure'] - dst_working['Proj Own']
dst_working['Team'] = dst_working['Player'].map(st.session_state.maps_dict['Team_map'])
st.session_state.dst_freq = dst_working.copy()
if sim_site_var1 == 'Draftkings':
team_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,11:12].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var1 == 'Fanduel':
team_working = pd.DataFrame(np.column_stack(np.unique(st.session_state.freq_copy.iloc[:,11:12].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
team_working['Freq'] = team_working['Freq'].astype(int)
team_working['Exposure'] = team_working['Freq']/(1000)
st.session_state.team_freq = team_working.copy()
with st.container():
if st.button("Reset Sim", key='reset_sim'):
for key in st.session_state.keys():
del st.session_state[key]
if 'player_freq' in st.session_state:
player_split_var2 = st.radio("Are you wanting to isolate any lineups with specific players?", ('Full Players', 'Specific Players'), key='player_split_var2')
if player_split_var2 == 'Specific Players':
find_var2 = st.multiselect('Which players must be included in the lineups?', options = st.session_state.player_freq['Player'].unique())
elif player_split_var2 == 'Full Players':
find_var2 = st.session_state.player_freq.Player.values.tolist()
if player_split_var2 == 'Specific Players':
st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame[np.equal.outer(st.session_state.Sim_Winner_Frame.to_numpy(), find_var2).any(axis=1).all(axis=1)]
if player_split_var2 == 'Full Players':
st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame
if 'Sim_Winner_Display' in st.session_state:
st.dataframe(st.session_state.Sim_Winner_Display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
if 'Sim_Winner_Export' in st.session_state:
st.download_button(
label="Export Full Frame",
data=st.session_state.Sim_Winner_Export.to_csv().encode('utf-8'),
file_name='MLB_consim_export.csv',
mime='text/csv',
)
tab1, tab2 = st.tabs(['Winning Frame Statistics', 'Flex Exposure Statistics'])
with tab1:
if 'Sim_Winner_Display' in st.session_state:
# Create a new dataframe with summary statistics
summary_df = pd.DataFrame({
'Metric': ['Min', 'Average', 'Max', 'STDdev'],
'Salary': [
st.session_state.Sim_Winner_Display['salary'].min(),
st.session_state.Sim_Winner_Display['salary'].mean(),
st.session_state.Sim_Winner_Display['salary'].max(),
st.session_state.Sim_Winner_Display['salary'].std()
],
'Proj': [
st.session_state.Sim_Winner_Display['proj'].min(),
st.session_state.Sim_Winner_Display['proj'].mean(),
st.session_state.Sim_Winner_Display['proj'].max(),
st.session_state.Sim_Winner_Display['proj'].std()
],
'Own': [
st.session_state.Sim_Winner_Display['Own'].min(),
st.session_state.Sim_Winner_Display['Own'].mean(),
st.session_state.Sim_Winner_Display['Own'].max(),
st.session_state.Sim_Winner_Display['Own'].std()
],
'Fantasy': [
st.session_state.Sim_Winner_Display['Fantasy'].min(),
st.session_state.Sim_Winner_Display['Fantasy'].mean(),
st.session_state.Sim_Winner_Display['Fantasy'].max(),
st.session_state.Sim_Winner_Display['Fantasy'].std()
],
'GPP_Proj': [
st.session_state.Sim_Winner_Display['GPP_Proj'].min(),
st.session_state.Sim_Winner_Display['GPP_Proj'].mean(),
st.session_state.Sim_Winner_Display['GPP_Proj'].max(),
st.session_state.Sim_Winner_Display['GPP_Proj'].std()
]
})
# Set the index of the summary dataframe as the "Metric" column
summary_df = summary_df.set_index('Metric')
# Display the summary dataframe
st.subheader("Winning Frame Statistics")
st.dataframe(summary_df.style.format({
'Salary': '{:.2f}',
'Proj': '{:.2f}',
'Fantasy': '{:.2f}',
'GPP_Proj': '{:.2f}'
}).background_gradient(cmap='RdYlGn', axis=0, subset=['Salary', 'Proj', 'Own', 'Fantasy', 'GPP_Proj']), use_container_width=True)
with tab2:
if 'Sim_Winner_Display' in st.session_state:
# Apply position mapping to FLEX column
flex_positions = st.session_state.freq_copy['FLEX'].map(st.session_state.maps_dict['Pos_map'])
# Count occurrences of each position in FLEX
flex_counts = flex_positions.value_counts()
# Calculate average statistics for each FLEX position
flex_stats = st.session_state.freq_copy.groupby(flex_positions).agg({
'proj': 'mean',
'Own': 'mean',
'Fantasy': 'mean',
'GPP_Proj': 'mean'
})
# Combine counts and average statistics
flex_summary = pd.concat([flex_counts, flex_stats], axis=1)
flex_summary.columns = ['Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']
flex_summary = flex_summary.reset_index()
flex_summary.columns = ['Position', 'Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']
# Display the summary dataframe
st.subheader("FLEX Position Statistics")
st.dataframe(flex_summary.style.format({
'Count': '{:.0f}',
'Avg Proj': '{:.2f}',
'Avg Fantasy': '{:.2f}',
'Avg GPP_Proj': '{:.2f}'
}).background_gradient(cmap='RdYlGn', axis=0, subset=['Count', 'Avg Proj', 'Avg Own', 'Avg Fantasy', 'Avg GPP_Proj']), use_container_width=True)
else:
st.write("Simulation data or position mapping not available.")
with st.container():
tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8, tab9 = st.tabs(['Overall Exposures', 'QB Exposures', 'RB-WR-TE Exposures', 'RB Exposures', 'WR Exposures', 'TE Exposures', 'FLEX Exposures', 'DST Exposures', 'Team Exposures'])
with tab1:
if 'player_freq' in st.session_state:
st.dataframe(st.session_state.player_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.player_freq.to_csv().encode('utf-8'),
file_name='player_freq_export.csv',
mime='text/csv',
key='overall'
)
with tab2:
if 'qb_freq' in st.session_state:
st.dataframe(st.session_state.qb_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.qb_freq.to_csv().encode('utf-8'),
file_name='qb_freq.csv',
mime='text/csv',
key='qb'
)
with tab3:
if 'rbwrte_freq' in st.session_state:
st.dataframe(st.session_state.rbwrte_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.rbwrte_freq.to_csv().encode('utf-8'),
file_name='rbwrte_freq.csv',
mime='text/csv',
key='rbwrte'
)
with tab4:
if 'rb_freq' in st.session_state:
st.dataframe(st.session_state.rb_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.rb_freq.to_csv().encode('utf-8'),
file_name='rb_freq.csv',
mime='text/csv',
key='rb'
)
with tab5:
if 'wr_freq' in st.session_state:
st.dataframe(st.session_state.wr_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.wr_freq.to_csv().encode('utf-8'),
file_name='wr_freq.csv',
mime='text/csv',
key='wr'
)
with tab6:
if 'te_freq' in st.session_state:
st.dataframe(st.session_state.te_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.te_freq.to_csv().encode('utf-8'),
file_name='te_freq.csv',
mime='text/csv',
key='te'
)
with tab7:
if 'flex_freq' in st.session_state:
st.dataframe(st.session_state.flex_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.flex_freq.to_csv().encode('utf-8'),
file_name='flex_freq.csv',
mime='text/csv',
key='flex'
)
with tab8:
if 'dst_freq' in st.session_state:
st.dataframe(st.session_state.dst_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.dst_freq.to_csv().encode('utf-8'),
file_name='dst_freq.csv',
mime='text/csv',
key='dst'
)
with tab9:
if 'team_freq' in st.session_state:
st.dataframe(st.session_state.team_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.team_freq.to_csv().encode('utf-8'),
file_name='team_freq.csv',
mime='text/csv',
key='team'
)
if selected_tab == "Showdown Contest Sims":
dk_raw, fd_raw = init_SD_baselines('Main Slate')
raw_baselines = dk_raw
column_names = dk_columns
with st.expander("Info and Filters"):
site_data_col, slate_data_col, contest_size_col, contest_sharpness_col = st.columns([1, 1, 1, 1])
with site_data_col:
sim_site_var2 = st.radio("What site are you working with?", ('Draftkings', 'Fanduel'), key='sim_site_var2')
with slate_data_col:
sim_slate_var2 = st.radio("Which data are you loading?", ('Main Slate', 'Secondary Slate'), key='sim_slate_var2')
with contest_size_col:
contest_var2 = st.selectbox("What contest size are you simulating?", ('Small', 'Medium', 'Large'), key='contest_var2')
if contest_var2 == 'Small':
Contest_Size = 1000
elif contest_var2 == 'Medium':
Contest_Size = 5000
elif contest_var2 == 'Large':
Contest_Size = 10000
elif contest_var2 == 'Custom':
Contest_Size = st.number_input("Insert contest size", value=100, placeholder="Type a number under 10,000...")
with contest_sharpness_col:
strength_var2 = st.selectbox("How sharp is the field in the contest?", ('Very', 'Above Average', 'Average', 'Below Average', 'Not Very'), key='strength_var2')
if strength_var2 == 'Not Very':
sharp_split = 500000
elif strength_var2 == 'Below Average':
sharp_split = 250000
elif strength_var2 == 'Average':
sharp_split = 100000
elif strength_var2 == 'Above Average':
sharp_split = 50000
elif strength_var2 == 'Very':
sharp_split = 10000
if st.button("Run Contest Sim"):
if 'sd_working_seed' not in st.session_state:
if sim_site_var2 == 'Draftkings':
st.session_state.sd_working_seed = init_DK_SD_seed_frames(sim_slate_var2, sharp_split)
export_id_dict = dict(zip(dk_raw.Player, dk_raw.player_ID))
raw_baselines = dk_raw
column_names = dk_columns
elif sim_site_var2 == 'Fanduel':
st.session_state.sd_working_seed = init_FD_SD_seed_frames(sim_slate_var2, sharp_split)
export_id_dict = dict(zip(fd_raw.Player, fd_raw.player_ID))
raw_baselines = fd_raw
column_names = fd_columns
maps_dict = {
'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
'cpt_projection_map':dict(zip(raw_baselines.Player,raw_baselines.cpt_Median)),
'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
'cpt_Own_map':dict(zip(raw_baselines.Player,raw_baselines['CPT_Own'])),
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev)),
'cpt_STDev_map':dict(zip(raw_baselines.Player,raw_baselines['CPT_STDev']))
}
Sim_Winners = sim_SD_contest(1000, st.session_state.sd_working_seed, maps_dict, Contest_Size)
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
#st.table(Sim_Winner_Frame)
# Initial setup
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
# Add percent rank columns for ownership at each roster position
# Calculate Dupes column for Fanduel
dup_count_columns = ['CPT_Own_percent_rank', 'FLEX1_Own_percent_rank', 'FLEX2_Own_percent_rank', 'FLEX3_Own_percent_rank', 'FLEX4_Own_percent_rank', 'FLEX5_Own_percent_rank']
own_columns = ['CPT_Own', 'FLEX1_Own', 'FLEX2_Own', 'FLEX3_Own', 'FLEX4_Own', 'FLEX5_Own']
calc_columns = ['own_product', 'avg_own_rank', 'dupes_calc']
Sim_Winner_Frame['CPT_Own_percent_rank'] = Sim_Winner_Frame.iloc[:,0].map(maps_dict['cpt_Own_map']).rank(pct=True)
Sim_Winner_Frame['FLEX1_Own_percent_rank'] = Sim_Winner_Frame.iloc[:,1].map(maps_dict['Own_map']).rank(pct=True)
Sim_Winner_Frame['FLEX2_Own_percent_rank'] = Sim_Winner_Frame.iloc[:,2].map(maps_dict['Own_map']).rank(pct=True)
Sim_Winner_Frame['FLEX3_Own_percent_rank'] = Sim_Winner_Frame.iloc[:,3].map(maps_dict['Own_map']).rank(pct=True)
Sim_Winner_Frame['FLEX4_Own_percent_rank'] = Sim_Winner_Frame.iloc[:,4].map(maps_dict['Own_map']).rank(pct=True)
Sim_Winner_Frame['FLEX5_Own_percent_rank'] = Sim_Winner_Frame.iloc[:,5].map(maps_dict['Own_map']).rank(pct=True)
Sim_Winner_Frame['CPT_Own'] = Sim_Winner_Frame.iloc[:,0].map(maps_dict['cpt_Own_map']) / 100
Sim_Winner_Frame['FLEX1_Own'] = Sim_Winner_Frame.iloc[:,1].map(maps_dict['Own_map']) / 100
Sim_Winner_Frame['FLEX2_Own'] = Sim_Winner_Frame.iloc[:,2].map(maps_dict['Own_map']) / 100
Sim_Winner_Frame['FLEX3_Own'] = Sim_Winner_Frame.iloc[:,3].map(maps_dict['Own_map']) / 100
Sim_Winner_Frame['FLEX4_Own'] = Sim_Winner_Frame.iloc[:,4].map(maps_dict['Own_map']) / 100
Sim_Winner_Frame['FLEX5_Own'] = Sim_Winner_Frame.iloc[:,5].map(maps_dict['Own_map']) / 100
# Calculate ownership product and convert to probability
Sim_Winner_Frame['own_product'] = (Sim_Winner_Frame[own_columns].product(axis=1))
# Calculate average of ownership percent rank columns
Sim_Winner_Frame['avg_own_rank'] = Sim_Winner_Frame[dup_count_columns].mean(axis=1)
# Calculate dupes formula
Sim_Winner_Frame['dupes_calc'] = ((Sim_Winner_Frame['own_product'] * Sim_Winner_Frame['avg_own_rank']) * (Contest_Size * 1.5)) + ((Sim_Winner_Frame['salary'] - 49800) / 100)
# Round and handle negative values
Sim_Winner_Frame['Dupes'] = np.where(
np.round(Sim_Winner_Frame['dupes_calc'], 0) <= 0,
0,
np.round(Sim_Winner_Frame['dupes_calc'], 0) - 1
)
Sim_Winner_Frame['Dupes'] = (Sim_Winner_Frame['Dupes'] * (500000 / sharp_split)) / 2
Sim_Winner_Frame['Dupes'] = np.round(Sim_Winner_Frame['Dupes'], 0)
Sim_Winner_Frame['Dupes'] = np.where(
np.round(Sim_Winner_Frame['dupes_calc'], 0) <= 0,
0,
np.round(Sim_Winner_Frame['dupes_calc'], 0)
)
Sim_Winner_Frame = Sim_Winner_Frame.drop(columns=dup_count_columns)
Sim_Winner_Frame = Sim_Winner_Frame.drop(columns=own_columns)
Sim_Winner_Frame = Sim_Winner_Frame.drop(columns=calc_columns)
Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
# Type Casting
type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32, 'Dupes': int}
Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
# Sorting
st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
# Data Copying
st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
st.session_state.Sim_Winner_Export.iloc[:, 0:6] = st.session_state.Sim_Winner_Export.iloc[:, 0:6].apply(lambda x: x.map(export_id_dict))
# Data Copying
st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
freq_copy = st.session_state.Sim_Winner_Display
else:
maps_dict = {
'Projection_map':dict(zip(raw_baselines.Player,raw_baselines.Median)),
'cpt_projection_map':dict(zip(raw_baselines.Player,raw_baselines.cpt_Median)),
'Salary_map':dict(zip(raw_baselines.Player,raw_baselines.Salary)),
'Pos_map':dict(zip(raw_baselines.Player,raw_baselines.Position)),
'Own_map':dict(zip(raw_baselines.Player,raw_baselines['Own'])),
'cpt_Own_map':dict(zip(raw_baselines.Player,raw_baselines['CPT_Own'])),
'Team_map':dict(zip(raw_baselines.Player,raw_baselines.Team)),
'STDev_map':dict(zip(raw_baselines.Player,raw_baselines.STDev)),
'cpt_STDev_map':dict(zip(raw_baselines.Player,raw_baselines['CPT_STDev']))
}
Sim_Winners = sim_SD_contest(1000, st.session_state.working_seed, maps_dict, Contest_Size)
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners))
#st.table(Sim_Winner_Frame)
# Initial setup
Sim_Winner_Frame = pd.DataFrame(np.concatenate(Sim_Winners), columns=column_names + ['Fantasy'])
Sim_Winner_Frame['GPP_Proj'] = (Sim_Winner_Frame['proj'] + Sim_Winner_Frame['Fantasy']) / 2
Sim_Winner_Frame['unique_id'] = Sim_Winner_Frame['proj'].astype(str) + Sim_Winner_Frame['salary'].astype(str) + Sim_Winner_Frame['Team'].astype(str) + Sim_Winner_Frame['Secondary'].astype(str)
Sim_Winner_Frame = Sim_Winner_Frame.assign(win_count=Sim_Winner_Frame['unique_id'].map(Sim_Winner_Frame['unique_id'].value_counts()))
# Type Casting
type_cast_dict = {'salary': int, 'proj': np.float16, 'Fantasy': np.float16, 'GPP_Proj': np.float32, 'Own': np.float32}
Sim_Winner_Frame = Sim_Winner_Frame.astype(type_cast_dict)
# Sorting
st.session_state.Sim_Winner_Frame = Sim_Winner_Frame.sort_values(by=['win_count', 'GPP_Proj'], ascending= [False, False]).copy().drop_duplicates(subset='unique_id').head(100)
st.session_state.Sim_Winner_Frame.drop(columns='unique_id', inplace=True)
# Data Copying
st.session_state.Sim_Winner_Export = Sim_Winner_Frame.copy()
# Data Copying
st.session_state.Sim_Winner_Display = Sim_Winner_Frame.copy()
freq_copy = st.session_state.Sim_Winner_Display
if sim_site_var2 == 'Draftkings':
freq_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,0:6].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
elif sim_site_var2 == 'Fanduel':
freq_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,0:5].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
freq_working['Freq'] = freq_working['Freq'].astype(int)
freq_working['Position'] = freq_working['Player'].map(maps_dict['Pos_map'])
freq_working['Salary'] = freq_working['Player'].map(maps_dict['Salary_map']) / 1.5
freq_working['Proj Own'] = freq_working['Player'].map(maps_dict['Own_map']) / 100
freq_working['Exposure'] = freq_working['Freq']/(1000)
freq_working['Edge'] = freq_working['Exposure'] - freq_working['Proj Own']
freq_working['Team'] = freq_working['Player'].map(maps_dict['Team_map'])
st.session_state.player_freq = freq_working.copy()
cpt_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,0:1].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
cpt_working['Freq'] = cpt_working['Freq'].astype(int)
cpt_working['Position'] = cpt_working['Player'].map(maps_dict['Pos_map'])
cpt_working['Salary'] = cpt_working['Player'].map(maps_dict['Salary_map'])
cpt_working['Proj Own'] = cpt_working['Player'].map(maps_dict['cpt_Own_map']) / 100
cpt_working['Exposure'] = cpt_working['Freq']/(1000)
cpt_working['Edge'] = cpt_working['Exposure'] - cpt_working['Proj Own']
cpt_working['Team'] = cpt_working['Player'].map(maps_dict['Team_map'])
st.session_state.sp_freq = cpt_working.copy()
flex_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,1:6].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
cpt_own_div = 600
flex_working['Freq'] = flex_working['Freq'].astype(int)
flex_working['Position'] = flex_working['Player'].map(maps_dict['Pos_map'])
flex_working['Salary'] = flex_working['Player'].map(maps_dict['Salary_map']) / 1.5
flex_working['Proj Own'] = (flex_working['Player'].map(maps_dict['Own_map']) / 100) - (flex_working['Player'].map(maps_dict['cpt_Own_map']) / 100)
flex_working['Exposure'] = flex_working['Freq']/(1000)
flex_working['Edge'] = flex_working['Exposure'] - flex_working['Proj Own']
flex_working['Team'] = flex_working['Player'].map(maps_dict['Team_map'])
st.session_state.flex_freq = flex_working.copy()
team_working = pd.DataFrame(np.column_stack(np.unique(freq_copy.iloc[:,8:9].values, return_counts=True)),
columns=['Player','Freq']).sort_values('Freq', ascending=False).reset_index(drop=True)
team_working['Freq'] = team_working['Freq'].astype(int)
team_working['Exposure'] = team_working['Freq']/(1000)
st.session_state.team_freq = team_working.copy()
with st.container():
if st.button("Reset Sim", key='reset_sim'):
for key in st.session_state.keys():
del st.session_state[key]
if 'player_freq' in st.session_state:
player_split_var2 = st.radio("Are you wanting to isolate any lineups with specific players?", ('Full Players', 'Specific Players'), key='player_split_var2')
if player_split_var2 == 'Specific Players':
find_var2 = st.multiselect('Which players must be included in the lineups?', options = st.session_state.player_freq['Player'].unique())
elif player_split_var2 == 'Full Players':
find_var2 = st.session_state.player_freq.Player.values.tolist()
if player_split_var2 == 'Specific Players':
st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame[np.equal.outer(st.session_state.Sim_Winner_Frame.to_numpy(), find_var2).any(axis=1).all(axis=1)]
if player_split_var2 == 'Full Players':
st.session_state.Sim_Winner_Display = st.session_state.Sim_Winner_Frame
if 'Sim_Winner_Display' in st.session_state:
st.dataframe(st.session_state.Sim_Winner_Display.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(precision=2), use_container_width = True)
if 'Sim_Winner_Export' in st.session_state:
st.download_button(
label="Export Full Frame",
data=st.session_state.Sim_Winner_Export.to_csv().encode('utf-8'),
file_name='NFL_SD_consim_export.csv',
mime='text/csv',
)
with st.container():
tab1, tab2, tab3, tab4 = st.tabs(['Overall Exposures', 'CPT Exposures', 'FLEX Exposures', 'Team Exposures'])
with tab1:
if 'player_freq' in st.session_state:
st.dataframe(st.session_state.player_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.player_freq.to_csv().encode('utf-8'),
file_name='player_freq_export.csv',
mime='text/csv',
key='overall'
)
with tab2:
if 'sp_freq' in st.session_state:
st.dataframe(st.session_state.sp_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.sp_freq.to_csv().encode('utf-8'),
file_name='cpt_freq.csv',
mime='text/csv',
key='sp'
)
with tab3:
if 'flex_freq' in st.session_state:
st.dataframe(st.session_state.flex_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(freq_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.flex_freq.to_csv().encode('utf-8'),
file_name='flex_freq.csv',
mime='text/csv',
key='flex'
)
with tab4:
if 'team_freq' in st.session_state:
st.dataframe(st.session_state.team_freq.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(percentages_format, precision=2), use_container_width = True)
st.download_button(
label="Export Exposures",
data=st.session_state.team_freq.to_csv().encode('utf-8'),
file_name='team_freq.csv',
mime='text/csv',
key='team'
)