Skip to content

RIFT'26 : AML (Anti-Money Laundering) graph intelligence engine that detects money mule networks in financial transaction data using purely deterministic, explainable graph algorithms

Notifications You must be signed in to change notification settings

Samrudhp/MM_Detection

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

14 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RIFT 2026 β€” Money Muling Detection Engine (Graph Theory Track)

Team Name : Basant

Tech Stack: FastAPI Β· NetworkX Β· Pandas Β· React Β· Cytoscape.js


Overview

A production-grade AML (Anti-Money Laundering) graph intelligence engine that detects money mule networks in financial transaction data using purely deterministic, explainable graph algorithms β€” zero machine learning.

Detected Patterns

Pattern Algorithm Description
Circular Fund Routing Depth-limited DFS Directed cycles of length 3–5
Smurfing Sliding-window fan-in/fan-out β‰₯10 unique counterparties within 72 h
Layered Shell Networks Shell-DFS Chains β‰₯3 through low-activity nodes

Architecture Diagram

flowchart TD
    User(["πŸ‘€ Analyst / User"])
    Upload["πŸ“ CSV Upload\n(React Frontend)"]
    API["⚑ FastAPI\nPOST /analyze"]
    Validator["πŸ” Validator\nSchema Β· Type Coercion Β· Timestamp Parsing"]
    GraphBuilder["πŸ•ΈοΈ TransactionGraph\nNetworkX DiGraph\nAdjacency Lookups O(n)"]

    subgraph Detectors["Detection Layer (Parallel)"]
        Cycle["πŸ”„ CycleDetector\nDepth-limited DFS\nCycles len 3–5"]
        Smurf["πŸ’Έ SmurfDetector\nSliding-window 72h\nFan-in / Fan-out β‰₯10"]
        Shell["🐚 ShellDetector\nShell-DFS\nChains β‰₯3 low-activity nodes"]
    end

    FeatureExtractor["πŸ“Š FeatureExtractor\nStructural Β· Flow Β· Temporal"]
    RiskScorer["βš–οΈ RiskScorer\nWeighted Rules\n+ MerchantDampeningRule"]
    Aggregator["πŸ—‚οΈ RingAggregator\n+ RingConsolidator"]
    JSONOut["πŸ“¦ JSON Response"]

    subgraph Frontend["React Frontend"]
        SummaryCards["πŸ“ˆ SummaryCards"]
        RingTable["πŸ“‹ RingTable"]
        GraphView["🌐 Cytoscape.js\nGraph Visualisation"]
        SuspiciousAcct["🚨 SuspiciousAccounts"]
    end

    User --> Upload
    Upload -->|"HTTP POST multipart/form-data"| API
    API --> Validator
    Validator -->|"Validated DataFrame"| GraphBuilder
    GraphBuilder --> Cycle
    GraphBuilder --> Smurf
    GraphBuilder --> Shell
    Cycle --> FeatureExtractor
    Smurf --> FeatureExtractor
    Shell --> FeatureExtractor
    FeatureExtractor --> RiskScorer
    RiskScorer --> Aggregator
    Aggregator --> JSONOut
    JSONOut -->|"JSON"| SummaryCards
    JSONOut -->|"JSON"| RingTable
    JSONOut -->|"JSON"| GraphView
    JSONOut -->|"JSON"| SuspiciousAcct

    style Detectors fill:#1e3a5f,stroke:#3b82f6,color:#fff
    style Frontend fill:#1a3a2a,stroke:#22c55e,color:#fff
    style Validator fill:#3b1f1f,stroke:#ef4444,color:#fff
    style GraphBuilder fill:#2a2a3a,stroke:#a78bfa,color:#fff
    style FeatureExtractor fill:#2a2a3a,stroke:#a78bfa,color:#fff
    style RiskScorer fill:#2a2a3a,stroke:#a78bfa,color:#fff
    style Aggregator fill:#2a2a3a,stroke:#a78bfa,color:#fff
Loading

Tech Stack

Backend

  • FastAPI β€” REST API server
  • NetworkX β€” directed graph construction and analysis
  • Pandas β€” data loading and temporal sliding windows
  • NumPy β€” statistical feature computation
  • Uvicorn β€” ASGI server

Frontend

  • React 18 β€” UI framework
  • Cytoscape.js β€” interactive graph visualisation
  • cytoscape-cola β€” force-directed layout
  • Axios β€” HTTP client

