Metrics — the underwriting numbers and how they are defined
The formulas a lender underwrites on. Formulas are domain-standard (✅); the thresholds are conventions we adopt as defaults and mark ⚠️ VALIDATE, and every threshold is per-lender configurable (
src/domain/policy.py, overridable per tenant). Status keys: seeREADME.md. All amounts INR; “month” = calendar month over the covered period.
1. Income
| Metric | Definition | Code |
|---|---|---|
| Average monthly income | Total income credits over the period ÷ number of covered months. Income credits exclude self-transfers, loan disbursals, refunds, one-off windfalls (see ontology §4). | IncomeAnalysis.average_monthly_income |
| Regularity | regular (recurring, low variation), irregular, or single. | .regularity |
| Stability score (0-100) | 100 × (1 − CV) of monthly income, where CV = coefficient of variation (σ/μ). Lower variation → higher stability. | .stability_score |
| Trend | rising / stable / declining, comparing first vs second half of the period. | .trend |
Detection heuristics (✅ SME-reviewed 2026-06-18 · configurable): a recurring credit group is
treated as income if it is salary-hinted (taxonomy.INCOME_HINT), or appears in ≥ 60% of
covered months (income_min_month_fraction) with median ≥ ₹10,000 (income_min_median) and CV
within a class-specific cap — ≤ 0.40 general (income_max_cv), ≤ 0.60 for
business/professional receipts (income_business_max_cv), which are lumpier by nature. Regularity is
regular when monthly and the monthly-income CV ≤ 0.2 (income_regular_max_cv). Every threshold
is a policy.py field, overridable per tenant.
2. Balances
| Metric | Definition | Code |
|---|---|---|
| Average daily balance (ADB) | Mean of end-of-day balances across the period (carry-forward between postings). The truest liquidity measure. | BalanceAnalysis.average_daily_balance |
| Average monthly balance (AMB) | Mean of the monthly average balances. | .average_monthly_balance |
| Minimum balance | Lowest end-of-day balance and its date. | .min_balance |
| Median balance | Median end-of-day balance — robust to one-off spikes (SME F6). | .median_balance |
| Liquidity buffer ratio | Median month-end balance ÷ monthly income — often more telling than AMB (SME F6). | .liquidity_buffer_ratio |
| Negative-balance days | Count of days the balance was below zero. A liquidity-stress signal. | .negative_balance_days |
| Days below 10% of income | Days the balance ran below a tenth of monthly income — a predictive liquidity-stress metric (SME F6). | .days_below_tenth_income |
Note (multi-account): balances are per-account, never summed — a combined “balance” across accounts is misleading. Consolidation reports
balance_by_account(seeborrower-case.md).
3. Cash flow
| Metric | Definition |
|---|---|
| Monthly credits / debits / net | Sum of inflows, outflows, and their difference per month. |
| Surplus / deficit months | Months with net ≥ 0 vs < 0. |
| Inflow:outflow ratio | Total credits ÷ total debits. > 1 means accumulating. |
In consolidation, inter-account self-transfers are removed before these are computed, so a borrower shuffling money between their own accounts does not inflate turnover.
4. Obligations and FOIR (the capacity metric)
FOIR — Fixed Obligation to Income Ratio ✅ (standard) — the share of income already committed to fixed obligations. The core measure of repayment capacity.
FOIR = total_monthly_fixed_obligations / average_monthly_income| Term | Definition | Code |
|---|---|---|
| Total monthly obligations | Sum of recurring fixed obligations (see ontology §5 for which types count — lender policy). | ObligationAnalysis.total_monthly_obligations |
| FOIR | The ratio above, 0-1. | .foir |
| Estimated disposable income | average_monthly_income − total_monthly_obligations. | .estimated_disposable_income |
What counts as an obligation is lender policy (ontology §5), now implemented: EMIs always;
rent + insurance count by default; SIP/subscription/utility/tax are excluded by default; each is a
policy.counts_toward_foir toggle. An obligation that is detected but not counted is still reported
(with counts_toward_foir=false), so the borrower’s full recurring-debit picture is visible while
FOIR reflects only what the lender treats as a commitment.
FOIR thresholds (✅ SME-reviewed 2026-06-18 · configurable): the ceiling is income-band
dependent — lower-income borrowers have less residual disposable income and face tighter
tolerances; higher-income (esp. stable salaried) get slight flexibility. Defaults
(foir_bands_for_income in policy.py):
| Income band | Moderate (−28) | Heavy (−42) | Knockout (decline) |
|---|---|---|---|
| ≤ ₹25,000 | > 35% | > 40% | > 55% |
| ₹25,000–₹75,000 (standard) | > 35% | > 50% | > 60% |
| > ₹75,000 | > 35% | > 55% | > 65% |
Basis: SME review (cite in references.md); still lender-configurable per their
own credit policy.
5. Coverage & verification (data-trust metrics)
| Metric | Definition |
|---|---|
| Extraction confidence (0-100) | Share of rows that reconcile against the running balance. < 100 routes to human review. |
| Coverage months | Distinct calendar months with ≥ 1 transaction (coverage_months). Underwriting policy (SME): < 3 months → “insufficient data / refer” (manual review, can’t read low); 3–5 → underwrite with a reduced-confidence flag; ≥ 6 → full; ≥ 12 preferred. |
| Income recency | Days from the last qualifying income credit to the statement end. Beyond the inactive window (salaried 90 / self-employed 120) the historical average isn’t treated as current. |
| Consolidation confidence | How clean a multi-statement merge was (gaps, seam discontinuities, identity mismatch, low-confidence transfers). |
These gate trust: a report on unreconciled or thin data is labelled, never silently scored.
✅ SME-reviewed (2026-06-18, Round 4). The gate is now confidence-weighted (F2): reconcile ≥97.5% auto-scores, ≥90% routes to manual review, <90% fails — a handful of bad rows no longer fails a long statement, and a data-quality failure is kept separate from borrower risk.