我抓交易欺诈用的六个 SQL 套路

查看原文 HN 讨论

文章摘要

作者在某政府福利项目的”项目合规(program integrity)”团队做数据分析。开篇就把热门技术全否了:抓欺诈”不需要机器学习、不需要图数据库,也不需要 Gartner 今年在吹什么”,绝大多数欺诈检测就是 SQL——对着正确的表,做正确的 join,找正确形状的数据。文章给出六个他每接手一个新数据集就会立刻搭起来的模式,按照构建顺序排列。

第一个是速度(velocity)——偷到信用卡的人最怕持卡人发现,于是会拼命刷。基本写法是按小时桶聚合统计交易数,超过阈值的就报警;进阶版用窗口函数做 5 分钟滑窗(QUALIFY tx_in_last_5min >= 5)。同时跑 1 分钟、5 分钟、1 小时三个版本,因为不同欺诈的节奏不一样:测卡机器人几秒一波,福利倒卖团伙可能慢悠悠刷一下午。第二个是不可能的旅行(impossible travel)——同一张卡七分钟前在芝加哥、七分钟后在洛杉矶,必定有一笔是克隆卡。用 LAG() 取前一笔的时间和地点,配合 haversine 函数算大圆距离,速度超过 600 mph(”比飞机还快”)就报警。

第三个是金额异常。两类金额在欺诈里超常见、在正常消费里几乎不出现:$1、$5、$10 等小额整数(测卡用——咖啡是 $4.73、加油是 $52.81,整数本身就是信号),以及刚好低于阈值的金额($99.99 卡在”$100 要查 ID”的线下、$499.99 卡在 ATM 日限的线下,作案者知道规则)。第四个是可疑商户——加油站读卡器被装了 skimmer 后,所有刷过的卡都进了黑库。症状是:短时间内大量陌生卡在同一个商户消费偏高。直接用静态阈值不行(Costco 90 秒就过),所以要用每个商户的 168 小时(一周)滚动平均作为基线,做 3 倍突刺检测。

第五个是反作息时间——朝九晚五的人不会半夜买汽油,所以先用 90 天历史给每个持卡人算个人的正常活跃小时段(用 FILTER (WHERE tx_count >= 2) 过滤掉偶发深夜消费,避免一次性事件污染基线),落在区间外的交易报警。新账户没有历史就跳过这条规则。第六个不是模式而是基础设施:用窗口函数把上面五个信号拼成可组合的链。作者强调 QUALIFY 在 Snowflake / BigQuery / Databricks / Teradata 里都能用,Postgres 没有就外面包一层 CTE。整体哲学是 KISS——能用 SQL 做完的就不要上 ML,可解释性远比 F1 分数重要。

HN 评论精华