Algorithm Details

1. Cycle Detection (Circular Fund Routing)

Algorithm: Depth-limited iterative-deepening DFS
Complexity: O(V Γ— d^5) where d = average out-degree (fast for sparse graphs)

For each node v:
  DFS(v, path=[v], depth_limit=5)
    For each successor u of current node:
      If u == v AND len(path) ∈ [3,5]:
        β†’ record cycle
      Elif u not in path:
        β†’ recurse

Normalise: rotate cycle to lex-smallest prefix β†’ deduplicate with set

Parameters: min cycle length = 3, max = 5

2. Smurfing Detection (Fan-in / Fan-out)

Algorithm: O(n log n) two-pointer sliding window
Complexity: O(n log n) β€” dominated by timestamp sort per account

For each account a:
  Sort transactions by timestamp
  Two-pointer window of width 72 hours:
    Count unique counterparties in window
    If count β‰₯ 10 β†’ SMURFING RING

Thresholds: 72-hour window, β‰₯10 unique counterparties

3. Layered Shell Network Detection

Algorithm: Shell-filtered DFS
Complexity: O(V Γ— k Γ— d^k) where k = max_chain_depth (capped at 8)

Precompute shell_accounts = {a : tx_count(a) ≀ 3}

For each non-shell start node s:
  DFS through only shell intermediaries
  If path length β‰₯ 3 β†’ record chain

Shell threshold: accounts with total_tx_count ≀ 3


Suspicion Score Methodology

No ML. Fully deterministic weighted scoring:

Signal Score
Cycle length 3 +40
Cycle length 4 +35
Cycle length 5 +30
Smurfing fan-in hub +45
Smurfing fan-out hub +40
Smurfing member +20
Shell intermediary +25
Shell final beneficiary +20
High clustering coefficient (>0.5) +10
High burst score (>0.7) +15
High uniformity score (>0.8) +10
High tx velocity (>10/hr) +10
  • Scores capped at 100, floored at 0
  • Rounded to 2 decimal places

False Positive Control β€” Merchant Dampening

High-volume legitimate merchants (e.g. payment processors) can exhibit fan-out patterns without being money mules. The dampening rule fires when:

distributor_flag = True
AND time_span_hours > 720   # active > 30 days
AND amount_variance > median_variance   # diverse transaction sizes
AND unique_receivers > 50   # genuinely broad customer base

Effect: multiply raw score Γ— 0.70 (βˆ’30% reduction) and add "merchant_dampening_applied" to detected_patterns for auditability.


Complexity Analysis

Operation Complexity
Graph construction O(n)
Cycle detection O(V Γ— d^5)
Smurfing detection O(n log n)
Shell detection O(V Γ— d^8) with pruning
Feature extraction O(n + E)
Risk scoring O(A) β€” A = accounts
Total ≀ O(n log n) practical

Designed to handle 10,000 transactions in ≀ 30 seconds.


JSON Output Format

{
  "suspicious_accounts": [
    {
      "account_id": "ACC_F001",
      "suspicion_score": 87.50,
      "detected_patterns": ["cycle_length_3", "high_velocity"],
      "ring_id": "RING_001"
    }
  ],
  "fraud_rings": [
    {
      "ring_id": "RING_001",
      "member_accounts": ["ACC_F001", "ACC_F002", "ACC_F003"],
      "pattern_type": "cycle",
      "risk_score": 87.50
    }
  ],
  "summary": {
    "total_accounts_analyzed": 500,
    "suspicious_accounts_flagged": 15,
    "fraud_rings_detected": 4,
    "processing_time_seconds": 2.30
  }
}

Installation Guide

Prerequisites

  • Python 3.11+
  • Node.js 18+

Backend

# From project root
pip install -r requirements.txt

# Run development server
uvicorn backend.main:app --reload --port 8000

Backend available at http://localhost:8000
Swagger UI at http://localhost:8000/docs

Frontend

cd frontend
npm install
npm start

Frontend available at http://localhost:3000

The React dev server proxies /graph-data and /analyze to localhost:8000.


