Quant Memo
Core

Kernel Density Estimation

A way to estimate the smooth probability density that generated a sample of data by placing a small bump on top of every observation and adding the bumps up, instead of forcing the data into rigid histogram bins.

Prerequisites: The Normal Distribution, Common Distributions

You have a year of daily returns for a stock and want to know the shape of the distribution they came from — is it roughly normal, or does it have a fat left tail from crash risk? A histogram is the obvious first move: chop the range into bins, count how many returns fall in each, draw bars. But histograms are jumpy and arbitrary. Shift the bin edges by half a bin width and the picture changes — a smooth bell shape can suddenly look bimodal, or a real second hump can vanish, purely because of where you happened to draw the lines. You want a picture of the underlying distribution that doesn't depend on an arbitrary grid.

An analogy: streetlights on a foggy road

Imagine each data point is a streetlight on a dark road, and each streetlight casts a small pool of light around itself rather than a single pinprick. Where streetlights cluster close together, their pools of light overlap and add up, making that stretch of road brighter — a visual signal that lights (data) are dense there. Where streetlights are sparse, the road stays mostly dark. If you stood back and looked at the total brightness along the road, you'd get a smooth glow that's bright where lights cluster and dim where they don't, with no sharp edges anywhere — unlike a histogram, which would report a count for each fixed slab of road regardless of where inside it the lights actually sit.

Kernel density estimation is exactly this: replace each data point with a small smooth "bump" of probability, and add all the bumps together to get one smooth curve.

The estimator, one symbol at a time

Let x1,,xnx_1, \dots, x_n be your nn observed returns. Let KK be the kernel — a smooth, symmetric bump function centered at zero, most commonly the standard normal density, which integrates to 1 and is highest at its center. Let hh, the bandwidth, control how wide each bump is spread.

The estimated density at any point xx is

f^(x)=1nhi=1nK ⁣(xxih).\hat{f}(x) = \frac{1}{n h} \sum_{i=1}^{n} K\!\left( \frac{x - x_i}{h} \right).

In plain English: for every observation xix_i, place a bump of width hh centered at xix_i; evaluate how tall that bump is at the point xx you care about; add up the heights from all nn bumps; divide by nhnh so the whole curve still integrates to 1, i.e., is still a proper probability density.

The bandwidth hh is the single knob that matters. A tiny hh makes each bump nearly a spike sitting right on top of its own data point — the resulting curve is jagged and shows every quirk of the sample, including pure noise (this is undersmoothing). A huge hh spreads every bump so wide that they all blur into one another — the resulting curve is a featureless mound that hides real structure, like a second mode (this is oversmoothing). Choosing hh is a bias–variance trade-off: small hh has low bias but high variance, large hh has low variance but high bias.

Worked example 1: five points by hand

Take five daily returns (in %): {2,1,0,0.5,3}\{-2, -1, 0, 0.5, 3\}. Use a simple triangular kernel, K(u)=max(1u,0)K(u) = \max(1 - |u|, 0), with bandwidth h=1h = 1. Evaluate the density estimate at x=0x = 0:

f^(0)=151[K(2)+K(1)+K(0)+K(0.5)+K(3)].\hat{f}(0) = \frac{1}{5 \cdot 1}\Big[ K(2) + K(1) + K(0) + K(-0.5) + K(-3) \Big].

Compute each term: K(2)=max(12,0)=0K(2) = \max(1-2,0)=0 (too far, no contribution). K(1)=max(11,0)=0K(1) = \max(1-1,0)=0 (exactly at the edge, zero). K(0)=max(10,0)=1K(0) = \max(1-0,0)=1 (the point sitting exactly at 0 contributes fully). K(0.5)K(0.5)=max(10.5,0)=0.5K(-0.5) \to K(|-0.5|)=\max(1-0.5,0)=0.5. K(3)=0K(-3) = 0 (far outside the bump's width). Sum: 0+0+1+0.5+0=1.50+0+1+0.5+0 = 1.5. So

f^(0)=1.55=0.3.\hat{f}(0) = \frac{1.5}{5} = 0.3 .

Only the two returns near 0 (the point at 0 itself, and the point at 0.5) contribute — the return at 2-2 and the outlier at 33 are too far away for their bumps (width h=1h=1) to reach x=0x=0 at all. This is the mechanism by which KDE stays local: distant points simply don't influence the estimate far from where they sit.

Worked example 2: bandwidth changes the picture

Using the same five returns, compare the estimated density at x=1x=1 under two bandwidths with the triangular kernel. With h=0.5h=0.5: only points within distance 0.5 of x=1x=1 contribute, which is just the return at 0.5 (distance 0.5, right at the kernel's edge, contributing 0), giving f^(1)0\hat f(1) \approx 0 — the curve reads essentially zero probability at x=1x=1 despite two nearby points at 0 and 0.5. With h=2h=2: the kernel reaches from x=1x=-1 to x=3x=3, now picking up contributions from 1-1 (distance 2, edge, 0), 00 (distance 1, K=0.5K=0.5), 0.50.5 (distance 0.5, K=0.75K=0.75), and 33 (distance 2, edge, 0). Sum =0.5+0.75=1.25= 0.5+0.75=1.25, so f^(1)=1.25/(5×2)=0.125\hat f(1) = 1.25/(5 \times 2) = 0.125. The wider bandwidth pulls in more neighbors and produces a noticeably different, smoother reading at the exact same point — which is why every KDE plot should be reported with its bandwidth, the same way a histogram should be reported with its bin width.

return sum of bumps = KDE curve
Each observation (dot on the axis) contributes its own small bump (dashed). Adding all the bumps together at every point gives the smooth KDE curve (solid).
return h too small (jagged) h too large (flat) h just right
The same underlying data under three bandwidths: too small chases every data point's noise, too large blurs away real structure like a second mode, and a well-chosen bandwidth reveals the true shape without either extreme.

What this means in practice

Quants use KDE to look at the actual shape of a return distribution before assuming normality — it's a natural first check before fitting a parametric model, and often reveals fat tails, skew, or a second mode (e.g., a mixture of calm-regime and stressed-regime days) that a normal-distribution assumption would hide. It's also used to visualize the distribution of a signal's information coefficient across many backtests, or the distribution of slippage across trades. The main practical decision is the bandwidth; common defaults (Silverman's rule of thumb, cross-validated bandwidth selection) exist precisely because eyeballing hh is unreliable. KDE says nothing about what happens beyond the range of your observed data — it's a smoothed picture of what you saw, not an extrapolation.

Kernel density estimation replaces each data point with a small smooth bump and sums the bumps to get a smooth estimate of the underlying probability density, avoiding the arbitrary binning of a histogram. The bandwidth hh controls the smoothness and is the one choice that matters — too small overfits noise, too large erases real structure.

The classic mistake is treating a KDE curve as if it were the true density rather than an estimate whose shape depends heavily on the chosen bandwidth — showing a KDE plot with no bandwidth reported, or worse, tuning the bandwidth until the plot supports a preferred narrative (e.g., shrinking hh until a bump appears that "confirms" a bimodal return distribution). Always report the bandwidth, and check that any feature you're reading off the curve — a second mode, a fat tail — survives a reasonable range of bandwidths rather than appearing only at one specific setting.

Related concepts

Practice in interviews

Further reading

  • Silverman, Density Estimation for Statistics and Data Analysis
  • Wasserman, All of Statistics, ch. 20
ShareTwitterLinkedIn