53. Brownian motion
Take a random walk. Shrink the steps, take them faster, and pass to the limit. What survives is Brownian motion — the continuous-time process at the centre of stochastic calculus, physics and mathematical finance.
The construction
Start with a simple random walk taking steps of size \Delta x every \Delta t. Over time t there are t/\Delta t steps, so
\operatorname{Var}(S_t) = \frac{t}{\Delta t}(\Delta x)^2
For a sensible limit we need this to stay finite and non-zero, which forces
\Delta x \propto \sqrt{\Delta t}
Space scales like the square root of time. That single relationship is the signature of diffusion, and it's the \sqrt n from the last lesson written in continuous time.
The definition
W(t) is a standard Brownian motion (or Wiener process) if:
- W(0) = 0.
- Independent increments: for disjoint intervals, the changes are independent.
- Normal increments: W(t) - W(s) \sim N(0,\; t - s) for s < t.
- Continuous paths, with probability 1.
Property 3 is the CLT (§3) cashed in: each increment is the limit of a sum of many tiny independent steps, so it is Normal regardless of what the steps looked like. Brownian motion inherits its Normality from the CLT, not by assumption.
Basic consequences:
E[W(t)] = 0, \qquad \operatorname{Var}(W(t)) = t, \qquad \operatorname{Cov}(W(s), W(t)) = \min(s,t)
That covariance is worth a moment: two times share exactly the randomness accumulated up to the earlier of them.
The paths are strange
Brownian paths are continuous everywhere and differentiable nowhere.
The reason is the \sqrt{\Delta t} scaling. A difference quotient behaves like
\frac{W(t + \Delta t) - W(t)}{\Delta t} \sim \frac{\sqrt{\Delta t}}{\Delta t} = \frac{1}{\sqrt{\Delta t}} \to \infty
The path moves too much over short intervals to have a slope. There is no velocity at any instant.
Two further properties follow:
- Infinite total variation on any interval — the path has infinite length.
- Finite quadratic variation: \sum (\Delta W)^2 \to t exactly.
That second fact is the foundation of stochastic calculus. In ordinary calculus (dx)^2 is negligible; here (dW)^2 = dt is a first-order quantity. That's why Itô's lemma carries an extra second-derivative term that the ordinary chain rule does not:
df(W_t) = f'(W_t)\,dW_t + \tfrac{1}{2}f''(W_t)\,dt
Also, by self-similarity, W(ct) has the same distribution as \sqrt c\,W(t): zoom in on a Brownian path and it looks statistically identical. It is a fractal.
Variants
With drift:
X(t) = \mu t + \sigma W(t), \qquad E[X(t)] = \mu t, \quad \operatorname{Var}(X(t)) = \sigma^2 t
Drift grows like t, noise like \sqrt t — so over long horizons the drift dominates, exactly as in the discrete walk.
Geometric Brownian motion, the standard model for asset prices:
dS = \mu S\,dt + \sigma S\,dW \implies S(t) = S(0)\exp\left(\left(\mu - \tfrac{\sigma^2}{2}\right)t + \sigma W(t)\right)
Here \log S(t) is Brownian motion with drift, so prices stay positive and returns rather than absolute changes are what's modelled.
The -\sigma^2/2 is easy to miss and important: it's the gap between the arithmetic and geometric mean growth rates. Volatility reduces compound growth even when it doesn't change the expected value — a fact with real consequences for anything that compounds.
Brownian bridge: Brownian motion conditioned to return to 0 at time T. Used for interpolation and in goodness-of-fit tests.
Where it shows up
- Physics: pollen grains in water (Brown, 1827; Einstein, 1905), diffusion, heat.
- Finance: Black–Scholes prices options by assuming geometric Brownian motion.
- Statistics: the limit of empirical processes, underlying the Kolmogorov–Smirnov test.
- Biology: population drift, animal movement.
Worked example
A stock follows geometric Brownian motion with S_0 = 100, \mu = 0.10/year, \sigma = 0.20/year. What's the distribution of the price after 1 year?
\log S(1) = \log 100 + \left(0.10 - \frac{0.04}{2}\right)(1) + 0.20\,W(1)
\log S(1) \sim N(\log 100 + 0.08,\; 0.04)
So S(1) is lognormal with \mu_{\log} = 4.6852 and \sigma_{\log} = 0.20.
Median price: e^{4.6852} = 100e^{0.08} \approx 108.33.
Mean price: E[S(1)] = S_0e^{\mu t} = 100e^{0.10} \approx 110.52.
The mean exceeds the median — a lognormal is right-skewed. Half of all outcomes fall below 108.33, yet the average is 110.52, pulled up by a thin tail of very large values. This is §0's skew lesson reappearing, and it's why "expected return" and "typical return" are different numbers for anything that compounds.
Probability the price exceeds 120:
P(S(1) > 120) = P\left(Z > \frac{\log 1.2 - 0.08}{0.20}\right) = P(Z > 0.5115) \approx 0.305
Doing it in Python
Building Brownian motion from its increments:
import numpy as np
rng = np.random.default_rng(0)
T, steps, paths = 1.0, 1_000, 20_000
dt = T / steps
# Increments are independent N(0, dt)
dW = rng.normal(0, np.sqrt(dt), size=(paths, steps))
W = np.cumsum(dW, axis=1)
print(f"{'t':>8} {'mean':>10} {'variance':>10} {'theory (=t)':>12}")
for i in (99, 249, 499, 999):
t = (i + 1) * dt
print(f"{t:>8.2f} {W[:, i].mean():>10.4f} {W[:, i].var():>10.4f} {t:>12.2f}")
print("\nVar(W(t)) = t exactly -- that's the defining scaling.")
The non-differentiability, made visible:
import numpy as np
rng = np.random.default_rng(1)
print("Difference quotient [W(t+h) - W(t)] / h as h shrinks:\n")
print(f"{'h':>12} {'typical |slope|':>18} {'1/sqrt(h)':>12}")
for h in (1e-1, 1e-2, 1e-3, 1e-4, 1e-5):
increments = rng.normal(0, np.sqrt(h), 20_000)
print(f"{h:>12.0e} {np.abs(increments / h).mean():>18.2f} "
f"{1/np.sqrt(h):>12.2f}")
print("\nThe slope diverges like 1/sqrt(h). No derivative exists anywhere.")
Quadratic variation converging to t — the fact stochastic calculus is built on:
import numpy as np
rng = np.random.default_rng(2)
T = 1.0
print(f"{'steps':>10} {'sum |dW|':>12} {'sum dW^2':>12}")
for steps in (100, 1_000, 10_000, 100_000):
dt = T / steps
dW = rng.normal(0, np.sqrt(dt), steps)
print(f"{steps:>10} {np.abs(dW).sum():>12.4f} {(dW**2).sum():>12.6f}")
print(f"\nTotal variation diverges (path length is infinite).")
print(f"Quadratic variation converges to T = {T}. Hence (dW)^2 = dt.")
Geometric Brownian motion, and the volatility drag:
import numpy as np
rng = np.random.default_rng(3)
S0, mu, sigma, T, paths = 100.0, 0.10, 0.20, 1.0, 200_000
W_T = rng.normal(0, np.sqrt(T), paths)
S_T = S0 * np.exp((mu - sigma**2 / 2) * T + sigma * W_T)
print(f"simulated mean {S_T.mean():.4f} theory {S0*np.exp(mu*T):.4f}")
print(f"simulated median {np.median(S_T):.4f} theory "
f"{S0*np.exp((mu - sigma**2/2)*T):.4f}")
print(f"P(S > 120) {(S_T > 120).mean():.4f}")
print(f"\nmean > median by {S_T.mean() - np.median(S_T):.2f} -- the lognormal is skewed.")
print("\nVolatility drag: same expected return, different volatilities")
print(f"{'sigma':>8} {'mean':>10} {'median':>10} {'drag':>10}")
for s in (0.0, 0.2, 0.4, 0.6):
med = S0 * np.exp((mu - s**2 / 2) * T)
print(f"{s:>8} {S0*np.exp(mu*T):>10.2f} {med:>10.2f} "
f"{S0*np.exp(mu*T) - med:>10.2f}")
print("\nThe mean is unchanged; the TYPICAL outcome falls as volatility rises.")
And the random walk converging to Brownian motion:
import numpy as np
rng = np.random.default_rng(4)
T, trials = 1.0, 50_000
print("Scaled random walk S_n / sqrt(n) vs N(0, 1):\n")
print(f"{'n steps':>10} {'mean':>10} {'variance':>10} {'P(|X|>1.96)':>14}")
for n in (10, 100, 1_000, 10_000):
S = rng.choice([-1, 1], size=(trials, n)).sum(axis=1) / np.sqrt(n)
print(f"{n:>10} {S.mean():>10.4f} {S.var():>10.4f} "
f"{(np.abs(S) > 1.96).mean():>14.4f}")
print("\ntheory: 0.0000 1.0000 0.0500")
print("The walk becomes Brownian motion in the limit -- by the CLT.")
Your turn
1. W(t) is standard Brownian motion. Find E[W(4)], \operatorname{Var}(W(4)) and \operatorname{Cov}(W(2), W(5)).
2. Why is Brownian motion nowhere differentiable?
3. A stock has \mu = 0.08 and \sigma = 0.30. What's the median annual growth factor, and why does it differ from e^{0.08}?
Solutions
1.
E[W(4)] = 0, \qquad \operatorname{Var}(W(4)) = 4
\operatorname{Cov}(W(2), W(5)) = \min(2, 5) = 2
The covariance formula reflects that W(5) = W(2) + (W(5) - W(2)), where the second term is independent of W(2). So all the shared randomness is whatever accumulated by time 2 — hence \min(s,t).
2. Because the increments scale like \sqrt{\Delta t} rather than \Delta t.
For a derivative to exist, the difference quotient must converge:
\frac{W(t+h) - W(t)}{h}
The numerator has standard deviation \sqrt h, so the quotient has standard deviation \sqrt h / h = 1/\sqrt h, which diverges as h \to 0.
The path is continuous — the increment \sqrt h \to 0, so there are no jumps — but it oscillates so violently at every scale that no tangent line exists. The self-similarity makes this exact: zooming in never smooths anything out, because the zoomed picture is statistically identical to the original.
This is why stochastic calculus needs its own machinery. You cannot write dW/dt, so integrals against dW must be defined directly, which is what the Itô integral does.
3. The median growth factor is
e^{(\mu - \sigma^2/2)t} = e^{0.08 - 0.045} = e^{0.035} \approx 1.0356
about 3.6%, against e^{0.08} \approx 1.0833, or 8.3%, for the mean.
The gap is the volatility drag, \sigma^2/2 = 0.045. Its source is the asymmetry of compounding: a 30% loss followed by a 30% gain leaves you at 0.7 \times 1.3 = 0.91, down 9%. Losses hurt more than equal-sized gains help, and volatility guarantees you experience both.
The mean is still e^{0.08} — nothing has changed about the expectation. But the mean is carried by a small number of very large outcomes in the lognormal's right tail, and the typical investor experiences something closer to the median.
This is the practical content of "mean ≠ median for skewed data" from §0, and the reason geometric returns are the honest way to report investment performance.
Check yourself in code
Simulate Brownian motion and confirm \operatorname{Var}(W(t)) = t, then verify the quadratic variation converges to T.
Print exactly this:
Var(W(0.5)) 0.4969
Var(W(1.0)) 0.996
variance matches t: True
quadratic variation 1.0
Use default_rng(0) with 20000 paths of 1000 steps over T = 1. Round the
variances to 4 decimal places and the quadratic variation to 1. Treat the
variance check as passing if both are within 0.02 of their theoretical values.
import numpy as np
rng = np.random.default_rng(0)
T, steps, paths = 1.0, 1_000, 20_000
dt = T / steps
dW = rng.normal(0, np.sqrt(dt), size=(paths, steps))
W = np.cumsum(dW, axis=1)
v_half = W[:, 499].var()
print("Var(W(0.5))", round(v_half, 4))
# Print Var(W(1.0)), whether both are within 0.02 of t, and the quadratic
# variation of a single path (sum of squared increments).
import numpy as np
rng = np.random.default_rng(0)
T, steps, paths = 1.0, 1_000, 20_000
dt = T / steps
dW = rng.normal(0, np.sqrt(dt), size=(paths, steps))
W = np.cumsum(dW, axis=1)
v_half = W[:, 499].var()
v_one = W[:, 999].var()
print("Var(W(0.5))", round(v_half, 4))
print("Var(W(1.0))", round(v_one, 4))
print("variance matches t:", bool(abs(v_half - 0.5) < 0.02 and abs(v_one - 1.0) < 0.02))
print("quadratic variation", round((dW[0] ** 2).sum(), 1))
Brownian motion is the scaling limit of a random walk, with space growing like the square root of time. Its increments are independent and Normal — the CLT again — and its paths are continuous but nowhere differentiable, with infinite length and finite quadratic variation. That last property is what makes (dW)^2 = dt and gives stochastic calculus its extra term.
Next: the class of processes for which "fair game" has a precise meaning.