Usage

  1. Generate or prepare a CSV with columns: transaction_id, sender_id, receiver_id, amount, timestamp

  2. Generate the included sample:

    python generate_sample.py
    # β†’ sample_transactions.csv (500 rows with embedded fraud patterns)
  3. Open the web app, upload the CSV, click Analyse Transactions.

  4. Explore:

    • Graph: red nodes = high risk, purple border = in a ring
    • Click any node to see its scores and patterns
    • Fraud Rings table: expand rows to see all member accounts
    • Download JSON button: exports the full detection report

API Endpoints

Method Path Description
GET /health Liveness check
POST /analyze Full analysis β†’ JSON report
POST /graph-data Full analysis + Cytoscape elements

Both POST endpoints accept multipart/form-data with a file field.


Deployment (Render - Free Tier)

Backend (Web Service)

  1. Push to GitHub
  2. New Web Service on render.com
  3. Root directory: backend
  4. Build: pip install -r requirements.txt
  5. Start: uvicorn main:app --host 0.0.0.0 --port $PORT

Frontend (Vercel or Render Static Site)

Option A: Vercel (Recommended for frontend)

  1. Go to vercel.com
  2. Import your GitHub repository
  3. Root directory: frontend
  4. Env var: VITE_API_URL=https://mm-detection.onrender.com
  5. Deploy! See VERCEL.md for details.

Option B: Render Static Site

  1. New Static Site on Render
  2. Root directory: frontend
  3. Build: npm install && npm run build
  4. Publish: frontend/dist
  5. Env var: VITE_API_URL=https://mm-detection.onrender.com

No credit card required! See DEPLOYMENT.md or VERCEL.md for detailed instructions.


Folder Structure

MM_Detection/
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ main.py                  # FastAPI app
β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”œβ”€β”€ graph/
β”‚   β”‚   └── builder.py           # TransactionGraph (DiGraph + lookups)
β”‚   β”œβ”€β”€ detection/
β”‚   β”‚   β”œβ”€β”€ cycle_detector.py    # DFS cycle detection
β”‚   β”‚   β”œβ”€β”€ smurf_detector.py    # Sliding-window smurfing
β”‚   β”‚   └── shell_detector.py    # Layered shell chains
β”‚   β”œβ”€β”€ scoring/
β”‚   β”‚   β”œβ”€β”€ feature_extractor.py # Per-account feature computation
β”‚   β”‚   └── risk_scorer.py       # Deterministic weighted scoring
β”‚   └── utils/
β”‚       β”œβ”€β”€ validator.py         # CSV schema validation
β”‚       └── aggregator.py        # Ring merging + risk aggregation
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ package.json
β”‚   └── src/
β”‚       β”œβ”€β”€ App.js
β”‚       β”œβ”€β”€ index.js
β”‚       β”œβ”€β”€ index.css
β”‚       └── components/
β”‚           β”œβ”€β”€ Upload.js        # Drag-and-drop CSV upload
β”‚           β”œβ”€β”€ GraphView.js     # Cytoscape.js graph
β”‚           β”œβ”€β”€ RingTable.js     # Fraud ring summary
β”‚           └── SuspiciousAccounts.js
β”œβ”€β”€ generate_sample.py           # Sample data generator
β”œβ”€β”€ requirements.txt             # Root-level (for Render)
β”œβ”€β”€ Procfile                     # Heroku/Railway start command
β”œβ”€β”€ render.yaml                  # Render deployment config
└── README.md

Known Limitations

  1. Cycle detection depth: capped at 5 hops. Deeper laundering chains are not detected (by design β€” hackathon constraint). Can be raised via MAX_CYCLE_LEN.

  2. Smurfing threshold: 10 unique counterparties. Adjust FAN_THRESHOLD in smurf_detector.py for different regulatory contexts.

  3. Shell threshold: ≀3 total transactions classifies an account as a shell. May cause false positives for genuinely new accounts.

  4. Graph layout: Cytoscape cola layout can be slow for >1,000 nodes. For very large graphs the fallback cose layout is used.

  5. No persistence: Results are not stored; each upload is a fresh analysis session.

  6. CSV size: Tested up to 10,000 transactions. Beyond this, performance is not guaranteed within 30 seconds.


Team / Hackathon

RIFT 2026 Β· Money Muling Detection Challenge Β· Graph Theory Track
Submission date: February 2026

About

RIFT'26 : AML (Anti-Money Laundering) graph intelligence engine that detects money mule networks in financial transaction data using purely deterministic, explainable graph algorithms

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •