The model was trained under a different XGBoost version than the one serving it, so ordinary payments scored as high-risk.
I retrained the model under the same XGBoost version that serves it, which restored sane scores for normal traffic.
Adding rule points straight onto the ML score pushed moderate and certain-fraud transactions to the same ceiling, so the score lost meaning.
Rules now use only the remaining headroom to 1.0, so scores stay meaningful even with several rule hits.
A graph-reachability rule looked promising but fired on 85.6% of synthetic traffic at only 2.2% precision.
I benchmarked the noisy rule and recorded its weakness instead of shipping it on faith.
Blocking fraud is easy. Blocking fraud without blocking your best customers is the hard part.
Risk analysts at banks and payment companies deal with this trade-off every day. Let fraud through, and money is lost. Block real customers, and trust is lost. When someone asks "why was this payment flagged?", the honest answer is often "the model said so."
TrustGuard is a real-time fraud-risk platform for the Sri Lankan payments market. Every decision comes with its reasoning attached.
Live: https://trustguard.madhushan.me
Source: https://github.com/sandunMadhushan/TrustGuard
Access: the analyst login is restricted. Contact me for a walkthrough.
The flow: Transaction in → ML score → local rules → plain-English reasons → Allow / Review / Block
ruleSum × (1 − mlScore)), so scores stay informative instead of clipping at 100.| Service | Tech | Role |
|---|---|---|
ml-service | Python, FastAPI, XGBoost, SHAP | Scores a transaction and explains the score |
backend | Java 17, Spring Boot | REST API, JWT auth, rules engine, persistence, notifications |
frontend | React 19, TypeScript, Vite, Tailwind v4 | Dashboard for risk analysts |
There is no real Sri Lankan bank fraud dataset, so the rule weights are calibrated on a 32,000-row synthetic dataset against the real deployed model. A real deployment would recalibrate on your own labeled outcomes.
Without real bank fraud data, the rules had to be validated without pretending they were proven.
A switchable v2-calibrated weight set cut the false-positive rate from 33% to 16% on synthetic data, at a recall trade-off (77% → 72%).