AI-система детекции договорных матчей

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-система детекции договорных матчей
Средняя
~2-4 недели
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    854
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

AI-система детекции договорных матчей

Договорные матчи — угроза интегритету спорта и финансовые преступления через ставки. AI-система анализирует нетипичные движения коэффициентов, поведение ставящих и игровую статистику, выявляя корреляции, невозможные без предварительного сговора.

Источники данных

Мультиканальный анализ:

data_sources = {
    'betting_markets': {
        'data': 'коэффициенты 50+ букмекеров + Betfair биржа',
        'metrics': ['odds_movement', 'trading_volume', 'market_liquidity'],
        'frequency': 'real-time (30-секундные снапшоты)'
    },
    'in_game_data': {
        'data': 'статистика матча: голы, желтые карточки, замены, expected goals',
        'metrics': ['xG_deviation', 'shot_quality', 'defensive_intensity'],
        'provider': 'Opta, StatsBomb, Wyscout'
    },
    'player_data': {
        'data': 'физические показатели GPS/heart rate (если доступны)',
        'metrics': ['sprint_count', 'distance_covered', 'heart_rate_zones']
    },
    'social_media': {
        'data': 'ставки в социальных сетях, инсайдерская информация',
        'nlp': 'детекция "tips" до матча, необычная уверенность'
    }
}

Анализ движения коэффициентов

Обнаружение аномального движения odds:

import numpy as np
import pandas as pd
from scipy.stats import zscore

def analyze_odds_movement(odds_history: pd.DataFrame,
                           match_id: str) -> dict:
    """
    Нормальное движение коэффициентов: реакция на новости (травмы, состав),
    балансировка позиций букмекером.
    Аномальное: резкое движение без публичных новостей = инсайдерская ставка.
    """
    match_odds = odds_history[odds_history['match_id'] == match_id].sort_values('timestamp')

    if len(match_odds) < 10:
        return {'status': 'insufficient_data'}

    # Ключевые метрики движения
    opening_odds_h = match_odds.iloc[0]['odds_home']
    closing_odds_h = match_odds.iloc[-1]['odds_home']

    movement_pct = abs(closing_odds_h - opening_odds_h) / opening_odds_h * 100

    # Timing: когда происходит движение?
    hours_before_kickoff = (match_odds['kickoff'] - match_odds['timestamp']).dt.total_seconds() / 3600

    # Аномальное движение ночью или за 6+ часов до матча (не ответ на состав)
    early_movement_mask = hours_before_kickoff > 12
    early_movement_pct = match_odds[early_movement_mask]['odds_home'].pct_change().abs().sum()

    # Steam move: одновременное движение у всех букмекеров (синхронный сигнал)
    if 'bookmaker_id' in match_odds.columns:
        bookmaker_movements = match_odds.groupby('bookmaker_id')['odds_home'].pct_change().abs()
        sync_movement = (bookmaker_movements > 0.03).groupby(match_odds['timestamp']).mean()
        steam_detected = (sync_movement > 0.7).any()  # > 70% букмекеров двигаются одновременно
    else:
        steam_detected = False

    # Comparison с историческим baseline для этого типа матча
    historical_movement_mean = 5.0  # % — типичное движение
    historical_movement_std = 2.5

    movement_z = (movement_pct - historical_movement_mean) / historical_movement_std

    return {
        'match_id': match_id,
        'total_movement_pct': round(movement_pct, 2),
        'early_movement_pct': round(early_movement_pct * 100, 2),
        'steam_move_detected': steam_detected,
        'movement_z_score': round(movement_z, 2),
        'anomaly': movement_z > 3 or (early_movement_pct > 0.05 and steam_detected),
        'risk_level': 'high' if movement_z > 4 else ('medium' if movement_z > 3 else 'low')
    }

Анализ игровой статистики

Отклонение от expected performance:

