Entimema

Automating Roll Rate & Migration Analysis: From R Transition Matrices to an AI Collections Analyst

Entimema
Contents

A risk analyst can calculate a transition matrix in R quickly. The recurring work is deciding which cells changed, whether cure is weakening, where deterioration persists, which segments and exposures explain it, and which cases deserve collections attention.

The matrix is automated. The investigation often is not. A transition matrix describes how risk moves; a useful collections system determines which movements matter and where intervention has the greatest potential value.

ENGINEERING

How do we operationalise it?

This build calculates, monitors and investigates transitions repeatedly at portfolio scale without duplicating the methodology article.

All definitions, code, data and results below are original, entirely hypothetical Entimema examples. They do not reproduce a bank's policy, data, thresholds, rules or procedures.

Comparable snapshots create observable migration

A hypothetical input uses account_id, customer_id, observation_date, dpd, state, ead, product, vintage, risk_grade, payment_amount and collection_status. Exact schemas vary; stable identity, observation dates, state, exposure and meaningful segmentation do not.

Sᵢ,ₜ   →   Sᵢ,ₜ₊₁
Account state at consecutive observations

Frequency must be consistent: a monthly transition is not comparable with a weekly one. The illustrative ordered states are S₀ Current, S₁ 1–30 DPD, S₂ 31–60 DPD, S₃ 61–90 DPD and Sᴰ Default. They are examples, not universal policy.

library(dplyr)

# Hypothetical buckets: replace only through controlled methodology.
portfolio <- portfolio %>%
  mutate(state = case_when(
    dpd == 0 ~ "Current", dpd <= 30 ~ "1-30",
    dpd <= 60 ~ "31-60", dpd <= 90 ~ "61-90",
    TRUE ~ "Default"
  ))

transitions <- current_snapshot %>%
  select(account_id, state_t = state, ead_t = ead) %>%
  inner_join(next_snapshot %>%
    select(account_id, state_t1 = state), by = "account_id")

The inner join is the analytical pair, not the reconciliation. New accounts, closed accounts and missing observations belong in explicit exception populations with counts and EAD; they must not silently disappear.

The transition matrix is the deterministic foundation

Nᵢⱼ = N(Sₜ=i, Sₜ₊₁=j)
pᵢⱼ = Nᵢⱼ / ΣⱼNᵢⱼ   ;   Σⱼpᵢⱼ = 1
Transition count and row probability
transition_counts <- transitions %>%
  count(state_t, state_t1, name = "accounts")

transition_matrix <- transition_counts %>%
  group_by(state_t) %>%
  mutate(transition_probability = accounts / sum(accounts)) %>%
  ungroup()

Counts expose workload but scale with portfolio size. Row probabilities describe the destination distribution conditional on each starting state. Production checks should reconcile every row to approximately 100%, subject only to rounding.

Illustrative monthly transition probabilities
From / ToCurrent1–3031–6061–90Default
Current 91% 6% 2% 0.5% 0.5%
1–30 36% 42% 15% 5% 2%
31–60 12% 18% 41% 24% 5%
61–90 5% 8% 14% 43% 30%
Default 2% 1% 1% 3% 93%
Every row sums to 100%. Arrows and symbols distinguish improvement, same state, deterioration and default without relying on colour.

Roll forward, roll back and cure are distinct

Under this ordered example, Sₜ₊₁ > Sₜ is roll forward: 1–30 → 31–60 is 15%, while 31–60 → 61–90 is 24%. Their incidence and economics differ. Sₜ₊₁ < Sₜ is roll back: 31–60 → 1–30 is 18%, while 1–30 → Current is 36%.

A roll back is not automatically a formal cure. One controlled hypothetical cure measure could require exit from delinquency and remaining Current for two subsequent observations. Sustained improvement, eligibility and any additional methodology must enter the engine as versioned configuration—not be inferred from one cell.

Baseline, persistence and velocity turn a matrix into monitoring

