Bucketwise Join waitlist

Learn / Walkthrough

DPD and buckets in practice: a worked example with ChatGPT and SQL

This guide follows one analysis from start to finish: DPD and bucket for every loan on 30 September 2026. You fill in the Bucketwise form, paste the prompt into ChatGPT, run the SQL it writes, check the result and put it in a short report. The screens use a sample loan extract, not a real portfolio. The tool and the prompt work the same way on your own tables.

What you are building

One row per loan, with five fields: the number of unpaid instalments, the overdue amount, the oldest unpaid due date, DPD and the bucket. You need two tables to get there. Tap any screenshot to open it full size.

TableOne row isColumns used
repay_scheduleOne instalment that falls dueloan_id, due_dt, due_amt
repay_txnOne payment received, bounced or reversedloan_id, pay_dt, pay_amt, txn_status

Your tables will have other names. You type yours into the form in the next step.

Before you start: check the extract

The SQL in this guide assumes that the data is clean. Check three things on your own extract before you run anything:

The extract used in this guide has been through these checks. If one of them fails on your data, fix the extract first. A duplicated instalment or a double-posted payment changes DPD and overdue amount for that loan, and the query will not warn you.

Step 1: Fill in the form

Open the DPD and buckets tool. The top of the form asks for the names of your tables and columns. The rest asks for the choices that change the answer.

The DPD and buckets form filled in with table names, payment status rule, as-of date, grace days and payment rules
The form. Table names first, then the definitions.

These are definitions, not table names. They are the choices a different lender would make differently, so the tool asks for them before the AI writes any code.

Step 2: Copy the prompt

Press Copy prompt. The full prompt is 29 lines and goes to your clipboard. The preview shows how it starts.

The start of the generated prompt with the role and the rules
The prompt starts with the rules: table and column names only, no customer data.

The prompt gives the AI your names and your definitions. It tells the AI to state its assumptions, write the code and ask at most two questions, and only if it cannot proceed without the answer. Use only an AI tool that your institution has approved.

Step 3: Paste it into ChatGPT

The prompt pasted into a new ChatGPT conversation
Paste the prompt into a new conversation.

ChatGPT started with its assumptions. Read them before you read the code. Each one is a decision, and you can change any of them.

ChatGPT listing nine assumptions including payment statuses, FIFO, early payments and part payments
Nine assumptions, in plain language.

Two are worth noticing. It treats a part-paid instalment as unpaid for the balance that remains, and it assumes the schedule has one row per loan per due date. That second assumption is exactly what the extract checks above confirm.

Then it wrote the query, in ten labelled steps with a comment on each. Copy it as it is.

The PostgreSQL query written by ChatGPT, shown in a code block
The query. Copy it from the code block.

Step 4: Run it in your SQL tool

Paste the query into the SQL tool you use for your own database and run it.

A SQL workbench with the query pasted and the cursor over the Run button
The query pasted into a SQL tool. Sample loan extract.

It returned one row per loan with an instalment due on or before 30 September: 5,988 rows on this extract.

The result grid with loan id, unpaid instalments, overdue amount, oldest unpaid due date, DPD and bucket
The result. Sample loan extract.

A loan with nothing overdue shows 0 unpaid instalments, an overdue amount of 0, no oldest unpaid date, DPD 0 and the bucket Current. Loan L000007 has two unpaid instalments, 26,772 overdue and an oldest unpaid due date of 20 August, so its DPD on 30 September is 41 and it sits in 31-60.

Step 5: Run the three checks ChatGPT gave you

The prompt asks for three validation queries. Run all three before you trust the result.

Check 1 counts payments by status. You should see SUCCESS, BOUNCED and REVERSAL and nothing unexpected, with reversals negative.

ChatGPT's first validation query, counting payments by status
The first check, as ChatGPT wrote it.
Result of the status check: SUCCESS, BOUNCED and REVERSAL with counts and amounts
Its result. Sample loan extract.

Check 2 looks for loans with two schedule rows for the same due date. It should return no rows.

ChatGPT's second validation query, looking for duplicate due dates
The second check.
The duplicate check returning 0 rows
Zero rows: no duplicate instalments. Sample loan extract.

Check 3 lists loans with no eligible payment at all. They should still appear in the main result, with all their dues unpaid.

ChatGPT's third validation query, listing loans with no eligible payments
The third check.
The loans with no payments: eight loans with their instalments due and total due amount
Eight loans with no payment. Sample loan extract.

On this extract, all three behaved as expected. The eight loans in Check 3 appear in the main result with every instalment unpaid.

Step 6: Check it yourself

The AI's checks test the logic it wrote. Add your own, because only you can compare against your own systems.

CheckWhat it should show
Row countEquals the number of loans with an instalment due by the as-of date. Here, 5,988.
ValuesNo negative DPD and no empty bucket.
Finance figureThe sum of the overdue amount agrees with your finance overdue figure within a small tolerance.
Ten loans by handPick ten loans across the buckets and trace each one to the schedule and the payments.

On this extract we also compared every loan against a separately calculated answer. DPD, bucket and overdue amount agreed on all 5,988 loans. On your own data, the ten-loan trace is how you get that comfort.

Step 7: Read the numbers and write it up

Group the result by bucket and put it on one page.

A one-page report with the bucket table, key figures and a benchmark note
A one-page summary built from the query result.

In this extract 5,290 loans are current, 428 are in 1-30, 50 in 31-60, 26 in 61-90 and 194 in 91+. That is 698 loans past due, 11.7% of the loans, with about 96.6 lakh overdue in total.

Be careful when you set the result beside a published figure. The Bucketwise benchmark for personal loans 90 or more days past due is 0.9% of balances (TransUnion CIBIL, Mar-26). This table counts loans, and its 91+ bucket includes loans past 179 days, so the two are directional at best. Compare only when the definition, the unit and the segment match.

Use it on your own tables

Try it on your own tables

The free tools give you the prompt, the checks and how to present the result. You enter table names only.

See the free tools

Frequently asked questions

Do I need to paste customer data into ChatGPT?

No. The prompt contains table and column names only, plus your definitions. Use an AI tool that your institution has approved, and check your information-security policy on schema names.

Will the AI ask me questions before it writes the query?

By default it states its assumptions and writes the code. It asks at most two questions, and only when something essential is missing. You correct any wrong assumption in one reply.

Can I use this with a database other than PostgreSQL?

Yes. The form has a database selector with PostgreSQL, MySQL, SQL Server, Oracle, BigQuery, Snowflake and Python with pandas, and the prompt asks for that syntax.

Which DPD rule does the tool use?

DPD is the as-of date minus the due date of the oldest instalment that is still unpaid after payments are allocated oldest due first, less any grace days you set. A loan with nothing overdue has DPD 0.

Keep reading