Quant Memo
Advanced

Propensity Score Methods

A way to compare a treated group against an untreated group as if treatment had been handed out at random, by first summarizing every unit's covariates into a single number — its odds of being treated — and matching or weighting on that number instead of on the raw covariates.

Prerequisites: The Potential Outcomes Framework, Hypothesis Testing

You want to know whether adding a stock to an index causes its liquidity to improve, or whether index funds only ever add stocks that were already becoming more liquid. You can't run a randomized experiment — nobody assigns index membership by coin flip. What you have instead is a pile of stocks that got added and a pile that didn't, differing on dozens of characteristics: market cap, sector, existing volume, volatility. A naive comparison of average liquidity between the two groups mixes the effect you want with every one of those pre-existing differences. You need a way to compare only the stocks that were genuinely similar before treatment, so that whatever gap remains after the fact is plausibly the treatment's doing.

An analogy: finding your twin

Imagine you're trying to measure whether a new diet works, using observational data where nobody was randomly assigned to it. The gold-standard approach, if you had unlimited data, would be to find pairs of people who are identical in every relevant way — same age, same starting weight, same activity level, same genetics — except that one went on the diet and the other didn't. Compare their outcomes and you've isolated the diet's effect, because everything else was held fixed by construction.

The problem is that matching on every characteristic at once is nearly impossible once you have more than two or three variables — you'll almost never find an exact twin. The propensity score is the trick that makes this tractable: instead of matching on ten characteristics separately, you compress all ten into a single number — each person's probability of having chosen the diet, given their characteristics — and match on that one number instead. Two people with the same propensity score are, on average, comparable across every characteristic that went into computing it.

The score, one symbol at a time

Let DD be the treatment indicator — D=1D=1 if a unit is treated, D=0D=0 if not (in our example, D=1D=1 means "was added to the index"). Let XX be the vector of observed covariates — market cap, sector, prior volume, whatever you believe drives both treatment and outcome. The propensity score, e(X)e(X), is defined as

e(X)=P(D=1X).e(X) = P(D = 1 \mid X) .

In plain English: the propensity score is the probability that a unit with covariates XX receives treatment, estimated from the data you have. It is not observed directly — you estimate it, almost always with logistic regression:

log(e(X)1e(X))=β0+β1X1+β2X2+\log\left(\frac{e(X)}{1 - e(X)}\right) = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots

In plain English: the log-odds of being treated is modeled as a linear function of the covariates, and inverting that logistic-regression fit gives each unit its predicted probability of treatment.

Once every unit has a score, you can use it two ways. Matching: pair each treated unit with an untreated unit that has a nearly identical score, then compare outcomes within pairs. Inverse probability weighting (IPW): reweight every unit by the inverse of the probability of receiving the treatment status it actually got,

τ^IPW=1ni=1n[DiYie(Xi)(1Di)Yi1e(Xi)].\hat{\tau}_{IPW} = \frac{1}{n}\sum_{i=1}^{n} \left[ \frac{D_i Y_i}{e(X_i)} - \frac{(1-D_i) Y_i}{1 - e(X_i)} \right] .

In plain English: treated units are up-weighted by how unlikely their treatment was, and untreated units are up-weighted by how unlikely their non-treatment was — so a treated unit that looked like it "shouldn't" have been treated counts extra, correcting for the fact that treatment wasn't randomly assigned.

Worked example 1: computing scores and matching by hand

Eight stocks, each with a covariate XX = prior-year trading volume (in millions of shares) and DD = whether the stock was added to an index this year.

StockX (volume, M)D (added)
A20
B30
C50
D61
E80
F91
G121
H141

Suppose fitting a logistic regression of DD on XX to this data yields, after estimation, fitted probabilities (propensity scores) roughly as follows — these are the model's output, not something you compute by hand from 8 points, so take them as given:

StockXDPropensity score e(X)e(X)
A200.05
B300.10
C500.30
D610.42
E800.55
F910.62
G1210.80
H1410.90

Nearest-neighbor matching on the score: D (0.42) matches to E (0.55) — closest untreated score, gap 0.13. F (0.62) also matches to E if we allow reuse, or to C (0.30) if not — take nearest unused, E is taken, so F matches to C, gap 0.32 (worse, illustrating a thin overlap region). G (0.80) has no close untreated match at all — the nearest is E at 0.55, a gap of 0.25, a warning sign of poor overlap for high-volume stocks. This already tells you something useful before computing any effect: matches are only trustworthy for D and E, the pair with genuinely comparable scores; G and H sit in a region with no untreated comparison stocks, so any conclusion about their effect is extrapolation, not comparison.

