Which sender → recipient pair just spiked?¶
Question-shaped walkthrough — Investigation dashboard, Volume Anomalies sheet.
The story¶
A counterparty that's been wiring routine amounts to the same beneficiary for weeks suddenly sends a wire that's an order of magnitude bigger. By itself the wire is unremarkable — well within the bank's daily limit, fully authorized, posts cleanly. What makes it interesting is that THIS pair, on a normal week, doesn't move that kind of money. The investigator needs a way to spot pair-windows that just spiked above their OWN baseline, separate from the absolute-dollar checks the bank already runs.
The question¶
"Which (sender, recipient) pair just moved a lot more money than this pair usually moves?"
Where to look¶
Open the Investigation dashboard, Volume Anomalies sheet.
The sheet has two controls in the top-right panel:
- Window End Date — limits the analysis window via
window_end. Default covers the trailing month; narrow to "this week" for a focused review, widen for back-tests. - Min sigma — the cutoff above which a pair-window appears in the KPI + table. Default is 2σ; drag to 1σ to surface marginal spikes (and a lot of noise), or to 3–4σ to focus on the extreme tail.
Three visuals:
- Flagged at current σ (top-left, third-width KPI) — count of (sender, recipient, window-end) tuples past the σ threshold.
- Pair-Window σ Distribution (top-right, two-thirds-width) — a
bar chart of every pair-window in the population bucketed into 5
bands (
0-1 sigma,1-2 sigma,2-3 sigma,3-4 sigma,4+ sigma). The chart intentionally IGNORES the σ slider, so the distribution shape stays visible — your cutoff lands in context. - Flagged Pair-Windows — Ranked (full-width below) — table of the flagged tuples sorted by z-score descending. Each row carries sender + recipient names, the window end date, the rolling 2-day SUM, the z-score and the σ bucket label.
The math, briefly¶
The matview spec_example_inv_pair_rolling_anomalies computes, per
(sender, recipient) pair, a 2-day rolling SUM (today + yesterday's
transfer amounts). Each window is then z-scored against that PAIR's
own history — the mean and sample standard deviation of the rolling
SUM across every window for that pair, NOT the global population
((value - pair_mean) / pair_stddev) — plus a 5-band bucket label.
Pairs with fewer than 3 windows of history get z=0: too little
signal to compute a meaningful divisor.
So the threshold is "this pair moved enough money in a 2-day window that, compared to its OWN history, this one is N standard deviations out." A pair that always moves $1M will not flag at 2σ unless this particular window is much more than $1M; a pair that usually moves $300 will flag at 2σ if it suddenly moves $5,000.
The window length is hardcoded at 2 days (a slider would need either multiple matviews or a generate_series scan at dataset time).
The matview does NOT auto-refresh. After every ETL load, the
operator runs
REFRESH MATERIALIZED VIEW spec_example_inv_pair_rolling_anomalies;
— see Refresh contract.
A skipped refresh means the z-scores reflect yesterday's data.
What it means¶
Volume Anomalies is a deviation detector, NOT a fraud verdict. A high z-score is consistent with money laundering but also with plenty of normal patterns:
- A merchant's monthly settlement landing on a single day after a long quiet stretch.
- A customer's annual bonus / tax refund / insurance settlement hitting a DDA that normally sees small payroll deposits.
- A counterparty that's been quiet for weeks resuming normal activity in a single batch.
The investigator's job is to RULE those out before treating the spike as suspicious. The chart is the first step — if the rest of the population is dense and your flag sits alone in the right tail (as the demo's $25,000 spike does), that's a stronger signal than a flag at the edge of a populated bucket.
A clean anomaly finding includes: the (sender, recipient) names + account IDs, the window end date, the 2-day SUM, the z-score and a one-line reason the deviation is or isn't expected for the pair.
Drilling in¶
Once you have a flagged pair-window, the next step depends on what you want to know:
- "Show me every transfer between this pair, not just the spike." → Account Network sheet. Set the anchor to either side; the touching- edges table lists every edge, and the directional Sankeys split inbound from outbound.
- "Where did this specific transfer come from?" → Money Trail sheet. Pick the chain root (typically the spike transfer itself if it's chain-rooted, or the transfer_parent_id chain it sits on).
- "Show me the underlying posting rows." → L1 Reconciliation
Dashboard, Transactions sheet, filtered to the sender or
recipient
account_id.
Next step¶
The fastest path from a 4σ flag to "is this a SAR or not" usually goes:
- Confirm the spike on this sheet's table — copy the sender, recipient, window end and z-score for the case file.
- Switch to Account Network with the recipient as the anchor — confirm whether the rest of the pair's history is consistent (regular wires) or sparse (one-shot relationship).
- Switch to Money Trail with the spike transfer's chain root — confirm whether the money moved on after landing (layering) or stayed put.
- Drop into the L1 Transactions sheet for the row-level postings if the case needs evidence at the leg level.
If the spike is the only data point — sender appeared once, money moved on the same day to a downstream account — it's a Money Trail case. If the spike is one of many irregular transfers from the same pair, it's an Account Network case. Volume Anomalies is the entry point, not the destination.
Related walkthroughs¶
- Who's getting money from too many senders? — the previous sheet. A pair-window spike on a recipient who ALSO shows up there is a stronger signal than either alone.
- Where did this transfer actually originate? — the right step when the spike transfer is part of a chain. Money Trail walks the chain end-to-end.
- What does this account's money network look like? — the right step when you need to see the full graph around the recipient (or sender) of the flagged pair.