File size: 7,129 Bytes
632ebd1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d589f1
632ebd1
 
bd7be98
632ebd1
bd7be98
632ebd1
 
 
 
 
 
8d589f1
632ebd1
 
62b58db
 
 
 
632ebd1
8d589f1
632ebd1
 
 
 
 
 
 
 
 
8d589f1
632ebd1
 
 
 
8d589f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4ac63e
 
 
 
 
8d589f1
 
 
62b58db
 
8d589f1
 
632ebd1
 
 
8d589f1
632ebd1
 
 
 
 
 
46cd261
632ebd1
aadcbf4
632ebd1
 
 
32a6c1b
632ebd1
 
 
 
8d589f1
632ebd1
 
8d589f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
632ebd1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import streamlit as st
import numpy as np
from numpy import where as np_where
import pandas as pd
import gspread
import plotly.express as px
import scipy.stats as stats
from pymongo import MongoClient
st.set_page_config(layout="wide")

@st.cache_resource
def init_conn():

        uri = st.secrets['mongo_uri']
        client = MongoClient(uri, retryWrites=True, serverSelectionTimeoutMS=100000)
        dfs_db = client["NCAAF_Database"]
        props_db = client["Props_DB"]

        return props_db, dfs_db
    
props_db, dfs_db = init_conn()

game_format = {'Win%': '{:.2%}', 'Vegas': '{:.2%}', 'Win% Diff': '{:.2%}'}
american_format = {'First Inning Lead Percentage': '{:.2%}', 'Fifth Inning Lead Percentage': '{:.2%}'}

@st.cache_resource(ttl=600)
def init_baselines():
    collection = dfs_db["NCAAF_GameModel"] 
    cursor = collection.find()
    raw_display = pd.DataFrame(list(cursor))
    game_model = raw_display[['Team', 'Opp', 'Win%', 'Vegas', 'Win% Diff', 'Win Line', 'Vegas Line', 'Line Diff', 'PD Spread', 'Vegas Spread', 'Spread Diff', 'O/U']]
    game_model = game_model.replace('', np.nan)
    game_model = game_model.sort_values(by='O/U', ascending=False)
    game_model.loc[:, ~game_model.columns.isin(['Team', 'Opp'])] = game_model.loc[:, ~game_model.columns.isin(['Team', 'Opp'])].apply(pd.to_numeric)

    collection = props_db["NCAAF_Props"] 
    cursor = collection.find()

    raw_display = pd.DataFrame(list(cursor))
    market_props = raw_display[['Name', 'Position', 'Projection', 'PropType', 'OddsType', 'over_pay', 'under_pay']]
    market_props['over_prop'] = market_props['Projection']
    market_props['over_line'] = market_props['over_pay'].apply(lambda x: (x - 1) * 100 if x >= 2.0 else -100 / (x - 1))
    market_props['under_prop'] = market_props['Projection']
    market_props['under_line'] = market_props['under_pay'].apply(lambda x: (x - 1) * 100 if x >= 2.0 else -100 / (x - 1))

    return game_model, market_props

def convert_df_to_csv(df):
    return df.to_csv().encode('utf-8')

def calculate_no_vig(row):
    def implied_probability(american_odds):
        if american_odds < 0:
            return (-american_odds) / ((-american_odds) + 100)
        else:
            return 100 / (american_odds + 100)

    over_line = row['over_line']
    under_line = row['under_line']
    over_prop = row['over_prop']
    
    over_prob = implied_probability(over_line)
    under_prob = implied_probability(under_line)
    
    total_prob = over_prob + under_prob
    no_vig_prob = (over_prob / total_prob + 0.5) * over_prop
    
    return no_vig_prob

prop_table_options = ['NCAAF_GAME_PLAYER_PASSING_ATTEMPTS', 'NCAAF_GAME_PLAYER_PASSING_COMPLETIONS', 'NCAAF_GAME_PLAYER_PASSING_INTERCEPTIONS',
                'NCAAF_GAME_PLAYER_PASSING_RUSHING_YARDS', 'NCAAF_GAME_PLAYER_PASSING_TOUCHDOWNS', 'NCAAF_GAME_PLAYER_PASSING_YARDS',
                'NCAAF_GAME_PLAYER_RECEIVING_RECEPTIONS', 'NCAAF_GAME_PLAYER_RECEIVING_TOUCHDOWNS', 'NCAAF_GAME_PLAYER_RECEIVING_YARDS',
                'NCAAF_GAME_PLAYER_RUSHING_ATTEMPTS', 'NCAAF_GAME_PLAYER_RUSHING_RECEIVING_YARDS', 'NCAAF_GAME_PLAYER_RUSHING_TOUCHDOWNS',
                'NCAAF_GAME_PLAYER_RUSHING_YARDS', 'NCAAF_GAME_PLAYER_SCORE_TOUCHDOWN']
