Method

Every number in the engine is computed from the bank's own monthly summaries. Nothing is a black box: each one fits in a sentence.

1. Definitions (exactly the judges')

ITypical monthly money inMedian of money_in
FTypical fixed costsMedian of household_bills + insurance + loan_payments
STypical monthly spendingMedian of money_out
BBufferMean of avg_daily_balance over the account's last 6 months
HHousehold billsMedian of household_bills (rent & utility shocks scale this)
PLoan paymentmonthly_payment if the loan is still running at end of 2025 (status C or D), else 0
buffer_left = B − one_off_costs
gap         = spending_after_shock − income_after_shock
if buffer_left <= 0:  runway = 0
elif gap <= 0:        runway = "no shortfall (120+)"
else:                 runway = min(buffer_left / gap, 120), rounded to 1 decimal

2. Verified, not hoped

A Python reference engine (pandas, the judges' definitions verbatim) and the in-browser TypeScript engine are compared on 36,000 cases: all 4,500 accounts × the brief's three example twists, a no-shock baseline and four random mixes of shocks. Zero mismatches to one decimal, including Python's round-half-to-even and the edge cases (14 accounts with no income, 77 with no spending, 23 with a negative buffer).