Synthetic AML transaction dataset with labelled typologies and ground truth

A bank's customers, accounts and transactions, with the laundering typologies labelled, the rule-based alerts raised, and the cases and SARs that followed.

A bank's first six months: 300 customers, their accounts, tens of thousands of transactions and a set of launderers whose behaviour follows named typologies (structuring, mules, layering, round-tripping and more). Rule-based alerts fire with real false positives, and investigators turn some of them into cases and suspicious activity reports. The labels are the ground truth, so you can score a detector honestly.

  • anti-money-laundering
  • AML
  • fraud detection
  • ground truth
  • fintech
  • machine learning
010,00020,000Mar 2026Apr 2026May 2026Jun 2026Jul 2026Aug 2026
Rows per month in transactions.txn_at, counted from the file.

Explore

Every table, profiled

Each column's type, spread, empties and most common values, measured from the CSVs in the download. Switch to the first rows to see the data exactly as it sits in the file.

transactions.csv

42,203 rows · 15 columns · 3 foreign keys

transaction_idprimary key
unique on every row
42,203 distinctno empties
account_idforeign key
points to accounts.account_id
482 distinctno empties
customer_idforeign key
points to customers.customer_id
298 distinctno empties
counterparty_idforeign key
points to counterparties.counterparty_id
1,237 distinct36% empty
txn_atdate
Mar 2026Aug 2026
2026-03-02 to 2026-08-31no empties
txn_typecategory
  • card_purchase
    21%
  • supplier_payment
    13%
  • transfer_out
    13%
  • transfer_in
    12%
  • customer_receipt
    7.7%
  • 9 more values · 34%
14 valuesno empties
directioncategory
  • debit
    62%
  • credit
    38%
2 valuesno empties
channelcategory
  • online
    37%
  • card
    27%
  • mobile
    15%
  • wire
    11%
  • branch
    5.1%
  • 1 more value · 3.8%
6 valuesno empties
amountnumber
0.91log scale11,671
mean 713.8median 101.70.5 to 475,000no empties
currencycategory
  • USD
    100%
1 valueno empties
counterparty_countrycategory
  • United States
    99%
  • Russia
    <0.1%
  • Spain
    <0.1%
  • Canada
    <0.1%
  • Panama
    <0.1%
  • 25 more values · 0.6%
30 values36% empty
is_cashyes / no
true · 8.9%false · 91%
no empties
is_suspiciousyes / no
true · 1.7%false · 98%
no empties
typologycategory
  • cash_commingling
    63%
  • mule_funnel
    14%
  • dormant_reactivation
    9.5%
  • structuring
    8.3%
  • layering
    3.6%
  • 2 more values · 1.0%
7 values98% empty
ring_idcategory
  • R00011
    41%
  • R00005
    22%
  • R00012
    7.0%
  • R00004
    5.4%
  • R00007
    4.3%
  • 10 more values · 20%
15 values98% empty

Keys

Every join resolves

8 foreign keys, 111,978 references checked against the table each one points at. None points at a row that does not exist.

accounts

  • customer_idcustomers.customer_id0 orphans

alerts

  • customer_idcustomers.customer_id0 orphans
  • account_idaccounts.account_id0 orphans

cases

  • customer_idcustomers.customer_id0 orphans
  • first_alert_idalerts.alert_id0 orphans

transactions

  • account_idaccounts.account_id0 orphans
  • customer_idcustomers.customer_id0 orphans
  • counterparty_idcounterparties.counterparty_id0 orphans

Checks

What we checked

  • 8 foreign-key relationships checked, 0 orphaned rows
  • No row is dated before the row it belongs to
  • 15 of 300 customers (5.0%) are launderers, and the rate asked for is the rate in the data
  • 726 suspicious transactions, each labelled with its typology (cash_commingling, dormant_reactivation, layering, mule_funnel, round_tripping, structuring, trade_based) so a detector can be scored against the truth
  • Alerts are rule-based, not oracles: 60% of 84 alerts are true positives and the rest are false alarms
  • 19 of 38 cases end in a filed suspicious activity report, and every one is filed after its case opened
  • Structuring is visible: 44% of the 57 structured cash deposits sit just under the 10,000 reporting threshold
  • Honest payments favour a few counterparties: the busiest 20% are on 63% of them, and every salaried customer is paid by one employer

The same checks ship in the zip as INTEGRITY.txt, so you can rerun them in any SQL engine. How we verify

Questions, answered

Worth asking it

