LC-TEST-23 — Math Behind Loans

🌍 Why This Document Exists

Most people learn Python by:

  • sorting lists
  • reversing strings
  • solving toy problems

But banks don’t care about toys.

Banks care about:

  • money over time
  • interest dynamics
  • human financial decisions

This document teaches Python + Math + Real Banking Logic
so students can see their future mortgage before signing it.


🧠 Core Math Behind Loans (Very Important)

When you borrow money, you are solving this problem:

$$ \text{Total Payment} = \sum_{t=1}^{T} \left( \text{Principal}_t + \text{Interest}_t \right) $$

Where interest usually follows:

interest_t = remaining_principal_t_1 * r_t

Understanding this formula is more important than memorizing code.


🟢 Problem 1 — Fixed Rate Mortgage (Reality Check)

📌 Scenario

  • Condo price: 3.3 million THB
  • Fixed interest rate: 6.5% per year
  • Loan duration: 30 years
  • No down payment

Assume:

  • Interest is compounded monthly
  • Payments are equal every month (standard mortgage)

🧮 Mathematical Hint

Monthly interest rate:

$$ r = \frac{0.065}{12} $$

Number of payments:

$$ N = 30 \times 12 $$

Monthly payment formula:

$$ M = P \cdot \frac{r(1+r)^N}{(1+r)^N - 1} $$


🎯 Tasks

  1. Compute monthly payment
  2. Compute total money paid
  3. Compute total interest paid
✅ Solution (Python)
P = 3_300_000
annual_rate = 0.065
r = annual_rate / 12
N = 30 * 12

monthly_payment = P * (r * (1 + r)**N) / ((1 + r)**N - 1)
total_payment = monthly_payment * N
total_interest = total_payment - P

print("Monthly payment:", round(monthly_payment, 2))
print("Total paid:", round(total_payment, 2))
print("Total interest:", round(total_interest, 2))

💡 Concept Insight

  • You borrow 3.3M
  • You return almost double
  • Time is more expensive than interest rate

🟢 Problem 2 — Fixed Rate vs Floating Rate (Bank Knowledge)

Before coding, you must understand bank language.


🏦 Interest Types Explained (Human Language)

Fixed Rate

Interest rate is locked for a period or entire contract.

Example:

  • 7% per year
  • Fixed for 4 years
  • No surprise

Floating Rate

Interest rate moves with the bank’s cost

Usually written as:

$$ \text{Interest} = \text{MRR} - x $$


📘 Bank Reference Rates

MLR — Minimum Loan Rate

Large, high-quality customers (business loans)

MRR — Minimum Retail Rate

Retail customers (home loans, personal loans)

MOR — Minimum Overdraft Rate

Overdraft credit lines


📌 New Scenario (Realistic Mortgage)

  • Condo price: 3.3M
  • Loan term: 30 years
  • First 3 years: MRR = 2.2%
  • Remaining years: MRR = 3.3%
  • No down payment

🧮 Mathematical Hint

Interest changes at time ( t = 36 ) months:

$$ r_t = \begin{cases} \frac{0.022}{12}, & t \le 36
\frac{0.033}{12}, & t > 36 \end{cases} $$


🎯 Tasks

  1. Total money paid
  2. Total interest paid
  3. Interest paid per year
✅ Solution (Python)
P = 3_300_000
years = 30
months = years * 12

rates = [0.022] * 36 + [0.033] * (months - 36)

balance = P
total_interest = 0
yearly_interest = {}

monthly_payment = P * 0.005  # simplified assumption for teaching

for m, rate in enumerate(rates, start=1):
    r = rate / 12
    interest = balance * r
    principal = monthly_payment - interest
    balance -= principal

    total_interest += interest
    year = (m - 1) // 12 + 1
    yearly_interest[year] = yearly_interest.get(year, 0) + interest

print("Total interest:", round(total_interest, 2))
print("Remaining balance:", round(balance, 2))
print("Interest per year:", yearly_interest)

💡 Teaching Insight

  • Floating rate = uncertainty
  • Early years matter more than later years
  • Banks earn most interest at the beginning

🟢 Problem 3 — Add 10% Down Payment

📌 Scenario Change

  • Down payment: 10%
  • Loan amount:

$$ P = 3.3M \times 0.9 $$

Repeat Problem 2 with new principal.

✅ Solution (Python)
P = 3_300_000 * 0.9
# reuse previous logic

