Collections optimisation with ML means scoring each delinquent account on two separate questions: how likely it is to self-cure or worsen if you do nothing, and how much a given contact action would change that. You then spend finite agent hours where the action actually moves the outcome. This is treatment selection under conduct constraints, and it behaves nothing like a louder dialer.
Most collections operations still work a queue sorted by days past due and balance. That ordering is intuitive and mostly wrong. The account thirty days down with a strong repayment history and a bounced direct debit will very likely cure on its own; a call there spends an agent hour to change nothing. The account with a slow drift across three cycles and a shrinking payment ratio is where the same hour earns its keep. Sorting by delinquency depth confuses how bad an account looks with how much you can do about it.
Separate the risk model from the treatment model
The first model answers a counterfactual: if this account receives no contact this cycle, what is the probability it rolls from its current bucket to the next one. This is a roll-rate or self-cure model, trained on accounts that were genuinely left alone or lightly touched, so the label is not contaminated by the collections activity you are trying to evaluate.
The second model is the one that actually drives the queue. For each available action, whether an SMS, a soft reminder call, a hardship-outreach call, or an offer of a payment plan, it estimates the change in roll probability that action produces. That uplift is the quantity worth ranking on. An account can be high-risk and untreatable, in which case no contact strategy rescues it and the cost belongs in provisioning rather than the agent’s day. Another can be low-risk but highly treatable, where a single well-timed message keeps it current.
Keeping the two models apart matters for a practical reason. When someone asks why an account sits high in the queue, you can answer with two legible numbers rather than one blended score nobody can interrogate. It also lets you retrain them on different cadences. Roll behaviour shifts slowly; treatment response drifts faster as channels saturate and customers start ignoring the third SMS in a week.
Point-in-time features or the model learns the future
Collections data is unusually good at leaking. The delinquency ledger is a moving object: payments post late, statuses get reversed when an account cures, and hardship flags are backfilled once a case is opened. If you build training features from the current-state table, you hand the model information that did not exist at the decision moment. The account shows a hardship arrangement because it defaulted later; the model reads the arrangement as a predictor and reports an accuracy it will never reproduce in production.
The fix is to reconstruct every feature as of the decision timestamp from an append-only event log, so a snapshot contains only what was knowable then. Concretely:
- Rebuild payment ratios, arrears balance, and bucket from ledger entries dated on or before the score date, never from the reconciled end-of-cycle figure.
- Treat cure and forbearance flags as events with their own timestamps, and exclude any that were set after the snapshot.
- Resolve the account to a customer across products before aggregating, so exposure and prior contact history are complete rather than split across systems, and so entity resolution does not itself pull in a future merge.
- Hold out an eval set drawn from a later time window than training, not a random split, because a random split lets near-duplicate cycles of the same account sit on both sides.
A feature store that serves the same point-in-time logic to training and to the live scorer is the cleanest way to stop the offline and online definitions from drifting apart. When they diverge, the model performs in the notebook and disappoints in the queue, and it takes weeks to work out why.
Optimise under constraints, and keep the audit trail
Ranking by uplift gives you a priority order. It does not give you a compliant strategy on its own, because the action that maximises expected recovery is sometimes an action you are not permitted to take. Affordability rules, forbearance obligations, contact-frequency caps, and vulnerability protections are not soft preferences the optimiser can trade away against recovery value. They belong in the model as hard constraints.
We tend to structure it as a constrained assignment: maximise expected uplift across the book subject to an agent-capacity limit, a per-customer contact cap, and a rule layer that removes disallowed actions before the optimiser ever sees them. A customer flagged as being in financial difficulty does not get routed to a pressure script no matter how high the recovery uplift; the eligible action set for that account is narrowed first, then ranked. The conduct rulebook decides what is allowed. The model only orders what remains.
Two things keep this defensible over time:
- A written action log for every contact: the features, both scores, the eligible action set, the action chosen, and the outcome. When a regulator or an internal reviewer asks why a specific customer was called, the answer is a record, not a reconstruction.
- Monitoring for conduct drift, not just model accuracy. Track contact intensity, offer mix, and cure rates broken down by protected characteristics, and alert when the distribution moves. A model can hold its overall performance while quietly concentrating pressure on one group as the population shifts underneath it.
None of this needs to be fully autonomous to pay off. Straight-through handling suits the easy tails: the near-certain self-cures that need one automated reminder, and the accounts where every eligible action scores near zero and the file should route to specialist hardship handling rather than a standard dialer. The contested middle, where uplift is real but the right treatment is a judgement call, is exactly where you want an experienced collector spending the hour the model just freed up.
FAQ
Should the roll-rate model and the treatment model be one model or two?
Two. One estimates the probability an account rolls to the next delinquency bucket if left alone, the other estimates how each contact action changes that probability. Collapsing them hides the fact that a high-risk account and a treatable account are not the same thing.
How do you keep collections optimisation inside conduct rules?
Encode the affordability and forbearance rules as hard constraints the optimiser cannot violate, log every action with the features and score that produced it, and monitor contact intensity and outcomes by protected group. The model ranks who to work; the rulebook still decides what you are allowed to do.
What is the biggest source of leakage in a delinquency model?
Payment and status fields that get backfilled after a cure. If your training snapshot reflects the account as it looks today rather than as it looked at the decision moment, the model learns from the future. Reconstruct features from a point-in-time ledger, not the current-state table.