Countersign
Real-time card fraud scoring that explains every decline.


The problem
Card issuers have milliseconds to approve, review or decline a payment, and they must say why a payment was declined. Fraud models often fail quietly in production: their training features are rebuilt later from tidy data, so they differ from what the live scorer saw at decision time.
Real payment streams are also messy. Events arrive late, out of order and twice, while the customer is still waiting at the till.
What I did
I built one feature engine for both training and live scoring, fed the same arrival-ordered stream, and proved the two produce identical vectors. Seventeen features per card cover spend against the card’s own history, bursts of tiny charges, new devices and impossible travel.
A logistic regression in numpy gives exact reasons for every review or decline. Thresholds come from validation days: analysts review 0.5% of traffic, and payments are declined only where precision was at least 90%.
Every evaluation splits by time, never at random, against hand-written rules and gradient-boosted trees.

The outcome
On 276,650 synthetic payments, reviewing 0.5% of traffic caught 154 of 176 frauds (88%) and $36,868 of $42,677, against 44% for hand-written rules. On the public ULB card dataset it caught 86% of fraud, and 50 of its 52 declines were fraud.
It scores a payment in about 8 µs, 84,000 a second on one core, and the browser demo matches the Python model on every decision.