💡 Key Insight

  • Small down payment = huge interest savings
  • Leverage is expensive

🟢 Problem 4 — Aggressive Payoff in 3 Years (No Down Payment)

📌 Scenario

  • Loan: 3.3M
  • Finish payment in 3 years
  • Same interest as Problem 2

🧮 Hint

Shorter time means:

$$ \text{Interest} \propto \text{Time} $$

But monthly cash flow explodes.

✅ Solution (Python)
P = 3_300_000
months = 36
rate = 0.022 / 12

monthly_payment = P / months + (P * rate)

total_paid = monthly_payment * months
total_interest = total_paid - P

print(total_paid, total_interest)

💡 Life Lesson

  • Banks hate early payoff
  • Discipline beats interest

🟢 Problem 5 — Extreme Discipline: Pay Off in 2 Years

Same logic as Problem 4, but:

$$ T = 24 \text{ months} $$

✅ Solution (Python)
months = 24
rate = 0.022 / 12

monthly_payment = P / months + (P * rate)
total_paid = monthly_payment * months
total_interest = total_paid - P

print(total_paid, total_interest)

💡 Final Insight

  • Interest is the price of time
  • Python helps you see the truth before signing

🎓 Final Takeaway

If a student finishes this chapter, they can:

  • read bank contracts
  • simulate real mortgages
  • explain interest mathematically
  • write Python like a finance engineer

This is real-world algorithmic thinking.


🌍 Why This Chapter Exists

Most people ask:

“Which bank is cheaper?”

Engineers ask:

“Which bank minimizes expected financial pain under uncertainty?”

Banks price risk, not kindness.

This chapter teaches:

  • how to compare banks algorithmically
  • how to think in risk-adjusted terms
  • how Python exposes hidden costs humans overlook

🧠 Mental Model: What Is a Risk-Adjusted Decision?

A naive decision minimizes:

$$ \min ; \text{Total Payment} $$

A risk-aware decision minimizes:

$$ \min ; \mathbb{E}[\text{Cost}] + \lambda \cdot \text{Risk} $$

Where:

expected_cost = E_cost # Expected total payment risk = volatility # Or uncertainty / worst-case exposure lambda_ = risk_aversion_level # Human parameter for risk aversion


🏦 Problem Setup — Comparing Bank A / B / C

📌 Loan Assumptions (Same for All Banks)

  • Condo price: 3.3M THB
  • Loan term: 30 years
  • No down payment
  • Monthly payment system

🏦 Bank Profiles (Very Realistic)

🟢 Bank A — Safe & Predictable

  • Fixed rate: 3.0% for entire loan

🟡 Bank B — Promotional Trap

  • 2.0% for first 3 years
  • 4.0% afterward

🔴 Bank C — Floating & Uncertain

  • MRR = 2.0% → 5.0%
  • Random yearly fluctuation

🟢 Question 1 — Pure Cost Comparison

🎯 Task

Calculate:

  1. Total payment
  2. Total interest

for Bank A and Bank B

Ignore uncertainty for now.


🧮 Hint

Monthly payment:

$$ M = P \cdot \frac{r(1+r)^N}{(1+r)^N - 1} $$

✅ Solution (Python)
def mortgage_total(P, annual_rate, years):
    r = annual_rate / 12
    N = years * 12
    M = P * (r * (1 + r)**N) / ((1 + r)**N - 1)
    return M * N, M * N - P

P = 3_300_000

bank_A = mortgage_total(P, 0.03, 30)
bank_B_part1 = mortgage_total(P, 0.02, 30)

print("Bank A:", bank_A)
print("Bank B (naive):", bank_B_part1)

💡 Insight

  • Promotional rates lie if you don’t model the future
  • Banks love customers who stop calculating at year 3

🟢 Question 2 — Correctly Modeling Bank B (Piecewise Rates)

🎯 Task

Bank B:

  • 2% for 3 years
  • 4% for remaining 27 years

Compute real total interest.


🧮 Mathematical Hint

Interest rate is time-dependent:

$$ r_t = \begin{cases} 0.02 & t \le 3
0.04 & t > 3 \end{cases} $$

✅ Solution (Python)
P = 3_300_000
balance = P
years = 30
monthly_payment = P * 0.005  # simplified for teaching

rates = [0.02]*36 + [0.04]*(years*12 - 36)

total_interest = 0

for rate in rates:
    interest = balance * (rate / 12)
    principal = monthly_payment - interest
    balance -= principal
    total_interest += interest

