File size: 3,916 Bytes
942b115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Triggering a fraud alert (demo/test guide)

The model learned one dominant signature from PaySim: **a `TRANSFER` or `CASH_OUT` that drains an account to exactly zero** β€” `amount == old balance` and `new balance == 0`. That pattern alone (regardless of the actual amount, RWF 181 or RWF 275,000) is what pushes the fraud probability toward 1.0 and the risk tier to **high**. `PAYMENT`, `CASH_IN`, and `DEBIT` transactions, and any partial (non-draining) transfer, score **low** almost every time β€” those are the two fraud-prone types identified in `reports/EDA_REPORT.md`.

## 1. Trigger it through the client UI (easiest, no raw PaySim fields needed)

The client-facing form (`/client/transactions/new`) only asks for type, amount, destination account, and date β€” balances are derived server-side from the account's real running balance. To reproduce the fraud pattern:

1. Log in as a client (or have an officer create one via `/officer/clients` first).
2. Note the account's **current balance** shown on `/client` (e.g. RWF 5,000).
3. Go to `/client/transactions/new`.
4. Type: **Transfer** (or **Cash out**)
5. Amount: **the exact current balance** (e.g. `5000.00`) β€” this drains the account to zero, the same signature real PaySim fraud rows have.
6. Destination: anything, e.g. `C_MULE_1`
7. Submit.

Expected result: `risk_tier: "high"`, and the UI shows *"This transaction is being reviewed for your security."* An alert appears immediately on `/officer/alerts` and on the client's own `/client/alerts`.

A **partial** transfer (e.g. RWF 2,000 out of a RWF 5,000 balance) stays low-risk β€” it's the *full drain to zero*, not the size of the transaction, that the model keys on.

## 2. Trigger it directly against `/api/predict` (officer-only, raw PaySim fields)

Useful for testing the model in isolation without going through the account-balance flow. Requires an officer session.

```bash
curl -X POST http://127.0.0.1:8811/api/predict \
  -H "Content-Type: application/json" \
  -b "session_token=<officer session cookie>" \
  -d '{
    "step": 5,
    "type": "TRANSFER",
    "amount": 181.0,
    "nameOrig": "CFXFRAUD000A",
    "oldbalanceOrg": 181.0,
    "newbalanceOrig": 0.0,
    "nameDest": "CFXFRAUD000B",
    "oldbalanceDest": 0.0,
    "newbalanceDest": 0.0
  }'
```

Expect `"risk_tier": "high"` with `probability` close to 1.0, and the top SHAP features dominated by the balance-drain signal.

### More fraud-triggering examples (any amount works, as long as it fully drains)

| type | amount | oldbalanceOrg | newbalanceOrig | oldbalanceDest | newbalanceDest |
|---|---|---|---|---|---|
| TRANSFER | 181.00 | 181.00 | 0.00 | 0.00 | 0.00 |
| TRANSFER | 2,500.00 | 2,500.00 | 0.00 | 0.00 | 0.00 |
| TRANSFER | 50,000.00 | 50,000.00 | 0.00 | 0.00 | 0.00 |
| TRANSFER | 275,000.50 | 275,000.50 | 0.00 | 0.00 | 0.00 |
| CASH_OUT | 300.00 | 300.00 | 0.00 | 0.00 | 0.00 |
| CASH_OUT | 15,000.00 | 15,000.00 | 0.00 | 0.00 | 0.00 |

These are drawn straight from `tests/fixtures/labeled_transactions.json` (28 hand-labeled fraud fixtures in total β€” search for `"expected_label": "fraud"`).

## 3. What does *not* trigger fraud (for contrast)

| type | amount | oldbalanceOrg | newbalanceOrig | Expected |
|---|---|---|---|---|
| PAYMENT | 45.00 | 5,000.00 | 4,955.00 | low |
| TRANSFER | 2,000.00 | 5,000.00 | 3,000.00 | low (partial, not a drain) |
| CASH_IN | 1,000.00 | 3,000.00 | 4,000.00 | low |
| DEBIT | 60.00 | 1,200.00 | 1,140.00 | low |

## Reference

- Alert threshold: `FRAUD_ALERT_THRESHOLD=0.5` (probability above this becomes an alert)
- Display risk tiers (independent of the alert threshold): **low** < 0.30, **medium** 0.30–0.70, **high** β‰₯ 0.70
- Full model methodology: `reports/MODEL_COMPARISON_conservative.md`, `reports/EDA_REPORT.md`
- Regenerate/inspect the full fixture set: `python -m scripts.generate_fixtures`, then `tests/fixtures/labeled_transactions.json`