Привет, Хабр. Меня зовут Виктор, я Big Data Engineer в antifraud-направлении. В этом посте хочу рассказать о том, как мы выстраивали процесс обнаружения подозрительных паттернов поведения в ставках на зарубежной БК-платформе DoseSports — без воды и маркетинга. Только архитектура, фичи, модели и выводы.

Исходные вводные

DoseSports — закрытая букмекерская платформа, ориентированная на mid/high-roll игроков. В отличие от большинства отечественных БК, здесь отсутствует агрессивное лимитирование по ставкам, поэтому спектр поведенческих сценариев шире. С одной стороны, это привлекает аудиторию. С другой — усложняет задачу antifraud-системы.

Перед нами стояла задача в real-time вычленять:

  • мультиаккаунтинг

  • ботов/скриптов

  • арбитражников

  • аномальное поведение по ROI и объёму ставок

Архитектура обработки

Ставки, логины, действия пользователей поступают в централизованный поток:

  • Kafka — основной брокер, разбит на топики bets, auth, sessions

  • Spark Structured Streaming — для оконной агрегации и feature extraction

  • ClickHouse — агрегаты и дешёвый OLAP

  • PostgreSQL — хранилище метаданных и результатов скоринга

  • S3 (Parquet) — архив событий для оффлайн-обучения

Формат и структура сообщений строго типизированы, схема событий валидируется через Avro.

Feature engineering

Основная сложность — не в данных, а в построении информативных признаков, отличающих нормальное поведение от аномального. Вот часть того, что оказалось полезным:

Признак

Описание

avg_bet_amount_window_5m

средняя сумма ставки в пятиминутном окне

time_to_first_bet

время между логином и первой ставкой

outcome_entropy

энтропия исходов ставок в текущей сессии

ip_change_ratio

доля смены IP за последние 24 часа

market_repeatability

сколько раз ставит на один и тот же маркет

ROI_volatility

отклонение ROI за 7 дней от медианного

Кроме того, применяли эмбеддинги по ставочным последовательностям и cosine similarity между сессиями разных пользователей.

ML-модель

После тестирования нескольких подходов (RandomForest, Isolation Forest, Autoencoder) остановились на XGBoost по ряду причин:

  • высокая скорость инференса

  • возможность кастомизации loss-функции

  • удобная explainability через feature importance

Работали в semi-supervised парадигме:

  1. Вручную размеченные кейсы → обучающая выборка

  2. Остальные кейсы — псевдометки через confident predictions

  3. Построение модели с регулярной переобучаемостью (раз в неделю)

Также делали эксперимент с LSTM (сессии как временные ряды), но из-за слабой интерпретируемости и большего inference-time он ушёл в оффлайн-анализ.

Тестирование и отладка

Чтобы не "ломать прод", создали локальный testbench:

  • генератор сессий со скриптовым поведением (на Go)

  • имитация вилок, дублирования, смены IP

  • latency-тестирование пайплайна (требование: <100мс в пике)

Кроме того, включили обратную связь от модераторов в виде ручной метки и комментариев — это пошло обратно в pipeline обучения.

Результаты

Метрика

Значение

Precision

~83%

Recall

~74%

False Positive Rate

ниже 4%

Обработка в проде

~2,5% действий маркируется как high-risk

Около 10–15 кейсов в месяц — передаются в compliance-отдел для дальнейших действий.

Плюсы и минусы платформы

Что порадовало в DoseSports:

  • Стабильный REST + WebSocket API

  • Доступ к сырым логам ставок (не агрегатам, что редкость)

  • Архитектура backend'а без "магии" — понятно, что проектировали инженеры

Что стоит улучшить:

  • Нет sandbox-среды для безопасного тестирования

  • Документация API/событий крайне фрагментирована

  • Клиентский фронт не всегда репрезентативен (расхождение с backend-таймингом)

Вывод

Для тех, кто работает в antifraud, risk management или просто интересуется применением ML в прикладных задачах — кейс DoseSports может быть интересен.
Сложностей хватает, но благодаря стабильному API, доступу к логам и адекватной архитектуре, проект оказался рабочим. Конечно, не enterprise-уровня, но в рамках fast-growing private продукта — вполне зрелый стек.

Если интересны детали кода, пайплайна или примеры фичей в Spark — пишите в комментарии, с радостью раскрою глубже.

Комментарии (0)