BraydenMoore commited on
Commit
fc2b782
β€’
1 Parent(s): 79347f6

Add results

Browse files
Source/Build/update.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import nfl_data_py.nfl_data_py as nfl
2
  import build
3
  import datetime as dt
@@ -6,10 +7,20 @@ import pandas as pd
6
  pd.set_option('chained_assignment',None)
7
  pd.set_option('display.max_columns',None)
8
  import os
 
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
  # get current season
15
  year = dt.datetime.now().year
@@ -20,3 +31,20 @@ current_season = year if month in [8,9,10,11,12] else year-1
20
  build.build_gbg_data(get_seasons=[current_season])
21
  build.add_odds_data()
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from operator import index
2
  import nfl_data_py.nfl_data_py as nfl
3
  import build
4
  import datetime as dt
 
7
  pd.set_option('chained_assignment',None)
8
  pd.set_option('display.max_columns',None)
9
  import os
10
+ import pickle as pkl
11
 
12
  current_directory = os.path.dirname(os.path.abspath(__file__))
13
  parent_directory = os.path.dirname(current_directory)
14
  data_directory = os.path.join(parent_directory, 'Data')
15
+ pickle_directory = os.path.join(parent_directory, 'Pickles')
16
+
17
+ # get team abbreviations
18
+ file_path = os.path.join(pickle_directory, 'team_name_to_abbreviation.pkl')
19
+ with open(file_path, 'rb') as f:
20
+ team_name_to_abbreviation = pkl.load(f)
21
+ file_path = os.path.join(pickle_directory, 'team_abbreviation_to_name.pkl')
22
+ with open(file_path, 'rb') as f:
23
+ team_abbreviation_to_name = pkl.load(f)
24
 
25
  # get current season
26
  year = dt.datetime.now().year
 
31
  build.build_gbg_data(get_seasons=[current_season])
32
  build.add_odds_data()
33
 
34
+ # get winners
35
+ pbp = build.get_pbp_data([2023])
36
+ pbp = pbp.drop_duplicates(subset='game_id')
37
+ pbp[['season','week','away','home']] = pbp['game_id'].str.split('_', expand=True)
38
+ games = pbp[['game_id','away_score','home_score','season','week','away','home']]
39
+ games[['away_score','home_score','season','week']] = games[['away_score','home_score','season','week']].astype(int)
40
+
41
+ games['away_team'] = games['away'].map(team_abbreviation_to_name)
42
+ games['home_team'] = games['home'].map(team_abbreviation_to_name)
43
+
44
+ games['total'] = games['away_score'] + games['home_score']
45
+ 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]
46
+
47
+ file_path = os.path.join(data_directory, 'results.csv')
48
+ games[['game_id','total','winner']].to_csv(file_path, index=False)
49
+
50
+
Source/Data/results.csv ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cba191ba24d4a23d9ebd2720203deb51546e3a121a335320bb50db8bcb6084b9
3
+ size 584
Source/Predict/predict.py CHANGED
@@ -16,6 +16,9 @@ pickle_directory = os.path.join(parent_directory, 'Pickles')
16
  file_path = os.path.join(data_directory, 'gbg_this_year.csv')
17
  gbg = pd.read_csv(file_path, low_memory=False)
18
 
 
 
 
19
  # get team abbreviations
20
  file_path = os.path.join(pickle_directory, 'team_name_to_abbreviation.pkl')
21
  with open(file_path, 'rb') as f:
@@ -77,41 +80,68 @@ def get_one_week(home,away,season,week):
77
 
78
  def predict(home,away,season,week,total):
79
  # finish preparing data
80
- home_abbrev = team_name_to_abbreviation[home]
81
- away_abbrev = team_name_to_abbreviation[away]
 
 
 
 
 
 
 
 
82
  data = get_one_week(home_abbrev,away_abbrev,season,week)
83
  data['Total Score Close'] = total
84
  matrix = xgb.DMatrix(data.astype(float).values)
85
 
 
 
 
86
  # moneyline
87
- model = 'xgboost_ML_no_odds_69.8%'
88
  file_path = os.path.join(model_directory, f'{model}.json')
