File size: 6,718 Bytes
2d7ef5b
3d75a25
 
2d7ef5b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d75a25
2d7ef5b
 
 
 
 
 
 
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
import streamlit as st
import numpy as np
import pandas as pd
from database import props_db, dfs_db
st.set_page_config(layout="wide")

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',
    )