def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if not seasons: messages.error_message("No season data found") for season in seasons: show_results(league, season, args.results)
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if args.history: seasons = seasons[-args.history:] this_season = seasons.pop() (row, ) = extract_picked_team(args.database, args.team, league) team = Team.inventory[row[0]] events = [win, loss] colors = ['dodgerblue', 'salmon'] data = [] for i, func in enumerate(events): title = '{} margin (Seasons:{}-{})'.format(Event.name(func, False), seasons[0].year, seasons[-1].year) container_a = BarContainer(colors[i], title) for season in seasons: populate(season, team, args.venue, args.half, container_a.data, func) title = '{} margin (Season:{})'.format(Event.name(func, False), this_season.year) container_b = BarContainer(colors[i], title) populate(this_season, team, args.venue, args.half, container_b.data, func) data.append([container_a, container_b]) fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(10, 10), squeeze=False, constrained_layout=True) for row in range(len(events)): containers = data[row] for col, container in enumerate(containers): ax = axs[row, col] add_bar_chart(ax, container) title = '{} {}: {}'.format(league.country, league.name, team.name) if args.venue == Venue.any: title = '{} ({} or {})'.format(title, Venue.home.name, Venue.away.name) else: title = '{} ({} only)'.format(title, args.venue.name) if args.half != Half.both: title = '{} ({} half)'.format(title, args.half.name) fig.suptitle(title, fontweight='bold', fontsize=14) plt.show(block=args.block)
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if not seasons: messages.error_message("No season data found") if args.history: seasons = seasons[-args.history:] selected_team = None if args.team: (row, ) = extract_picked_team(args.database, get_unique_team(args), league) selected_team = Team.inventory[row[0]] intervals = [] create_intervals(intervals, args.intervals, 0) create_intervals(intervals, args.intervals, 45) season_to_summary = OrderedDict() with ThreadPoolExecutor(max_workers=8) as executor: future_to_data = { executor.submit(compute_summaries, args.database, season, intervals, selected_team, args.venue): season for season in seasons } for future in as_completed(future_to_data): season = future_to_data[future] overall, for_team, against_team = future.result() if overall: season_to_summary[season] = (overall, for_team, against_team) title = 'Goal times: {} {}'.format(league.country, league.name) if selected_team: title = '{} and {}'.format(title, selected_team.name) if args.venue == Venue.any: title = '{} ({} or {})'.format(title, Venue.home.name, Venue.away.name) else: title = '{} ({} only)'.format(title, args.venue.name) show(title, season_to_summary, args.block)
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if args.history: seasons = seasons[-args.history:] head_season = seasons[-1] head_table = LeagueTable(head_season, args.half) table_map = head_table.group(args.chunks) predicates = predicate_table[args.analysis] matrix = np.zeros(shape=(table_map.number_of_chunks(), len(predicates.functions)), dtype=np.int32) for season in seasons: table = LeagueTable(season, args.half) table_map = table.group(args.chunks) fill_matrix(matrix, table_map, table, predicates, args.half) datum = pd.DataFrame(matrix) datum.columns = [ Event.name(func, negate=False, short=True) for func in predicates.functions ] datum.index = create_chunk_labels(table_map) fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(10, 10), constrained_layout=True) heatmap(datum, cmap='coolwarm', linewidth=0.5, annot=True, fmt='d', ax=ax) ax.set_ylabel('Positions') ax.set_xlabel(args.analysis.name.capitalize()) sublists = split_into_contiguous_groups( [season.year for season in seasons]) title = '{} {} Seasons:{}'.format(league.country, league.name, to_string(sublists)) if args.half != Half.both: title = '{} ({} half)'.format(title, args.half.name) fig.suptitle(title, fontweight='bold', fontsize=14) plt.show(block=args.block)
def get_current_season(db: Database, league: League): country_constraint = "{}='{}' {} {}".format(ColumnNames.Country.name, league.country, Keywords.COLLATE.name, Keywords.NOCASE.name) name_constraint = "{}='{}' {} {}".format(ColumnNames.Code.name, league.name, Keywords.COLLATE.name, Keywords.NOCASE.name) current_constraint = "{}={}".format(ColumnNames.Current.name, Characters.TRUE.value) constraints = [country_constraint, name_constraint, current_constraint] season_rows = db.fetch_all_rows(Season.sql_table(), constraints) if season_rows: (season, ) = season_rows return season
def update_all(database: str, past: bool, force: bool): codes = [] with Database(database) as db: team_rows = db.fetch_all_rows(Team.sql_table()) for row in team_rows: create_team_from_row(row) for code, league in league_register.items(): constraints = [ "{}='{}'".format(ColumnNames.Country.name, league.country), "{}='{}'".format(ColumnNames.Code.name, league.name) ] season_rows = db.fetch_all_rows(Season.sql_table(), constraints) for season_row in season_rows: season = create_season_from_row(season_row) if season.current: if force or fixtures_played(database, season): codes.append(code) update_leagues(database, codes, past, force or codes)
def show_results(league: League, season: Season, results: List[str]): matched = [] for fixture in season.fixtures(): result = fixture.full_time() if result: for given_result in results: left, right = map(int, given_result.split('-')) if left == result.left and right == result.right: matched.append(fixture) else: messages.warning_message('Ignoring {}'.format(fixture)) if matched: table = LeagueTable(season, Half.both) print('>' * 40, season.year, '<' * 40) for fixture in matched: print('{:<2} vs {:<2}: {}'.format( table.team_position(fixture.home_team) + 1, table.team_position(fixture.away_team) + 1, fixture)) print()
def compute_statistics(season: Season, team: Team, venue: Venue, game_states: List[str]): fixtures = [] for fixture in season.fixtures(): if fixture.first_half() is not None and fixture.second_half( ) is not None: if venue == Venue.any: if fixture.home_team == team or fixture.away_team == team: fixtures.append(fixture) elif venue == Venue.away: if fixture.away_team == team: fixtures.append(fixture) elif venue == Venue.home: if fixture.home_team == team: fixtures.append(fixture) stats = MatchStatistics() for fixture in fixtures: if fixture.home_team == team: first_half = fixture.first_half() second_half = fixture.second_half() full_time = fixture.full_time() else: first_half = fixture.first_half().reverse() second_half = fixture.second_half().reverse() full_time = fixture.full_time().reverse() analyse = True if game_states: analyse = False for state in game_states: left, right = map(int, state.split('-')) if not analyse: analyse = left == first_half.left and right == first_half.right if analyse: update_stats(stats.first_half, first_half) update_stats(stats.second_half, second_half) update_stats(stats.both_halves, full_time) return stats
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if args.history: seasons = seasons[-args.history:] if args.relative: team_names = get_multiple_teams(args) table = LeagueTable(seasons[-1], args.half) lower, upper = table.positions(Position.from_string(args.relative)) positions = [i for i in range(lower, upper)] compute_relative_performance(args, league, seasons, team_names, positions) elif args.position: team_names = get_multiple_teams(args) compute_relative_performance(args, league, seasons, team_names, args.position) elif args.average: team_name = get_unique_team(args) compute_average_performance(args, league, seasons, team_name) else: compute_individual_performance(args, league, seasons)
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if not seasons: messages.error_message("No season data found") season_to_summary = OrderedDict() ylim = 0 for season in seasons: summary = compute_summary(season, args.half) if summary: season_to_summary[season] = summary ylim = max(ylim, season_to_summary[season].home_goals, season_to_summary[season].away_goals) ylim += 25 title = '{} {}'.format(league.country, league.name) if args.half != Half.both: title += ' ({} half)'.format(args.half.name) show(title, season_to_summary, ylim, args.block)
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if not seasons: messages.error_message("No season data found") if args.history: seasons = seasons[-args.history:] if args.team: (row, ) = extract_picked_team(args.database, args.team, league) selected_team = Team.inventory[row[0]] else: selected_team = None func = Event.get(get_unique_event(args)) if args.chunks: data = compute_chunked_data(seasons, func, args.negate, args.venue, args.half, args.chunks) nrows = len(data) if selected_team is not None: ncols = 3 else: ncols = 1 fig, axes = plt.subplots(nrows=len(data), ncols=ncols, figsize=(20, 13), squeeze=False, constrained_layout=True) x_limit, _ = find_limits(data) for i, datum in enumerate(data): ax = axes[i, 0] plot(ax, datum, x_limit, args.lines) if selected_team is not None: golden_season = seasons[-1] golden_table = LeagueTable(golden_season, args.half) golden_map = golden_table.group(args.chunks) chunk_to_seasons = OrderedDict() for chunk_id in range(golden_map.number_of_chunks()): if chunk_id not in chunk_to_seasons: chunk_to_seasons[chunk_id] = [] for season in seasons: if season != golden_season: table = LeagueTable(season, args.half) table_map = table.group(args.chunks) if selected_team in season.teams(): position = table.team_position(selected_team) chunk_id = table_map.get_chunk(position) chunk_to_seasons[chunk_id].append(season) chunk_to_datum = OrderedDict() for chunk_id, chunk_seasons in chunk_to_seasons.items(): if chunk_seasons: datum = DataUnit(Counter(), chunk_seasons, team=selected_team, positions=golden_map.get_rows(chunk_id)) chunk_to_datum[chunk_id] = datum for season in seasons: if season == golden_season: position = golden_table.team_position(selected_team) datum = DataUnit(Counter(), [golden_season], team=selected_team, positions=[position], highlight=True) golden_datum = datum else: if selected_team in season.teams(): table = LeagueTable(season, args.half) table_map = table.group(args.chunks) position = table.team_position(selected_team) chunk_id = table_map.get_chunk(position) datum = chunk_to_datum[chunk_id] count_events(season, selected_team, args.venue, args.half, func, args.negate, datum) position = golden_table.team_position(selected_team) chunk_id = golden_map.get_chunk(position) ax = axes[chunk_id, 1] plot(ax, golden_datum, x_limit, args.lines) used = {(chunk_id, 1)} for chunk_id, datum in chunk_to_datum.items(): ax = axes[chunk_id, 2] plot(ax, datum, x_limit, args.lines) used.add((chunk_id, 2)) for i in range(0, nrows): for j in range(1, 3): if (i, j) not in used: fig.delaxes(axes[i, j]) else: data = compute_aggregated_data(seasons, selected_team, func, args.negate, args.venue, args.half) x_limit, _ = find_limits(data) display = DisplayGrid(len(data), 2) fig, axes = plt.subplots(nrows=display.nrows, ncols=display.ncols, figsize=(20, 10), squeeze=False) for i, datum in enumerate(data): cell_x, cell_y = display.index(i) ax = axes[cell_x, cell_y] plot(ax, datum, x_limit, args.lines) title = construct_title(league, func, args.negate, args.venue, args.half) fig.suptitle(title, fontweight='bold', fontsize=14) plt.show(block=args.block)
def main(args: Namespace): league = league_register[get_unique_league(args)] load_database(args.database, league) seasons = Season.seasons(league) this_season = seasons.pop() assert this_season.current func = Event.get(get_unique_event(args)) for i in range(1, 38): prediction = Prediction(func, i) penalties = Counter() for season in seasons: table = LeagueTable(season, Half.both) states = {team: TeamState() for team in season.teams()} season.sort_fixtures() fixture: Fixture for fixture in season.fixtures(): if args.half == Half.both: result = fixture.full_time() elif args.half == Half.first: result = fixture.first_half() elif args.half == Half.second: result = fixture.second_half() if result: home_result = fixture.canonicalise_result( fixture.home_team, result) home_outcome = prediction.func(home_result) home_state = states[fixture.home_team] if not home_outcome: home_state.fixtures.append(fixture) else: if home_state.alive: index = len( home_state.fixtures) - prediction.minimum + 1 penalties[index] += 1 states[fixture.home_team] = TeamState() if len(home_state.fixtures) == prediction.minimum: final_position = table.team_position(fixture.home_team) if final_position not in [ 0, 1, len(table) - 2, len(table) - 1 ]: home_state.alive = True away_result = fixture.canonicalise_result( fixture.away_team, result) away_outcome = prediction.func(away_result) away_state = states[fixture.away_team] if not away_outcome: away_state.fixtures.append(fixture) else: if away_state.alive: index = len( away_state.fixtures) - prediction.minimum + 1 penalties[index] += 1 states[fixture.away_team] = TeamState() away_state.fixtures.append(fixture) if len(away_state.fixtures) == prediction.minimum: final_position = table.team_position(fixture.away_team) if final_position not in [ 0, 1, len(table) - 2, len(table) - 1 ]: away_state.alive = True total_penalty = 0 total_correct = 0 for distance, correct in penalties.items(): exponent = distance this_penalty = 2**exponent - 1 total_penalty += this_penalty * correct total_correct += correct if total_penalty: print( 'Betting from sequences of {} returns {} right with a penalty of {}' .format(i, total_correct, total_penalty))
def main(args: Namespace): load_teams(args.database) func = Event.get(get_unique_event(args)) train_data = [] train_history = [] for code in args.league: league = league_register[code] load_league(args.database, league) seasons = Season.seasons(league) *seasons, _ = seasons collect_data(seasons, func, train_data, train_history) dependent_variable = Event.name(func, False) df = pd.DataFrame.from_records(train_data) cols = [] for x in HistorySummary.__slots__: cols.extend(['H({})'.format(x), 'A({})'.format(x)]) cols.append(dependent_variable) df.columns = cols plt.figure() y_train = df[dependent_variable] x_train = df.drop([dependent_variable], axis=1) rf = RandomForestClassifier() rf.fit(x_train, y_train) print("Features sorted by their score:") print( sorted(zip(map(lambda x: round(x, 4), rf.feature_importances_), x_train), reverse=True)) model = RandomForestClassifier() # Fit the model model.fit(x_train, y_train) # Accuracy score = model.score(x_train, y_train) print(score) test_data = [] test_history = [] for code in args.league: league = league_register[code] load_league(args.database, league) seasons = Season.seasons(league) *_, this_season = seasons collect_data([this_season], func, test_data, test_history) df = pd.DataFrame.from_records(test_data) cols = [] for x in HistorySummary.__slots__: cols.extend(['H({})'.format(x), 'A({})'.format(x)]) cols.append(dependent_variable) df.columns = cols y_test = df[dependent_variable] x_test = df.drop([dependent_variable], axis=1) predicted = list(model.predict(x_test)) true_positives = [] true_negatives = [] false_positives = [] false_negatives = [] for i in range(len(y_test)): if y_test[i] and predicted[i]: true_positives.append(test_history[i]) elif not y_test[i] and not predicted[i]: true_negatives.append(test_history[i]) elif not y_test[i] and predicted[i]: false_positives.append(test_history[i]) elif y_test[i] and not predicted[i]: false_negatives.append(test_history[i]) print() print('>>>>>>>>>>>>>>>>>>> True positives') for fixture in true_positives: print(fixture) print() print('>>>>>>>>>>>>>>>>>>> True negatives') for fixture in true_negatives: print(fixture) print() print('>>>>>>>>>>>>>>>>>>> False positives') for fixture in false_positives: print(fixture) print() print('>>>>>>>>>>>>>>>>>>> False negatives') for fixture in false_negatives: print(fixture) print('TP={} TN={} FP={} FN={}'.format(len(true_positives), len(true_negatives), len(false_positives), len(false_negatives)))
def count_events(season: Season, team: Team, venue: Venue, half: Half, func: Callable, negate: bool, data: DataUnit): fixtures = [] for fixture in season.fixtures(): if venue == Venue.any: if fixture.home_team == team or fixture.away_team == team: fixtures.append(fixture) elif venue == Venue.away: if fixture.away_team == team: fixtures.append(fixture) elif venue == Venue.home: if fixture.home_team == team: fixtures.append(fixture) sequence = [] for fixture in fixtures: results = [] if half == Half.both: if fixture.full_time() is not None: results.append(fixture.full_time()) elif half == Half.first: if fixture.first_half() is not None: results.append(fixture.first_half()) else: warning_message('No 1st half result for fixture {}'.format(fixture)) elif half == Half.second: if fixture.second_half() is not None: results.append(fixture.second_half()) else: warning_message('No 2nd half result for fixture {}'.format(fixture)) elif half == Half.separate: if fixture.first_half() is not None: results.append(fixture.first_half()) if fixture.second_half() is not None: results.append(fixture.second_half()) else: assert False if results: for result in results: if fixture.home_team != team: result = result.reverse() if negate: outcome = not func(result) else: outcome = func(result) if outcome: sequence.append(fixture) else: data.last = len(sequence) data.counter[len(sequence)] += 1 sequence = [] if sequence: data.last = len(sequence) data.counter[len(sequence)] += 1 else: data.last = None
def main(args: Namespace): load_teams(args.database) league = league_register[get_unique_league(args)] load_league(args.database, league) seasons = Season.seasons(league) if args.history: seasons = seasons[-args.history:] event = Event.get(get_unique_event(args)) head_season = seasons[-1] head_table = LeagueTable(head_season, args.half) if head_table.played() == 0: head_season = seasons[-2] head_table = LeagueTable(head_season, args.half) nrows = 1 else: nrows = 2 head_map = head_table.group(args.chunks) shape = (head_map.number_of_chunks(), head_map.number_of_chunks()) historical_matrix = np.zeros(shape=shape, dtype=np.int32) historical_seasons = seasons[:-1] for season in historical_seasons: table = LeagueTable(season, args.half) fill_matrix(event, args.symmetry, historical_matrix, head_map, table, args.half) display = DisplayGrid(nrows, 1) fig, axs = plt.subplots(nrows=display.nrows, ncols=display.ncols, figsize=(15, 12), squeeze=False, constrained_layout=True) datum = pd.DataFrame(historical_matrix) sublists = split_into_contiguous_groups( [season.year for season in historical_seasons]) title = 'Seasons:{}'.format(to_string(sublists)) cell_x, cell_y = display.index(0) ax = axs[cell_x, cell_y] populate_axis(head_map, datum, ax, title) if nrows == 2: now_matrix = np.zeros(shape=shape, dtype=np.int32) fill_matrix(event, args.symmetry, now_matrix, head_map, head_table, args.half) datum = pd.DataFrame(now_matrix) title = 'Season:{}'.format(head_season.year) cell_x, cell_y = display.index(1) ax = axs[cell_x, cell_y] populate_axis(head_map, datum, ax, title) title = '{} {}: {}'.format(league.country, league.name, Event.name(event, args.negate)) if args.half != Half.both: title = '{} ({} half)'.format(title, args.half.name) fig.suptitle(title, fontweight='bold', fontsize=14) plt.show(block=args.block)