89
  xgb_ml = xgb.Booster()
90
  xgb_ml.load_model(file_path)
 
 
 
 
 
 
91
  try:
92
  ml_predicted_proba = xgb_ml.predict(matrix)[0][1]
93
- print(xgb_ml.predict(matrix))
94
  winner_proba = max([ml_predicted_proba, 1-ml_predicted_proba]).item()
95
- moneyline = {'Winner': [home if ml_predicted_proba>0.6 else away if ml_predicted_proba<0.4 else 'Toss-Up'],
96
- 'Probabilities':[winner_proba]}
 
97
  except:
98
  moneyline = {'Winner': 'NA',
99
- 'Probabilities':['N/A']}
 
100
 
101
  # over/under
102
  model = 'xgboost_OU_no_odds_60.8%'
103
  file_path = os.path.join(model_directory, f'{model}.json')
104
  xgb_ou = xgb.Booster()
105
  xgb_ou.load_model(file_path)
 
 
 
 
 
 
 
106
  try:
107
  ou_predicted_proba = xgb_ou.predict(matrix)[0][1]
108
  ou_proba = max([ou_predicted_proba, 1-ou_predicted_proba]).item()
 
109
  over_under = {'Over/Under': ['Over' if ou_predicted_proba>0.5 else 'Under'],
110
- 'Probability': [ou_proba]}
 
111
  except:
112
  over_under = {'Over/Under': 'N/A',
113
- 'Probability': ['N/A']}
 
114
 
115
- # create game id to save predictions
116
- game_id = str(season) + '_' + str(week) + '_' + away_abbrev + '_' + home_abbrev
117
  return game_id, moneyline, over_under
 
16
  file_path = os.path.join(data_directory, 'gbg_this_year.csv')
17
  gbg = pd.read_csv(file_path, low_memory=False)
18
 
19
+ file_path = os.path.join(data_directory, 'results.csv')
20
+ results = pd.read_csv(file_path, low_memory=False)
21
+
22
  # get team abbreviations
23
  file_path = os.path.join(pickle_directory, 'team_name_to_abbreviation.pkl')
24
  with open(file_path, 'rb') as f:
 
80
 
81
  def predict(home,away,season,week,total):
82
  # finish preparing data
83
+ if len(home)>4:
84
+ home_abbrev = team_name_to_abbreviation[home]
85
+ else:
86
+ home_abbrev = home
87
+
88
+ if len(away)>4:
89
+ away_abbrev = team_name_to_abbreviation[away]
90
+ else:
91
+ away_abbrev = away
92
+
93
  data = get_one_week(home_abbrev,away_abbrev,season,week)
94
  data['Total Score Close'] = total
95
  matrix = xgb.DMatrix(data.astype(float).values)
96
 
97
+ # create game id
98
+ game_id = str(season) + '_0' + str(week) + '_' + away_abbrev + '_' + home_abbrev
99
+
100
  # moneyline
101
+ model = 'xgboost_ML_no_odds_71.4%'
102
  file_path = os.path.join(model_directory, f'{model}.json')
103
  xgb_ml = xgb.Booster()
104
  xgb_ml.load_model(file_path)
105
+
106
+ try:
107
+ moneyline_result = results.loc[results['game_id']==game_id, 'winner'].item()
108
+ except:
109
+ moneyline_result = 'N/A'
110
+
111
  try:
112
  ml_predicted_proba = xgb_ml.predict(matrix)[0][1]
 
113
  winner_proba = max([ml_predicted_proba, 1-ml_predicted_proba]).item()
114
+ moneyline = {'Winner': [home if ml_predicted_proba>0.5 else away if ml_predicted_proba<0.5 else 'Toss-Up'],
115
+ 'Probabilities':[winner_proba],
116
+ 'Result': moneyline_result}
117
  except:
118
  moneyline = {'Winner': 'NA',
119
+ 'Probabilities':['N/A'],
120
+ 'Result': moneyline_result}
121
 
122
  # over/under
123
  model = 'xgboost_OU_no_odds_60.8%'
124
  file_path = os.path.join(model_directory, f'{model}.json')