Each answer is the query's result on these exact files. Open one for its SQL and rows, then check your own query against it.

  1. 1What precision and recall does a simple amount-threshold rule reach against the typology labels?Flagging amounts of $10,000 or more: precision 16.1%, recall 6.1%.
    with thresholds as (
      select 5000 as threshold union all select 9000 union all select 10000 union all select 50000
    )
    select t.threshold,
           sum(case when x.amount >= t.threshold then 1 else 0 end) as flagged,
           sum(case when x.amount >= t.threshold and x.is_suspicious then 1 else 0 end) as true_hits,
           round(100.0 * sum(case when x.amount >= t.threshold and x.is_suspicious then 1 else 0 end)
                 / nullif(sum(case when x.amount >= t.threshold then 1 else 0 end), 0), 1) as precision_pct,
           round(100.0 * sum(case when x.amount >= t.threshold and x.is_suspicious then 1 else 0 end)
                 / sum(case when x.is_suspicious then 1 else 0 end), 1) as recall_pct
    from thresholds t
    cross join transactions x
    group by t.threshold
    order by t.threshold
    thresholdflaggedtrue_hitsprecision_pctrecall_pct
    5,00092713514.618.6
    9,0003477120.59.8
    10,0002744416.16.1
    50,000131076.91.4
  2. 2Which typology is hardest to catch with rules alone?layering is caught least: 10 of 12 customers using it drew a true alert.
    with launderers as (
      select distinct customer_id, typology
      from transactions
      where is_suspicious
    ),
    alerted as (
      select distinct customer_id from alerts where is_true_positive
    )
    select l.typology,
           count(*) as customers,
           sum(case when a.customer_id is not null then 1 else 0 end) as alerted,
           round(100.0 * sum(case when a.customer_id is not null then 1 else 0 end) / count(*), 1) as detected_pct
    from launderers l
    left join alerted a on a.customer_id = l.customer_id
    group by l.typology
    order by detected_pct, customers desc
    typologycustomersalerteddetected_pct
    layering121083.3
    mule_funnel33100
    structuring33100
    dormant_reactivation22100
    cash_commingling22100
    trade_based11100
    round_tripping11100
  3. 3How many alerts does an investigator work for each true launderer found?84 alerts find 22 of the 24 customers in suspicious activity: 3.8 alerts for each one found.
    select count(*) as alerts,
           sum(case when is_true_positive then 1 else 0 end) as true_alerts,
           count(distinct case when is_true_positive then customer_id end) as launderers_found,
           (select count(distinct customer_id) from transactions where is_suspicious) as customers_in_suspicious_activity,
           round(1.0 * count(*) / count(distinct case when is_true_positive then customer_id end), 1) as alerts_per_launderer_found
    from alerts
    alertstrue_alertslaunderers_foundcustomers_in_suspicious_activityalerts_per_launderer_found
    845022243.8
  4. 4Do structured cash deposits cluster in the days before a case opens?Structured deposits by when they fell against their customer's case: 8-30 days before 25, 0-7 days before 25, after the case opened 10.
    with d as (
      select extract(epoch from (c.opened_at - t.txn_at)) / 86400 as days_before
      from transactions t
      join cases c on c.customer_id = t.customer_id
      where t.typology = 'structuring'
    )
    select case when days_before < 0 then 'after the case opened'
                when days_before <= 7 then '0-7 days before'
                when days_before <= 30 then '8-30 days before'
                when days_before <= 90 then '31-90 days before'
                else 'over 90 days before' end as timing,
           count(*) as deposits
    from d
    group by 1
    order by min(days_before) desc
    timingdeposits
    8-30 days before25
    0-7 days before25
    after the case opened10

Every query runs on the files in the download as they are. ANSWERS.sql holds all of them; run it in DuckDB from the dataset's folder.

Full version · $5

This sample, or the full AML Transaction Monitoring

A UAE bank's whole trail from KYC to STR, with the laundering nobody caught. Try its free preview before you decide.

This sampleAML Transaction Monitoring
Rows44,61211,711,393
Tables616
Columns63172
FormatsCSVCSV
AuditKeys and the checks listed above129 checks, all listed
LicenceCC0, freeCommercial use, $5 once
Built foranti-money-laundering, AML, fraud detection, ground truthTransaction monitoring and model benchmarks, Alert triage and false positives, Case management and STR workflow, Targeted financial sanctions, Drift and robustness, Graph and network detection, KYC, beneficial ownership and screening, A bank that lives in the UAE, Teaching and demos

Use it

Take it, or make one shaped like yours

Rebuild it byte for byte

The zip includes RECIPE.json: the Studio pack, the overrides and seed 20260921 that made these exact rows.

Your own tables, your own numbers

Describe the data you need in Studio and get connected tables with the totals you state, profiled like this and checked before you download.

The full version, and what goes with it

All premium
  • transactions, rows per monthMay 2025 – Oct 2026

    One UAE bank, 10,000 customers, eighteen months

    A UAE bank's whole trail from KYC to STR, with the laundering nobody caught

    Answer key

    • is_suspicious
    • typology
    • ring_id
    • +7 more
    Rows
    11,711,393
    Tables
    16
    Checks
    129 of 129
    Free previewProfile and preview
  • Card spending each month, debit and credit

    2,500 US households at five banks and seven card issuers, two years

    Five banks' raw statement lines, with every label behind them

    Answer key

    • description
    • merchant_name
    • category
    • +6 more
    Rows
    7,627,186
    Tables
    14
    Checks
    50 of 50
    Free previewProfile and preview
  • Weekly sales, at regular price and on promotion

    Grocery chain, 10 stores, fiscal 2024 and 2025

    Two fiscal years of a grocery chain, from the shelf to the receipt

    Answer key

    • baseline_units
    • price_effect
    • promo_lift
    • +7 more
    Rows
    2,790,852
    Tables
    14
    Checks
    117 of 117
    Free preview18-question projectProfile and preview

Related free datasets

All 12

Fully synthetic. No real person, company or transaction is represented, and no production data was read to make it. CC0: use it anywhere, no attribution needed.