AI in Finance & Fraud · Lesson 4 of 8
Feature Engineering for Transactions & Graph Fraud
In fraud detection, features matter more than the algorithm. A plain gradient-boosted model with strong behavioural features beats a fancy model on raw columns. This lesson covers the main feature families and how graphs expose fraud rings.
Behavioural (velocity) features
Compare now with the customer's normal behaviour:
- Count and sum of transactions in the last 1 h / 24 h / 7 d, per card, device, IP and merchant.
- Amount relative to the customer's average:
amount / mean_amount_90d, z-score. - Time since the last transaction; time since the account or card was created.
- New merchant, new device, new country for this customer.
- Distance from the usual location; "impossible travel" (two far-apart places within minutes).
df = df.sort_values("ts")
g = df.set_index("ts").groupby("card_id")["amount"]
df["cnt_1h"] = g.rolling("1h").count().reset_index(level=0, drop=True).values
df["sum_24h"] = g.rolling("24h").sum().reset_index(level=0, drop=True).values
df["amt_vs_avg"] = df.amount / df.groupby("card_id").amount.transform(lambda s: s.shift().expanding().mean()).fillna(df.amount)
- Point-in-time correctness: each feature must use only data available before the transaction. Notice
shift()above, which excludes the current row.
Entity and context features
- Merchant risk: historical fraud rate (target-encoded with smoothing, computed out-of-fold), category (MCC), merchant age.
- Device and network: emulator or rooted flags, IP reputation, VPN/proxy, device age.
- Channel: card-present vs online, wallet, UPI, recurring payment.
- Customer profile: tenure, KYC level, product holdings.
Graph features: catching rings
Fraudsters reuse resources: devices, phone numbers, addresses, beneficiary accounts. Build a graph:
- Nodes: customers, accounts, devices, phones, emails, IPs, merchants.
- Edges: "uses", "pays to", "shares".
Useful signals:
- Connected-component size around a customer (how many accounts share this device or phone).
- Degree of a beneficiary account (how many senders); mule accounts receive from many.
- Distance to known fraud: hops from a confirmed fraudster.
- PageRank or label propagation of fraud risk across the graph.
- Graph neural networks (GraphSAGE, GAT) for large graphs, with features learned from neighbours.
import networkx as nx
G = nx.Graph()
G.add_edges_from(zip("acct:" + df.account_id, "dev:" + df.device_id))
size = {n: len(c) for c in nx.connected_components(G) for n in c}
df["device_cluster_size"] = ("acct:" + df.account_id).map(size)
Serving features in real time
- A streaming layer (Kafka + Flink/Spark Streaming) updates aggregates as events arrive.
- An online feature store (Redis, Feast) serves them in milliseconds.
- The same feature definitions feed offline training, which avoids training-serving skew.
Check yourself
What is point-in-time correctness and why does it matter?
Each feature value must be computed only from data available before the event. Otherwise the model learns from the future (leakage), and offline performance will not hold in production.How do graph features help detect money mules?
Mule accounts often receive money from many unrelated senders and quickly pass it on. A high in-degree from new senders, shared devices or phones with other suspicious accounts, and proximity to confirmed fraud all stand out in a graph.How should merchant fraud rate be encoded without leakage?
Use out-of-fold target encoding with smoothing towards the global rate, computed only from transactions before the scoring time.Created by Ajeetkumar