Custom_ROO_Tool / app.py
James McCool
Add MLB support to ROO build functions and Streamlit display, including percentage formatting and data upload instructions
95b08b3
#initial imports
import streamlit as st
st.set_page_config(layout="wide")
import numpy as np
import pandas as pd
import time
from fuzzywuzzy import process
# Bring in numpy reqs
from numpy import nan as np_nan
from numpy import where as np_where
from numpy import random as np_random
from numpy import zeros as np_zeros
from numpy import array as np_array
from pandas import concat as pd_concat
from pandas import merge as pd_merge
from pandas import DataFrame
#bring in functions
from function_hold.NBA_functions import DK_NBA_ROO_Build, FD_NBA_ROO_Build
from function_hold.MMA_functions import DK_MMA_ROO_Build, FD_MMA_ROO_Build
from function_hold.NHL_functions import DK_NHL_ROO_Build, FD_NHL_ROO_Build
from function_hold.NFL_functions import DK_NFL_ROO_Build, FD_NFL_ROO_Build
from function_hold.MLB_functions import DK_MLB_ROO_Build, FD_MLB_ROO_Build
nba_percentages_format = {'Top_finish': '{:.2%}', 'Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '4x%': '{:.2%}', '5x%': '{:.2%}', '6x%': '{:.2%}', 'GPP%': '{:.2%}'}
nhl_percentages_format = {'Top_finish': '{:.2%}', 'Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '4x%': '{:.2%}', '5x%': '{:.2%}', '6x%': '{:.2%}', 'GPP%': '{:.2%}'}
nfl_percentages_format = {'Top_finish': '{:.2%}', 'Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '4x%': '{:.2%}', '5x%': '{:.2%}', '6x%': '{:.2%}', 'GPP%': '{:.2%}'}
mma_percentages_format = {'Top_finish': '{:.2%}', 'Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '100+%': '{:.2%}', '10x%': '{:.2%}', '11x%': '{:.2%}', '12x%': '{:.2%}', 'GPP%': '{:.2%}'}
mlb_percentages_format = {'Top_finish': '{:.2%}', 'Top_5_finish': '{:.2%}', 'Top_10_finish': '{:.2%}', '20+%': '{:.2%}', '2x%': '{:.2%}', '3x%': '{:.2%}', '4x%': '{:.2%}', 'GPP%': '{:.2%}'}
def load_file(upload):
if upload is not None:
try:
if upload.name.endswith('.csv'):
df = pd.read_csv(upload)
df['Salary'] = df['Salary'].astype(str).str.replace(',', '').astype(int)
elif upload.name.endswith(('.xls', '.xlsx')):
df = pd.read_excel(upload)
df['Salary'] = df['Salary'].astype(str).str.replace(',', '').astype(int)
else:
st.error('Please upload either a CSV or Excel file')
return None
export_df = df.copy()
return export_df, df
except Exception as e:
st.error(f'Error loading file: {str(e)}')
return None
return None
tab1, tab2 = st.tabs(["Data Load", "Create ROO"])
with tab1:
if st.button('Clear data', key='reset1'):
st.session_state.clear()
sport_var = st.selectbox("Select Sport", ["NBA", "NFL", "MLB", "MMA"])
st.subheader("Projections File")
if sport_var == "NBA":
st.info("upload a projections file that has Data oriented in the following format: 'Player', 'Team', 'Opp', 'Position', 'Salary', 'Median', 'Minutes', 'Own'")
elif sport_var == "NFL":
st.info("upload a projections file that has Data oriented in the following format: 'Player', 'Team', 'Opp', 'Position', 'Salary', 'Median', 'Rush Yards', 'Receptions', 'Own'")
elif sport_var == "MLB":
st.info("upload a projections file that has Data oriented in the following format: 'Player', 'Team', 'Opp', 'Position', 'Salary', 'Median', 'Own'")
elif sport_var == "MMA":
st.info("upload a projections file that has Data oriented in the following format: 'Player', 'Salary', 'Median', 'KO Odds', 'Submission Odds', 'Own'")
# Create two columns for the uploader and template button
upload_col, template_col = st.columns([3, 1])
with upload_col:
projections_file = st.file_uploader("Upload Projections File (CSV or Excel)", type=['csv', 'xlsx', 'xls'])
with template_col:
if sport_var == "NBA":
template_df = pd.DataFrame(columns=['Player', 'Team', 'Opp', 'Position', 'Salary', 'Median', 'Minutes', 'Own'])
elif sport_var == "NFL":
template_df = pd.DataFrame(columns=['Player', 'Team', 'Opp', 'Position', 'Salary', 'Median', 'Rush Yards', 'Receptions', 'Own'])
elif sport_var == "MLB":
template_df = pd.DataFrame(columns=['Player', 'Team', 'Opp', 'Position', 'Salary', 'Median', 'Own'])
elif sport_var == "MMA":
template_df = pd.DataFrame(columns=['Player', 'Salary', 'Median', 'KO_odds', 'Sub_odds', 'Own'])
# Add download button for template
st.download_button(
label="Template",
data=template_df.to_csv(index=False),
file_name="projections_template.csv",
mime="text/csv"
)
if projections_file:
export_projections, projections = load_file(projections_file)
if projections is not None:
st.success('Projections file loaded successfully!')
st.dataframe(projections)
with tab2:
if st.button('Clear data', key='reset2'):
st.session_state.clear()
with st.sidebar:
site_var_sb = st.selectbox("Select Site", ["Draftkings", "Fanduel"])
distribution_type_sb = st.selectbox("Select Distribution Type", ['normal', 'poisson', 'bimodal'])
st.info("The distribution type will determine the shape of the distribution of the ROO values. The normal distribution is for more linear projections, the poisson distribution is for stats like HRs and other counting stats, and the bimodal distribution is useful for event oriented outcomes frequent in MMA.")
if sport_var == "MMA":
st.info("MMA utilizes imputs from the projections file to determine distribution ranges, floor and ceiling are determined by Knockout/Submission Odds.")
elif sport_var != "MMA":
floor_var_sb = st.number_input("Floor (low end multiplier)", min_value=0.00, max_value=.50, value=.25, step=.01)
ceiling_var_sb = st.number_input("Ceiling (high end multiplier)", min_value=1.50, max_value=3.00, value=2.00, step=.01)
if sport_var == "MMA":
std_var_sb = st.number_input("Standard Deviation (variance within distribution)", min_value=1.00, max_value=5.00, value=3.00, step=.01)
elif sport_var != "MMA":
std_var_sb = st.number_input("Standard Deviation (variance within distribution)", min_value=1.00, max_value=5.00, value=4.00, step=.01)
if projections_file:
if st.button('Build ROO'):
if sport_var == "NBA":
if site_var_sb == "Draftkings":
disp_file = DK_NBA_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif site_var_sb == "Fanduel":
disp_file = FD_NBA_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif sport_var == "NHL":
if site_var_sb == "Draftkings":
disp_file = DK_NHL_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif site_var_sb == "Fanduel":
disp_file = FD_NHL_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif sport_var == "NFL":
if site_var_sb == "Draftkings":
disp_file = DK_NFL_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif site_var_sb == "Fanduel":
disp_file = FD_NFL_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif sport_var == "MLB":
if site_var_sb == "Draftkings":
disp_file = DK_MLB_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif site_var_sb == "Fanduel":
disp_file = FD_MLB_ROO_Build(projections, floor_var_sb, ceiling_var_sb, std_var_sb, distribution_type_sb)
elif sport_var == "MMA":
if site_var_sb == "Draftkings":
disp_file = DK_MMA_ROO_Build(projections, std_var_sb, distribution_type_sb)
elif site_var_sb == "Fanduel":
disp_file = FD_MMA_ROO_Build(projections, std_var_sb, distribution_type_sb)
try:
if 'disp_file' in locals():
if sport_var == "NBA":
st.dataframe(disp_file.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(nba_percentages_format, precision=2), height=1000, use_container_width = True)
elif sport_var == "NHL":
st.dataframe(disp_file.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(nhl_percentages_format, precision=2), height=1000, use_container_width = True)
elif sport_var == "NFL":
st.dataframe(disp_file.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(nfl_percentages_format, precision=2), height=1000, use_container_width = True)
elif sport_var == "MMA":
st.dataframe(disp_file.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(mma_percentages_format, precision=2), height=1000, use_container_width = True)
elif sport_var == "MLB":
st.dataframe(disp_file.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').format(mlb_percentages_format, precision=2), height=1000, use_container_width = True)
except:
pass