Deviationᵢⱼ,ₜ = pᵢⱼ,ₜ − Baselineᵢⱼ
Transition deviation
transition_diagnostics <- current_rates %>%
  left_join(historical_baseline,
    by = c("state_t", "state_t1")) %>%
  mutate(deviation = transition_probability - baseline_probability)

The baseline might be a selected historical median or another approved reference. It is controlled context, not permanent truth. Rising Current → 1–30, 1–30 → 31–60 and 31–60 → 61–90 alongside falling 1–30 → Current is more informative than one isolated cell: entry, progression and weakening improvement reinforce one another.

Persistenceᵢⱼ,ₜ = Σᵗₖ₌ₜ₋ₕ I(Deviationᵢⱼ,ₖ > c)
Velocityᵢⱼ,ₜ = pᵢⱼ,ₜ − pᵢⱼ,ₜ₋₁
Persistence and transition velocity

The threshold c and horizon are not universal. One abnormal month may be noise; repeated deviation increases confidence that a change may be structural. A transition can be worse than baseline, continuing to worsen, or both.

ENTIMEMA FRAMEWORKThe Migration DiagnosticFour separate dimensions lead to a controlled investigation, rather than a single unexplained alert.
  1. Direction
  2. Magnitude
  3. Persistence
  4. Materiality
  5. Investigation

Borrower incidence and exposure economics tell different stories

pᴬᶜᶜᵒᵘⁿᵗˢᵢⱼ = Nᵢⱼ / Nᵢ
pᴱᴬᴰᵢⱼ = Σₖ∈ᵢ→ⱼ EADₖ / Σₖ∈ᵢ EADₖ
Account- and EAD-weighted migration

Account weighting gives each account equal influence and supports behavioural incidence, borrower counts and workload. EAD weighting asks what share of starting-state exposure migrated and can reveal concentration in a few large accounts.

ead_transitions <- transitions %>%
  group_by(state_t, state_t1) %>%
  summarise(transition_ead = sum(ead_t, na.rm = TRUE), .groups = "drop") %>%
  group_by(state_t) %>%
  mutate(ead_transition_rate = transition_ead / sum(transition_ead)) %>%
  ungroup()

The denominator is total observed ead_t in the starting-state row. In a hypothetical 31–60 → 61–90 transition, an 18% account rate and 31% EAD rate mean relatively fewer accounts deteriorated but carried disproportionately large exposure—materially raising investigation priority.

Controlled drill-down isolates where migration changed

The engine can compare product, vintage, risk grade, acquisition channel and relevant customer segment. Dimensions should be approved and analytically meaningful; unconstrained slicing creates multiple-comparison noise and fragile stories.

PortfolioTransitionProductVintageRisk gradeExposure

If the overall 31–60 → 61–90 rate worsens, a vintage breakdown may show concentration in the hypothetical 2026-03 cohort. Product analysis may show Pᵢⱼᴾʳᵒᵈᵘᶜᵗ A ≠ Pᵢⱼᴾʳᵒᵈᵘᶜᵗ B. The Agent can then distinguish a portfolio-wide change from a Product B cohort concentration.

MIGRATION ANALYSIS

Through which states?

Cohort deterioration + state migration = richer portfolio diagnosis.

Move from an R script to a reusable migration engine

R / DETERMINISTIC CALCULATIONExport snapshotsRun RBuild transition matrixCompare month
MANUAL INVESTIGATION & PRIORITISATIONIdentify worsening cellFilter segmentCheck EADIdentify accountsPrepare collections analysisReport
Calculation may be automated while comparison, drill-down and prioritisation remain manual.
assign_state()                    pair_snapshots()
calculate_transition_matrix()     calculate_roll_rates()
calculate_cure_rates()            compare_to_baseline()
calculate_persistence()           compare_account_vs_ead()
analyse_segment()                 rank_deteriorating_transitions()

These are conceptual interfaces, not claims of existing software. A structured output might be:

transition: 31-60 -> 61-90
current_rate: 0.24        baseline_rate: 0.16
deviation: +0.08          persistence_periods: 3
ead_affected: 18.4m       largest_segment: Product B

