def _log(substatistic, which): if which is None: get_logger().debug('%s', substatistic.to_string(index=False)) else: log_columns = ['date', 'home', 'away'] + wrap(which) get_logger().debug( '%s', substatistic[log_columns].to_string(index=False))
def _fit(self, **kwargs): get_logger('prediction').info('Условие для получения заголовков: %s', str(self.sample_condition)) self.match_headers = get_match_headers(self.sample_condition) get_logger('prediction').info('Получены заголовки матчей: %u штук', self.match_headers.shape[0]) # TODO: Решить, что с этим делать self.statistic = self.match_headers.copy()
def _fit(self, match_header, **kwargs): statistic = self.previous_fitter.statistic.copy() if statistic.shape[0] == 0: self.statistic = statistic return self.match_date = match_header['date'] self.last_datetime = eve_datetime(self.match_date) transformed_statistic = statistic[ statistic['date'] <= self.last_datetime] self.statistic = transformed_statistic.copy() get_logger('prediction').info( 'Отобраны заголовки матчей, доступные на %s: %u штук', self.last_datetime.strftime('%Y-%m-%d %H:%M:%S'), self.statistic.shape[0])
def _fit(self, match_header, **kwargs): statistic = self.previous_fitter.statistic.copy() if statistic.shape[0] == 0: self.statistic = statistic return self.tournament_id = match_header['tournamentId'] transformed_statistic = statistic[statistic['tournament_id'] == self.tournament_id] self.statistic = transformed_statistic.copy() get_logger('prediction').info( 'Отобраны заголовки матчей, произошедших в рамках турнира %s (%u): %u штук', get_value(tournaments_data, 'whoscoredTournamentId', self.tournament_id, 'whoscoredTournamentName'), self.tournament_id, self.statistic.shape[0])
def _fit(self, match_header, **kwargs): statistic = self.previous_fitter.statistic.copy() if statistic.shape[0] == 0: self.statistic = statistic return self.match_date = match_header['date'] self.first_datetime = eve_datetime(self.match_date - self.delta) self.last_datetime = eve_datetime(self.match_date) transformed_statistic = statistic[ (statistic['date'] >= self.first_datetime) & (statistic['date'] <= self.last_datetime)] self.statistic = transformed_statistic.copy() get_logger('prediction').info( 'Отобраны заголовки матчей, произошедших не более чем за %s до матча (с %s по %s): %u штук', str(self.delta), self.first_datetime.strftime('%Y-%m-%d'), self.last_datetime.strftime('%Y-%m-%d'), self.statistic.shape[0])
def _get_match_value(match_uuid, crosses_first_period_statistic, shots_first_period_statistic): crosses_first_period_home_count = crosses_first_period_statistic.at[ match_uuid, 'events_home_count'] crosses_first_period_away_count = crosses_first_period_statistic.at[ match_uuid, 'events_away_count'] get_logger('betting').debug('Количество кроссов в 1-м тайме: %u : %u', crosses_first_period_home_count, crosses_first_period_away_count) shots_first_period_home_count = shots_first_period_statistic.at[ match_uuid, 'events_home_count'] shots_first_period_away_count = shots_first_period_statistic.at[ match_uuid, 'events_away_count'] get_logger('betting').debug('Количество ударов в 1-м тайме: %u : %u', shots_first_period_home_count, shots_first_period_away_count) match_value = ((crosses_first_period_home_count - crosses_first_period_away_count) + (shots_first_period_home_count - shots_first_period_away_count)) / 2 get_logger('betting').debug('"Значение" предыдущего матча: %f', match_value) return match_value
def _fit(self, match_header, **kwargs): statistic = self.previous_fitter.statistic.copy() if statistic.shape[0] == 0: self.statistic = statistic return self.home = match_header['home'] self.away = match_header['away'] last_home_uuids = statistic[(statistic['home'] == self.home) | ( statistic['away'] == self.home)].index.values[:self.n] last_away_uuids = statistic[(statistic['away'] == self.away) | ( statistic['home'] == self.away)].index.values[:self.n] last_uuids = np.unique( np.concatenate([last_home_uuids, last_away_uuids])) transformed_statistic = statistic.loc[last_uuids] self.statistic = transformed_statistic.copy() get_logger('prediction').info( 'Отобраны последние %u заголовков матчей, где команда %s также была хозяйкой, и последние %u заголовков матчей, где команда %s также была гостей: %u штук', self.n, match_header['home'], self.n, match_header['away'], self.statistic.shape[0])
def _predict(self, fitteds, match_header, **kwargs): [corners_diffs_diff_fitted] = fitteds get_logger('prediction').info('Предсказываем разницу угловых...') corners_diffs_diff_prediction = self._corners_diffs_diff_predictor._predict( [corners_diffs_diff_fitted], match_header, **kwargs) if corners_diffs_diff_prediction is None: get_logger('prediction').info('Алгоритм не выдал предсказание') return None get_logger('prediction').info('Предсказание разницы угловых: %.1f', corners_diffs_diff_prediction) return corners_diffs_diff_prediction
def _predict(self, fitteds, match_header, **kwargs): [corners_results_fitted] = fitteds get_logger('prediction').info('Предсказываем угловые...') corners_result_prediction = self._corners_results_result_predictor._predict( [corners_results_fitted], match_header, **kwargs) if corners_result_prediction is None: get_logger('prediction').info('Алгоритм не выдал предсказание') return None get_logger('prediction').info('Предсказание угловых: %.1f:%.1f', corners_result_prediction[0], corners_result_prediction[1]) return corners_result_prediction
def _predict(self, fitteds, match_header, **kwargs): [statistic_fitted] = fitteds statistic = statistic_fitted.statistic get_logger('prediction').info('В собранной статистике %u матчей', statistic.shape[0]) if statistic.shape[0] == 0: get_logger('prediction').info( 'В собранной статистике нет матчей, не могу сделать предсказание' ) return None additional_info = get_additional_info(match_header['uuid']) if additional_info is None: return None if 'homePlayers' not in additional_info or 'awayPlayers' not in additional_info: get_logger('prediction').info( 'В матче не известен состав игроков, не могу сделать предсказание' ) return None home_player_names = [ player['playerName'] for player in additional_info['homePlayers'] if player['isFirstEleven'] ] get_logger('prediction').info('Игроки хозяев: %s', str(home_player_names)) away_player_names = [ player['playerName'] for player in additional_info['awayPlayers'] if player['isFirstEleven'] ] get_logger('prediction').info('Игроки гостей: %s', str(away_player_names)) if len(home_player_names) != 11 or len(away_player_names) != 11: print('Bad players count in match %s' % (get_match_title(match_header, show_uuid=True), )) get_logger('prediction').info( 'В матче неверное количество игроков (известны не все игроки?), не могу сделать предсказание' ) return None events_home_counts = [] get_logger('prediction').info('Рассчитаем среднее по игрокам хозяев') for player_name in frozenset( statistic.columns.values) & frozenset(home_player_names): if self.n is not None: get_logger('prediction').info( 'Выберем %u последних матчей из статистики игрока %s', self.n, player_name) else: get_logger('prediction').info( 'Выберем всю статистику игрока %s', player_name) events_player_counts = get_substatistic(statistic, n=self.n, min_n=self.min_n, sort_by='date', ascending=False, which=player_name, notnull=player_name) if events_player_counts is None: get_logger('prediction').info( 'Матчей оказалось меньше порога в %u матча', self.min_n) continue weights_full = get_weights_array(events_player_counts.shape[0], self.weights) get_logger('prediction').info('Веса: %s', str(weights_full)) events_player_counts_mean = np.sum(events_player_counts * weights_full) get_logger('prediction').info('Взвешанное среднее: %s', str(events_player_counts_mean)) events_home_counts.append(events_player_counts_mean) get_logger('prediction').info( 'Получили следующие средние для игроков хозяев (%u значений): %s', len(events_home_counts), events_home_counts) if len(events_home_counts) < self.min_real_players: get_logger('prediction').info( 'Значений оказалось меньше порога в %u матча', self.min_real_players) return None events_home_counts_mean = np.sum(events_home_counts) get_logger('prediction').info('Среднее для хозяев: %f', events_home_counts_mean) events_away_counts = [] get_logger('prediction').info('Рассчитаем среднее по игрокам гостей') for player_name in frozenset( statistic.columns.values) & frozenset(away_player_names): if self.n is not None: get_logger('prediction').info( 'Выберем %u последних матчей из статистики игрока %s', self.n, player_name) else: get_logger('prediction').info( 'Выберем всю статистику игрока %s', player_name) events_player_counts = get_substatistic(statistic, n=self.n, min_n=self.min_n, sort_by='date', ascending=False, which=player_name, notnull=player_name) if events_player_counts is None: get_logger('prediction').info( 'Матчей оказалось меньше порога в %u матча', self.min_n) continue weights_full = get_weights_array(events_player_counts.shape[0], self.weights) get_logger('prediction').info('Веса: %s', str(weights_full)) events_player_counts_mean = np.sum(events_player_counts * weights_full) get_logger('prediction').info('Взвешанное среднее: %s', str(events_player_counts_mean)) events_away_counts.append(events_player_counts_mean) get_logger('prediction').info( 'Получили следующие средние для игроков гостей (%u значений): %s', len(events_away_counts), events_away_counts) if len(events_away_counts) < self.min_real_players: get_logger('prediction').info( 'Значений оказалось меньше порога в %u матча', self.min_real_players) return None events_away_counts_mean = np.sum(events_away_counts) get_logger('prediction').info('Среднее для гостей: %f', events_away_counts_mean) result_prediction = (events_home_counts_mean, events_away_counts_mean) get_logger('prediction').info('Итого, предсказание: %.1f:%.1f', result_prediction[0], result_prediction[1]) return result_prediction
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info( 'Добавлена информация (по каждой команде) о количестве событий "красная карточка" (матч)' )
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info( 'Добавлена информация (по каждой команде) о количестве событий "кросс" (2-й тайм)' )
def _predict(self, fitteds, match_header, **kwargs): [ crosses_first_period_statistic_fitted, shots_first_period_statistic_fitted ] = fitteds crosses_first_period_statistic = crosses_first_period_statistic_fitted.statistic shots_first_period_statistic = shots_first_period_statistic_fitted.statistic crosses_first_period_match_uuids = set( crosses_first_period_statistic['uuid'].values) shots_first_period_match_uuids = set( shots_first_period_statistic['uuid'].values) if crosses_first_period_match_uuids != shots_first_period_match_uuids: get_logger('betting').info( 'В собранных статистиках (кроссы, 1-й тайм; удары, 1-й тайм) - различные матчи!' ) raise RuntimeError('different matches in statistics!') statistic_match_headers = crosses_first_period_statistic[[ 'date', 'home', 'away' ]].copy() get_logger('betting').info('В собранной статистике - %u матчей', statistic_match_headers.shape[0]) if statistic_match_headers.shape[0] == 0: get_logger('betting').info( 'В собранной статистике нет матчей, не могу сделать предсказание' ) return None if not self._match_same_location_only: get_logger('betting').info( 'Выберем последний матч из статистики, где играла команда %s', match_header['home']) home_matches = statistic_match_headers[ (statistic_match_headers['home'] == match_header['home']) | (statistic_match_headers['away'] == match_header['home'])] else: get_logger('betting').info( 'Выберем последний матч из статистики, где играла команда %s, причем так же дома', match_header['home']) home_matches = statistic_match_headers[ statistic_match_headers['home'] == match_header['home']] if home_matches.shape[0] == 0: get_logger('betting').info( 'Такого матча нет, не могу сделать предсказание') return None last_home_match_uuid = home_matches['date'].argmax() last_home_match = home_matches.loc[last_home_match_uuid] get_logger('betting').info('Предыдущий матч хозяев: %s', get_match_title(last_home_match)) was_last_home_match_home = match_header['home'] == last_home_match[ 'home'] if was_last_home_match_home: get_logger('betting').info( 'Хозяева так же играли дома в последнем матче') last_home_match_competitor = last_home_match['away'] else: get_logger('betting').info( 'Хозяева играли в гостях в последнем матче') last_home_match_competitor = last_home_match['home'] last_home_match_value = self._get_match_value( last_home_match_uuid, crosses_first_period_statistic, shots_first_period_statistic) get_logger('betting').info('"Значение" предыдущего матча хозяев: %f', last_home_match_value) home_number = last_home_match_value if was_last_home_match_home else -last_home_match_value get_logger('betting').info('"Число для хозяев": %f', home_number) corrected_home_number = home_number if not was_last_home_match_home: get_logger('betting').info( 'Последний матч хозяева играли в гостях, поэтому прибавляем 3') corrected_home_number += 3 get_logger('betting').info( 'Ограничиваем "число для хозяев" отрезком [-7, 7]') corrected_home_number = np.clip(corrected_home_number, -7, 7) if last_home_match_competitor in self._favorites: return None # Версия отказа при "проигрыше" сопернику-фавориту: """ if home_number < -1: get_logger('betting').info('Соперники хозяев в их предыдущем матче - фавориты, и они "проиграли", исходя из значения матча; отказываюсь от предсказания') return None else: get_logger('betting').info('Соперники хозяев в их предыдущем матче - фавориты, но они "выиграли", исходя из значения матча; будем делать предсказание, но поставим только на хозяев') propose_away_bets = False """ get_logger('betting').info('"Число для хозяев", скорректированное: %f', corrected_home_number) if not self._match_same_location_only: get_logger('betting').info( 'Выберем последний матч из статистики, где играла команда %s', match_header['away']) away_matches = statistic_match_headers[ (statistic_match_headers['home'] == match_header['away']) | (statistic_match_headers['away'] == match_header['away'])] else: get_logger('betting').info( 'Выберем последний матч из статистики, где играла команда %s, причем так же в гостях', match_header['away']) away_matches = statistic_match_headers[ statistic_match_headers['away'] == match_header['away']] if away_matches.shape[0] == 0: get_logger('betting').info( 'Такого матча нет, не могу сделать предсказание') return None last_away_match_uuid = away_matches['date'].argmax() last_away_match = away_matches.loc[last_away_match_uuid] get_logger('betting').info('Предыдущий матч гостей: %s', get_match_title(last_away_match)) was_last_away_match_away = match_header['away'] == last_away_match[ 'away'] if was_last_away_match_away: get_logger('betting').info( 'Гости так же играли в гостях в последнем матче') last_away_match_competitor = last_away_match['home'] else: get_logger('betting').info('Гости играли дома в последнем матче') last_away_match_competitor = last_away_match['away'] last_away_match_value = self._get_match_value( last_away_match_uuid, crosses_first_period_statistic, shots_first_period_statistic) get_logger('betting').info('"Значение" предыдущего матча гостей: %f', last_away_match_value) away_number = -last_away_match_value if was_last_away_match_away else last_away_match_value get_logger('betting').info('"Число для гостей": %f', away_number) corrected_away_number = away_number if not was_last_away_match_away: get_logger('betting').info( 'Последний матч гостей играли дома, поэтому отнимаем 3') corrected_away_number -= 3 get_logger('betting').info( 'Ограничиваем "число для гостей" отрезком [-7, 7]') corrected_away_number = np.clip(corrected_away_number, -7, 7) if last_away_match_competitor in self._favorites: return None # Версия отказа при "проигрыше" сопернику-фавориту: """ if away_number > 1: get_logger('betting').info('Соперники гостей в их предыдущем матче - фавориты, и они "проиграли", исходя из значения матча; отказываюсь от предсказания') return None else: get_logger('betting').info('Соперники гостей в их предыдущем матче - фавориты, но они "выиграли", исходя из значения матча; будем делать предсказание, но поставим только на гостей') propose_home_bets = False """ get_logger('betting').info('"Число для хозяев", скорректированное: %f', corrected_away_number) return (corrected_home_number, corrected_away_number)
def _predict(self, fitteds, match_header, **kwargs): [statistic_fitted] = fitteds statistic = statistic_fitted.statistic get_logger('prediction').info('В собранной статистике %u матчей', statistic.shape[0]) if statistic.shape[0] == 0: get_logger('prediction').info( 'В собранной статистике нет матчей, не могу сделать предсказание' ) return None get_logger('prediction').info( 'Выберем %u последних матчей из статистики, где команда %s тоже была хозяйкой', self.n, match_header['home']) # Статистика матчей, где match_header['home'] тоже была хозяйкой events_home_counts = get_substatistic(statistic, notnull='events_home_count', by='home', value=match_header['home'], n=self.n, min_n=self.min_n, sort_by='date', ascending=False, which='events_home_count') if events_home_counts is None: get_logger('prediction').info( 'Матчей оказалось меньше порога в %u матча', self.min_n) return None get_logger('prediction').info('Количество событий: %s', str(events_home_counts)) home_weights_full = get_weights_array(events_home_counts.size, self.home_weights) get_logger('prediction').info('Веса: %s', str(home_weights_full)) events_home_counts_mean = np.sum(events_home_counts * home_weights_full) get_logger('prediction').info('Взвешанное среднее: %f', events_home_counts_mean) get_logger('prediction').info( 'Выберем %u последних матчей из статистики, где команда %s тоже была гостьей', self.n, match_header['away']) # Статистика матчей, где match_header['away'] тоже была гостьей events_away_counts = get_substatistic(statistic, notnull='events_away_count', by='away', value=match_header['away'], n=self.n, min_n=self.min_n, sort_by='date', ascending=False, which='events_away_count') if events_away_counts is None: get_logger('prediction').info( 'Матчей оказалось меньше порога в %u матча', self.min_n) return None get_logger('prediction').info('Количество событий: %s', str(events_away_counts)) away_weights_full = get_weights_array(events_away_counts.size, self.away_weights) get_logger('prediction').info('Веса: %s', str(away_weights_full)) events_away_counts_mean = np.sum(events_away_counts * away_weights_full) get_logger('prediction').info('Взвешанное среднее: %f', events_away_counts_mean) result_prediction = (events_home_counts_mean, events_away_counts_mean) get_logger('prediction').info('Итого, предсказание: %.1f:%.1f', result_prediction[0], result_prediction[1]) return result_prediction
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info( 'Добавлена информация (по каждому игроку) о количестве событий "угловой" (2-й тайм)' )
def handle(self, match_uuid, fit_kwargs=None, predict_kwargs=None, handle_kwargs=None, **kwargs): if fit_kwargs is None: fit_kwargs = {} if predict_kwargs is None: predict_kwargs = {} if handle_kwargs is None: handle_kwargs = {} match_header = get_match_header(match_uuid) if match_header is None: return log_capture_string = io.StringIO() ch = logging.StreamHandler(log_capture_string) ch.setLevel(logging.DEBUG) get_logger().addHandler(ch) # get_logger('prediction').debug('Провайдер: %s', str(self)) get_logger('prediction').info('Описание провайдера: %s', self.description) get_logger('prediction').info( 'Предсказание для матча %s', get_match_title(match_header, show_uuid=True)) fitters_for_predictor = [] for fitters_set in self.fitters_sets: if len(fitters_set) == 0: continue fitters_set[0].fit(match_header=match_header, **fit_kwargs) for j in range(1, len(fitters_set)): fitters_set[j].fit(match_header=match_header, **fit_kwargs) fitters_for_predictor.append(fitters_set[-1]) prediction = self.predictor.predict(fitters_for_predictor, match_header, **predict_kwargs) get_logger().removeHandler(ch) log_contents = log_capture_string.getvalue() log_capture_string.close() prediction_info_uuid = get_identifier() prediction_info = { 'uuid': prediction_info_uuid, 'match_uuid': match_uuid, 'provider_class_name': self.__class__.__name__, 'provider_description': self.description, 'provider_uuid': self.uuid, 'prediction': prediction, 'log': log_contents } prediction_infos_collection = db['prediction_infos'] prediction_infos_collection.insert_one(prediction_info) for proposer in self.proposers: proposer.handle(match_header, prediction_info=prediction_info, **handle_kwargs) self.attempt_matches.add(match_header['uuid'])
def _predict(self, fitteds, match_header, **kwargs): [statistic_fitted, tournament_event_counts_means_fitted] = fitteds statistic = statistic_fitted.statistic get_logger('prediction').info('В собранной статистике %u матчей', statistic.shape[0]) if statistic.shape[0] == 0: get_logger('prediction').info( 'В собранной статистике нет матчей, не могу сделать предсказание' ) return None tournament_id = match_header['tournamentId'] # Среднее количество голов, забиваемых хозяевами матчей в турнире tournament_events_home_counts_mean = tournament_event_counts_means_fitted.tournament_event_home_counts_means[ tournament_id] # Среднее количество голов, забиваемых гостями матчей в турнире tournament_events_away_counts_mean = tournament_event_counts_means_fitted.tournament_event_away_counts_means[ tournament_id] if tournament_events_home_counts_mean == 0 or tournament_events_away_counts_mean == 0: return None get_logger('prediction').info( 'Выберем %u последних матчей из статистики, где команда %s тоже была хозяйкой', self.n, match_header['home']) # Статистика матчей, где match_header['home'] тоже была хозяйкой home_events_counts = get_substatistic(statistic, notnull='events_home_count', by='home', value=match_header['home'], n=self.n, min_n=self.min_n, sort_by='date', ascending=False, which='events_home_count') if home_events_counts is None: get_logger('prediction').info( 'Матчей оказалось меньше порога в %u матча', self.min_n) return None get_logger('prediction').info('Количество событий: %s', str(home_events_counts)) home_weights_full = get_weights_array(home_events_counts.size, self.home_weights) get_logger('prediction').info('Веса: %s', str(home_weights_full)) get_logger('prediction').info( 'Выберем %u последних матчей из статистики, где команда %s тоже была гостьей', self.n, match_header['away']) # Статистика матчей, где match_header['away'] тоже была гостьей away_events_counts = get_substatistic(statistic, notnull='events_away_count', by='away', value=match_header['away'], n=self.n, min_n=self.min_n, sort_by='date', ascending=False, which='events_away_count') if away_events_counts is None: get_logger('prediction').info( 'Матчей оказалось меньше порога в %u матча', self.min_n) return None get_logger('prediction').info('Количество событий: %s', str(away_events_counts)) away_weights_full = get_weights_array(away_events_counts.size, self.away_weights) get_logger('prediction').info('Веса: %s', str(away_weights_full)) # Во сколько раз превышает среднее по турниру число голов, забитых match_header['home'] в домашних матчах? home_attack = np.sum( home_events_counts * home_weights_full) / tournament_events_home_counts_mean # Во сколько раз превышает среднее по турниру число голов, пропущенных match_header['away'] в гостевых матчах? away_defense = np.sum( home_events_counts * home_weights_full) / tournament_events_home_counts_mean # Во сколько раз превышает среднее по турниру число голов, пропущенных match_header['home'] в домашних матчах? home_defense = np.sum( away_events_counts * away_weights_full) / tournament_events_away_counts_mean # Во сколько раз превышает среднее по турниру число голов, забитых match_header['away'] в гостевых матчах? away_attack = np.sum( away_events_counts * away_weights_full) / tournament_events_away_counts_mean home_events_count_prediction = home_attack * away_defense * tournament_events_home_counts_mean away_events_count_prediction = away_attack * home_defense * tournament_events_away_counts_mean result_prediction = (home_events_count_prediction, away_events_count_prediction) get_logger('prediction').info('Итого, предсказание: %.1f:%.1f', result_prediction[0], result_prediction[1]) return result_prediction
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info( 'Добавлена информация (по каждому игроку) о количестве событий "кросс" (матч)' )
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info('Добавлена информация (по каждой команде) о количестве событий "угловой" (матч, только периоды, пока хозяева побеждают)')
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info('Добавлена информация (по каждой команде) о количестве событий "угловой" (1-й тайм, пока гости побеждают)')
def _fit(self, **kwargs): super()._fit(**kwargs) get_logger('prediction').info( 'Добавлена информация о продолжительности игровых ситуаций по голам (матч)' )