show/hide
years <- 0:40
balance <- 10000 * (1.07)^years
plot(years, balance, type = "l",
xlab = "Years", ylab = "Balance ($)",
main = "$10,000 at 7% compounded annually")A short tour of the concepts behind every investment decision.
Compounding is interest earning interest. Over long horizons, it does the heavy lifting.
years <- 0:40
balance <- 10000 * (1.07)^years
plot(years, balance, type = "l",
xlab = "Years", ylab = "Balance ($)",
main = "$10,000 at 7% compounded annually")years = list(range(0, 41))
balance = [10000 * (1.07) ** y for y in years]
balance[-1] # ending balance after 40 years
#> 149744.57839206984Formula: FV = PV × (1 + r)^n
Where: FV = future value, PV = present value, r = annual return, n = years
The shortcut you should memorize is the Rule of 72:
Years to double your money = 72 ÷ annual return %
At 7% return, money doubles every ~10 years. At 10%, every ~7 years. This single insight reframes every spending decision.
See Math for Investing Basics below for the future_value() and rule_of_72() functions in R and Python, plus the math for regular contributions and inflation-adjusted returns.
Higher expected return = higher expected volatility. Choose a level you can stick with through downturns, not just one that looks attractive on a spreadsheet.
Don’t bet on one company, one sector, or one country. Broad index funds make this nearly free.
Investing math is mostly one idea, compounding, applied in a few different ways. Each calculation below is written as an R and Python function, following the same pattern introduced in the Budgeting chapter.
In code, the ^ symbol (R) and ** symbol (Python) both mean “raise to the power of.” So (1 + 0.07)^10 means “1.07 multiplied by itself 10 times.”
Formula: FV = PV × (1 + r)^n
Where: FV = future value, PV = present value (today’s amount), r = annual return, n = years.
The companion shortcut is the Rule of 72: divide 72 by the return percentage to estimate how many years it takes your money to double.
Years to double ≈ 72 ÷ annual return %
Example: $10,000 at 7% for 10 years grows to ~$19,672, and at 7% money doubles roughly every 10 years.
future_value <- function(present_value, rate, years) {
present_value * (1 + rate)^years
}
rule_of_72 <- function(annual_return_pct) {
72 / annual_return_pct
}
# scalar: $10,000 at 7% for 10 years
future_value(present_value = 10000, rate = 0.07, years = 10)
#> [1] 19671.51
# how long until your money doubles at 7%?
rule_of_72(annual_return_pct = 7)
#> [1] 10.28571
# vectorized: same $10,000 at 7% across multiple horizons
data.frame(
years = c(5, 10, 20, 30),
value = future_value(present_value = 10000, rate = 0.07, years = c(5, 10, 20, 30))
)
#> # A tibble: 4 × 2
#> years value
#> <dbl> <dbl>
#> 1 5 14026.
#> 2 10 19672.
#> 3 20 38697.
#> 4 30 76123.import numpy as np
def future_value(present_value, rate, years):
return present_value * (1 + rate) ** years
def rule_of_72(annual_return_pct):
return 72 / annual_return_pct
# scalar: $10,000 at 7% for 10 years
print(future_value(present_value=10000, rate=0.07, years=10))
#> 19671.513572895663
# how long until your money doubles at 7%?
print(rule_of_72(annual_return_pct=7))
#> 10.285714285714286
# vectorized: numpy lets us pass an array of horizons in one call
horizons = np.array([5, 10, 20, 30])
future_value(present_value=10000, rate=0.07, years=horizons)
#> array([14025.517307 , 19671.5135729 , 38696.84462486, 76122.55042662])Most people don’t invest a lump sum once; they add money every month. The future value of a stream of equal contributions is:
Formula: FV = PMT × [((1 + r)^n − 1) ÷ r]
Where: PMT = the amount contributed each period, r = the return per period, n = the number of periods.
Example: $500/month for 30 years (360 months) at a 7% annual return (~0.583% per month) grows to ~$610,000, of which only $180,000 is money you actually put in.
future_value_series <- function(contribution, rate, periods) {
contribution * (((1 + rate)^periods - 1) / rate)
}
# $500/month for 30 years at a 7% annual return (monthly rate = 0.07 / 12)
future_value_series(contribution = 500, rate = 0.07 / 12, periods = 30 * 12)
#> [1] 609985.5def future_value_series(contribution, rate, periods):
return contribution * (((1 + rate) ** periods - 1) / rate)
# $500/month for 30 years at a 7% annual return (monthly rate = 0.07 / 12)
future_value_series(contribution=500, rate=0.07 / 12, periods=30 * 12)
#> 609985.4978879723A 7% return with 3% inflation does not leave you 4% richer in spending power; the relationship is multiplicative, not subtractive.
Formula: Real Return = (1 + nominal) ÷ (1 + inflation) − 1
Example: (1.07 ÷ 1.03) − 1 = ~3.88%, slightly less than the 4% you’d get by simple subtraction.
real_return <- function(nominal, inflation) {
(1 + nominal) / (1 + inflation) - 1
}
# 7% nominal return against 3% inflation
real_return(nominal = 0.07, inflation = 0.03)
#> [1] 0.03883495def real_return(nominal, inflation):
return (1 + nominal) / (1 + inflation) - 1
# 7% nominal return against 3% inflation
real_return(nominal=0.07, inflation=0.03)
#> 0.03883495145631066