> ## 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.

# Event-Regeln: Velocity, Ratio, Sequenz, Korrelation

> Velocity-, Ratio-, Sequenz- und Korrelationsregeln für Event-Daten in Didit, im selben Regel-Builder wie Ihre Transaktionsregeln.

[Ereignisse](https://docs.didit.me/de/transaction-monitoring/events.md) werden von derselben Engine ausgewertet wie Transaktionen. Es gibt ein Regelmodell, ein Bedingungsvokabular und einen Satz von Aktionen. Eine Regel legt lediglich fest, auf welche Datensatztypen sie angewendet wird.

## Gilt für

`scope.record_types` bestimmt, bei welchen Datensatztypen eine Regel ausgelöst wird.

| `record_types` | Wird ausgelöst bei |
| - | - |
| weggelassen oder `["transaction"]` | Nur Transaktionen – **der Standard** |
| `["event"]` | Nur Ereignisse |
| `["transaction", "event"]` | Beide |

> [!NOTE]
>
> Wird der Eintrag weggelassen, bleibt eine Regel auf Transaktionen beschränkt. Jede Regel, die vor der Einführung von Ereignissen geschrieben wurde, verhält sich weiterhin genauso wie zuvor. Eine Regel beginnt nie, Logins zu erfassen, nur weil ihr Scope zufällig leer war.

In der Konsole ist dies der Selektor **Gilt für** im Trigger-Schritt einer Regel. Wenn Sie Ereignisse wählen, erscheint eine Checkliste **Ereigniskategorien**, die die Regel weiter eingrenzt. Lassen Sie alle Kategorien unmarkiert, um jede Kategorie auszuwerten.

```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__"` bedeutet „derselbe Wert wie das gerade ausgewertete Ereignis“. Damit gibt eine Regel *pro Subjekt*, *pro Gerät* oder *pro Runde* an, ohne einen konkreten Wert zu nennen.

Datensätze ohne den gruppierten Wert werden nie zusammengefasst. Ein Ereignis ohne Geräte-Fingerprint ist nicht „dasselbe Gerät“ wie andere Ereignisse ohne Fingerprint, und ein Ereignis ohne Subjektangabe ist nicht „dasselbe Subjekt“ wie andere anonyme Ereignisse. Hat das ausgewertete Ereignis für ein `"__current__"`-Feld keinen Wert, greift diese Aggregation unabhängig vom Operator nicht.

## Ereignisfelder

Bedingungen lesen Pfade mit Namensraum. Das Transaktionsvokabular, das Sie bereits kennen (`action_type`, `subject_vendor_data`, `subject_ip_country`, `custom_values.<key>`), wird auch bei einem Ereignis aufgelöst.

| Gruppe | Pfade |
| - | - |
| Ereignis | `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` |
| Gerät und Netzwerk | `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` |
| Gameplay | `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` |
| Zahlung und Streitfall | `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` |
| Sicherheit und verantwortungsvolles Spielen | `event.security.changed_field`, `event.responsible_gambling.identity_match_ref` |
| Bot- und Assistenz-Telemetrie | `event.bot.timing_variance_ms`, `event.bot.actions_per_minute`, `event.bot.pointer_entropy`, `event.bot.reaction_time_ms_p50`, `event.bot.assistance_indicator` |
| Subjektsignale | `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` |
| Sonstiges | `event.payload.<key>`, `custom_values.<key>` |

Subjektsignale werden beim überwachten Benutzer zwischengespeichert und nicht pro Ereignis neu berechnet. So kann eine Regel sie mit der Geschwindigkeit der Ereigniserfassung auswerten.

## Aggregationen

### Geschwindigkeit

Die Reducer, die Sie bereits bei Transaktionen verwenden (`count`, `sum`, `avg`, `min`, `max`, `distinct_count`), über ein rollierendes `window` (`30m`, `24h`, `7d`, `30d`).

### Verhältnis

Zwei Reducer über dasselbe Zeitfenster. So werden Wett-zu-Einzahlungs-, Auszahlungs-zu-Einzahlungs-, Bonus-zu-Einzahlungs- und Chargeback-Raten ausgedrückt.

```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
}
```

Einzahlung 1.000, Wette 20, Auszahlung angefordert, und das Verhältnis beträgt 0,02 – klassische Geldwäsche durch minimales Spielen.

> [!NOTE]
>
> Ein Verhältnis ohne Nenner greift nie. Keine Einzahlungen ergeben kein Verhältnis von null, sondern keinen Nachweis. Ein Treffer an dieser Stelle würde jeden neuen Benutzer markieren.

### Sequenz

Geordnete Prädikate innerhalb eines Zeitfensters. Jeder Schritt wird anhand von `action_type`, `event_category` oder einem beliebigen `match`-Filter abgeglichen und kann `min_count` Vorkommen verlangen, bevor die Sequenz fortschreitet.

```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" }
  ]
}
```

Credential-Stuffing, dann die MFA-Übernahme, dann die Umleitung der Auszahlung, dann das Leeren des Kontos. Die Regel löst bei dem Ereignis aus, das die Kette abschließt. Die zugehörigen Nachweise listen die Ereignis-IDs jedes Schritts auf.

Der Sequenzstatus wird pro Regel und Subjekt gehalten. So schreitet er mit eintreffenden Ereignissen voran, statt die Zeitleiste erneut zu durchsuchen. Fortschritt, der älter als das Zeitfenster ist, wird verworfen und nicht mitgezählt.

### Korrelation

Eine Verknüpfung über Subjekte hinweg: Reduziert wird über jedes Ereignis, das dieselbe Gruppe wie dieses Ereignis teilt.

```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` gleicht die beiden Enden als ungeordnete Menge ab, sodass A→B und B→A in dieselbe Gruppe fallen. So kann eine Regel beide Hälften einer Absprache sehen. Chip-Dumping, Gegenwetten und Selbstempfehlung über Affiliates haben alle diese Form.

Geben Sie einer Korrelationsregel immer einschränkende `filters` an. Ohne sie berücksichtigt sie jedes Ereignis im Zeitfenster.

## Echtzeit- und asynchrone Regeln

Manche Regeln können innerhalb der Ingestion-Anfrage antworten, andere nicht.

| Ausführung | Welche Regeln |
| - | - |
| **In der Anfrage** | Velocity-Regeln, Verhältnisregeln und zeitlich begrenzte Sequenzen (Fenster bis 24 Stunden) |
| **Innerhalb von Minuten, asynchron** | Korrelationsregeln und Sequenzen mit einem Fenster von mehr als 24 Stunden |

Ein Ereignis, dessen Regeln noch ausstehen, wird mit `"correlation_pending": true` zurückgegeben. Status und Score werden **im bestehenden Ereignis aktualisiert**, sobald der asynchrone Durchlauf abgeschlossen ist. Erneutes Ausführen ist idempotent, daher wendet eine Regel ihren Score nie zweimal an.

Diese Trennung ist bewusst so gewählt: Eine subjektübergreifende Ringabfrage darf keinen Login verzögern.

## Aktionen

Es gilt dasselbe Aktionsvokabular wie bei Transaktionsregeln: `add_score`, `change_status`, `add_tags`, `add_note`, `add_to_list`, `open_case`.

Bei Ereignissen gibt es zwei Unterschiede:

* `change_status` auf `AWAITING_USER` ist ein reines Transaktionsergebnis (es gibt keinen Behebungs-Workflow für Ereignisse) und wird als `IN_REVIEW` angewendet.
* `open_case` verknüpft den Fall mit dem **Subjekt** statt mit einer Transaktion und speichert die Ereignis-ID des Treffers im Fall.

## Belege

Jeder Treffer speichert, was er gesehen hat: das Aggregationsfenster, den berechneten Wert, den erwarteten Wert, stichprobenartig ausgewählte Ereignis-IDs und die **Quelle jedes übereinstimmenden Felds**.

| Quelle | Bedeutung |
| - | - |
| `server` | Didit hat den Wert abgeleitet (IP, User-Agent, Herkunft). Maßgeblich. |
| `sdk` | Das Didit SDK hat den Wert vom Gerät gemeldet. |
| `customer` | Ihre Systeme haben den Wert geliefert. |

So kann ein Analyst eine serverseitig erfasste IP von einem clientseitigen Hinweis unterscheiden, bevor er einen Treffer bearbeitet. Die Konsole zeigt in der Ereignisseitenleiste neben jedem gematchten Feld dessen Quelle an.

## Praxisbeispiele

> [accordion] Geldwäsche mit minimalem Spiel
>
> Einzahlung, Token-Spiel, schnelle Auszahlung. Bedingung `event.action_type eq withdrawal_requested` sowie das oben beschriebene Verhältnis von Einsatz zu Einzahlung bei `lte 0.1` über `24h`.

> [accordion] Freundschaftsbetrug
>
> Verhältnis von `count(chargeback_opened)` zu `count(deposit_completed)` pro Subjekt über `30d`, `gte 0.5`. Gruppieren Sie nach `event.payment.payment_fingerprint` statt nach dem Subjekt, um ein Zahlungsmittel über mehrere Konten hinweg zu erkennen.

> [accordion] Abfluss nach einer Kontoübernahme
>
> Die oben beschriebene Sequenz `ato_drain` mit `add_score 90` und `change_status DECLINED`.

> [accordion] Chip-Dumping
>
> Die oben beschriebene Paarkorrelation. Erhöhen Sie `value` auf den Betrag, der für Ihre Tische wesentlich ist, und fügen Sie `event.gameplay.game_id` zu `group_by` hinzu, damit Spiele getrennt bleiben.

> [accordion] Bot-Spiel und Echtzeitunterstützung
>
> Bedingungen für `event.action_type eq bot_signal_observed`, `event.bot.timing_variance_ms lte 10` und `event.device.bot_score gte 90`, mit `add_tags`. Kombinieren Sie dies mit einem `distinct_count` von `event.device.fingerprint` pro IP, um eine Farm statt eines einzelnen Skripts zu finden.

> [accordion] Umgehung der Selbstsperre
>
> Bedingung für `event.action_type eq self_exclusion_match` und `event.payload.re_registration_attempt eq true`, mit Eskalation über `open_case`.

## Weiter

> [card] [Ereigniserfassung](https://docs.didit.me/de/transaction-monitoring/events.md)
>
> Die **Nachrichtenhülle**, die zehn Kategorien und der Batch-Vertrag.

> [card] [Regel-API](https://docs.didit.me/de/transaction-monitoring/rules-api.md)
>
> Regeln programmatisch erstellen, aktualisieren und rückwirkend testen.


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