> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Правила для событий: скорость, соотношение, корреляция

> Didit: правила по скорости, соотношению, последовательности и корреляции субъектов в данных о событиях. Пишутся в том же конструкторе, что правила транзакций.

[События](https://docs.didit.me/ru/transaction-monitoring/events.md) оцениваются тем же движком, что и транзакции. Здесь используется единая модель правил, общий словарь условий и один набор действий - правило лишь объявляет, к каким типам записей оно применяется.

## Применяется к

`scope.record_types` определяет, на что срабатывает правило.

| `record_types` | Срабатывает на |
| - | - |
| не указано или `["transaction"]` | Только транзакции - **по умолчанию** |
| `["event"]` | Только события |
| `["transaction", "event"]` | И то, и другое |

> [!NOTE]
>
> Если не указывать этот параметр, правило будет применяться только к транзакциям. Любое правило, созданное до появления событий, работает в точности так же, как и раньше, и правило никогда не начнет сопоставляться со входами в систему только потому, что его область действия оказалась пустой.

В консоли это селектор **Применяется к** на шаге «Триггер» правила. При выборе «События» появляется список флажков **Категории событий**, который позволяет дополнительно сузить область действия правила; оставьте все пункты невыбранными, чтобы оценивать все категории.

```json theme={null}
{
  "title": "Failed login burst",
  "scope": {
    "record_types": ["event"],
    "event_categories": ["security"]
  },
  "aggregation": [
    {
      "metric": "count",
      "operator": "gte",
      "value": 3,
      "window": "30m",
      "filters": {
        "subject_vendor_data": "__current__",
        "event.action_type": "login_failed"
      }
    }
  ],
  "actions": [
    { "type": "add_score", "value": 40 },
    { "type": "change_status", "value": "IN_REVIEW" }
  ]
}
```

`"__current__"` означает «то же значение, что и у оцениваемого события» - именно так в правиле задается условие *для субъекта*, *для устройства* или *для раунда* без указания конкретного значения.

Записи без значения группировки никогда не объединяются в одну группу. Событие без цифрового отпечатка устройства не считается «тем же устройством», что и другие события без него, а событие без указания субъекта не считается «тем же субъектом», что и другие анонимные события: если у оцениваемого события нет значения для поля `"__current__"`, эта агрегация не сработает независимо от используемого оператора.

## Поля событий

В условиях используются пути с пространствами имен. Уже знакомый вам словарь транзакций (`action_type`, `subject_vendor_data`, `subject_ip_country`, `custom_values.<key>`) также доступен и для событий.

| Группа | Пути |
| - | - |
| Событие | `event.category`, `event.action_type`, `event.occurred_at`, `event.amount`, `event.currency`, `event.direction`, `event.session_id`, `event.session_sequence`, `event.score`, `event.status`, `event.ingest_source`, `event.retention_class`, `event.subject_vendor_data`, `event.business_vendor_data` |
| Устройство и сеть | `event.device.fingerprint`, `event.device.persistent_device_id`, `event.device.bot_score`, `event.ip.address`, `event.ip.country`, `event.ip.asn_number`, `event.ip.asn_organization`, `event.ip.is_vpn_or_tor`, `event.ip.is_data_center`, `event.ip.proxy_type`, `event.ip.country_name`, `event.ip.city`, `event.ip.connection_type`, `event.ip.travel_distance_km`, `event.ip.travel_speed_kmh` |
| Игровой процесс | `event.gameplay.game_id`, `event.gameplay.table_id`, `event.gameplay.round_id`, `event.gameplay.hand_id`, `event.gameplay.match_id`, `event.gameplay.market_id`, `event.gameplay.side`, `event.gameplay.role`, `event.gameplay.counterparty_vendor_data`, `event.gameplay.net_result_amount`, `event.bonus.bonus_id`, `event.affiliate.affiliate_code` |
| Платежи и споры | `event.payment.reference_id`, `event.payment.payment_fingerprint`, `event.payment.instrument_reference_hash`, `event.payment.withdrawal_address_hash`, `event.dispute.dispute_id`, `event.dispute.chargeback_id` |
| Безопасность и ответственная игра | `event.security.changed_field`, `event.responsible_gambling.identity_match_ref` |
| Телеметрия ботов и ассистентов | `event.bot.timing_variance_ms`, `event.bot.actions_per_minute`, `event.bot.pointer_entropy`, `event.bot.reaction_time_ms_p50`, `event.bot.assistance_indicator` |
| Сигналы субъекта | `subject.email.risk_score`, `subject.email.social_count`, `subject.email.is_disposable`, `subject.email.deliverability`, `subject.email.domain_reputation`, `subject.email.first_seen_days`, `subject.email.is_breached`, `subject.phone.risk_score`, `subject.phone.line_type`, `subject.phone.social_count`, `subject.phone.carrier`, `subject.phone.country`, `subject.phone.is_disposable` |
| Все остальное | `event.payload.<key>`, `custom_values.<key>` |

Сигналы субъекта кэшируются на уровне отслеживаемого пользователя, а не вычисляются заново для каждого события, поэтому правило может считывать их со скоростью приема данных.

## Агрегации

### Скорость

Редукторы, которые вы уже используете для транзакций - `count`, `sum`, `avg`, `min`, `max`, `distinct_count` - по скользящему окну `window` (`30m`, `24h`, `7d`, `30d`).

### Соотношение

Два редуктора по одному и тому же окну. Таким способом выражаются соотношения ставок к депозитам, выводов средств к депозитам, бонусов к депозитам и доля чарджбэков.

```json theme={null}
{
  "metric": "ratio",
  "window": "24h",
  "filters": { "subject_vendor_data": "__current__" },
  "numerator":   { "metric": "sum", "field": "event.amount", "filters": { "event.action_type": "bet_placed" } },
  "denominator": { "metric": "sum", "field": "event.amount", "filters": { "event.action_type": "deposit_completed" } },
  "operator": "lte",
  "value": 0.1
}
```

Внесите депозит 1,000, поставьте 20, запросите вывод средств, и соотношение составит 0.02 - классическое отмывание денег через минимальную игру.

> [!NOTE]
>
> Соотношение **без знаменателя никогда не срабатывает**. Отсутствие депозитов не означает нулевое соотношение, это отсутствие доказательств, и срабатывание в таком случае помечало бы каждого нового пользователя.

### Последовательность

Упорядоченные предикаты внутри окна. Каждый шаг сопоставляется по `action_type`, `event_category` или произвольному фильтру `match`, а также может требовать `min_count` вхождений перед переходом к следующему шагу последовательности.

```json theme={null}
{
  "metric": "sequence",
  "key": "ato_drain",
  "window": "24h",
  "steps": [
    { "event_category": "security", "action_type": "login_failed", "min_count": 3 },
    { "event_category": "security", "action_type": "mfa_changed" },
    { "event_category": "payment",  "action_type": "withdrawal_address_changed" },
    { "event_category": "payment",  "action_type": "withdrawal_requested" }
  ]
}
```

Подстановка учетных данных, затем перехват MFA, затем перенаправление выплаты, затем опустошение баланса. Правило срабатывает на событии, завершающем цепочку, а в подтверждающих данных перечисляются идентификаторы событий для каждого шага.

Состояние последовательности сохраняется отдельно для каждого правила и субъекта, поэтому оно обновляется по мере поступления событий, а не путем повторного сканирования временной шкалы. Прогресс старше заданного окна отбрасывается, а не учитывается.

### Корреляция

Объединение между субъектами: агрегация по каждому событию, входящему в группу данного события.

```json theme={null}
{
  "metric": "correlation",
  "window": "7d",
  "pair": true,
  "group_by": ["subject_vendor_data", "event.gameplay.counterparty_vendor_data"],
  "filters": { "event.action_type": "p2p_settlement" },
  "correlate": {
    "metric": "sum",
    "field": "event.gameplay.net_result_amount",
    "filters": { "event.gameplay.role": "winner" }
  },
  "operator": "gte",
  "value": 500
}
```

`"pair": true` сопоставляет обе стороны как неупорядоченное множество, благодаря чему A→B и B→A попадают в одну группу - именно это позволяет одному правилу видеть обе стороны сговора. Сброс фишек, противоположные ставки и самореферал партнёра строятся по этой схеме.

Всегда задавайте в правиле корреляции ограничивающие `filters`. Без них оно будет анализировать каждое событие в окне.

## Правила в реальном времени и асинхронные правила

Некоторые правила могут возвращать ответ непосредственно в запросе на прием событий, а некоторые нет.

| Выполнение | Какие правила |
| - | - |
| **В запросе** | Правила скорости, соотношения и ограниченные последовательности (окно до 24 часов) |
| **В течение нескольких минут, асинхронно** | Корреляционные правила и последовательности с окном более 24 часов |

Событие, правила для которого еще находятся в процессе обработки, возвращается с параметром `"correlation_pending": true`. Его статус и оценка обновляются на месте после завершения асинхронного прохода; повторный запуск идемпотентен, поэтому правило никогда не начислит свои баллы дважды.

Это разделение сделано намеренно: запрос по кольцу между субъектами не должен заставлять пользователя ждать при входе в систему.

## Действия

Используется тот же набор действий, что и для правил транзакций - `add_score`, `change_status`, `add_tags`, `add_note`, `add_to_list`, `open_case`.

Два отличия для событий:

* `change_status` на `AWAITING_USER` применяется только к транзакциям (для событий нет процесса устранения последствий) и применяется как `IN_REVIEW`.
* `open_case` привязывает кейс к **субъекту**, а не к транзакции, и сохраняет идентификатор сработавшего события в кейсе.

## Доказательства

Каждое срабатывание сохраняет зафиксированные данные: окно агрегации, вычисленное значение, ожидаемое значение, идентификаторы событий из выборки и **источник каждого сопоставленного поля**.

| Источник | Значение |
| - | - |
| `server` | Определено Didit (IP, агент пользователя, источник запроса). Достоверный источник. |
| `sdk` | Передано из Didit SDK с устройства. |
| `customer` | Предоставлено вашими системами. |

Таким образом, аналитик может отличить заверенный сервером IP-адрес от переданной клиентом подсказки, прежде чем принимать меры по результату срабатывания. Панель управления отображает источник рядом с каждым сопоставленным полем в боковой панели события.

## Практические примеры

> [accordion] Отмывание через минимальную игру
>
> Депозит, игра на символическую сумму, быстрый вывод. Условие `event.action_type eq withdrawal_requested`, плюс приведенное выше соотношение ставок к депозитам со значением `lte 0.1` за `24h`.

> [accordion] Дружественное мошенничество
>
> Отношение `count(chargeback_opened)` к `count(deposit_completed)` по субъекту за `30d`, `gte 0.5`. Группировка по `event.payment.payment_fingerprint` вместо субъекта, чтобы выявлять один платежный инструмент в разных аккаунтах.

> [accordion] Вывод средств при захвате аккаунта
>
> Приведенная выше последовательность `ato_drain` с действиями `add_score 90` и `change_status DECLINED`.

> [accordion] Слив фишек
>
> Приведенная выше парная корреляция. Увеличьте `value` до суммы, являющейся существенной для ваших столов, и добавьте `event.gameplay.game_id` в `group_by`, чтобы разделять игры.

> [accordion] Игра с ботами и помощь в реальном времени
>
> Условия `event.action_type eq bot_signal_observed`, `event.bot.timing_variance_ms lte 10` и `event.device.bot_score gte 90` с действием `add_tags`. Объедините с `distinct_count` для `event.device.fingerprint` на один IP, чтобы обнаружить ферму, а не отдельный скрипт.

> [accordion] Обход самоисключения
>
> Условие `event.action_type eq self_exclusion_match` и `event.payload.re_registration_attempt eq true` с эскалацией через `open_case`.

## Что дальше

> [card] [Прием событий](https://docs.didit.me/ru/transaction-monitoring/events.md)
>
> Конверт событий, десять категорий и контракт пакетной передачи.

> [card] [API правил](https://docs.didit.me/ru/transaction-monitoring/rules-api.md)
>
> Программное создание, обновление и тестирование правил на исторических данных.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.