Skip to content

B. Structuring and smurfing

Structuring means deliberately breaking a large amount into smaller transactions so that none of them crosses a reporting or monitoring threshold. Smurfing is the same thing done with helpers — several people (the “smurfs”) or several agents each handle a small piece.

Someone holding GHS 200,000 in cash they cannot explain knows that one deposit would be reported. So instead they make twenty deposits of GHS 9,800, perhaps at different agents, on different days. Each looks ordinary. Together they are a classic red flag — in many jurisdictions, structuring to avoid reporting is itself an offence.

Structuring rules do not look at one transaction; they look at patterns over a time window.

ID Rule Mode Status
B1 Multiple deposits just below threshold PE Ships (core, post-event)
B2 Split cash-in across multiple agents PE Ships (gh-psp, post-event)
B3 Many small deposits, one large withdrawal PE Ships (core, post-event)
B4 Repeated round amounts PE Ships (core, post-event)
B5 Same amount repeated to different recipients PE Ships (core, post-event)
GB1 Cash deposits split across branches SCH Ships (gh-bank, scheduled hourly)

What it looks for: several deposits within a time window that each fall just below a threshold — inside a margin you set.

Example

With threshold set to GHS 50,000, margin_pct 10% (so the “just below” band is GHS 45,000 to GHS 49,999), min_count 3 and window 7 days:

  • ✅ Fires: deposits of GHS 48,500 on Monday, GHS 49,200 on Wednesday and GHS 47,900 on Friday.
  • ❌ Does not fire: two deposits of GHS 49,000 in the week (below min_count).
  • ❌ Does not fire: three deposits of GHS 30,000 (outside the band).

Parameters

Parameter Meaning How to tune
threshold The threshold people are trying to avoid Use the same number as your reporting threshold in A2
margin_pct How close below the threshold counts as “just below” (for example 10%) Wider margins catch more but add noise; 5–15% is a typical range to test
min_count How many such deposits trigger the rule 2 is aggressive; 3 or more is more common
window The period the deposits must fall within Days to weeks. Longer windows catch slower structuring

Mode and pack: post-event.

False positives: businesses that deposit their takings regularly and happen to turn over a similar amount each time. Look at the customer’s history — a steady pattern for months is different from a sudden run of near-threshold deposits.

Data it needs: amount, direction (deposits), channel.


What it looks for: one customer’s wallet being funded with cash through several different agents in a short period, adding up to a significant total. This is smurfing adapted to mobile money: each agent sees only a small cash-in.

Example

With min_agents 4, window 24 hours and min_total GHS 20,000:

  • ✅ Fires: GHS 5,500 cash-in at an agent in Madina, GHS 5,000 in Adenta, GHS 6,000 in Kotobabi and GHS 4,800 in Achimota, all on the same day (GHS 21,300 through four agents).
  • ❌ Does not fire: the same total through one agent (that is a job for A-series rules).
  • ❌ Does not fire: four small cash-ins totalling GHS 2,000.

Parameters

Parameter Meaning How to tune
min_agents Number of distinct agents used Most genuine customers use one or two agents near home or work
window The period the cash-ins must fall within Hours to a few days
min_total Minimum combined amount Stops small everyday top-ups from firing

Mode and pack: post-event. Most relevant to mobile money operators (gh-psp).

False positives: traders and drivers who travel and top up wherever they are. Segment them separately if your data identifies them.

Data it needs: the agent involved in each cash-in (agent account or agent ID), amount, channel.


B3 Many small deposits, one large withdrawal

Section titled “B3 Many small deposits, one large withdrawal”

What it looks for: money arriving as many small payments and leaving as one large withdrawal. The account is being used to consolidate structured cash before it is taken out.

Example

With the defaults (min_deposits 10, withdrawal_ratio 0.8, max_deposit_share 0.2, min_amount 5,000):

  • ✅ Fires: fifteen payments of around GHS 2,000 (GHS 30,000 in total) over six days, then a single GHS 27,000 cash-out. 27,000 is 90% of the inflow, and the largest payment in (GHS 2,400) is under 20% of the cash-out.
  • ❌ Does not fire: the same fifteen payments followed by ordinary spending of a few hundred cedis at a time.
  • ❌ Does not fire: one GHS 25,000 payment in and GHS 25,000 out: that is a single large deposit, not many small ones, and C5 (pass-through) is the rule for it.

Parameters

Parameter Meaning How to tune
min_deposits Payments in over the 7 days, at least Higher for accounts that receive many small payments legitimately
withdrawal_ratio The withdrawal as a share of the 7-day inflow 0.7–0.9 are typical values to test
max_deposit_share The largest payment in, as a share of the withdrawal, at most Keeps the rule to small deposits. 0.2 means no single deposit was more than a fifth of the withdrawal
min_amount Withdrawal at or above (base currency) Stops small consolidations from alerting

The window is fixed at 7 days.

Mode and pack: post-event, in core 1.1.0.