print("Total interest Bank B:", round(total_interest, 2))

💡 Engineering Lesson

  • Time segmentation matters
  • Banks profit from human short-term thinking

🧠 Question 3 — Modeling Risk: Bank C (Floating Rate)

📌 Scenario

Bank C interest:

  • Starts at 2%
  • Every year randomly moves ±1%
  • Capped at 5%

🎯 Task

Simulate 1000 futures and compute:

  • Expected total interest
  • Worst 10% outcome (risk)

🧮 Hint (Monte Carlo Thinking)

$$ \mathbb{E}[X] \approx \frac{1}{N} \sum_{i=1}^N X_i $$

✅ Solution (Python)
import random

def simulate_bank_c(P, years, simulations=1000):
    results = []

    for _ in range(simulations):
        balance = P
        total_interest = 0
        rate = 0.02

        for _ in range(years * 12):
            if random.random() < 1/12:
                rate += random.choice([-0.01, 0.01])
                rate = min(max(rate, 0.02), 0.05)

            interest = balance * (rate / 12)
            balance -= (P / (years*12))
            total_interest += interest

        results.append(total_interest)

    results.sort()
    return sum(results)/len(results), results[int(0.9*len(results))]

expected, worst_10 = simulate_bank_c(3_300_000, 30)

print("Expected interest:", expected)
print("Worst 10% interest:", worst_10)

💡 Deep Insight

  • Floating rate is not “cheaper”
  • It is a distribution
  • Humans underestimate tail risk

🧠 Question 4 — Risk-Adjusted Decision Rule

🎯 Task

Define a decision score:

$$ \text{Score} = \mathbb{E}[\text{Interest}] + \lambda \cdot \text{WorstCase} $$

Compare banks for:

lambda_value = 0 # Risk-neutral lambda_value = 0.5 # Moderately risk-averse lambda_value = 1.0 # Highly risk-averse


✅ Solution (Python)
banks = {
    "A": {"expected": 1.9e6, "risk": 0.1e6},
    "B": {"expected": 1.7e6, "risk": 0.4e6},
    "C": {"expected": expected, "risk": worst_10}
}

for lam in [0, 0.5, 1.0]:
    print("\nLambda =", lam)
    for k, v in banks.items():
        score = v["expected"] + lam * v["risk"]
        print(k, round(score, 2))

💡 Human Insight

  • Young + rich → Bank C
  • Family + fixed income → Bank A
  • Optimists regret Bank B

🎓 Final Mental Upgrade

After this chapter, students can:

  • model banks as stochastic systems
  • quantify financial risk
  • explain why “cheapest” ≠ “best”
  • think like a bank risk analyst

This is real Python for real life decisions.


🌍 Why This Chapter Exists

Most mortgage calculators assume:

“The future is stable.”

Banks never assume that.

Banks ask:

  • What if income drops?
  • What if interest spikes?
  • What if humans panic?

This chapter teaches:

  • how to simulate recession scenarios
  • how to evaluate decisions using expected utility
  • why banks survive crises while households don’t

🧠 Core Upgrade: Cost Is Not Pain

Humans don’t minimize money.

They minimize pain.

Economics models this using utility.


📘 Expected Utility Theory (Very Simple)

Instead of minimizing cost:

$$ \min ; \mathbb{E}[\text{Cost}] $$

Humans actually maximize:

$$ \max ; \mathbb{E}[U(W)] $$

Where:

  • ( W ) = wealth after paying mortgage
  • ( U(\cdot) ) = utility function (how painful money loss feels)

🧠 Common Utility Function (Risk-Averse Human)

$$ U(W) = \sqrt{W} $$

Why?

  • Losing 100k hurts more when you are poor
  • Rich people absorb shocks better

🏦 Recession Model — What Changes?

During a recession, three things happen together:

  1. Interest rates increase
  2. Income becomes unstable
  3. Forced selling risk appears

We simulate interest shock + income shock


🟢 Question 1 — Modeling a Recession Shock

📌 Scenario

At year 5:

  • Interest jumps by +2%
  • Monthly income drops by 30% for 2 years

🎯 Task

Simulate mortgage under recession and compute:

  • total interest
  • minimum remaining cash buffer

🧮 Mathematical Hint

Interest rate shift:

$$ r_t = \begin{cases} r & t < t_c \ r + 0.02 & t \ge t_c \end{cases} $$

Income shock:

$$ I_t = 0.7 I \quad \text{during recession} $$

✅ Solution (Python)
P = 3_300_000
balance = P
years = 30
monthly_income = 80_000
monthly_payment = 25_000
cash_buffer = 500_000

rate = 0.03
total_interest = 0
min_cash = cash_buffer

for m in range(1, years * 12 + 1):
    if m == 5 * 12:
        rate += 0.02

    income = monthly_income
    if 5 * 12 <= m <= 7 * 12:
        income *= 0.7

    interest = balance * (rate / 12)
    principal = monthly_payment - interest
    balance -= principal
    total_interest += interest

    cash_buffer += income - monthly_payment
    min_cash = min(min_cash, cash_buffer)

print("Total interest:", round(total_interest, 2))
print("Minimum cash buffer:", round(min_cash, 2))

💡 Reality Insight

  • Interest shock hurts slowly
  • Income shock kills fast
  • Liquidity > interest rate

🧠 Question 2 — Probability of Default (Human View)

📌 Default Rule

Household defaults if:

$$ \text{Cash Buffer} < 0 $$


🎯 Task

Simulate 1000 recession paths and compute:

  • probability of default

✅ Solution (Python)
import random

def simulate_default():
    cash = 500_000
    balance = 3_300_000
    rate = 0.03
    income = 80_000
    payment = 25_000

    for m in range(1, 30*12):
        if m == 5 * 12:
            rate += 0.02

        shock = random.random() < 0.3
        current_income = income * (0.7 if shock else 1.0)

        interest = balance * (rate / 12)
        balance -= (payment - interest)
        cash += current_income - payment

        if cash < 0:
            return True

    return False

defaults = sum(simulate_default() for _ in range(1000))
print("Default probability:", defaults / 1000)

💡 Bank Insight

  • Banks don’t care about averages
  • They price default probability

🧠 Question 3 — Expected Utility Comparison (Bank A vs C)

📌 Setup

We compare two choices:

  • Bank A: fixed rate, low volatility
  • Bank C: floating rate, high volatility

🎯 Task

Compute expected utility under recession risk.


🧮 Utility Function

$$ U(W) = \sqrt{W} $$

Where:

$$ W = \text{Final Wealth} = \text{Savings} - \text{Total Paid} $$

✅ Solution (Python)
import math

def utility(wealth):
    return math.sqrt(max(wealth, 0))

def expected_utility(simulations, bank_type):
    utilities = []

    for _ in range(simulations):
        savings = 2_000_000
        total_paid = 0

        if bank_type == "A":
            rate = 0.03
        else:
            rate = random.uniform(0.02, 0.05)

        total_paid = 3_300_000 * (1 + rate * 30)
        wealth = savings - total_paid
        utilities.append(utility(wealth))

    return sum(utilities) / len(utilities)

print("EU Bank A:", expected_utility(1000, "A"))
print("EU Bank C:", expected_utility(1000, "C"))

💡 Key Insight

  • Higher expected cost can still give higher utility
  • Safety has value
  • Volatility destroys utility faster than it saves money

🧠 Question 4 — Why Banks Win (Final Truth)

Banks optimize:

$$ \max ; \mathbb{E}[\text{Profit}] - \text{Tail Risk} $$

Humans ignore tail risk.


🎯 Thought Question (No Code)

Why do banks survive recessions while households don’t?

Hint:

$$ \text{Diversification} + \text{Capital Buffer} \gg \text{Single Mortgage} $$


🎓 Final Mental Shift

After this chapter, students understand:

  • why floating rate is psychologically dangerous
  • why recession kills liquidity, not math
  • why expected utility beats “lowest interest”
  • why banks always design contracts to win

You are no longer a borrower.

You are a system thinker.


🌍 Why This Chapter Exists

People often say:

“Banks are greedy.”

That is emotionally true — but technically incomplete.

Banks do not survive because of greed.
They survive because of structure.

This chapter explains:

  • why banks can take risks households cannot
  • why leverage hurts humans more than math predicts
  • why loss hurts more than gain feels good

🏦 Part I — Bank Capital vs Household Leverage

🧠 Core Asymmetry (Very Important)

A household usually has:

$$ \text{Leverage} = \frac{\text{Debt}}{\text{Income}} \gg 1 $$

A bank operates under:

$$ \text{Capital Ratio} = \frac{\text{Equity}}{\text{Risk-Weighted Assets}} \ge 8% $$

Same money system — completely different survival rules.