Place an AI Collections Analyst above deterministic evidence

The Agent does not calculate probabilities from prose. It asks: what changed, where, for how long, how much exposure is affected, which segments or borrowers explain it, and which cases deserve attention first?

Separation of calculation and investigation
Migration EngineAI Collections Analyst
Assigns statesInterprets state movement
Calculates transitions and roll ratesExplains deterioration
Calculates controlled cureInvestigates weakening cure
Measures persistence and EAD impactSynthesises material evidence
Returns structured evidenceProduces analyst-ready context and priorities
get_transition_matrix()
compare_transition_to_baseline()
get_roll_forward_changes()       get_cure_rate_changes()
compare_account_vs_ead()         breakdown_transition_by_segment()
get_accounts_in_transition()     rank_collection_priorities()
AgentToolDeterministic resultAgent interpretationAnalyst review

Never: Prompt → LLM-invented transition matrix.

Why has the 31–60 DPD portfolio deteriorated this month?

The Agent queries the matrix, baseline, persistence, account/EAD movement, product and vintage breakdowns, then the largest exposures. It returns evidence, not unsupported causality:

HYPOTHETICAL DIAGNOSTIC / 31–60 → 61–90
Current / baseline
24% / 16%
Deviation / persistence
+8 pp / 3 periods
EAD-weighted transition
31%
EAD affected
18.4m
Primary concentration
Product B / vintage 2026-03
Interpretation
Concentrated, not portfolio-wide
Next investigation
Underwriting and collections behaviour
Causality
Not established

Current state and expected trajectory are different risk dimensions

Two borrowers can both be 30 DPD. Borrower A may have a high estimated probability of cure; Borrower B a high estimated probability of further deterioration. Therefore:

CurrentStateᴬ = CurrentStateᴮ   ⇏   ExpectedTrajectoryᴬ = ExpectedTrajectoryᴮ
State does not determine trajectory

This is the bridge from portfolio migration monitoring to collections prioritisation. The same delinquency queue can contain materially different forward risk and potential value from intervention.

Priorityᵢ = f(CurrentStateᵢ, ForwardRiskᵢ, EADᵢ, PDᵢ, Persistenceᵢ)
Conceptual collections priority

Current state

Observed delinquency position and operational status.

Forward risk

Controlled estimate of further adverse migration, not an LLM guess.

EAD

Exposure potentially affected and its concentration.

PD

Approved risk estimate used with its definition and horizon.

Persistence

Whether adverse behaviour or signals repeat across observations.

Priority

A governed ranking for investigation—not an automatic customer treatment decision.

No universal priority formula is imposed. Policy must define eligibility, weights, constraints, capacity and human authority. Forward migration risk may be estimated by an approved model or segment transition evidence; its version, horizon and validation status must remain visible.

Controls make assistance operationally credible

  • Data reconciliation: account and EAD totals, duplicates, missing snapshots, new and closed populations.
  • Methodology control: version state order, snapshot frequency, eligibility, cure, baseline, thresholds and weighting.
  • Calculation tests: non-negative counts, complete destinations and probability rows reconciling to one.
  • Lineage: retain snapshot, code, configuration, engine and tool-call versions behind every result.
  • Access: account-level tools expose only authorised fields and log every query.
  • Human authority: the Agent proposes priorities and investigation paths; analysts approve interpretation and collections action.

Backtest alerts: did persistent deviations precede later adverse outcomes, how much lead time existed, and how many false investigations were created? Monitor baseline drift and challenger configurations without optimising blindly to historical noise.

The resolve is recurring portfolio and collections intelligence

The finished path is Account snapshots → state assignment → transition pairing → matrix → baseline → deviation → persistence → exposure materiality → segment drill-down → collections priority → AI investigation → analyst action.

Methodology → R implementation → deterministic analytical engine → AI-assisted workflow. R preserves the arithmetic. The engine standardises evidence. The Agent investigates controlled outputs. The analyst owns decisions and intervention.