125
  xgb_ou = xgb.Booster()
126
  xgb_ou.load_model(file_path)
127
+
128
+ try:
129
+ result = results.loc[results['game_id']==game_id, 'total'].item()
130
+ over_under_result = 'Over' if float(result)>float(total) else 'Under'
131
+ except:
132
+ over_under_result = 'N/A'
133
+
134
  try:
135
  ou_predicted_proba = xgb_ou.predict(matrix)[0][1]
136
  ou_proba = max([ou_predicted_proba, 1-ou_predicted_proba]).item()
137
+
138
  over_under = {'Over/Under': ['Over' if ou_predicted_proba>0.5 else 'Under'],
139
+ 'Probability': [ou_proba],
140
+ 'Result': over_under_result}
141
  except:
142
  over_under = {'Over/Under': 'N/A',
143
+ 'Probability': ['N/A'],
144
+ 'Result': over_under_result}
145
 
146
+ print(moneyline)
 
147
  return game_id, moneyline, over_under
Templates/index.html CHANGED
@@ -82,11 +82,13 @@
82
  position: relative;
83
  width: 100%;
84
  text-align: center;
 
 
 
85
  }
86
  .winner-image {
87
- width: 50px;
88
  height: auto;
89
- margin: auto;
90
  transition: opacity 0.3s ease;
91
  }
92
  .overlay {
@@ -95,7 +97,7 @@
95
  left: 0;
96
  width: 100%;
97
  height: 100%;
98
- background-color: rgba(0, 0, 0, 0.7);
99
  color: white;
100
  display: flex;
101
  justify-content: center;
@@ -117,23 +119,25 @@
117
  }
118
  .over-under-text {
119
  display: inline-block;
120
- margin: auto;
 
 
121
  }
122
  .over {
123
- background-color: green;
124
  }
125
  .under {
126
- background-color: red;
127
  }
128
  .na {
129
- background-color: grey;
130
  }
131
  .over-under-wrapper .overlay {
132
  position: absolute;
133
  top: 0;
134
  left: 0;
135
  width: 100%;
136
- background-color: rgba(0, 0, 0, 0.7);
137
  color: white;
138
  display: flex;
139
  justify-content: center;
@@ -259,36 +263,36 @@
259
 
260
  <script>
261
  async function fetchGames() {
262
- const response = await fetch('/get_games');
263
- const games = await response.json();
264
- const table = document.getElementById('gameTable');
265
- const columns = ['Date','Away Team', 'Home Team'];
266
-
267
- games.forEach((game) => {
268
- const row = table.insertRow(-1);
269
-
270
- columns.forEach((column) => {
271
- const cell = row.insertCell(-1);
272
- if (column === 'Away Team' || column === 'Home Team') {
273
- const img = document.createElement('img');
274
- img.src = `/Static/${game[column]}.webp`;
275
- img.alt = game[column];
276
- img.width = 50;
277
- cell.appendChild(img);
278
- } else {
279
- cell.textContent = game[column];
280
- }
281
- });
282
 
283
- for (let i = 0; i < 3; i++) {
284
- const cell = row.insertCell(-1);
285
- if (i<1) {
286
- const input = document.createElement('input');
287
- input.type = 'text';
288
- cell.appendChild(input);
 
289
  }
290
- }
291
- });
292
  }
293
 
294
  fetchGames();
@@ -341,6 +345,18 @@
341
  winnerImg.className = 'winner-image hidden';
342
  wrapperDiv.appendChild(winnerImg);
343
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  setTimeout(() => {
345
  winnerImg.classList.remove('hidden');
346
  }, 10);
@@ -370,6 +386,18 @@
370
 
371
  overUnderDiv.appendChild(textDiv);
372
 
 
 
 
 
 
 
 
 
 
 
 
 
373
  setTimeout(() => {
374
  overUnderDiv.classList.remove('hidden');
375
  }, 10);
@@ -380,6 +408,7 @@
380
  overUnderDiv.appendChild(overUnderOverlayDiv);
381
 
382
  overUnderCell.appendChild(overUnderDiv);
 
383
  });
384
  }
385
  });
 
