Loans and Bonds: The Mechanics of Borrowing and Default Risk
A quantitative guide to loan amortization and bond pricing. Learn to derive payment formulas, simulate default risk, and understand coupon rates using Python.
Imagine a young couple, Sara and Tom, who have been dreaming of owning their first home. With a small savings account and a lot of determination, they finally step into a bank to discuss a mortgage loan. This moment marks a significant turning point in their lives, as the financial leverage they gain through the loan will enable them to move into their dream house, a place where they will raise their family. Financial loans sit at the core of how modern economies work. Whether it’s a family buying a house, a company expanding its operations, or the government funding a public project, loans provide the upfront capital needed to make things happen. Yet, while most people understand the idea of borrowing and paying back with interest, the broader mechanics behind loans and how they evolve into more complex financial instruments are far less understood. In this post, we will start breaking down what a loan really is and how lenders manage the risk of loaning money. From there, we will work towards understanding bonds, which can be seen as loans packaged, traded, and scaled for markets. By understanding these concepts, we are building the right mental framework to start working with more complicated financial instruments.
Loans
In its essence, a loan is pretty simple: we borrow some money and pay it back over time. We can analyze the repayment of the money pretty easily. For example, we take a mortgage of and plan to repay it in equal monthly payments with an interest rate of per month.
Most of us can probably quantify how much we need to pay each month by using our intuition. The lowerbound of our monthly payment would be since this is the amount we would pay each month in interest. The upper bound of our payment would be , since this would cover the entire loan, including interest compounded over the full amount.
But what if we can estimate the monthly share of the principal at plus an interest of . We can calculate this interest by dividing by 2 since the interest would vanish over time. With this, our monthly payment would be . But is it fair to assume this as our monthly payment? Let’s try to calculate it.
def loan_payment(X, r, N):
"""
Compute the fixed payment amount A for a loan.
X: initial loan amount
r: interest rate per period (e.g., 0.05 for 5%)
N: number of payments
"""
if r == 0:
return X / N
return X * (r * (1 + r)**N) / ((1 + r)**N - 1)
def simulate_loan(X, r, N):
"""
Simulate the loan balance D_k using the difference equation.
"""
A = loan_payment(X, r, N)
D = [X] # D_0 = X
for k in range(N):
D_next = (1 + r) * D[-1] - A
D.append(D_next)
return A, D
def main():
# Parameters
X = 300000.0 # initial amount borrowed
annual_rate = 0.06
payments_per_year = 12
years = 5
# Convert to rate per period and number of periods
r = annual_rate / payments_per_year
N = payments_per_year * years
A, D = simulate_loan(X, r, N)
print(f"Loan amount (X): {X:,.2f}")
print(f"Interest rate per period (r): {r:.6f}")
print(f"Number of payments (N): {N}")
print(f"Payment per period (A): {A:,.2f}\n")
print("k\tOutstanding Balance (D_k)")
for k, balance in enumerate(D):
print(f"{k}\t{balance:,.2f}")
if __name__ == "__main__":
main()
According to this script, our monthly payments would be €1753.77. We got to this amount by first establishing the value of (the amount borrowed). We will pay this back by paying at time , then at time , and so on, **until we reach time , at which point we owe no money. Let be the amount we owe at the payment. We know that and , so we need to solve a difference equation. So to summarize:
| Symbol | Meaning | Units |
|---|---|---|
| amount we owe at the payment | Currency | |
| Payment per period | Currency | |
| Number of payments | ||
| Time between payments | Time | |
| Interest rate per period | ||
| Principal (amount borrowed at time t) | Currency |
We can look at what happens between two consecutive payments. At the start of period you owe . So during the next time interval :
- The loan accrues interest at rate , so it grows to .
- Then you make a payment , reducing your balance.
Thus the amount owed after the next payment (just after ) is:
Now we need to find a closed form for which is a non-homogeneous linear recurrence relation. We know the boundary conditions of our scenario. The initial condition is us owing the full loan at , and the final condition is us owing noting after payments at . Knowing this we can solve for :
So,
Given the fixed payment per period we will have completely repaid the loan of amount after equal payments.
Bonds
If loans are the backbone of personal and corporate finance, then bonds are their large-scale, institutional counterpart. While a loan typically involves direct agreements between a borrower and a lender, bonds take that same idea and expand it to the financial markets. In this section, we will explore what bonds are, how they function, and why they are so important for funding governments and corporations. Understanding bonds will be an important part of our ability to understand and build more complex quantitative financial models.
Simply put, a bond is a loan that is sold to an investor. Bonds have many interesting quantitative features; for example, their values fluctuate with interest rates, and they often contain embedded options that allow them to be repaid or called back. Sometimes bonds are issued in a foreign currency to investors, introducing foreign exchange risk. While these are all interesting, the most important risk we need to determine is whether the lender can repay the borrowed money.
We can start with unraffling a simple bond for which the borrower receives . In exchange, the borrower will repay at time , where **is the coupon rate and **is **the bond’s term. An important question we should ask here is: what is a fair value for ? How much should we be compensated for borrowing our money? To find the value of ,** we first need to know the risk-free rate **r**. The risk-free rate is the rate that theoretically entails no financial risk, meaning the borrower is certain to repay the loan. Think of the risk-free rate as the minimum expected return on your investment. When making any investment, our expected return should exceed the risk-free rate. If this is not the case, you can not justify the risk you are taking. In a perfect world, we could even say that a fair value for .
To find a fair value for , we need to quantify the bond default rate. A simple model assumes that at time , the bond either defaults or is repaid in full. When the bond defaults, we assume the investor will lose some value of their entire investment. So, with probability , the bondholder receives at time , and with probability , they receive at time . We can say a fair rate for c is when the investor, on average, gets back their principal, adjusted for the time value of money. The lender must also charge a large enough coupon so that they do no worse than lending at the risk-free rate. This can be computed as follows:
Or,
Or even simpler:
Given this formula, a lender will, on average, break even after accounting for the time value of money and the risk of default. But which investor will take this risk to just break even? Many investors will ask for a far greater coupon to justify their risk and increase the chance of making some money. The difference between the fair coupon and the actual coupon is often determined during negotiations between the lender and borrower.
Instead of increasing the coupon, we can also reduce our risk by finding many different borrowers, each with an independent chance of defaulting. Let me give you a one-sentence roadmap of the upcoming simulation: we will explore how varying default outcomes across ten distinct loans affects our risk profile. Let’s run a simple simulation to see how our risk changes. We will work with the following fixed parameters:
| Param | Value |
|---|---|
| X | €1000 |
| r | 3% |
| p | 5% |
| R | 0 |
import random
import math
def main():
trials = 100
num_loans = 10
X = 1000.0
r = 0.03
p = 0.05
R = 0.0
# Coupon rate
c = (r + p * (1 - R)) / (1 - p * (1 - R))
returns = []
for _ in range(trials):
portfolio_return = 0.0
for _ in range(num_loans):
defaults = random.random() < p # Bernoulli(p)
if defaults:
portfolio_return += 0.0
else:
portfolio_return += X * (1.0 + c)
total_initial = num_loans * X
yearly_return = (portfolio_return - total_initial) / total_initial
returns.append(yearly_return)
# Statistics
mean = sum(returns) / trials
best = max(returns)
worst = min(returns)
variance = sum((r - mean) ** 2 for r in returns) / trials
stddev = math.sqrt(variance)
# Output
print(f"Bond Portfolio Simulation Results after {trials} trials with coupon: {c * 100:.2f}%")
print("--------------------------------------------")
print(f"Average return: {mean * 100:.2f} %")
print(f"Best-case return: {best * 100:.2f} %")
print(f"Worst-case return: {worst * 100:.2f} %")
print(f"Standard deviation: {stddev * 100:.2f} %")
if __name__ == "__main__":
main()
From this result, we can see that, on average, our return exceeds the risk-free rate, but not by much. Considering that if we had one lender, our potential worst-case scenario would be 100% loss. Having 10 different lenders has changed this to a worst-case loss of only -24%. However, this setup invites us to reflect on additional risk-mitigation strategies. How might tools like collateral or credit default swaps provide extra layers of protection against worst-case outcomes? Incorporating such alternatives could further enhance our ability to manage financial risk and potentially reduce it.
Closing thoughts
Loans and bonds may look like everyday financial tools, but beneath the surface, they are built on clear mathematical structures and carefully managed risk. By breaking down how a simple loan works, how payments are determined, and how interest shapes repayment over time, we lay the foundations for understanding larger, more complex financial instruments.
Bonds follow the same principle as a loan, but scale it to markets. Their pricing depends on many factors, some of which we discussed, such as credit risk, recovery assumptions, and exposure diversification across many borrowers. As the simulation showed, spreading risk across a portfolio of independent loans dramatically reduces the worst-case outcomes, illustrating why diversification is central to modern finance.
Ultimately, understanding loans and bonds gives us more than just the ability to calculate payments or yields. It builds the mental framework needed to navigate the financial system as a whole. With this foundation, we can start exploring some more complex financial instruments.
⚠️ Financial Education Disclaimer
This post discusses the mathematical foundations of loans, mortgages, and bonds for educational and research purposes only.
- Not Financial Advice: The calculations, Python simulations, and scenarios (including the example mortgage) are illustrative. They do not constitute professional financial advice or a recommendation for any specific loan product.
- Model Simplifications: These models assume fixed interest rates and specific compounding frequencies. Real-world loans may include variable rates, taxes, insurance (PITI), and origination fees not captured in these scripts.
- Market Risk: Bond pricing and default probabilities () are subject to extreme market volatility. Past performance and statistical averages do not guarantee future results.
- Consult a Professional: Always speak with a certified financial advisor or mortgage specialist before entering into a significant debt obligation.