prop_format = {'L3 Success': '{:.2%}', 'L6_Success': '{:.2%}', 'L10_success': '{:.2%}', 'Trending Over': '{:.2%}', 'Trending Under': '{:.2%}',
               'Implied Over': '{:.2%}', 'Implied Under': '{:.2%}', 'Over Edge': '{:.2%}', 'Under Edge': '{:.2%}'}

game_model, market_props = init_baselines()

tab1, tab2 = st.tabs(["Game Model", "Prop Market"])

with tab1:
    if st.button("Reset Data", key='reset1'):
              st.cache_data.clear()
              game_model, market_props = init_baselines()
    line_var1 = st.radio('How would you like to display odds?', options = ['Percentage', 'American'], key='line_var1')
    team_frame = game_model
    if line_var1 == 'Percentage':
        team_frame = team_frame[['Team', 'Opp', 'Win%', 'Vegas', 'Win% Diff', 'PD Spread', 'Vegas Spread', 'Spread Diff']]
        team_frame = team_frame.set_index('Team')
        try:
            st.dataframe(team_frame.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['PD Spread', 'Vegas Spread', 'Spread Diff']).format(game_format, precision=2), use_container_width = True)
        except:
            st.dataframe(team_frame.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn').background_gradient(cmap='RdYlGn_r', subset=['PD Spread', 'Vegas Spread']).format(precision=2), use_container_width = True)
    if line_var1 == 'American':
        team_frame = team_frame[['Team', 'Opp', 'Win Line', 'Vegas Line', 'Line Diff', 'PD Spread', 'Vegas Spread', 'Spread Diff']]
        team_frame = team_frame.set_index('Team')
        st.dataframe(team_frame.style.background_gradient(axis=0).background_gradient(cmap='RdYlGn_r').format(precision=2), height = 1000, use_container_width = True)
    
    st.download_button(
        label="Export Team Model",
        data=convert_df_to_csv(team_frame),
        file_name='NCAAF_team_betting_export.csv',
        mime='text/csv',
        key='team_export',
    )

with tab2:
    if st.button("Reset Data", key='reset4'):
                st.cache_data.clear()
                game_model, market_props = init_baselines()
    market_type = st.selectbox('Select type of prop are you wanting to view', options = prop_table_options, key = 'market_type_key')
    disp_market = market_props.copy()
    disp_market = disp_market[disp_market['PropType'] == market_type]
    disp_market['No_Vig_Prop'] = disp_market.apply(calculate_no_vig, axis=1)
    fanduel_frame = disp_market[disp_market['OddsType'] == 'FANDUEL']
    fanduel_dict = dict(zip(fanduel_frame['Name'], fanduel_frame['No_Vig_Prop']))
    draftkings_frame = disp_market[disp_market['OddsType'] == 'DRAFTKINGS']
    draftkings_dict = dict(zip(draftkings_frame['Name'], draftkings_frame['No_Vig_Prop']))
    mgm_frame = disp_market[disp_market['OddsType'] == 'MGM']
    mgm_dict = dict(zip(mgm_frame['Name'], mgm_frame['No_Vig_Prop']))
    bet365_frame = disp_market[disp_market['OddsType'] == 'BET_365']
    bet365_dict = dict(zip(bet365_frame['Name'], bet365_frame['No_Vig_Prop']))

    disp_market['FANDUEL'] = disp_market['Name'].map(fanduel_dict)
    disp_market['DRAFTKINGS'] = disp_market['Name'].map(draftkings_dict)
    disp_market['MGM'] = disp_market['Name'].map(mgm_dict)
    disp_market['BET365'] = disp_market['Name'].map(bet365_dict)

    disp_market = disp_market[['Name', 'Position','FANDUEL', 'DRAFTKINGS', 'MGM', 'BET365']]
    disp_market = disp_market.drop_duplicates(subset=['Name'], keep='first', ignore_index=True)

    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)
    st.download_button(
        label="Export Market Props",
        data=convert_df_to_csv(disp_market),
        file_name='NCAAF_market_props_export.csv',
        mime='text/csv',
    )