-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnfl.py
More file actions
352 lines (308 loc) · 9.15 KB
/
Copy pathnfl.py
File metadata and controls
352 lines (308 loc) · 9.15 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
#!/usr/bin/env python3
"""
NFL Prediction CLI Tool
A command-line interface for managing NFL data and predictions.
"""
import click
import nflreadpy as nfl
from src.model.train import train_model
from src.model.predict import get_future_predictions, get_past_predictions
from src.config.feature_selection import run_feature_selection
from src.config.random_search import run_random_search
from src.config.optimize_confidence import run_optimization
from src.data.data import backfil_data
from src.data.update_spreads import update_current_spreads
from src.reports.qb_changes import get_qb_change
from src.data.backup import backup_database
from src.reports.nfl_past_prediction_report import (
generate_past_prediction_report,
load_data,
save_accuracy_metrics_to_db,
)
from src.reports.compare_configs_report import generate_compare_configs_report
from src.reports.nfl_power_ranking_report import generate_power_rankings_report
from src.reports.nfl_future_prediction_report import generate_future_predictions_report
from src.reports.past_predictions_analysis import print_bucket_analysis
from src.reports.analyze_future_bucket_confidence import print_future_analysis
from src.reports.analyze_past_bucket_confidence import print_past_bucket_analysis
@click.group()
def cli():
"""NFL prediction and data management tool."""
pass
@cli.group()
def data():
"""Data management commands."""
pass
@data.command()
@click.option(
"--backup",
is_flag=True,
help="Create a backup of the database before refreshing data.",
)
@click.option(
"--backfill-date",
type=int,
default=2003,
help="Date to backfill data from (default: 2003).",
)
@click.option(
"--spreads",
is_flag=True,
help="Update current spread data only.",
)
def refresh(backfill_date, backup, spreads):
"""Refresh NFL data from sources."""
print("Running: nfl data refresh")
if backup:
backup_database()
if spreads:
update_current_spreads()
else:
backfil_data(backfill_date)
@cli.group()
def model():
"""Model training, optimization, and prediction commands."""
pass
@model.group()
def predict():
"""Prediction commands."""
pass
@predict.command()
@click.option(
"--year",
type=str,
default="2025",
help="Year(s) to generate predictions for. Can be a single year (2025), multiple years (2024,2025), or 'all' (default: 2025).",
)
@click.option(
"--report",
is_flag=True,
help="Generate prediction report after predictions are made.",
)
@click.option(
"--spread-line",
is_flag=True,
help="Use the nflreadpy spread line for predictions instead of Yahoo spread.",
)
def past(year, report, spread_line):
"""Generate predictions for past games."""
print("Running: nfl model predict past")
get_past_predictions(year, spread_line)
if report:
df = load_data()
generate_past_prediction_report(df)
save_accuracy_metrics_to_db(df)
@predict.command()
@click.option(
"--report",
is_flag=True,
help="Generate prediction report after predictions are made.",
)
@click.option(
"--spread-line",
is_flag=True,
help="Use the nflreadpy spread line for predictions instead of Yahoo spread.",
)
@click.option(
"--bucket",
is_flag=True,
help="Show bucket-based confidence accuracy for each prediction.",
)
def future(report, spread_line, bucket):
"""Generate predictions for future games."""
print("Running: nfl model predict future")
get_future_predictions(spread_line, bucket)
if report:
df = load_data()
save_accuracy_metrics_to_db(df)
generate_future_predictions_report()
@click.option(
"--spread-line",
is_flag=True,
help="Use the nflreadpy spread line for predictions instead of Yahoo spread.",
)
@model.command()
def train(spread_line):
"""Train the prediction model."""
print("Running: nfl model train")
train_model(spread_line)
@cli.group()
def config():
"""Configuration commands."""
pass
@config.command()
@click.option(
"--granularity",
type=click.Choice(["coarse", "fine", "ultra"]),
default="coarse",
help="Search granularity: coarse (fast, default), fine (balanced), ultra (slow but thorough).",
)
@click.option(
"--min-features",
type=int,
default=3,
help="Minimum number of features in each combination. Default: 3",
)
@click.option(
"--max-features",
type=int,
default=7,
help="Maximum number of features in each combination. Default: 7",
)
@click.option(
"--workers",
type=int,
default=None,
help="Number of parallel workers (default: auto-detect CPU count). Use 1 to disable multiprocessing.",
)
@click.option(
"--verify",
is_flag=True,
help="Run verification check before optimization to ensure calculations work correctly.",
)
@click.option(
"--top-features",
type=int,
default=12,
help="Only consider top N features by correlation with correct predictions. Default: 12",
)
def optimize_confidence(
granularity, min_features, max_features, workers, verify, top_features
):
"""Optimize the confidence formula to maximize confidence points for correct predictions."""
print("Running: nfl config optimize-confidence")
run_optimization(
granularity, min_features, max_features, workers, verify, top_features
)
@click.option(
"--spread-line",
is_flag=True,
help="Use the nflreadpy spread line for predictions instead of Yahoo spread.",
)
@config.command()
def feature_selection(spread_line):
"""Perform feature selection for the model."""
print("Running: nfl model feature-selection")
run_feature_selection(spread_line)
@config.command()
@click.option(
"--iterations",
type=int,
default=100,
help="Number of hyperparameter combinations to test (default: 100).",
)
@click.option(
"--threshold",
type=float,
default=55.0,
help="Minimum required 2025 prediction score (default: 55.0).",
)
@click.option("--resume", is_flag=True, help="Resume from previous random search run.")
@click.option(
"--min-train-r2",
type=float,
default=0.27,
help="Minimum required training R² (default: 0.27)",
)
@click.option(
"--min-iterations",
type=int,
default=20,
help="Minimum required early stopping iterations (default: 20)",
)
@click.option(
"--spread-line",
is_flag=True,
help="Use the nflreadpy spread line for predictions instead of Yahoo spread.",
)
def random_search(
iterations, threshold, resume, min_train_r2, min_iterations, spread_line
):
"""Perform random search for hyperparameter optimization."""
print("Running: nfl model random-search")
print(
f"Parameters: iterations={iterations}, threshold={threshold}, resume={resume}, min_train_r2={min_train_r2}, min_iterations={min_iterations}"
)
run_random_search(
iterations, threshold, resume, min_train_r2, min_iterations, spread_line
)
@cli.group()
def report():
"""Report generation commands."""
pass
@report.command()
def qb_change():
"""Identify quarterback changes for the current week."""
print("Running: nfl data qb-change")
get_qb_change()
@report.command()
def past_predictions():
"""Generate predictions report."""
df = load_data()
generate_past_prediction_report(df)
save_accuracy_metrics_to_db(df)
@report.command()
def future_predictions():
"""Generate outlier report for future predictions."""
generate_future_predictions_report()
@report.command()
@click.option(
"--log-file",
type=str,
default="random_search_results.txt",
help="Path to random_search_results.txt (default: random_search_results.txt)",
)
@click.option(
"--top-n",
type=int,
default=None,
help="Only evaluate top N configs by original score (default: None)",
)
@click.option(
"--output-file",
type=str,
default="config_comparison.html",
help="Output HTML file (default: config_comparison.html)",
)
@click.option(
"--spread-line",
is_flag=True,
help="Use the nflreadpy spread line for predictions instead of Yahoo spread.",
)
def compare_configs(log_file, top_n, output_file, spread_line):
"""Generate compare configs report."""
generate_compare_configs_report(log_file, top_n, output_file, spread_line)
@click.option(
"--season",
type=int,
default=2025,
help="Season year (default: 2025)",
)
@report.command()
def power_rankings(season):
"""Generate power rankings report."""
generate_power_rankings_report(season=season)
@click.option(
"--future",
is_flag=True,
help="Show future predictions bucket confidence analysis.",
)
@click.option(
"--past",
is_flag=True,
help="Show past predictions bucket confidence analysis.",
)
@report.command()
def bucket_analysis(future, past):
"""Analyze past predictions performance by metric buckets."""
print("Running: nfl report bucket-analysis")
if future:
print("Future Predictions Bucket Confidence Analysis:")
print_future_analysis()
if past:
print("Past Predictions Bucket Confidence Analysis:")
print_past_bucket_analysis()
if not future and not past:
print_bucket_analysis()
if __name__ == "__main__":
cli()