C. Velocity and behaviour change
Ce contenu n’est pas encore disponible dans votre langue.
Fixed thresholds treat every customer the same. Velocity and behaviour rules do something smarter: they compare a customer with their own history. A GHS 20,000 week is routine for a wholesaler and alarming for a student.
These rules catch:
- Accounts that have been taken over — a fraudster spends very differently from the owner.
- Accounts that have been sold or rented to criminals — a quiet account suddenly becomes busy.
- Pass-through accounts — money arrives and leaves almost immediately, which is how mule accounts are used.
SpeculaPro builds a profile for each customer and account — typical counts, typical amounts, typical hours — and keeps it up to date with every transaction. See Feature store for how this works.
Rules in this category
Section titled “Rules in this category”| ID | Rule | Mode | Status |
|---|---|---|---|
| C1 | Transaction count spike vs profile | RT/PE | Ships (core, post-event) |
| C2 | Value spike vs profile | RT/PE | Ships (core, post-event) |
| C3 | Dormant account reactivated with high activity | PE/SCH | Ships (core, post-event) |
| C4 | New account, high value early | RT/PE | Ships (core, post-event) |
| C5 | Rapid in-and-out (pass-through) | PE | Ships (core, post-event) |
| C6 | Unusual hour for this customer | RT | Ships (fraud, real-time) |
| C7 | Burst of payouts | RT | Ships (fraud, real-time) |
C1 Transaction count spike vs profile
Section titled “C1 Transaction count spike vs profile”What it looks for: an account making many more transactions in a day than it usually does: a takeover, a newly recruited mule, or a business that has outgrown its profile.
Example
With the defaults (multiplier 5, min_count 10, min_baseline_days 30), for an account that made
60 transactions in the 29 days before today (about 2 a day):
- ✅ Fires: 12 transactions in the last 24 hours: at least 10, and more than 5 × 2.07.
- ❌ Does not fire: 9 transactions in a day (under
min_count), however quiet the account usually is. - ❌ Does not fire: an account opened 10 days ago (younger than
min_baseline_days), or one with no opening date.
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
multiplier |
How many times the account’s average day counts as a spike | Lower values catch more; 3–10 are typical values to test |
min_count |
Transactions in the last 24 hours, at least | Stops a jump from 1 to 6 transactions alerting |
min_baseline_days |
How old the account must be before the rule applies, in days (7 to 3,650) | 30 days or more gives a stable average |
The windows are fixed: the last 24 hours, against the 29 days before them. Every transaction counts, in either direction.
Mode and pack: post-event, in core 1.1.0.
False positives: festive seasons, salary days and month-end, when everyone is busier. Watch alert volume around these dates during shadow testing.
Data it needs: the account’s opening date (opened_at on the
account), and a continuous transaction history.
C2 Value spike vs profile
Section titled “C2 Value spike vs profile”What it looks for: a customer moving a much larger total than usual in a period.
Example
With multiplier 5 and window 7 days, for a customer whose weekly total is usually about
GHS 2,000:
- ✅ Fires: GHS 14,000 moved this week (7× normal).
- ❌ Does not fire: GHS 6,000 in a week when rent was paid (3×).
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
multiplier |
How many times the usual value counts as a spike | As C1 |
window |
The period totalled | Days to weeks |
Mode and pack: real-time or post-event.
False positives: one-off life events — buying a car, paying a deposit on land, funeral contributions. These are exactly what an analyst should confirm and close quickly; record the explanation in the case.
Data it needs: amount (base currency) and a continuous history.
C3 Dormant account reactivated with high activity
Section titled “C3 Dormant account reactivated with high activity”What it looks for: an account that has been inactive for a long time suddenly receiving or sending significant amounts. Dormant accounts are attractive to criminals: they are already verified, and their owner is not watching them.
Example
With the shipped rule, dormant_days 180 and min_amount GHS 10,000:
- ✅ Fires: an account opened two years ago, with nothing in the last 90 days, receives GHS 25,000 and starts sending it on.
- ❌ Does not fire: the same account receives GHS 300.
- ❌ Does not fire: an account opened four months ago and unused since; it is younger than 180 days.
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
dormant_days |
How old the account must be (the quiet period itself is fixed at 90 days) | At least the 90-day quiet period, so only established accounts count |
min_amount |
The transaction needed after reactivation to fire | Set so small “test” transactions don’t trigger alerts |
Mode and pack: post-event, or as a scheduled sweep.
False positives: customers returning from abroad, seasonal workers, students. A check of the customer’s contact details and recent KYC usually resolves these.
Data it needs: full history (so the dormant period can be seen), account status.
C4 New account, high value early
Section titled “C4 New account, high value early”What it looks for: a newly opened account moving large amounts straight away. Criminals open accounts specifically to receive fraud proceeds and use them before they are noticed.
Example
With account_age_days 30 and threshold_amount GHS 20,000:
- ✅ Fires: an account opened 9 days ago receives GHS 35,000.
- ❌ Does not fire: an account opened 9 days ago receives a GHS 2,500 salary.
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
account_age_days |
How long an account counts as “new” | 30–90 days are common |
threshold_amount |
Amount that is unusual for a new account | Lower for retail, higher for business onboarding |
Mode and pack: real-time or post-event.
False positives: new business accounts receiving their opening balance, customers moving their salary to a new bank. Segment business customers separately.
Data it needs: account opening date (opened_at), amount.
C5 Rapid in-and-out (pass-through)
Section titled “C5 Rapid in-and-out (pass-through)”What it looks for: money that arrives and leaves again almost immediately, with nearly the whole amount passed on. The account is a pipe, not a destination — the defining behaviour of a money mule.
Example
With out_pct_of_in 90%, window 24 hours and min_amount GHS 5,000:
- ✅ Fires: GHS 18,000 arrives at 10:05; GHS 17,500 is sent to three other wallets by 13:30.
- ❌ Does not fire: GHS 18,000 arrives and GHS 4,000 is spent over the next week.
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
out_pct_of_in |
Share of incoming money that leaves | 80–95% are typical values to test |
window |
How quickly it must leave | Hours to a day or two |
min_amount |
Minimum amount passed through | Ignores small everyday transfers |
Mode and pack: post-event.
False positives: customers who move their own salary from one account to another on payday, and payment aggregators. Check whether the outgoing destination is the customer’s own account.
Data it needs: amount, direction, counterparties.
C6 Unusual hour for this customer
Section titled “C6 Unusual hour for this customer”What it looks for: a payout at an hour this customer does not use, for example 03:00 for someone who only ever pays during the day. Payouts while the owner sleeps are a common sign that someone else is using the account.
Example
With the defaults (min_history 30, max_prior_at_hour 0, min_amount 1,000), for a customer
with 80 transactions in 90 days, all between 07:00 and 21:00:
- ✅ Fires: a GHS 4,000 transfer at 02:40. None of the 80 was in the 02:00 hour, so the customer is asked to prove it’s them.
- ❌ Does not fire: a GHS 50 airtime purchase at 02:40 (below
min_amount). - ❌ Does not fire: a customer with only 12 transactions in 90 days (not enough history).
- ❌ Does not fire, for now: any customer in the first weeks after the upgrade that introduced the hour counters, until those counters have seen 30 of their transactions.
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
min_history |
Transactions in the last 90 days before it applies, at least | Higher means a better-known pattern and fewer alerts |
max_prior_at_hour |
Earlier transactions at this hour of the day, at most | 0 means “never at this hour”; 1 tolerates a single earlier one |
min_amount |
Payout at or above (base currency) | Keeps small late-night purchases out |
An hour means a clock hour (02:00 to 02:59), and every transaction counts towards the history, in either direction.
Mode and pack: real-time, added in fraud 1.1.0 and made like-for-like in fraud
1.2.0. Like every real-time rule, it only sees payments sent to the decision API.
False positives: shift workers, and travellers in other time zones. A step-up is a light answer: the genuine customer confirms and pays.
Data it needs: accurate transaction timestamps (occurred_at) and enough history.
C7 Burst of payouts
Section titled “C7 Burst of payouts”What it looks for: many outgoing payments in a few minutes. A genuine customer rarely sends five payments in ten minutes; someone emptying a wallet they’ve taken over, or a script, often does. It’s a velocity rule built for real time: it has to act while the burst is still happening.
Example
With max_payouts 5 and min_total GHS 1,000:
- ✅ Fires: six transfers of GHS 400 to different wallets between 22:01 and 22:07. The fifth already fires (five payouts, GHS 2,000).
- ❌ Does not fire: five airtime purchases of GHS 10 in ten minutes (total under
min_total). - ❌ Does not fire: four payouts of GHS 3,000 (fewer than
max_payouts).
Parameters
| Parameter | Meaning | How to tune |
|---|---|---|
max_payouts |
Payouts in 10 minutes, this one included, from which it fires | Above what your busiest genuine customers do: merchants and agents may need a separate rule |
min_total |
Smallest 10-minute total that counts | Keeps bursts of tiny payments (airtime, transport) quiet |
Mode and pack: real-time, fraud pack. Ships today. It answers step_up, so a
genuine customer passes with an OTP while a fraudster without the phone is stopped.
False positives: businesses paying staff or suppliers in a batch, and customers splitting a bill. Consider a suppression for a known business, or a segment check in a custom version.
Data it needs: direction and amount, with payouts sent through a real-time decision as they happen. A backlog sent late isn’t counted; see Late and backdated data.
Related
Section titled “Related”- D. Mule and network patterns — what pass-through accounts are part of
- H. Card and online fraud — account takeover signals
- Feature store — how profiles are built
- Tuning and calibration