← All work

RiskWise — Credit Risk Analysis

A credit-risk platform that scores customer default probability from card payment history, behind role-based access control.

  • Python
  • FastAPI
  • scikit-learn
  • Random Forest
  • MySQL
  • JWT
  • Vanilla JS

Screens

Prediction form and model output — default probability with a recommended action
Prediction form and model output — default probability with a recommended action
Per-customer risk assessment report, generated from real prediction history
Per-customer risk assessment report, generated from real prediction history
Automated alerts when a customer is scored high-risk
Automated alerts when a customer is scored high-risk
Role-based access with an admin approval gate on every new account
Role-based access with an admin approval gate on every new account
Account settings and the per-user audit trail
Account settings and the per-user audit trail
Transaction logging — the payment behaviour the model scores against
Transaction logging — the payment behaviour the model scores against

Problem

Deciding whether a card customer is likely to default is a judgement made repeatedly, on the same handful of signals, and made inconsistently when it is made by eye. The goal was to put a trained model behind that call and make its reasoning inspectable rather than leaving it as a number nobody can interrogate.

Role

Built the whole stack: data preprocessing and model training through to the FastAPI service, the MySQL schema, auth and role-based access control, and the frontend.

Key decisions

Google Sign-In sits behind an admin approval gate — an account exists only once an admin approves it, because self-service signup on a system holding customer credit data is a liability, not a convenience. The frontend is deliberately vanilla JS: the UI is forms and tables against a REST API, and a framework would have added a build step and a dependency tree without changing a single thing on screen.

Challenges

The honest difficulty was accuracy, not code. Default prediction on this data is heavily imbalanced — most customers do not default — so a model can score well on raw accuracy while being useless on the class that matters. Getting to 81.6% on held-out data meant treating the preprocessing and the choice of repayment-history features as the real work, and reading the model's feature importances rather than trusting a single headline number.

Outcome

81.6% test accuracy on held-out payment history, served live behind role-based access control.