9  Investing Basics


A short tour of the concepts behind every investment decision.

9.1 Compounding

Compounding is interest earning interest. Over long horizons, it does the heavy lifting.

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")

show/hide
years = list(range(0, 41))
balance = [10000 * (1.07) ** y for y in years]
balance[-1]  # ending balance after 40 years
#> 149744.57839206984

Formula: 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.

9.2 Risk vs. return

Higher expected return = higher expected volatility. Choose a level you can stick with through downturns, not just one that looks attractive on a spreadsheet.

9.3 Diversification

Don’t bet on one company, one sector, or one country. Broad index funds make this nearly free.

9.4 Math for Investing Basics

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.”

Future Value and the Rule of 72

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.

show/hide
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.
show/hide
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])

Future Value of Regular Contributions

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.

show/hide
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.5
show/hide
def 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.4978879723

Real (Inflation-Adjusted) Return

A 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.

show/hide
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.03883495
show/hide
def 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