False positives: small savings groups (susu) collecting contributions and paying out a lump sum; shop owners banking daily takings and paying a supplier. Check the customer’s declared occupation, and use a suppression with a documented reason for a known susu collector.

Data it needs: amount and direction, and type on the withdrawal (withdrawal, cash_out or transfer).


What it looks for: an unusual number of payments in of exact round amounts (GHS 1,000, GHS 5,000, GHS 10,000). Genuine payments for goods and services rarely come out to exact round figures; cash being placed in neat bundles often does.

Example

With the defaults (round_to 1,000, min_count 5, min_amount 1,000):

  • ✅ Fires: six payments in of GHS 5,000, GHS 3,000, GHS 10,000, GHS 2,000, GHS 5,000 and GHS 4,000 in one week. The alert fires on the fifth.
  • ❌ Does not fire: payments of GHS 4,870, GHS 1,250 and GHS 3,415.
  • ❌ Does not fire: GHS 1,000.50: it must be a whole amount, with no pesewas.

Parameters

Parameter Meaning How to tune
round_to What counts as round: 100 or 1000, a choice of the two (since core 1.2.0; earlier versions accepted any number from 100 to 1,000 but treated all but 100 as 1,000) 100 is very common in everyday mobile money; 1,000 is more selective
min_count Round payments in over the 7 days, at least Raise it if many of your customers receive rent or school fees in round amounts
min_amount This payment at or above (base currency) Stops small round top-ups from counting towards an alert

Round means round in your base currency (the amount after conversion), so a payment made in another currency rarely counts.

Mode and pack: post-event, in core 1.1.0.

False positives: rent, allowances, family support and loan repayments are often round. Consider lowering its severity or score so that it adds weight to other alerts on the same subject rather than leading the queue on its own.

Data it needs: amount and direction.


B5 Same amount repeated to different recipients

Section titled “B5 Same amount repeated to different recipients”

What it looks for: the same amount (or nearly) sent to many different recipients in a short time. It is typical of paying out mules, distributing the proceeds of a scam, or splitting a large sum to stay under limits.

Example

With the defaults (min_recipients 5, amount_tolerance 0.05, min_amount 200, individuals only):

  • ✅ Fires: GHS 1,950, GHS 2,000, GHS 1,980, GHS 2,000 and GHS 1,990 sent to five different wallets within a day. The average is GHS 1,984; the largest, GHS 2,000, is within 5% of it.
  • ❌ Does not fire: GHS 500, GHS 2,000 and GHS 4,000 to five people: the largest is far above the average.
  • ❌ Does not fire: the same amount to the same person five times (one recipient).

Parameters

Parameter Meaning How to tune
min_recipients Different recipients in 24 hours, at least. The customer must also have made at least this many payments Higher if your individual customers often pay several people the same amount
amount_tolerance How close counts as “the same”: 0.05 is within 5% of the average A small percentage catches deliberate variation (GHS 1,950 against GHS 2,000)
min_amount The average payment at or above (base currency) Leaves out small everyday transfers
customer_types Which customers it watches: individual, business Businesses paying wages do this legitimately, which is why the default is individuals only

Mode and pack: post-event, in core 1.1.0.

False positives: family support split between relatives, and chama or susu payouts of equal shares. For businesses, payroll is exactly this pattern, which is why they are left out by default.

Data it needs: amount, and the counterparty on each payment, so recipients can be counted.


What it looks for: B1’s pattern spread across a bank’s branches. Each branch sees one deposit just under the cash reporting threshold; only the bank as a whole sees that together they are well over it.

Example

With the defaults (threshold 50,000, margin 0.15, min_branches 2, min_deposits 3, window_hours 48):

  • ✅ Fires: GHS 48,000 at the Kumasi Adum branch on Monday morning, GHS 47,500 at Kejetia on Monday afternoon and GHS 49,000 at Suame on Tuesday: three deposits, three branches, GHS 144,500 together.
  • ❌ Does not fire: the same three deposits at one branch (B1’s pattern, not this one).
  • ❌ Does not fire: GHS 30,000 at each of three branches: below the “just under” band of GHS 42,500 to GHS 49,999.99.

Parameters

Parameter Meaning How to tune
threshold The reporting threshold being avoided (base currency) The same value as your cash reporting threshold
margin How far below counts as “just below”: 0.15 is within 15% 0.1–0.2 are typical values to test
min_branches Different branches, at least (2 to 100) 2 catches the pattern early; 3 is quieter
min_deposits Deposits, at least (2 to 1,000)
window_hours The period, in hours (1 to 168) 48 matches how quickly people usually move between branches

Mode and pack: scheduled, every hour (hourly :20), in gh-bank 1.0.0. See Scheduled rules. Unlike most scheduled rules, it also counts deposits a real-time decision blocked: a deposit split to stay under the threshold is structuring whether or not it went through.

False positives: businesses whose staff bank the day’s takings at whichever branch is nearest, for example a fuel distributor with several stations. Check the customer’s declared business.

Data it needs: type deposit or cash_in, channel branch or cash, and the branch on each deposit as a branch or branch_code attribute. Deposits with no branch are not counted.