0.0 1.0 A B C D E F G H good match: D↔E poor match: G has no close untreated score
Amber dots are treated (index-added) stocks, blue are untreated, positioned by propensity score. D and E sit close together and match well; G and H sit in a region with no untreated stocks nearby — no comparison exists for them.

Worked example 2: estimating an average treatment effect via IPW

Take the same eight stocks and suppose you observe a post-treatment liquidity outcome YY (a liquidity index, higher is better) for each:

StockDe(X)e(X)YWeightWeighted contribution
A00.05401/(10.05)=1.0531/(1-0.05)=1.0531.053×40=42.1-1.053 \times 40 = -42.1
B00.10421/0.90=1.1111/0.90=1.11146.7-46.7
C00.30451/0.70=1.4291/0.70=1.42964.3-64.3
D10.42601/0.42=2.3811/0.42=2.381+142.9+142.9
E00.55501/0.45=2.2221/0.45=2.222111.1-111.1
F10.62651/0.62=1.6131/0.62=1.613+104.8+104.8
G10.80701/0.80=1.2501/0.80=1.250+87.5+87.5
H10.90751/0.90=1.1111/0.90=1.111+83.3+83.3

Sum the treated contributions: 142.9+104.8+87.5+83.3=418.5142.9 + 104.8 + 87.5 + 83.3 = 418.5. Sum the untreated contributions (as positive magnitudes): 42.1+46.7+64.3+111.1=264.242.1+46.7+64.3+111.1 = 264.2. The IPW estimator is

τ^IPW=18(418.5264.2)=154.38=19.3.\hat{\tau}_{IPW} = \frac{1}{8}\left(418.5 - 264.2\right) = \frac{154.3}{8} = 19.3 .

So the estimated effect of index inclusion on liquidity is about +19.3+19.3 points. Compare this to the naive difference in raw group means — treated mean (60+65+70+75)/4=67.5(60+65+70+75)/4 = 67.5, untreated mean (40+42+45+50)/4=44.25(40+42+45+50)/4 = 44.25, difference 23.2523.25 — and you can see IPW pulled the estimate down, because it downweights the comparison toward stocks with more balanced scores (like the D–E pair) and away from the poorly-overlapped extremes.

To see why the weights behave this way in general, and to build intuition for how logistic regression turns covariates into a bounded probability in the first place, it helps to watch a fitted curve respond to data directly.

Regression explorer
amber = residuals
fitted slope 1.133true slope 1.00 0.642SSres 42.0

What this means in practice

Propensity score methods show up wherever a quant wants to evaluate an intervention that wasn't randomized — index additions, a broker's algo-routing change rolled out to some accounts but not others, a company's decision to buy back stock, or a regulatory rule that applied to some firms but not others based on size. In every case, the units that "chose" or "received" treatment differ systematically from those that didn't, and a naive before/after or treated/control comparison bakes in that selection. Propensity scores only remove the bias coming from observed covariates — anything driving treatment that you didn't measure still contaminates the estimate, which is why this method lives or dies on the DAG-level question of whether you've captured every confounder, discussed in DAGs for causality.

The propensity score compresses many covariates into one number — the probability of treatment — and matching or weighting on that single number balances all of them at once, provided every real confounder was included when the score was estimated. It fixes selection on observables; it cannot fix selection on unobservables.

A common confusion is treating a good propensity-score balance check as proof of a valid causal estimate. Balance only confirms that the observed covariates are similar across matched treated and untreated groups — it says nothing about unobserved confounders. Two stocks can have identical propensity scores derived from volume and sector, and still differ on something unmeasured (say, an analyst's private expectation of index inclusion) that also drives the outcome. Propensity score methods assume "unconfoundedness" — that conditional on XX, treatment is as good as random — and this assumption is never testable from the data itself, only arguable from domain knowledge.

Related concepts

Practice in interviews

Further reading

  • Rosenbaum & Rubin, 'The Central Role of the Propensity Score in Observational Studies', Biometrika 1983
  • Cunningham, Causal Inference: The Mixtape, ch. 5
ShareTwitterLinkedIn