📘 Definitions (Plain English)

Household Leverage

  • One income stream
  • One large loan
  • Failure = life disruption

Bank Capital

  • Thousands of borrowers
  • Diversification
  • Loss absorption buffer

🟢 Question 1 — Leverage Comparison (Math Reality)

📌 Scenario

Household:

  • Income: 80,000 THB/month
  • Mortgage: 3.3M

Bank:

  • Loans issued: 1,000 × 3.3M
  • Capital ratio: 10%

🎯 Tasks

  1. Compute household leverage
  2. Compute bank equity buffer
  3. Compare shock tolerance

🧮 Mathematical Hint

$$ \text{Household Leverage} = \frac{\text{Debt}}{\text{Annual Income}} $$

$$ \text{Bank Capital} = 0.10 \times \text{Total Loans} $$

✅ Solution (Python)
household_income = 80_000 * 12
household_debt = 3_300_000

leverage = household_debt / household_income

bank_loans = 3_300_000 * 1000
bank_capital = bank_loans * 0.10

print("Household leverage:", round(leverage, 2))
print("Bank capital buffer:", bank_capital)

💡 Interpretation

  • Household leverage ≈ 3–5× income → fragile
  • Bank absorbs millions of defaults before dying

🧠 Question 2 — Shock Absorption Test

📌 Scenario

  • Economic shock causes 5% of borrowers to default
  • Each default loses 50% of loan value

🎯 Tasks

  1. Compute total bank loss
  2. Check if bank survives
  3. Compare to household shock

✅ Solution (Python)
default_rate = 0.05
loss_given_default = 0.5

loss = bank_loans * default_rate * loss_given_default
bank_survives = loss < bank_capital

print("Bank loss:", loss)
print("Bank survives:", bank_survives)

💡 Key Truth

Banks are built to expect failure. Households are not.


🧠 Part II — Prospect Theory (Why Humans Panic)

📘 Classical Economics Assumption (Wrong)

Humans maximize expected value:

$$ \max ; \mathbb{E}[W] $$


🧠 Prospect Theory (Reality)

Humans evaluate gains and losses asymmetrically.

Utility function:

$$ U(x) = \begin{cases} x^\alpha & x \ge 0
-\lambda |x|^\beta & x < 0 \end{cases} $$

Where:

  • ( \lambda > 1 ) (loss hurts more than gain)
  • Typically ( \lambda \approx 2.25 )

🟢 Question 3 — Loss Aversion in Mortgage Decisions

📌 Scenario

Two outcomes:

  • Option A: Save 100,000 THB
  • Option B: Risk losing 100,000 THB

Expected value = same.


🎯 Task

Compare utility using prospect theory.


✅ Solution (Python)
def prospect_utility(x, alpha=0.88, beta=0.88, lam=2.25):
    if x >= 0:
        return x ** alpha
    else:
        return -lam * (abs(x) ** beta)

gain = prospect_utility(100_000)
loss = prospect_utility(-100_000)

print("Utility of gain:", gain)
print("Utility of loss:", loss)

💡 Psychological Truth

  • Losing 100k hurts ~2× more than gaining 100k feels good
  • Floating rate mortgages amplify psychological pain

🧠 Question 4 — Why Households Panic-Sell

📌 Scenario

During recession:

  • House price drops 15%
  • Mortgage balance unchanged

🎯 Task

Compute perceived loss vs actual loss.


🧮 Hint

Reference point matters:

$$ \text{Loss} = P_{\text{peak}} - P_{\text{current}} $$

✅ Solution (Python)
house_price = 3_300_000
price_drop = 0.15

actual_loss = house_price * price_drop
perceived_pain = prospect_utility(-actual_loss)

print("Actual loss:", actual_loss)
print("Perceived pain:", perceived_pain)

💡 Key Insight

People sell not because of math — they sell because of pain.

Banks know this.


🧠 Question 5 — Final Synthesis (No Code)

Why do banks:

  • encourage leverage?
  • offer floating rates?
  • survive crises?

Answer (Hint):

$$ \text{Diversification} + \text{Capital} + \text{Asymmetric Psychology} $$

Households face:

  • concentrated risk
  • no buffer
  • loss aversion

🎓 Final Mental Model

Entity Risk Buffer Psychology
Household Concentrated None Loss-averse
Bank Diversified Capital Risk-neutral

Banks don’t win by cheating.

They win because the system was never symmetric.

You now see the matrix.


Previous