def analyze_performance_deviation(match_stats: dict,
                                   player_id: str,
                                   season_stats: pd.DataFrame) -> dict:
    """
    Игрок, возможно, играет ниже своих возможностей.
    xG-модель: насколько сложны были удары? Нормально ли не забить?
    """
    # Сезонная точность игрока
    player_season = season_stats[season_stats['player_id'] == player_id]

    if player_season.empty:
        return {'status': 'no_baseline'}

    season_conversion_rate = player_season['goals'].sum() / (player_season['shots_on_target'].sum() + 1)

    # В текущем матче
    match_xG = match_stats.get('xG', 0)
    match_goals = match_stats.get('goals', 0)
    match_shots = match_stats.get('shots', 0)

    # xG overperformance: если xG высокий, но голей нет
    xg_performance = match_goals - match_xG  # negative = underperformance

    # Физическая интенсивность
    distance_covered = match_stats.get('distance_km', 10.5)
    season_avg_distance = player_season['distance_km'].mean()

    distance_deviation = (distance_covered - season_avg_distance) / (season_avg_distance + 1e-9)

    # Необычно низкая вовлечённость
    touches = match_stats.get('touches', 50)
    season_avg_touches = player_season['touches'].mean()
    touch_deviation = (touches - season_avg_touches) / (season_avg_touches + 1e-9)

    # Composite score
    underperformance_score = (
        max(0, -xg_performance / 0.5) * 0.4 +  # не реализовал xG
        max(0, -distance_deviation) * 0.3 +      # мало бегал
        max(0, -touch_deviation) * 0.3           # мало касаний
    )

    return {
        'player_id': player_id,
        'xg_performance': round(xg_performance, 3),
        'distance_deviation': round(distance_deviation, 3),
        'touch_deviation': round(touch_deviation, 3),
        'underperformance_score': round(underperformance_score, 3),
        'suspicious': underperformance_score > 0.6
    }

Паттерны ставок

Детекция скоординированных ставок:

def detect_coordinated_betting(bet_records: pd.DataFrame, match_id: str) -> dict:
    """
    Синхронные крупные ставки от разных аккаунтов = скоординированная игра.
    Один бенефициар, несколько аккаунтов — split betting.
    """
    match_bets = bet_records[bet_records['match_id'] == match_id]

    # Временная кластеризация крупных ставок
    large_bets = match_bets[match_bets['stake_usd'] > match_bets['stake_usd'].quantile(0.95)]

    if len(large_bets) < 3:
        return {'sufficient_data': False}

    # Ставки за короткий промежуток (< 5 минут)
    large_bets_sorted = large_bets.sort_values('timestamp')
    time_diffs = large_bets_sorted['timestamp'].diff().dt.total_seconds()
    rapid_cluster = (time_diffs < 300).sum()

    # Похожие суммы (round numbers)
    round_number_bets = large_bets['stake_usd'].apply(
        lambda x: x % 100 == 0 or x % 1000 == 0
    ).mean()

    # Один outcome — необычная концентрация
    outcome_concentration = large_bets['outcome_bet'].value_counts().max() / len(large_bets)

    coordination_score = (
        min(1, rapid_cluster / 5) * 0.4 +
        round_number_bets * 0.3 +
        (outcome_concentration - 0.5) * 2 * 0.3
    )

    return {
        'match_id': match_id,
        'large_bets_count': len(large_bets),
        'rapid_cluster_count': rapid_cluster,
        'round_number_ratio': round(round_number_bets, 2),
        'outcome_concentration': round(outcome_concentration, 2),
        'coordination_score': round(coordination_score, 3),
        'flag_for_investigation': coordination_score > 0.6
    }

Интеграция: ESTS (Sports Betting Integrity), Sportradar Fraud Detection API, ESSA (European Sports Security Association). Уведомление Sports Governing Body (FIFA, UEFA, национальные федерации) при обнаружении критических паттернов.

Сроки: Odds movement детекция + performance baseline + дашборд — 4-5 недель. Coordinated betting граф, NLP социальных медиа, real-time алерты, ESSA интеграция — 3-4 месяца.