The normal distribution
Measurements, not counts: density against probability, areas and percentiles.
Measurements, not counts
A count takes whole values; a measurement can fall anywhere in a range. The time a dose takes to work, the weight of a filled bottle and the daily return on a share are measurements, and many of them pile up around a typical value with fewer and fewer further out on either side. The normal distribution is the model for that bell-shaped pattern:
Two numbers describe it completely: the mean \(\mu\), where the bell is centred, and the standard deviation \(\sigma\), how wide it is. It is symmetric, so the mean is also the median, and it has no ends: every value has some density, however far out.
μ moves it, σ widens it
Changing \(\mu\) slides the bell along the axis without changing its shape. Changing \(\sigma\) stretches or squeezes it, and because the area under it is always 1, a narrower bell must be taller: its peak is \(\tfrac{1}{\sigma\sqrt{2\pi}}\). With \(\sigma = 0.25\) the peak is 1.5958, a density above 1, which is fine: a density is probability per unit, not a probability.
Area is probability
For a measurement, a probability is an area under the density. The chance of a value between \(a\) and \(b\) is
The normal CDF has no formula in elementary functions, so software (or a table) computes it. And since a single point has no width, \(P(X = x) = 0\) and \(P(X < x) = P(X \le x)\): for a measurement, unlike a count, the boundary never matters.
Brambleford: the time a dose takes to work
Brambleford records how many hours each of 50 volunteers took to recover fully after a dose (the lab's dataset dose-times.csv). The sample's mean is 13.39 hours and its standard deviation 4.76 hours, and the histogram looks roughly like a bell, so the team models the time as \(X \sim N(13.39, 4.76)\).
The chance that a dose works in under 11.5 hours is \(P(X < 11.5) = 0.3457\); in the sample, 17 of the 50 did, a share of 0.34. The chance that it takes more than 10 hours is \(P(X > 10) = 1 - F(10) = 0.7618\), against 38 of 50, or 0.76, in the sample. The model and the data agree closely, as they should for a sample that looks normal.
Percentiles
A percentile turns the question round: which time do 90 % of doses beat? The PPF, the inverse of the CDF, answers it: \(F^{-1}(0.9) = 19.49\) hours, so nine doses in ten take effect within about 19 and a half hours. For the normal, every percentile is \(\mu + z\sigma\) for a fixed \(z\) (1.2816 for the 90th), which chapter 8 explains.
The simulated share's daily log returns
A share's daily log return is \(r_t = \ln(P_t / P_{t-1})\), where \(P_t\) is the closing price. Log returns add up: the returns over 251 days sum to \(\ln(P_{\text{last}} / P_{\text{first}})\). The simulated share's 252 closes (share-close.csv) give 251 daily log returns with a mean of 0.0012 and a standard deviation of 0.0279. The normal model \(N(0.0012, 0.0279)\) peaks at a density of 14.3, since a day's return is tiny.
The model answers questions about prices only once each price change is turned into a log return. A 5 % fall in a day leaves 0.95 of the price, a log return of \(\ln 0.95 = -0.0513\), not −0.05; the model gives it a probability of \(P(r \le -0.0513) = 0.0299\) a day (0.0332 with −0.05).
Over a year of 250 trading days, the log returns add up: the yearly log return has a mean of 250 times the daily mean, 0.3072, and a standard deviation of \(\sqrt{250}\) times the daily one, 0.4412 (chapter 10 explains why the standard deviation grows with \(\sqrt{250}\)). A 50 % drop in a year leaves half the price, a log return of \(\ln 0.5 = -0.6931\):
That is about 1.2 %. Reading the 50 % drop as a log return of −0.5 gives 0.0337, about 3.4 %, nearly three times too high. Likewise the 50th percentile of the yearly log return is 0.3072, which says the median price after a year is \(e^{0.3072} = 1.3596\) times today's, not that the price rises by 0.3072 dollars.
When the normal is the wrong tool
- Skew. Waiting times, incomes and claim sizes have a long right tail and no left one. A symmetric bell puts too much probability below the mean and too little far above it; chapter 9's exponential is one alternative.
- Bounds. A time cannot be negative, yet \(N(13.39, 4.76)\) gives \(P(X < 0) = 0.0025\). That is small enough to ignore here; for a quantity close to a bound, such as a share near 0 or 1, it is not.
- Fat tails. Financial returns have far more extreme days than a normal allows. The normal is fine near the middle and badly wrong in the tails, which is where the risk is.
The simulated share's returns show the fat tails plainly. The normal expects 11.4 of the 251 days to lie more than 2 standard deviations from the mean, and 15 did; it expects 0.68 days beyond 3 standard deviations, and 4 did; it expects 0.016 days beyond 4, and 2 did. The excess kurtosis, 0 for a normal, is 6.75.
The worst day, day 67, had a log return of −0.1595, a fall of 14.7 %. That is 5.76 standard deviations below the mean, and the normal model gives a day at least that bad a chance of one in about 236 million trading days, once in close to a million years. It happened in the very year of data the model was fitted to. So the normal model does not show that a share is "safe to invest": it understates exactly the days an investor fears.
In code
| What it computes | Python (scipy.stats) | Excel |
|---|---|---|
| Under 11.5 hours | norm.cdf(11.5, 13.39, 4.76) |
=NORM.DIST(11.5, 13.39, 4.76, TRUE) |
| More than 10 hours | norm.sf(10, 13.39, 4.76) |
=1-NORM.DIST(10, 13.39, 4.76, TRUE) |
| The 90th percentile | norm.ppf(0.9, 13.39, 4.76) |
=NORM.INV(0.9, 13.39, 4.76) |
| Daily log returns | np.log(df['close']).diff() |
=LN(B3/B2) |
| A 50 % drop in a year | norm.cdf(np.log(0.5), 250*mu, np.sqrt(250)*sd) |
=NORM.DIST(LN(0.5), 250*mu, SQRT(250)*sd, TRUE) |
| Excess kurtosis | returns.kurt() |
=KURT(C3:C253) |
In scipy, norm(loc=μ, scale=σ): the second and third arguments are the mean and the standard deviation, not the variance.
Quiz
Three questions on the chapter. Your best score is kept in this browser.