82
  position: relative;
83
  width: 100%;
84
  text-align: center;
85
+ display: flex;
86
+ justify-content: center;
87
+ align-items: center;
88
  }
89
  .winner-image {
 
90
  height: auto;
91
+ margin: 0;
92
  transition: opacity 0.3s ease;
93
  }
94
  .overlay {
 
97
  left: 0;
98
  width: 100%;
99
  height: 100%;
100
+ background-color: rgba(0, 0, 0, 0.9);
101
  color: white;
102
  display: flex;
103
  justify-content: center;
 
119
  }
120
  .over-under-text {
121
  display: inline-block;
122
+ margin: 0;
123
+ margin-right: 2px;
124
+ font-weight: bold;
125
  }
126
  .over {
127
+ color: green;
128
  }
129
  .under {
130
+ color: red;
131
  }
132
  .na {
133
+ color: white;
134
  }
135
  .over-under-wrapper .overlay {
136
  position: absolute;
137
  top: 0;
138
  left: 0;
139
  width: 100%;
140
+ background-color: rgba(0, 0, 0, 0.9);
141
  color: white;
142
  display: flex;
143
  justify-content: center;
 
263
 
264
  <script>
265
  async function fetchGames() {
266
+ const response = await fetch('/get_games');
267
+ const pulled_games = await response.json();
268
+ const table = document.getElementById('gameTable');
269
+ const columns = ['Date','Away Team', 'Home Team'];
270
+
271
+ pulled_games.forEach((game) => {
272
+ const row = table.insertRow(-1);
273
+
274
+ columns.forEach((column) => {
275
+ const cell = row.insertCell(-1);
276
+ if (column === 'Away Team' || column === 'Home Team') {
277
+ const img = document.createElement('img');
278
+ img.src = `/Static/${game[column]}.webp`;
279
+ img.alt = game[column];
280
+ img.width = 50;
281
+ cell.appendChild(img);
282
+ } else {
283
+ cell.textContent = game[column];
284
+ }
285
+ });
286
 
287
+ for (let i = 0; i < 3; i++) {
288
+ const cell = row.insertCell(-1);
289
+ if (i<1) {
290
+ const input = document.createElement('input');
291
+ input.type = 'text';
292
+ cell.appendChild(input);
293
+ }
294
  }
295
+ });
 
296
  }
297
 
298
  fetchGames();
 
345
  winnerImg.className = 'winner-image hidden';
346
  wrapperDiv.appendChild(winnerImg);
347
 
348
+ const winnerEmojiDiv = document.createElement('div');
349
+ winnerEmojiDiv.className = 'emoji';
350
+ if (moneyline.Winner === moneyline.Result) {
351
+ winnerEmojiDiv.textContent = 'βœ…';
352
+ } else {
353
+ winnerEmojiDiv.textContent = '❌';
354
+ }
355
+ if (moneyline.Result === 'N/A') {
356
+ winnerEmojiDiv.textContent = '';
357
+ }
358
+ wrapperDiv.appendChild(winnerEmojiDiv);
359
+
360
  setTimeout(() => {
361
  winnerImg.classList.remove('hidden');
362
  }, 10);
 
386
 
387
  overUnderDiv.appendChild(textDiv);
388
 
389
+ const overEmojiDiv = document.createElement('div');
390
+ overEmojiDiv.className = 'emoji';
391
+ if (data.over_unders[index]['Over/Under'] === data.over_unders[index]['Result']) {
392
+ overEmojiDiv.textContent = 'βœ…';
393
+ } else {
394
+ overEmojiDiv.textContent = '❌';
395
+ }
396
+ if (data.over_unders[index]['Result'] === 'N/A') {
397
+ overEmojiDiv.textContent = '';
398
+ }
399
+ overUnderDiv.appendChild(overEmojiDiv);
400
+
401
  setTimeout(() => {
402
  overUnderDiv.classList.remove('hidden');
403
  }, 10);
 
408
  overUnderDiv.appendChild(overUnderOverlayDiv);
409
 
410
  overUnderCell.appendChild(overUnderDiv);
411
+
412
  });
413
  }
414
  });