Разработка системы аналитики крипто-казино
Аналитика казино — это инструмент для операционных решений: понимание поведения игроков, оптимизация бонусных программ, выявление мошенничества, планирование ликвидности. Без качественной аналитики казино работает вслепую.
Ключевые метрики
GGR (Gross Gaming Revenue) = суммарные ставки − суммарные выигрыши. Базовая метрика дохода казино.
NGR (Net Gaming Revenue) = GGR − бонусы − рейкбэк − промо-затраты. Реальный доход.
RTP (Return to Player) = суммарные выигрыши / суммарные ставки × 100%. Теоретически зависит от игры; фактически — показатель волатильности за период.
Player Lifetime Value (LTV) — прогнозируемый суммарный NGR от игрока за всё время.
Churn Rate — % игроков, переставших играть за период.
Average Session Duration, Bet Frequency, Average Bet Size — поведенческие метрики.
Аналитическое хранилище
Для аналитики казино оптимально использовать star schema в ClickHouse или BigQuery:
-- Fact table: каждая ставка
CREATE TABLE fact_bets (
bet_id String,
user_id String,
game_id String,
session_id String,
bet_time DateTime,
amount Decimal(24, 8),
currency LowCardinality(String),
winnings Decimal(24, 8),
ggr Decimal(24, 8), -- amount - winnings
is_free_bet Bool,
bonus_used Nullable(String),
game_category LowCardinality(String),
country LowCardinality(String),
device_type LowCardinality(String),
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(bet_time)
ORDER BY (user_id, bet_time);
-- Dimension: игроки
CREATE TABLE dim_users (
user_id String,
registration_date Date,
country LowCardinality(String),
acquisition_channel LowCardinality(String),
vip_level LowCardinality(String),
first_deposit_date Nullable(Date),
total_deposits Decimal(24, 8),
total_withdrawals Decimal(24, 8),
)
ENGINE = ReplacingMergeTree()
ORDER BY user_id;
ETL Pipeline
class CasinoAnalyticsETL:
async def run_hourly_aggregation(self):
"""Обновляем аналитические агрегации каждый час"""
now = datetime.utcnow()
hour_start = now.replace(minute=0, second=0, microsecond=0)
# Загружаем raw данные из операционной БД
bets = await self.bet_repo.get_settled_bets_since(hour_start - timedelta(hours=1))
# Трансформируем и загружаем в ClickHouse
rows = [self.transform_bet(bet) for bet in bets]
if rows:
await self.clickhouse.insert('fact_bets', rows)
# Обновляем материализованные представления
await self.update_materialized_views()
def transform_bet(self, bet: Bet) -> dict:
return {
"bet_id": str(bet.id),
"user_id": str(bet.user_id),
"game_id": bet.game_id,
"bet_time": bet.settled_at,
"amount": float(bet.amount),
"currency": bet.currency,
"winnings": float(bet.winnings),
"ggr": float(bet.amount - bet.winnings),
"is_free_bet": bet.is_free_bet,
"game_category": bet.game_category,
"country": bet.user_country,
"device_type": bet.device_type,
}
Аналитические запросы
Когортный анализ удержания:
SELECT
registration_cohort,
days_since_registration,
count(DISTINCT user_id) AS active_users,
sum(ggr) AS cohort_ggr
FROM (
SELECT
b.user_id,
toStartOfWeek(u.registration_date) AS registration_cohort,
dateDiff('day', u.registration_date, b.bet_time) AS days_since_registration,
b.ggr
FROM fact_bets b
JOIN dim_users u ON b.user_id = u.user_id
WHERE b.bet_time >= today() - 180
)
GROUP BY registration_cohort, days_since_registration
ORDER BY registration_cohort, days_since_registration;
Анализ RTP по играм:
SELECT
game_id,
game_category,
count() AS bet_count,
sum(amount) AS total_wagered,
sum(winnings) AS total_paid,
sum(ggr) AS total_ggr,
sum(winnings) / sum(amount) AS actual_rtp,
countIf(ggr < 0) AS losing_rounds,
countIf(ggr >= 0) AS winning_rounds
FROM fact_bets
WHERE bet_time BETWEEN '2024-01-01' AND '2024-02-01'
AND NOT is_free_bet
GROUP BY game_id, game_category
ORDER BY total_wagered DESC;
Fraud Detection Analytics
-- Аномальная выигрышность (возможный чит)
SELECT
user_id,
count() AS bet_count,
sum(winnings) / sum(amount) AS rtp,
sum(ggr) AS user_ggr,
max(winnings) AS max_single_win
FROM fact_bets
WHERE bet_time >= today() - 7
GROUP BY user_id
HAVING rtp > 1.5 -- выигрывает более 150% от ставок
AND bet_count > 50 -- достаточно ставок для статистики
ORDER BY rtp DESC
LIMIT 100;
Dashboard: ключевые панели
Operational Dashboard (обновляется в реальном времени):
- Текущий онлайн (активных сессий)
- GGR за последний час / 24 часа
- Активные бонусы и их exposure
- Pending выводы
Financial Dashboard (ежедневный):
- NGR по дням, с breakdown по каналам привлечения
- Bonus cost / NGR ratio
- Топ игроков по GGR
- RTP по играм (сравнение с теоретическим)
Retention Dashboard (еженедельный):
- Cohort retention curves
- Churn rate по сегментам
- LTV прогнозы
- Эффективность бонусных кампаний
BI-инструменты: Apache Superset (open source) или Metabase для внутренних команд, Grafana для операционных метрик в реальном времени.







