Spaces:
Running
Running
BraydenMoore
commited on
Commit
•
d547283
1
Parent(s):
a2525f9
Update with up to date data
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +0 -36
- Dockerfile +0 -31
- README.md +0 -10
- Source/Build/__pycache__/build.cpython-310.pyc +0 -0
- Source/Build/__pycache__/build.cpython-311.pyc +0 -0
- Source/Build/__pycache__/build.cpython-39.pyc +0 -0
- Source/Build/build.py +0 -197
- Source/Build/nfl_data_py +0 -1
- Source/Build/update.py +0 -59
- Source/Data/gbg.csv +0 -3
- Source/Data/gbg_and_odds.csv +0 -3
- Source/Data/gbg_and_odds_this_year-Thinkpad.csv +0 -3
- Source/Data/predictions.csv +0 -3
- Source/Data/record.json +1 -1
- Source/Models/__init__.py +0 -0
- Source/Models/xgboost_ATS_no_odds_57.3%.json +0 -0
- Source/Models/xgboost_ML_75.4%.json +0 -0
- Source/Models/xgboost_ML_no_odds_56.8%.json +0 -0
- Source/Models/xgboost_ML_no_odds_60.8%.json +0 -0
- Source/Models/xgboost_ML_no_odds_61.3%.json +0 -0
- Source/Models/xgboost_ML_no_odds_62.3%.json +0 -0
- Source/Models/xgboost_ML_no_odds_63.3%.json +0 -0
- Source/Models/xgboost_ML_no_odds_63.8%.json +0 -0
- Source/Models/xgboost_ML_no_odds_64.3%.json +0 -0
- Source/Models/xgboost_ML_no_odds_64.8%.json +0 -0
- Source/Models/xgboost_ML_no_odds_66.3%.json +0 -0
- Source/Models/xgboost_ML_no_odds_66.8%.json +0 -0
- Source/Models/xgboost_ML_no_odds_68.8%.json +0 -0
- Source/Models/xgboost_ML_no_odds_69.3%.json +0 -0
- Source/Models/xgboost_ML_no_odds_70.4%.json +0 -0
- Source/Models/xgboost_ML_no_odds_71.4%.json +0 -0
- Source/Models/xgboost_OU_59.3%.json +0 -0
- Source/Models/xgboost_OU_no_odds_51.8%.json +0 -0
- Source/Models/xgboost_OU_no_odds_53.3%.json +0 -0
- Source/Models/xgboost_OU_no_odds_55.8%.json +0 -0
- Source/Models/xgboost_OU_no_odds_58.3%.json +0 -0
- Source/Models/xgboost_OU_no_odds_59.8%.json +0 -0
- Source/Models/xgboost_OU_no_odds_60.8%.json +0 -0
- Source/Predict/.DS_Store +0 -0
- Source/Predict/__pycache__/predict.cpython-310.pyc +0 -0
- Source/Predict/__pycache__/predict.cpython-311.pyc +0 -0
- Source/Predict/__pycache__/predict.cpython-312.pyc +0 -0
- Source/Predict/__pycache__/predict.cpython-39.pyc +0 -0
- Source/Predict/predict.py +0 -156
- Source/Test/__init__.py +0 -0
- Source/Test/xgboost_ATS.py +0 -73
- Source/Test/xgboost_ATS_no_odds_55.3%_dark.png +0 -0
- Source/Test/xgboost_ATS_no_odds_57.3%_dark.png +0 -0
- Source/Test/xgboost_ML.py +0 -59
- Source/Test/xgboost_ML_75.4%.png +0 -0
.gitattributes
DELETED
@@ -1,36 +0,0 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
-
*.csv filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dockerfile
DELETED
@@ -1,31 +0,0 @@
|
|
1 |
-
|
2 |
-
# Use the official lightweight Python image.
|
3 |
-
# https://hub.docker.com/_/python
|
4 |
-
FROM python:3.11-slim
|
5 |
-
|
6 |
-
# Allow statements and log messages to immediately appear in the logs
|
7 |
-
ENV PYTHONUNBUFFERED True
|
8 |
-
|
9 |
-
# Copy local code to the container image.
|
10 |
-
ENV APP_HOME /app
|
11 |
-
WORKDIR $APP_HOME
|
12 |
-
COPY . ./
|
13 |
-
|
14 |
-
# Install production dependencies.
|
15 |
-
RUN pip install -r requirements.txt
|
16 |
-
|
17 |
-
RUN useradd -m -u 1000 user
|
18 |
-
USER user
|
19 |
-
ENV HOME=/home/user \
|
20 |
-
PATH=/home/user/.local/bin:$PATH
|
21 |
-
|
22 |
-
WORKDIR $APP_HOME
|
23 |
-
|
24 |
-
COPY --chown=user . $HOME/app
|
25 |
-
|
26 |
-
# Run the web service on container startup. Here we use the gunicorn
|
27 |
-
# webserver, with one worker process and 8 threads.
|
28 |
-
# For environments with multiple CPU cores, increase the number of workers
|
29 |
-
# to be equal to the cores available.
|
30 |
-
# Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
|
31 |
-
CMD exec gunicorn --bind 0.0.0.0:7860 --workers 4 --threads 8 --timeout 0 main:app
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README.md
DELETED
@@ -1,10 +0,0 @@
|
|
1 |
-
---
|
2 |
-
title: MARCI (NFL Betting)
|
3 |
-
emoji: 🏈
|
4 |
-
colorFrom: red
|
5 |
-
colorTo: blue
|
6 |
-
sdk: docker
|
7 |
-
pinned: false
|
8 |
-
---
|
9 |
-
|
10 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source/Build/__pycache__/build.cpython-310.pyc
DELETED
Binary file (9.16 kB)
|
|
Source/Build/__pycache__/build.cpython-311.pyc
DELETED
Binary file (20.3 kB)
|
|
Source/Build/__pycache__/build.cpython-39.pyc
DELETED
Binary file (9.41 kB)
|
|
Source/Build/build.py
DELETED
@@ -1,197 +0,0 @@
|
|
1 |
-
from nfl_data_py import nfl_data_py as nfl
|
2 |
-
from tqdm import tqdm
|
3 |
-
import numpy as np
|
4 |
-
import pandas as pd
|
5 |
-
pd.set_option('chained_assignment',None)
|
6 |
-
pd.set_option('display.max_columns',None)
|
7 |
-
import os
|
8 |
-
import datetime as dt
|
9 |
-
|
10 |
-
current_directory = os.path.dirname(os.path.abspath(__file__))
|
11 |
-
parent_directory = os.path.dirname(current_directory)
|
12 |
-
data_directory = os.path.join(parent_directory, 'Data')
|
13 |
-
|
14 |
-
year = dt.datetime.now().year
|
15 |
-
month = dt.datetime.now().month
|
16 |
-
current_season = year if month in [8,9,10,11,12] else year-1
|
17 |
-
|
18 |
-
def get_pbp_data(get_seasons=[]):
|
19 |
-
"""
|
20 |
-
Pull data from nflFastR's Github repo.
|
21 |
-
|
22 |
-
"""
|
23 |
-
pbp = nfl.import_pbp_data(get_seasons)
|
24 |
-
#pbp = pd.read_csv(r"C:\Users\brayd\Downloads\play_by_play_2023.csv")
|
25 |
-
pbp['TOP_seconds'] = pbp['drive_time_of_possession'].apply(lambda x: int(x.split(':')[0]) * 60 + int(x.split(':')[1]) if pd.notnull(x) else 0)
|
26 |
-
|
27 |
-
return pbp
|
28 |
-
|
29 |
-
|
30 |
-
def build_gbg_data(get_seasons=[]):
|
31 |
-
"""
|
32 |
-
Build a game-by-game dataset to use for prediction models.
|
33 |
-
|
34 |
-
"""
|
35 |
-
print('Loading play-by-play data.')
|
36 |
-
pbp = get_pbp_data(get_seasons)
|
37 |
-
game_date_dict = dict(pbp[['game_id','game_date']].values)
|
38 |
-
teams = list(set(list(pbp['home_team'].unique()) + list(pbp['away_team'].unique())))
|
39 |
-
seasons = pbp['season'].unique()
|
40 |
-
|
41 |
-
print('Building game-by-game data.')
|
42 |
-
data = pd.DataFrame()
|
43 |
-
for season in seasons:
|
44 |
-
print(season)
|
45 |
-
for team_name in tqdm(teams):
|
46 |
-
# create features
|
47 |
-
team = pbp.loc[((pbp['home_team']==team_name) | (pbp['away_team']==team_name)) & (pbp['season']==season)]
|
48 |
-
team['GP'] = team['week']
|
49 |
-
team['W'] = [1 if r>0 and team_name==h else 1 if r<0 and team_name==a else 0 for r,a,h in team[['result','away_team','home_team']].values]
|
50 |
-
team['L'] = [0 if r>0 and team_name==h else 0 if r<0 and team_name==a else 1 for r,a,h in team[['result','away_team','home_team']].values]
|
51 |
-
team['W_PCT'] = team['W']/team['GP']
|
52 |
-
team['TOP'] = [t if team_name==p else 0 for t,p in team[['TOP_seconds','posteam']].values]
|
53 |
-
team['FGA'] = [1 if team_name==p and f==1 else 0 for p,f in team[['posteam','field_goal_attempt']].values]
|
54 |
-
team['FGM'] = [1 if team_name==p and f=='made' else 0 for p,f in team[['posteam','field_goal_result']].values]
|
55 |
-
team['FG_PCT'] = team['FGM']/team['FGA']
|
56 |
-
team['PassTD'] = np.where((team['posteam'] == team_name) & (team['pass_touchdown'] == 1), 1, 0)
|
57 |
-
team['RushTD'] = np.where((team['posteam'] == team_name) & (team['rush_touchdown'] == 1), 1, 0)
|
58 |
-
team['PassTD_Allowed'] = np.where((team['defteam'] == team_name) & (team['pass_touchdown'] == 1), 1, 0)
|
59 |
-
team['RushTD_Allowed'] = np.where((team['defteam'] == team_name) & (team['rush_touchdown'] == 1), 1, 0)
|
60 |
-
team['PassYds'] = [y if p==team_name else 0 for p,y in team[['posteam','passing_yards']].values]
|
61 |
-
team['RushYds'] = [y if p==team_name else 0 for p,y in team[['posteam','rushing_yards']].values]
|
62 |
-
team['PassYds_Allowed'] = [y if d==team_name else 0 for d,y in team[['defteam','passing_yards']].values]
|
63 |
-
team['RushYds_Allowed'] = [y if d==team_name else 0 for d,y in team[['defteam','rushing_yards']].values]
|
64 |
-
team['Fum'] = np.where((team['defteam'] == team_name) & (team['fumble_lost'] == 1), 1, 0)
|
65 |
-
team['Fum_Allowed'] = np.where((team['posteam'] == team_name) & (team['fumble_lost'] == 1), 1, 0)
|
66 |
-
team['INT'] = np.where((team['defteam'] == team_name) & (team['interception'] == 1), 1, 0)
|
67 |
-
team['INT_Allowed'] = np.where((team['posteam'] == team_name) & (team['interception'] == 1), 1, 0)
|
68 |
-
team['Sacks'] = np.where((team['defteam'] == team_name) & (team['sack'] == 1), 1, 0)
|
69 |
-
team['Sacks_Allowed'] = np.where((team['posteam'] == team_name) & (team['sack'] == 1), 1, 0)
|
70 |
-
team['Penalties'] = np.where((team['penalty_team'] == team_name), 1, 0)
|
71 |
-
team['FirstDowns'] = [1 if team_name==p and f==1 else 0 for p,f in team[['posteam','first_down']].values]
|
72 |
-
team['3rdDownConverted'] = [1 if p==team_name and t==1 else 0 for p,t in team[['posteam','third_down_converted']].values]
|
73 |
-
team['3rdDownFailed'] = [1 if p==team_name and t==1 else 0 for p,t in team[['posteam','third_down_failed']].values]
|
74 |
-
team['3rdDownAllowed'] = [1 if d==team_name and t==1 else 0 for d,t in team[['defteam','third_down_converted']].values]
|
75 |
-
team['3rdDownDefended'] = [1 if d==team_name and t==1 else 0 for d,t in team[['defteam','third_down_failed']].values]
|
76 |
-
team['PTS'] = [ap if at==team_name else hp if ht==team_name else None for ht,at,hp,ap in team[['home_team','away_team','home_score','away_score']].values]
|
77 |
-
team['PointDiff'] = [r if team_name==h else -r if team_name==a else 0 for r,a,h in team[['result','away_team','home_team']].values]
|
78 |
-
|
79 |
-
# aggregate from play-by-play to game-by-game
|
80 |
-
features = {
|
81 |
-
'GP':'mean',
|
82 |
-
'W':'mean',
|
83 |
-
'L':'mean',
|
84 |
-
'W_PCT':'mean',
|
85 |
-
'TOP':'sum',
|
86 |
-
'FGA':'sum',
|
87 |
-
'FGM':'sum',
|
88 |
-
'FG_PCT':'mean',
|
89 |
-
'PassTD':'sum',
|
90 |
-
'RushTD':'sum',
|
91 |
-
'PassTD_Allowed':'sum',
|
92 |
-
'RushTD_Allowed':'sum',
|
93 |
-
'PassYds':'sum',
|
94 |
-
'RushYds':'sum',
|
95 |
-
'PassYds_Allowed':'sum',
|
96 |
-
'RushYds_Allowed':'sum',
|
97 |
-
'Fum':'sum',
|
98 |
-
'Fum_Allowed':'sum',
|
99 |
-
'INT':'sum',
|
100 |
-
'INT_Allowed':'sum',
|
101 |
-
'Sacks':'sum',
|
102 |
-
'Sacks_Allowed':'sum',
|
103 |
-
'Penalties':'sum',
|
104 |
-
'FirstDowns':'sum',
|
105 |
-
'3rdDownConverted':'sum',
|
106 |
-
'3rdDownFailed':'sum',
|
107 |
-
'3rdDownAllowed':'sum',
|
108 |
-
'3rdDownDefended':'sum',
|
109 |
-
'PTS':'mean',
|
110 |
-
'PointDiff':'mean'
|
111 |
-
}
|
112 |
-
|
113 |
-
game = team.groupby('game_id').agg(features).reset_index().sort_values('GP')
|
114 |
-
game[['W','L']] = game[['W','L']].expanding().sum()
|
115 |
-
game[game.columns[4:]] = game[game.columns[4:]].expanding().mean()
|
116 |
-
if season != current_season:
|
117 |
-
game[game.columns[1:]] = game[game.columns[1:]].shift()
|
118 |
-
game['TEAM'] = team_name
|
119 |
-
game['Season'] = season
|
120 |
-
else:
|
121 |
-
game['TEAM'] = team_name
|
122 |
-
game['Season'] = season
|
123 |
-
|
124 |
-
data = pd.concat([data,game])
|
125 |
-
|
126 |
-
# separate home and away data and merge
|
127 |
-
data = data.merge(pbp[['game_id','home_team','away_team']].drop_duplicates())
|
128 |
-
home = data.loc[data['home_team']==data['TEAM']]
|
129 |
-
away = data.loc[data['away_team']==data['TEAM']]
|
130 |
-
away.columns = [f'{i}.Away' for i in away.columns]
|
131 |
-
gbg = home.merge(away,left_on='game_id',right_on='game_id.Away')
|
132 |
-
gbg.drop(columns=['TEAM','TEAM.Away','home_team.Away','away_team.Away','Season.Away','game_id.Away'], inplace=True)
|
133 |
-
gbg['game_date'] = gbg['game_id'].map(game_date_dict)
|
134 |
-
|
135 |
-
# save current data
|
136 |
-
if current_season in get_seasons:
|
137 |
-
gbg_this_year = gbg.loc[gbg['Season']==current_season]
|
138 |
-
file_path = os.path.join(data_directory, 'gbg_this_year.csv')
|
139 |
-
gbg_this_year.to_csv(file_path, index=False)
|
140 |
-
|
141 |
-
# save historical data
|
142 |
-
if get_seasons != [current_season]:
|
143 |
-
gbg = gbg.loc[gbg['Season']!=current_season]
|
144 |
-
file_path = os.path.join(data_directory, 'gbg.csv')
|
145 |
-
gbg.to_csv(file_path, index=False)
|
146 |
-
|
147 |
-
|
148 |
-
def add_odds_data():
|
149 |
-
"""
|
150 |
-
Get odds from Australian Sports Betting's free online dataset and merge it with game-by-game data.
|
151 |
-
|
152 |
-
"""
|
153 |
-
|
154 |
-
# get team abbreviations
|
155 |
-
team_descriptions = nfl.import_team_desc()
|
156 |
-
team_abbreviation_dict = dict(team_descriptions[['team_name','team_abbr']].values)
|
157 |
-
|
158 |
-
# get odds
|
159 |
-
odds = pd.read_excel('https://www.aussportsbetting.com/historical_data/nfl.xlsx')
|
160 |
-
odds['Home Team'] = odds['Home Team'].str.replace('Washington Redskins','Washington Commanders').str.replace('Washington Football Team','Washington Commanders')
|
161 |
-
odds['Away Team'] = odds['Away Team'].str.replace('Washington Redskins','Washington Commanders').str.replace('Washington Football Team','Washington Commanders')
|
162 |
-
odds['Season'] = [i.year if i.month in [8,9,10,11,12] else i.year-1 for i in odds['Date']]
|
163 |
-
odds['Home Team Abbrev'] = odds['Home Team'].map(team_abbreviation_dict).str.replace('LAR','LA')
|
164 |
-
odds['Away Team Abbrev'] = odds['Away Team'].map(team_abbreviation_dict).str.replace('LAR','LA')
|
165 |
-
odds = odds[['Date','Home Score','Away Score','Home Team Abbrev','Away Team Abbrev','Home Odds Close','Away Odds Close','Total Score Close','Home Line Close']]
|
166 |
-
odds['Key'] = odds['Date'].astype(str) + odds['Home Team Abbrev'] + odds['Away Team Abbrev']
|
167 |
-
odds = odds.drop(columns=['Date','Home Team Abbrev','Away Team Abbrev']).dropna()
|
168 |
-
odds['Home Odds'] = [round((i-1)*100) if i>= 2 else round(-100/(i-1)) for i in odds['Home Odds Close']]
|
169 |
-
odds['Away Odds'] = [round((i-1)*100) if i>= 2 else round(-100/(i-1)) for i in odds['Away Odds Close']]
|
170 |
-
odds['Home Winnings'] = [ho-1 if h>a else -1 if a>h else 0 for ho,h,a in odds[['Home Odds Close','Home Score','Away Score']].values]
|
171 |
-
odds['Away Winnings'] = [ao-1 if a>h else -1 if h>a else 0 for ao,h,a in odds[['Away Odds Close','Home Score','Away Score']].values]
|
172 |
-
|
173 |
-
# load gbg data
|
174 |
-
file_path = os.path.join(data_directory, 'gbg.csv')
|
175 |
-
gbg = pd.read_csv(file_path)
|
176 |
-
file_path = os.path.join(data_directory, 'gbg_this_year.csv')
|
177 |
-
gbg_this_year = pd.read_csv(file_path)
|
178 |
-
|
179 |
-
# merge and save
|
180 |
-
dataframes = [gbg, gbg_this_year]
|
181 |
-
for idx in range(2):
|
182 |
-
i = dataframes[idx]
|
183 |
-
i['Key'] = i['game_date'].astype(str) + i['home_team'] + i['away_team']
|
184 |
-
gbg_and_odds = i.merge(odds, left_on='Key', right_on='Key')
|
185 |
-
gbg_and_odds['Home-Team-Cover'] = [1 if (h-a)>-l else 0 if (h-a)<-l else 2 for h,a,l in gbg_and_odds[['Home Score','Away Score','Home Line Close']].values]
|
186 |
-
gbg_and_odds['Home-Team-Win'] = (gbg_and_odds['Home Score']>gbg_and_odds['Away Score']).astype(int)
|
187 |
-
gbg_and_odds['Over'] = ((gbg_and_odds['Home Score'] + gbg_and_odds['Away Score'])>gbg_and_odds['Total Score Close']).astype(int)
|
188 |
-
|
189 |
-
if idx==0:
|
190 |
-
file_path = os.path.join(data_directory, 'gbg_and_odds.csv')
|
191 |
-
else:
|
192 |
-
file_path = os.path.join(data_directory, 'gbg_and_odds_this_year.csv')
|
193 |
-
|
194 |
-
gbg_and_odds.drop_duplicates(subset='game_id').to_csv(file_path, index=False)
|
195 |
-
|
196 |
-
|
197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source/Build/nfl_data_py
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
Subproject commit e4988dc303bc441108dd11f4ae93a8200aab10e1
|
|
|
|
Source/Build/update.py
DELETED
@@ -1,59 +0,0 @@
|
|
1 |
-
import nfl_data_py.nfl_data_py as nfl
|
2 |
-
import build
|
3 |
-
import datetime as dt
|
4 |
-
import numpy as np
|
5 |
-
import pandas as pd
|
6 |
-
pd.set_option('chained_assignment',None)
|
7 |
-
pd.set_option('display.max_columns',None)
|
8 |
-
import os
|
9 |
-
import pickle as pkl
|
10 |
-
|
11 |
-
current_directory = os.path.dirname(os.path.abspath(__file__))
|
12 |
-
parent_directory = os.path.dirname(current_directory)
|
13 |
-
data_directory = os.path.join(parent_directory, 'Data')
|
14 |
-
pickle_directory = os.path.join(parent_directory, 'Pickles')
|
15 |
-
|
16 |
-
# get team abbreviations
|
17 |
-
file_path = os.path.join(pickle_directory, 'team_name_to_abbreviation.pkl')
|
18 |
-
with open(file_path, 'rb') as f:
|
19 |
-
team_name_to_abbreviation = pkl.load(f)
|
20 |
-
file_path = os.path.join(pickle_directory, 'team_abbreviation_to_name.pkl')
|
21 |
-
with open(file_path, 'rb') as f:
|
22 |
-
team_abbreviation_to_name = pkl.load(f)
|
23 |
-
|
24 |
-
# get current season
|
25 |
-
year = dt.datetime.now().year
|
26 |
-
month = dt.datetime.now().month
|
27 |
-
current_season = year if month in [8,9,10,11,12] else year-1
|
28 |
-
|
29 |
-
# get schedule
|
30 |
-
print('Getting schedule.\n')
|
31 |
-
url = 'https://www.nbcsports.com/nfl/schedule'
|
32 |
-
df = pd.read_html(url)
|
33 |
-
file_path = os.path.join(pickle_directory, 'schedule.pkl')
|
34 |
-
with open(file_path, 'wb') as f:
|
35 |
-
pkl.dump(df, f)
|
36 |
-
|
37 |
-
# update current season
|
38 |
-
build.build_gbg_data(get_seasons=[current_season])
|
39 |
-
#build.build_gbg_data(get_seasons=range(2014,2024))
|
40 |
-
build.add_odds_data()
|
41 |
-
|
42 |
-
# get winners
|
43 |
-
pbp = build.get_pbp_data([current_season])
|
44 |
-
pbp = pbp.drop_duplicates(subset='game_id')
|
45 |
-
pbp[['season','week','away','home']] = pbp['game_id'].str.split('_', expand=True)
|
46 |
-
games = pbp[['game_id','away_score','home_score','season','week','away','home']]
|
47 |
-
games[['away_score','home_score','season','week']] = games[['away_score','home_score','season','week']].astype(int)
|
48 |
-
|
49 |
-
games['away_team'] = games['away'].map(team_abbreviation_to_name)
|
50 |
-
games['home_team'] = games['home'].map(team_abbreviation_to_name)
|
51 |
-
|
52 |
-
games['total'] = games['away_score'] + games['home_score']
|
53 |
-
games['winner'] = [a if a_s>h_s else h if h_s>a_s else 'Tie' for a,h,a_s,h_s in games[['away_team','home_team','away_score','home_score']].values]
|
54 |
-
|
55 |
-
file_path = os.path.join(data_directory, 'results.csv')
|
56 |
-
games[['game_id','total','winner']].to_csv(file_path, index=False)
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source/Data/gbg.csv
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:4b03612517c6505adabfc11be02fbd51be8ab8c104361f645401c58c128fd2d7
|
3 |
-
size 1613287
|
|
|
|
|
|
|
|
Source/Data/gbg_and_odds.csv
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:d6f1a3ea061ed26a13c2398938efe0a60267d07abfde4baaff82db22ec35e79f
|
3 |
-
size 1663814
|
|
|
|
|
|
|
|
Source/Data/gbg_and_odds_this_year-Thinkpad.csv
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:ffb812ba82afc8e124ea3186f8bcc04e66a10b15e9507e6fa8e6eba18463c5f7
|
3 |
-
size 276
|
|
|
|
|
|
|
|
Source/Data/predictions.csv
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:0c67a5b32fca86661a44a993df5b8001073ab8e99fc0a588d050bfc04bb4f0c3
|
3 |
-
size 20000
|
|
|
|
|
|
|
|
Source/Data/record.json
CHANGED
@@ -1 +1 @@
|
|
1 |
-
{"winners_correct": "74", "winners_incorrect": "38", "winners_tie": "", "winners_return": "66.1% accuracy, -3.0x return", "over_unders_correct": "68", "over_unders_incorrect": "76", "over_unders_push": "-2", "over_unders_return": "46.6% accuracy, -14.1x return", "latest_game": "Monday, 12/25", "over_unders_binom": "72.0% chance of equal or better performance by flipping a coin.", "winners_binom": "
|
|
|
1 |
+
{"winners_correct": "74", "winners_incorrect": "38", "winners_tie": "", "winners_return": "66.1% accuracy, -3.0x return", "over_unders_correct": "68", "over_unders_incorrect": "76", "over_unders_push": "-2", "over_unders_return": "46.6% accuracy, -14.1x return", "latest_game": "Monday, 12/25", "over_unders_binom": "72.0% chance of equal or better performance by flipping a coin.", "winners_binom": "0.0% chance of equal or better performance by flipping a coin."}
|
Source/Models/__init__.py
DELETED
File without changes
|
Source/Models/xgboost_ATS_no_odds_57.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_75.4%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_56.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_60.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_61.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_62.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_63.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_63.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_64.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_64.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_66.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_66.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_68.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_69.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_70.4%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_ML_no_odds_71.4%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_59.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_no_odds_51.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_no_odds_53.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_no_odds_55.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_no_odds_58.3%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_no_odds_59.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Models/xgboost_OU_no_odds_60.8%.json
DELETED
The diff for this file is too large to render.
See raw diff
|
|
Source/Predict/.DS_Store
DELETED
Binary file (6.15 kB)
|
|
Source/Predict/__pycache__/predict.cpython-310.pyc
DELETED
Binary file (5.54 kB)
|
|
Source/Predict/__pycache__/predict.cpython-311.pyc
DELETED
Binary file (12.4 kB)
|
|
Source/Predict/__pycache__/predict.cpython-312.pyc
DELETED
Binary file (10.1 kB)
|
|
Source/Predict/__pycache__/predict.cpython-39.pyc
DELETED
Binary file (5.65 kB)
|
|
Source/Predict/predict.py
DELETED
@@ -1,156 +0,0 @@
|
|
1 |
-
import xgboost as xgb
|
2 |
-
import numpy as np
|
3 |
-
import pandas as pd
|
4 |
-
import pickle as pkl
|
5 |
-
import os
|
6 |
-
import requests
|
7 |
-
from bs4 import BeautifulSoup
|
8 |
-
import warnings
|
9 |
-
warnings.filterwarnings("ignore")
|
10 |
-
from datetime import datetime
|
11 |
-
|
12 |
-
# set dirs for other files
|
13 |
-
current_directory = os.path.dirname(os.path.abspath(__file__))
|
14 |
-
parent_directory = os.path.dirname(current_directory)
|
15 |
-
data_directory = os.path.join(parent_directory, 'Data')
|
16 |
-
model_directory = os.path.join(parent_directory, 'Models')
|
17 |
-
pickle_directory = os.path.join(parent_directory, 'Pickles')
|
18 |
-
|
19 |
-
file_path = os.path.join(data_directory, 'gbg_this_year.csv')
|
20 |
-
gbg = pd.read_csv(file_path, low_memory=False)
|
21 |
-
|
22 |
-
file_path = os.path.join(data_directory, 'results.csv')
|
23 |
-
results = pd.read_csv(file_path, low_memory=False)
|
24 |
-
|
25 |
-
# get team abbreviations
|
26 |
-
file_path = os.path.join(pickle_directory, 'team_name_to_abbreviation.pkl')
|
27 |
-
with open(file_path, 'rb') as f:
|
28 |
-
team_name_to_abbreviation = pkl.load(f)
|
29 |
-
|
30 |
-
file_path = os.path.join(pickle_directory, 'team_abbreviation_to_name.pkl')
|
31 |
-
with open(file_path, 'rb') as f:
|
32 |
-
team_abbreviation_to_name = pkl.load(f)
|
33 |
-
|
34 |
-
# get schedule
|
35 |
-
file_path = os.path.join(pickle_directory, 'schedule.pkl')
|
36 |
-
with open(file_path, 'rb') as f:
|
37 |
-
schedule = pkl.load(f)
|
38 |
-
|
39 |
-
# get current week
|
40 |
-
file_path = os.path.join(pickle_directory, 'the_week.pkl')
|
41 |
-
with open(file_path, 'rb') as f:
|
42 |
-
the_week = pkl.load(f)
|
43 |
-
|
44 |
-
# load models
|
45 |
-
# moneyline
|
46 |
-
model = 'xgboost_ML_no_odds_71.4%'
|
47 |
-
file_path = os.path.join(model_directory, f'{model}.json')
|
48 |
-
xgb_ml = xgb.Booster()
|
49 |
-
xgb_ml.load_model(file_path)
|
50 |
-
|
51 |
-
# over/under
|
52 |
-
model = 'xgboost_OU_no_odds_59.8%'
|
53 |
-
file_path = os.path.join(model_directory, f'{model}.json')
|
54 |
-
xgb_ou = xgb.Booster()
|
55 |
-
xgb_ou.load_model(file_path)
|
56 |
-
|
57 |
-
|
58 |
-
def get_week():
|
59 |
-
week = the_week['week']
|
60 |
-
year = the_week['year']
|
61 |
-
return int(week), int(year)
|
62 |
-
|
63 |
-
|
64 |
-
def get_games(week):
|
65 |
-
df = schedule[week-1]
|
66 |
-
df['Away Team'] = [' '.join(i.split('\xa0')[1:]) for i in df['Away TeamAway Team']]
|
67 |
-
df['Home Team'] = [' '.join(i.split('\xa0')[1:]) for i in df['Home TeamHome Team']]
|
68 |
-
df['Date'] = pd.to_datetime(df['Game TimeGame Time'])
|
69 |
-
df['Date'] = df['Date'].dt.strftime('%A %d/%m %I:%M %p')
|
70 |
-
df['Date'] = df['Date'].apply(lambda x: f"{x.split()[0]} {int(x.split()[1].split('/')[1])}/{int(x.split()[1].split('/')[0])} {x.split()[2]}".capitalize())
|
71 |
-
return df[['Away Team','Home Team','Date']]
|
72 |
-
|
73 |
-
|
74 |
-
def get_one_week(home,away,season,week):
|
75 |
-
try:
|
76 |
-
max_GP_home = gbg.loc[((gbg['home_team'] == home) | (gbg['away_team'] == home)) & (gbg['GP'] < week)]['GP'].max()
|
77 |
-
max_GP_away = gbg.loc[((gbg['home_team'] == away) | (gbg['away_team'] == away)) & (gbg['GP'] < week)]['GP'].max()
|
78 |
-
|
79 |
-
home_df = gbg.loc[((gbg['away_team']==home) | (gbg['home_team']==home)) & (gbg['Season']==season) & (gbg['GP']==max_GP_home)]
|
80 |
-
gbg_home_team = home_df['home_team'].item()
|
81 |
-
home_df.drop(columns=['game_id','home_team','away_team','Season','game_date'], inplace=True)
|
82 |
-
home_df = home_df[[i for i in home_df.columns if '.Away' not in i] if gbg_home_team==home else [i for i in home_df.columns if '.Away' in i]]
|
83 |
-
home_df.columns = [i.replace('.Away','') for i in home_df.columns]
|
84 |
-
|
85 |
-
away_df = gbg.loc[((gbg['away_team']==away) | (gbg['home_team']==away)) & (gbg['Season']==season) & (gbg['GP']==max_GP_away)]
|
86 |
-
gbg_home_team = away_df['home_team'].item()
|
87 |
-
away_df.drop(columns=['game_id','home_team','away_team','Season','game_date'], inplace=True)
|
88 |
-
away_df = away_df[[i for i in away_df.columns if '.Away' not in i] if gbg_home_team==away else [i for i in away_df.columns if '.Away' in i]]
|
89 |
-
away_df.columns = [i.replace('.Away','') + '.Away' for i in away_df.columns]
|
90 |
-
|
91 |
-
df = home_df.reset_index(drop=True).merge(away_df.reset_index(drop=True), left_index=True, right_index=True)
|
92 |
-
return df
|
93 |
-
except ValueError:
|
94 |
-
return pd.DataFrame()
|
95 |
-
|
96 |
-
|
97 |
-
def predict(home,away,season,week,total):
|
98 |
-
global results
|
99 |
-
|
100 |
-
# finish preparing data
|
101 |
-
if len(home)>4:
|
102 |
-
home_abbrev = team_name_to_abbreviation[home]
|
103 |
-
else:
|
104 |
-
home_abbrev = home
|
105 |
-
|
106 |
-
if len(away)>4:
|
107 |
-
away_abbrev = team_name_to_abbreviation[away]
|
108 |
-
else:
|
109 |
-
away_abbrev = away
|
110 |
-
|
111 |
-
data = get_one_week(home_abbrev,away_abbrev,season,week)
|
112 |
-
data['Total Score Close'] = total
|
113 |
-
matrix = xgb.DMatrix(data.astype(float).values)
|
114 |
-
|
115 |
-
# create game id
|
116 |
-
if week < 10:
|
117 |
-
game_id = str(season) + '_0' + str(int(week)) + '_' + away_abbrev + '_' + home_abbrev
|
118 |
-
else:
|
119 |
-
game_id = str(season) + '_' + str(int(week)) + '_' + away_abbrev + '_' + home_abbrev
|
120 |
-
|
121 |
-
try:
|
122 |
-
moneyline_result = results.loc[results['game_id']==game_id, 'winner'].item()
|
123 |
-
except:
|
124 |
-
moneyline_result = 'N/A'
|
125 |
-
|
126 |
-
try:
|
127 |
-
ml_predicted_proba = xgb_ml.predict(matrix)[0][1]
|
128 |
-
winner_proba = max([ml_predicted_proba, 1-ml_predicted_proba]).item()
|
129 |
-
moneyline = {'Winner': [home if ml_predicted_proba>0.5 else away if ml_predicted_proba<0.5 else 'Toss-Up'],
|
130 |
-
'Probabilities':[winner_proba],
|
131 |
-
'Result': moneyline_result}
|
132 |
-
except:
|
133 |
-
moneyline = {'Winner': 'NA',
|
134 |
-
'Probabilities':['N/A'],
|
135 |
-
'Result': moneyline_result}
|
136 |
-
|
137 |
-
try:
|
138 |
-
result = results.loc[results['game_id']==game_id, 'total'].item()
|
139 |
-
over_under_result = 'Over' if float(result)>float(total) else 'Push' if float(result)==float(total) else 'Under'
|
140 |
-
|
141 |
-
except:
|
142 |
-
over_under_result = 'N/A'
|
143 |
-
|
144 |
-
try:
|
145 |
-
ou_predicted_proba = xgb_ou.predict(matrix)[0][1]
|
146 |
-
ou_proba = max([ou_predicted_proba, 1-ou_predicted_proba]).item()
|
147 |
-
|
148 |
-
over_under = {'Over/Under': ['Over' if ou_predicted_proba>0.5 else 'Under'],
|
149 |
-
'Probability': [ou_proba],
|
150 |
-
'Result': over_under_result}
|
151 |
-
except:
|
152 |
-
over_under = {'Over/Under': 'N/A',
|
153 |
-
'Probability': ['N/A'],
|
154 |
-
'Result': over_under_result}
|
155 |
-
|
156 |
-
return game_id, moneyline, over_under
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source/Test/__init__.py
DELETED
File without changes
|
Source/Test/xgboost_ATS.py
DELETED
@@ -1,73 +0,0 @@
|
|
1 |
-
from cgi import test
|
2 |
-
import xgboost as xgb
|
3 |
-
import pandas as pd
|
4 |
-
import pickle as pkl
|
5 |
-
import numpy as np
|
6 |
-
import os
|
7 |
-
|
8 |
-
model = 'xgboost_ATS_no_odds_57.3%'
|
9 |
-
|
10 |
-
current_directory = os.path.dirname(os.path.abspath(__file__))
|
11 |
-
parent_directory = os.path.dirname(current_directory)
|
12 |
-
data_directory = os.path.join(parent_directory, 'Data')
|
13 |
-
model_directory = os.path.join(parent_directory, 'Models')
|
14 |
-
pickle_directory = os.path.join(parent_directory, 'Pickles')
|
15 |
-
|
16 |
-
file_path = os.path.join(model_directory, f'{model}.json')
|
17 |
-
xgb_ml = xgb.Booster()
|
18 |
-
xgb_ml.load_model(file_path)
|
19 |
-
|
20 |
-
file_path = os.path.join(pickle_directory, 'test_games_ATS_no_odds.pkl')
|
21 |
-
with open(file_path,'rb') as f:
|
22 |
-
test_games = pkl.load(f).tolist()
|
23 |
-
|
24 |
-
file_path = os.path.join(data_directory, 'gbg_and_odds.csv')
|
25 |
-
gbg_and_odds = pd.read_csv(file_path)
|
26 |
-
test_data = gbg_and_odds.loc[gbg_and_odds['game_id'].isin(test_games)]
|
27 |
-
test_data_matrix = xgb.DMatrix(test_data.drop(columns=['game_id','Home-Team-Win','Home-Team-Cover','Over','Season','home_team','away_team','game_date','Key','Home Score','Away Score','Home Odds Close','Away Odds Close','Home Winnings','Away Winnings','Away Odds','Home Odds']).astype(float).values)
|
28 |
-
|
29 |
-
predicted_probas = xgb_ml.predict(test_data_matrix)
|
30 |
-
predictions = np.argmax(predicted_probas, axis=1)
|
31 |
-
test_data['predicted_proba'] = [i[1] for i in predicted_probas]
|
32 |
-
test_data['prediction'] = predictions
|
33 |
-
test_data['correct'] = test_data['Home-Team-Cover']==test_data['prediction']
|
34 |
-
print(test_data['predicted_proba'])
|
35 |
-
print(test_data['correct'].mean())
|
36 |
-
|
37 |
-
bets = test_data.loc[(test_data['predicted_proba']>0.5) | (test_data['predicted_proba']<0.5)]
|
38 |
-
bets['winnings'] = [0.91 if c==1 else -1 for c in bets['correct']]
|
39 |
-
|
40 |
-
print('Actual')
|
41 |
-
print(bets.loc[bets['Home-Team-Cover']==1].shape)
|
42 |
-
print(bets.loc[bets['Home-Team-Cover']==0].shape)
|
43 |
-
print(bets.loc[bets['Home-Team-Cover']==2].shape)
|
44 |
-
|
45 |
-
print('Predicted')
|
46 |
-
print(bets.loc[bets['prediction']==1].shape)
|
47 |
-
print(bets.loc[bets['prediction']==0].shape)
|
48 |
-
print(bets.loc[bets['prediction']==2].shape)
|
49 |
-
|
50 |
-
|
51 |
-
import matplotlib.pyplot as plt
|
52 |
-
fig = plt.figure(facecolor='black')
|
53 |
-
ax = fig.add_subplot(1, 1, 1, facecolor='black')
|
54 |
-
|
55 |
-
# Plot data with line color as RGB(0, 128, 0)
|
56 |
-
ax.plot(bets['winnings'].cumsum().values*100, linewidth=3, color=(0/255, 128/255, 0/255))
|
57 |
-
|
58 |
-
# Set title and labels
|
59 |
-
ax.set_title('MARCI 3.0 - Against the Spread', color='white')
|
60 |
-
ax.set_xlabel('Games Bet On', color='white')
|
61 |
-
ax.set_ylabel('Return (%)', color='white')
|
62 |
-
|
63 |
-
# Change tick colors to white
|
64 |
-
ax.tick_params(axis='x', colors='white')
|
65 |
-
ax.tick_params(axis='y', colors='white')
|
66 |
-
|
67 |
-
# Change axis edge colors
|
68 |
-
ax.spines['bottom'].set_color('white')
|
69 |
-
ax.spines['top'].set_color('white')
|
70 |
-
ax.spines['left'].set_color('white')
|
71 |
-
ax.spines['right'].set_color('white')
|
72 |
-
|
73 |
-
plt.savefig(f'{model}_dark.png', facecolor='black')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source/Test/xgboost_ATS_no_odds_55.3%_dark.png
DELETED
Binary file (33.2 kB)
|
|
Source/Test/xgboost_ATS_no_odds_57.3%_dark.png
DELETED
Binary file (31.2 kB)
|
|
Source/Test/xgboost_ML.py
DELETED
@@ -1,59 +0,0 @@
|
|
1 |
-
import xgboost as xgb
|
2 |
-
import pandas as pd
|
3 |
-
import pickle as pkl
|
4 |
-
import numpy as np
|
5 |
-
import os
|
6 |
-
|
7 |
-
model = 'xgboost_ML_no_odds_71.4%'
|
8 |
-
|
9 |
-
current_directory = os.path.dirname(os.path.abspath(__file__))
|
10 |
-
parent_directory = os.path.dirname(current_directory)
|
11 |
-
data_directory = os.path.join(parent_directory, 'Data')
|
12 |
-
model_directory = os.path.join(parent_directory, 'Models')
|
13 |
-
pickle_directory = os.path.join(parent_directory, 'Pickles')
|
14 |
-
|
15 |
-
file_path = os.path.join(model_directory, f'{model}.json')
|
16 |
-
xgb_ml = xgb.Booster()
|
17 |
-
xgb_ml.load_model(file_path)
|
18 |
-
|
19 |
-
file_path = os.path.join(pickle_directory, 'test_games_ML_no_odds.pkl')
|
20 |
-
with open(file_path,'rb') as f:
|
21 |
-
test_games = pkl.load(f).tolist()
|
22 |
-
|
23 |
-
file_path = os.path.join(data_directory, 'gbg_and_odds.csv')
|
24 |
-
gbg_and_odds = pd.read_csv(file_path)
|
25 |
-
test_data = gbg_and_odds.loc[gbg_and_odds['game_id'].isin(test_games)]
|
26 |
-
test_data_matrix = xgb.DMatrix(test_data.drop(columns=['game_id','Over','Home-Team-Win','Season','home_team','away_team','game_date','Key','Home Score','Away Score','Home Odds Close','Away Odds Close','Home Winnings','Away Winnings','Away Odds','Home Odds']).astype(float).values)
|
27 |
-
|
28 |
-
predicted_probas = xgb_ml.predict(test_data_matrix)
|
29 |
-
predictions = np.argmax(predicted_probas, axis=1)
|
30 |
-
test_data['predicted_proba'] = [i[1] for i in predicted_probas]
|
31 |
-
test_data['prediction'] = (test_data['predicted_proba']>0.5).astype(int)
|
32 |
-
test_data['correct'] = test_data['Home-Team-Win']==test_data['prediction']
|
33 |
-
|
34 |
-
bets = test_data.loc[(test_data['predicted_proba']>0.6) | (test_data['predicted_proba']<0.4)]
|
35 |
-
bets['winnings'] = [h if p==1 else a for h,a,p in bets[['Home Winnings','Away Winnings','prediction']].values]
|
36 |
-
|
37 |
-
import matplotlib.pyplot as plt
|
38 |
-
fig = plt.figure(facecolor='black')
|
39 |
-
ax = fig.add_subplot(1, 1, 1, facecolor='black')
|
40 |
-
|
41 |
-
# Plot data with line color as RGB(0, 128, 0)
|
42 |
-
ax.plot(bets['winnings'].cumsum().values*100, linewidth=3, color=(0/255, 128/255, 0/255))
|
43 |
-
|
44 |
-
# Set title and labels
|
45 |
-
ax.set_title('MARCI 3.0 - MoneyLine w/ 60% Confidence Threshold', color='white')
|
46 |
-
ax.set_xlabel('Games Bet On', color='white')
|
47 |
-
ax.set_ylabel('Return (%)', color='white')
|
48 |
-
|
49 |
-
# Change tick colors to white
|
50 |
-
ax.tick_params(axis='x', colors='white')
|
51 |
-
ax.tick_params(axis='y', colors='white')
|
52 |
-
|
53 |
-
# Change axis edge colors
|
54 |
-
ax.spines['bottom'].set_color('white')
|
55 |
-
ax.spines['top'].set_color('white')
|
56 |
-
ax.spines['left'].set_color('white')
|
57 |
-
ax.spines['right'].set_color('white')
|
58 |
-
|
59 |
-
plt.savefig(f'{model}_dark.png', facecolor='black')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source/Test/xgboost_ML_75.4%.png
DELETED
Binary file (35.5 kB)
|
|