Compute the Repayment Schedule and Verify the Interest
Goal
You calculate loan repayment schedules directly in two methods, and confirm by hand where the numbers of bank deposits and lending come from — deposit interest and tax, late interest, asset quality classification, and provisions.
Why it matters
Half of a bank system's requirements is "why does this number come out like this?" With equal principal-and-interest repayment, the monthly payment is the same, and with equal-principal repayment, the monthly principal repaid is the same. It is the same loan, yet total interest differs, the first month's payment differs, and the principal remaining at early repayment differs. If you do not know this difference, you cannot tell a bug on the repayment schedule screen from normal behavior.
Interest calculation has conventions. The monthly rate is the annual rate divided by 12, deposit interest counts days and divides by 365, and at which stage and how amounts below one won are dropped is set differently by each company. This lab fixes those conventions as this lab's rules — in practice, those rules are in your company's product definition document. If the rules differ, the numbers are off by 1 won, and that 1 won is caught in ledger reconciliation.
Being overdue is both an interest matter and a classification matter. Depending on how many days late, it is divided into normal, precautionary, and substandard, and that classification sets the provisions the bank must build up. Provisions are reflected immediately in profit and loss, so a single classification changes that quarter's results.
Rules of this lab
- Monthly rate = annual rate ÷ 12 (used as is, without rounding). Each month's interest = previous balance × monthly rate, rounded to the nearest won.
- The monthly payment for equal principal-and-interest is
P × r ÷ (1 − (1 + r)^−n)rounded to the nearest won, and the last month repays all the remaining principal. - The monthly principal for equal principal is the quotient (rounded down) of
P ÷ n, and the remainder that does not divide evenly is added to the last month. - Deposit interest = principal × annual rate × days ÷ 365, truncated below one won. Days is the number of days from the subscription date to the maturity date. Income tax is 14% of the interest and local income tax is 10% of the income tax, both truncated below 10 won.
- Late interest = the contractual payment of the overdue installment × (contract rate + 3.0)% × days overdue ÷ 365, truncated below one won. The reference date is
2026-08-31, and the days overdue for an unpaid installment is the number of days from the payment date to the reference date. - The quality classification, based on the oldest unpaid installment, is
NORMALfor 0–29 days,PRECAUTIONARYfor 30–89 days, andSUBSTANDARDfor 90 days or more. The provision ratios are 1.0%, 10.0%, and 20.0% respectively, and provision = balance × ratio, truncated below one won.
Steps
- Save the generator in the example on the right as
/root/bank/make_loans.pyand run it withpython3 make_loans.py.loans.csv(6 loans),payments.csv(32 installments of payments), anddeposits.csv(3 deposits) are created. - Write the equal principal-and-interest repayment schedule for
L001in/root/bank/schedule_L001.csv, 360 lines with the headern,payment,interest,principal,balance. - Write the equal-principal repayment schedule for
L002in/root/bank/schedule_L002.csv, 36 lines with the same header. - Calculate
L003in both methods and write six lines in/root/bank/compare_L003.txt:annuity_payment=,annuity_total_interest=,equal_first_payment=,equal_last_payment=,equal_total_interest=, andinterest_diff=.interest_diffis the equal principal-and-interest total interest minus the equal-principal total interest. - Write the maturity interest and tax for the 3 deposits in
/root/bank/deposit_interest.csvwith the headerdep_id,principal,days,interest,income_tax,local_tax,net.netis the principal plus the interest minus the two taxes. - Write the installments in
payments.csvthat were paid late or not yet paid in/root/bank/overdue.csvwith the headerloan_id,seq,due_date,days_late,late_interest, and write four lines in/root/bank/overdue.txt:overdue_rows=,late_interest_total=,max_days_late=, andmax_loan=. - Write all 6 loans in
/root/bank/provision.csvwith the headerloan_id,days_overdue,class,outstanding,rate_pct,provision, and write three lines in/root/bank/provision.txt:total_outstanding=,total_provision=, andsubstandard_count=.outstandingisoutstanding_20260831fromloans.csv. - In
/root/bank/loan_report.md, write a report in four sections:## Repayment comparison,## Deposit interest and tax,## Overdue and classification, and## What the system must keep.
Notes
- Calculating in Python is faster. Read with the
csvmodule and subtract dates withdatetime.date.fromisoformatto get the days. - Python's
round()sends .5 toward the even side. For rounding below one won useint(x + 0.5), and for truncation useint(x). - Common mistake 1: starting after rounding the monthly rate at the fourth decimal place. If you cut
L001's 4.50 ÷ 12 = 0.00375 to four decimal places, the interest is off by 15,000 won from the very first month, and writing it as 0.0037 leaves the 360-month total interest 3,843,336 won short. CuttingL002's 7.50 ÷ 12 = 0.00625 to four decimal places also puts the interest off by 1,500 won from the first month. - Common mistake 2: counting the overdue days from today's date instead of the reference date. The grader uses
2026-08-31as the reference. - Common mistake 3: applying tax once on the interest total. Calculate and truncate separately for each deposit.
Create the loan and deposit data
Save the generator in the example on the right as /root/bank/make_loans.py and run it with python3 make_loans.py. loans.csv (6 loans), payments.csv (32 installments of payments), and deposits.csv (3 deposits) are created.
Save the generator in the lab instructions as /root/bank/make_loans.py and run it with python3. If you edit it by hand, all the numbers in the later steps go off.
Produce the equal principal-and-interest schedule
Write the equal principal-and-interest repayment schedule for L001 in /root/bank/schedule_L001.csv, 360 lines with the header n,payment,interest,principal,balance.
Monthly rate r = 4.50 ÷ 100 ÷ 12. Payment = P × r ÷ (1 − (1 + r)^−360), rounded to the nearest won. Each month's interest = previous balance × r, rounded; principal = payment − interest; in the last month, all of the remaining balance. Round with int(x + 0.5).
Produce the equal-principal schedule
Write the equal-principal repayment schedule for L002 in /root/bank/schedule_L002.csv, 36 lines with the same header.
Monthly principal = 30,000,000 // 36 (rounded down). Each month's interest = previous balance × (7.50 ÷ 100 ÷ 12), rounded. Payment = interest + principal. The last month's principal is all of the remaining balance, so the remainder of 12 won is added there.
Compare the same loan in two methods
Calculate L003 in both methods and write six lines in /root/bank/compare_L003.txt: annuity_payment=, annuity_total_interest=, equal_first_payment=, equal_last_payment=, equal_total_interest=, and interest_diff=. interest_diff is the equal principal-and-interest total interest minus the equal-principal total interest.
Apply the calculators from steps 2 and 3 as they are to L003 (50,000,000 · 3.75% · 36 months) and sum the interest column of each schedule. The equal principal-and-interest side is larger.
Calculate deposit interest and withholding tax
Write the maturity interest and tax for the 3 deposits in /root/bank/deposit_interest.csv with the header dep_id,principal,days,interest,income_tax,local_tax,net. net is the principal plus the interest minus the two taxes.
days = maturity date − subscription date (subtracting datetime.date values gives .days). interest = int(P × rate/100 × days/365). income_tax = int(interest × 0.14) truncated below 10 won, local_tax = 10% of that, truncated below 10 won.
Calculate overdue installments and late interest
Write the installments in payments.csv that were paid late or not yet paid in /root/bank/overdue.csv with the header loan_id,seq,due_date,days_late,late_interest, and write four lines in /root/bank/overdue.txt: overdue_rows=, late_interest_total=, max_days_late=, and max_loan=.
If paid_date exists, the overdue days are paid_date − due_date; if not, 2026-08-31 − due_date. Zero or less is not overdue. Late interest = int(amount_due × (rate + 3.0)/100 × days/365). Take the contract rate per loan from loans.csv.
Work out the quality classification and provisions
Write all 6 loans in /root/bank/provision.csv with the header loan_id,days_overdue,class,outstanding,rate_pct,provision, and write three lines in /root/bank/provision.txt: total_outstanding=, total_provision=, and substandard_count=. outstanding is outstanding_20260831 from loans.csv.
For each loan, find the earliest due_date among the installments whose paid_date is empty and subtract it from 2026-08-31. If there is no unpaid installment, it is 0 days. 0–29 NORMAL, 30–89 PRECAUTIONARY, 90 or more SUBSTANDARD. Provision = int(outstanding × ratio/100).
Write the deposits and lending verification report
In /root/bank/loan_report.md, write a report in four sections: ## Repayment comparison, ## Deposit interest and tax, ## Overdue and classification, and ## What the system must keep.
Use one line starting with ## for each of the four section titles in the task (the English titles in backticks, or titles with the same meaning in Korean, Japanese, or Chinese). In the repayment comparison, write L003's total interest difference (interest_diff); in the deposit section, the tax rates; and in the overdue section, every loan number that fell to SUBSTANDARD and the provision total, all as numbers.