Skip to content
Finance Lessons

Causal Inference for Alpha & Execution

Double Machine Learning

Keep your gradient-boosted and deep models and still get an unbiased causal estimate: Neyman orthogonality, cross-fitting, partialling-out high-dimensional confounders with ML nuisance models, and why naive 'throw the treatment into the feature set' plug-in estimates are biased.

22 min Updated Jun 23, 2026

By now you can state the causal question precisely, draw the DAG, name the confounders, and — when you are lucky — exploit a natural experiment. But most of the time you are not lucky. You have dozens of confounders (the entire factor-exposure set, microstructure state, regime indicators), the relationships between them and the outcome are nonlinear, and you would dearly love to model them with the gradient-boosted trees and deep nets you already trust. The trouble: the moment you let a flexible machine-learning model touch the problem the naive way — toss the treatment in as one more feature and read off its coefficient — your causal estimate is silently, systematically biased. Not noisy. Biased, in a direction you can’t sign and at a rate that does not vanish.

Double Machine Learning (DML) is the procedure that lets you keep all that ML horsepower and still recover a causal coefficient that is unbiased, n\sqrt{n}-consistent, and comes with honest confidence intervals. It rests on two ideas — orthogonalisation (partialling-out) and cross-fitting — and one beautiful property, Neyman orthogonality, that makes the whole thing work. This lesson installs all three.

The plug-in trap: regularization bias leaks into your effect

Before you read — take a guess

You have 200 candidate confounders and want the causal effect of a signal T on returns Y. You fit one big gradient-boosted model of Y on T plus all 200 confounders and read off T's 'importance'/coefficient. What goes wrong?

Analogy. You hire one contractor to do two jobs at once: estimate the effect of a new window on your heating bill, while also accounting for insulation, weather, and house size. To finish on budget (regularization), the contractor cuts corners on the hard part — modelling insulation and weather — and quietly shoves the leftover error into the one number you actually asked for, the window’s effect. The corners he cut on the nuisance work don’t cancel; they pile onto your answer. You wanted a clean measurement and got a measurement plus the contractor’s accumulated shortcuts.

Definition. Write the partially linear model

Y=θ0T+g0(X)+U,E[UT,X]=0,Y = \theta_0 T + g_0(X) + U, \qquad \mathbb{E}[U \mid T, X] = 0,

where TT is the treatment, XX is the (high-dimensional) confounder vector, g0g_0 is an unknown nuisance function, and θ0\theta_0 is the causal parameter you want. The treatment is itself driven by the confounders, T=m0(X)+VT = m_0(X) + V with E[VX]=0\mathbb{E}[V \mid X] = 0. The plug-in estimator fits g^\hat g and θ^\hat\theta jointly with one regularized learner and reports θ^\hat\theta. Its error decomposes into a well-behaved n\sqrt{n} term plus a regularization bias term that scales like the nuisance estimation error in m^\hat m times the error in g^\hat g — and for any learner that must regularize, that product shrinks slower than 1/n1/\sqrt{n}, so it dominates and does not vanish.

Worked example. Suppose the true effect is θ0=0\theta_0 = 0 (the signal causes nothing) but a confounder XX raises both TT and YY. A regularized learner shrinks its fitted g^(X)\hat g(X) toward zero, so it under-explains YY from XX and leaves residual outcome variation that still correlates with TT through the confounder. Numerically: say the regularization leaves g^\hat g capturing only 90% of the confounder’s effect on YY, and TT shares variance with that uncaptured 10%. The leftover correlation maps to a spurious θ^0.4\hat\theta \approx 0.4 where the truth is 00. Collect ten times more data and the bias barely moves — because regularization strength scales with dimension, not just sample size. You have a confident, tight, wrong confidence interval centred on 0.40.4.

Warning:

A tighter CI is not a more correct one

The plug-in’s failure is insidious because more data shrinks the variance (your interval gets narrower) while leaving the bias roughly intact. So the estimate looks more precise as nn grows, lulling you into trusting it, even as it stays parked at the wrong value. Bias and variance are different enemies: cross-validation and bigger datasets fight variance and overfitting; they do nothing for the structural regularization bias that DML is built to kill.

When to use it

Recognise the plug-in trap whenever you see “we controlled for everything by putting it all in the model and reading off the treatment’s SHAP value / coefficient.” That is the trap, verbatim. Any time the same flexible model both absorbs the confounders and estimates the effect, the effect is contaminated. The fix is never “use a better learner” — it is to separate the nuisance estimation from the effect estimation, which is exactly what the next section does.

Name the bias the plug-in suffers.

Pick the right option for each blank, then check.

Jointly fitting the nuisance and the effect with one regularized learner injects into the treatment coefficient, and it shrinks slower than root-n so it does not wash out with more data.

Partialling-out: residualize both sides, then regress the residuals

Before you read — take a guess

DML's first move is to 'partial out' the confounders. Concretely, what does it residualize?

Analogy. Two friends always show up to dinner having both already eaten — because the same host (the confounder XX) fed them beforehand. To learn whether one friend’s appetite genuinely drives the other’s, you first subtract off “how much the host fed each of them.” What’s left is each friend’s unexplained hunger. Correlate those leftovers and you’ve removed the host entirely. Residualizing YY and TT on XX is subtracting the host’s meal from both plates before you compare.

Definition. This is the Frisch-Waugh-Lovell (FWL) theorem, dragged into the ML era. Classic FWL says: in a linear regression, the coefficient on TT equals the slope you’d get by (1) regressing YY on the other variables and taking residuals Y~\tilde Y, (2) regressing TT on the other variables and taking residuals T~\tilde T, (3) regressing Y~\tilde Y on T~\tilde T. DML replaces the two “regress on XX” steps with arbitrary ML nuisance models:

Y~=Yg^(X),T~=Tm^(X),θ^=Cov^(T~,Y~)Var^(T~).\tilde Y = Y - \hat g(X), \qquad \tilde T = T - \hat m(X), \qquad \hat\theta = \frac{\widehat{\mathrm{Cov}}(\tilde T, \tilde Y)}{\widehat{\mathrm{Var}}(\tilde T)}.

Here g^(X)=E[YX]\hat g(X) = \mathbb{E}[Y \mid X] is the outcome model and m^(X)=E[TX]\hat m(X) = \mathbb{E}[T \mid X] is the propensity / treatment model. Both may be gradient-boosted trees, random forests, neural nets — anything. The estimator θ^\hat\theta is just a one-variable regression of clean residuals on clean residuals.

Worked example. Five observations of a signal TT and next-period return YY, with confounder predictions m^(X)\hat m(X) and g^(X)\hat g(X) already fitted by some ML model. Compute the residuals, then θ^\hat\theta.

ObsTTm^(X)\hat m(X)T~=Tm^\tilde T = T-\hat mYYg^(X)\hat g(X)Y~=Yg^\tilde Y = Y-\hat g
11.00.6+0.42.21.4+0.8
20.40.5−0.11.01.2−0.2
30.90.7+0.21.91.5+0.4
40.20.5−0.30.81.4−0.6
50.50.7−0.21.11.5−0.4

The residuals are mean-zero. Now θ^=T~Y~T~2\hat\theta = \frac{\sum \tilde T\,\tilde Y}{\sum \tilde T^2}:

T~Y~=(0.4)(0.8)+(0.1)(0.2)+(0.2)(0.4)+(0.3)(0.6)+(0.2)(0.4)=0.32+0.02+0.08+0.18+0.08=0.68,\textstyle\sum \tilde T\,\tilde Y = (0.4)(0.8)+(-0.1)(-0.2)+(0.2)(0.4)+(-0.3)(-0.6)+(-0.2)(-0.4) = 0.32+0.02+0.08+0.18+0.08 = 0.68, T~2=0.16+0.01+0.04+0.09+0.04=0.34,θ^=0.680.34=2.0.\textstyle\sum \tilde T^2 = 0.16+0.01+0.04+0.09+0.04 = 0.34, \qquad \hat\theta = \frac{0.68}{0.34} = 2.0.

So after scrubbing the confounders out of both sides, a one-unit change in the confounder-free part of the signal moves the confounder-free part of the return by 2.02.0. That slope is the causal θ^\hat\theta — and notice it came from a trivial univariate regression once the ML had done the partialling-out.

Warning:

Residualize the treatment too — not just the outcome

The single most common DML mistake is to residualize only YY (build a great outcome model) and then regress those residuals on the raw treatment TT. That leaves the confounders’ fingerprints all over TT, so the back door is still open and θ^\hat\theta is biased. You must also build m^(X)\hat m(X) and form T~\tilde T. Both residualizations are load-bearing; dropping the treatment model collapses DML back into a dressed-up plug-in.

When to use it

Reach for partialling-out whenever the confounder structure is high-dimensional or nonlinear but the effect of interest is a single, low-dimensional parameter you can defend as roughly linear (a per-unit signal effect, an average treatment effect). Let the ML do the messy, high-dimensional nuisance work where flexibility pays; keep θ\theta in a simple, interpretable, low-dimensional regression where you actually want inference. That division of labour — flexible nuisances, simple target — is the heart of DML.

Pick a term, then click its definition.

Neyman orthogonality: why slow ML nuisances still give a clean effect

Before you read — take a guess

The residual-on-residual (orthogonalized) estimator tolerates noisy, slowly-converging ML nuisance fits and still gives an unbiased root-n theta. Why?

Analogy. Imagine balancing a marble in a bowl. At the very bottom — the orthogonal point — the surface is flat: nudge the marble a little in any direction and its height barely changes, because the slope is zero there. The plug-in estimator parks the marble on a slope instead: the same small nudge (a small nuisance error) rolls it noticeably downhill, changing your answer. Orthogonalising the moment condition moves you to the flat bottom of the bowl, where small mistakes in the nuisance models simply don’t tilt the estimate.

Definition. Let ψ(W;θ,η)\psi(W; \theta, \eta) be the score (estimating equation) whose root defines θ^\hat\theta, where η=(g,m)\eta = (g, m) are the nuisances. The score is Neyman-orthogonal if its Gâteaux derivative with respect to η\eta, evaluated at the truth, is zero:

rE[ψ(W;θ0,η0+r(ηη0))]r=0=0.\left.\frac{\partial}{\partial r}\, \mathbb{E}\big[\psi(W; \theta_0, \eta_0 + r(\eta - \eta_0))\big]\right|_{r=0} = 0 .

For the partially linear model the orthogonal score is the residual-on-residual moment ψ=(Yg(X)θ(Tm(X)))(Tm(X))\psi = (Y - g(X) - \theta(T - m(X)))(T - m(X)). Because the first-order term vanishes, the estimator’s bias depends only on the product of the nuisance errors, schematically g^g0m^m0\lVert \hat g - g_0 \rVert \cdot \lVert \hat m - m_0 \rVert. If each ML model converges at the modest rate n1/4n^{-1/4} — far slower than the n1/2n^{-1/2} a parametric model needs — the product converges at n1/2n^{-1/2}, fast enough that θ^\hat\theta is n\sqrt{n}-consistent and asymptotically normal. The naive plug-in’s score is not orthogonal: its derivative is nonzero, so nuisance error enters linearly at the slow n1/4n^{-1/4} rate and swamps the n\sqrt{n} signal.

Worked example. Suppose each ML nuisance has estimation error of size 0.10.1 (i.e. g^\hat g and m^\hat m are each off by about 10%). In the non-orthogonal plug-in, that 0.10.1 enters θ^\hat\theta‘s bias linearly → bias 0.1\approx 0.1, a large, persistent offset. In the orthogonal DML score, the same errors enter only through their product → bias 0.1×0.1=0.01\approx 0.1 \times 0.1 = 0.01, an order of magnitude smaller, and it keeps shrinking as the nuisances improve. Same imperfect models, same data; orthogonality alone turned a 0.10.1 bias into a 0.010.01 one. That is the entire payoff of moving to the flat bottom of the bowl.

Warning:

Orthogonality buys insensitivity, not immunity

Neyman orthogonality kills the first-order dependence on nuisance error, not all of it. The second-order product term still needs both g^\hat g and m^\hat m to converge at a combined rate beating n1/2n^{-1/2} (e.g. each at n1/4n^{-1/4}). If one nuisance model is hopeless — say the treatment is nearly unpredictable from XX and m^\hat m never converges — the product term does not vanish and DML’s guarantees lapse. Orthogonality is a powerful insurance policy with a deductible, not a blank cheque to use garbage learners.

When to use it

Lean on orthogonality precisely when your nuisance models are good but not great — flexible ML that you trust to converge, but slowly and with bias you can’t characterise. That describes essentially every real high-dimensional finance problem. When instead you have a clean low-dimensional parametric nuisance you fully believe, you don’t strictly need DML’s machinery — but using the orthogonal score costs nothing and protects you if that belief is wrong, so orthogonalising is a no-regret default.

Sort each statement under the estimator whose behaviour it describes.

Place each item in the right group.

  • A tighter confidence interval that stays centred on the wrong value
  • Allows root-n inference with nuisances converging only at the quarter-root rate
  • Nuisance error enters the effect linearly, at the slow rate
  • Nuisance error enters only through the product of the two errors
  • Bias persists even as the sample grows
  • The score's derivative in the nuisances is zero at the truth

Cross-fitting: estimate the nuisance and the effect on different data

Before you read — take a guess

Even with an orthogonal score, DML splits the data: nuisances are fit on one fold, residuals/score evaluated on the held-out fold, then folds are swapped and averaged. What does this cross-fitting buy you?

Analogy. Don’t let students grade their own exams. If the same person who wrote the answer key also marks their paper, they’ll unconsciously mark themselves generous — the “error” they’re measuring includes the help they gave themselves. Cross-fitting splits the class: group A writes the key (fits the nuisance), group B is graded by it (scored on held-out data), then they swap so everyone gets both written and graded. Nobody marks their own work, so the measured residuals are honest.

Definition. Cross-fitting (a.k.a. sample-splitting / DML2) partitions the data into KK folds. For each fold kk: fit g^\hat g and m^\hat m on all other folds (k-k), then form residuals and evaluate the orthogonal score only on fold kk using those out-of-fold nuisances. Average the per-fold θ^k\hat\theta_k (or pool the scores) into one estimate. Because each observation is scored by a nuisance model that never saw it, the residuals carry no own-observation overfitting, and the remainder terms that orthogonality controls actually go to zero. Orthogonality handles the bias from imperfect nuisances; cross-fitting handles the bias from a nuisance peeking at the very point it scores. You need both.

Worked example — a 2-fold cross-fit. Split the sample in half. Fold A’s nuisances are trained on Fold B’s data and used to score Fold A; Fold B’s nuisances are trained on Fold A and score Fold B. Average the two slopes.

StepTrain nuisances onScore (form residuals + theta) onFold estimate
Pass 1Fold BFold Aθ^A=1.9\hat\theta_A = 1.9
Pass 2Fold AFold Bθ^B=2.1\hat\theta_B = 2.1
Combineθ^=12(1.9+2.1)=2.0\hat\theta = \tfrac12(1.9 + 2.1) = 2.0

Each half is scored by a model that never trained on it, so neither θ^A\hat\theta_A nor θ^B\hat\theta_B is inflated by self-grading. The averaged θ^=2.0\hat\theta = 2.0 uses the full sample for inference while keeping fitting and scoring strictly disjoint.

Now the time-series catch. A plain random fold split leaks the future into the past: a nuisance trained on a fold containing tomorrow’s data, then scoring today, has peeked across the autocorrelation. So in finance you cross-fit with the purged, embargoed splits from the deep-learning lesson — folds respect time order, observations near the train/test boundary whose label windows overlap are purged, and a short embargo gap after each test block prevents leakage through serial correlation. Cross-fitting and purged CV are the same idea wearing two hats: keep the scoring data strictly out-of-sample relative to the fitting data — in features and in time.

Purged & embargoed k-fold: stop the backtest from seeing the future
TrainTestPurgedEmbargo
earlierlater (time →)
Train26Test8Purged4Embargo2

Purged, embargoed cross-validation: training blocks (one fold) and a held-out test block, with purged observations and an embargo gap removed at the boundary. DML cross-fitting on time series uses exactly this scheme — nuisances are fit on the train blocks and the orthogonal score is evaluated on the embargoed, purged test block, so no future information leaks into the residuals through autocorrelation.

Warning:

Random K-fold quietly leaks the future

The default scikit-learn KFold shuffles rows, which is fine for i.i.d. data and catastrophic for returns. With overlapping label windows or autocorrelation, a shuffled fold lets a nuisance model train on data adjacent (in time) to the very points it scores, manufacturing artificially small residuals and an overconfident, biased θ^\hat\theta. On any time series, cross-fit with purged-and-embargoed splits — never a naive random shuffle. The leakage doesn’t announce itself; it just hands you a too-good, too-tight estimate.

When to use it

Always cross-fit — it is not optional polish but a load-bearing pillar of the DML guarantees, and the cost is only refitting the nuisances KK times (use K=5K = 5 or 1010). The choice that varies is the splitting scheme: i.i.d. cross-sectional data tolerates ordinary K-fold; anything with a time index, overlapping horizons, or serial correlation demands purged-and-embargoed folds. Pick the split that matches your dependence structure, then cross-fit without exception.

If the orthogonal score is already insensitive to nuisance error, why do we still need cross-fitting at all?

Answer. Orthogonality and cross-fitting fight different terms in the error expansion. Orthogonality kills the first-order bias from nuisances being systematically wrong (regularised, biased). Cross-fitting kills the own-observation bias from a nuisance being fit to the very point it then scores — a correlation between the nuisance estimate and the scoring residual that the orthogonality argument explicitly assumes away (it needs the nuisance to be independent of the evaluation sample). Skip cross-fitting and you reintroduce an O(1)O(1) overfitting term that orthogonality cannot touch, especially with flexible learners that overfit hard. They are complementary: orthogonality + cross-fitting together are what deliver n\sqrt{n}-consistent, asymptotically normal θ^\hat\theta. Drop either and the guarantee lapses.

DML for alpha and treatment effects — and its honest limits

Before you read — take a guess

A quant uses DML to estimate the causal effect of a sentiment signal on returns, flexibly controlling for the full factor-exposure set with gradient boosting, with clean overlap and purged cross-fitting. What can DML still NOT save them from?

Analogy. DML is a spectacular pair of noise-cancelling headphones for measured noise: feed it the frequencies of the confounders you can hear (the factor exposures, liquidity state, regime) and it cancels them flawlessly, however complex their waveform. But it cancels nothing it can’t sample. A confounder you never measured is a sound outside the microphone’s range — the headphones can’t subtract what they never recorded. DML upgrades how well you cancel observed noise; it does not upgrade what you’re able to hear.

Definition. In finance DML answers questions of the form “what is the causal effect of treatment TT on outcome YY, flexibly adjusting for the entire observed confounder set XX?”:

  • Alpha / signal evaluation. TT = the signal (or a do-able version of it), YY = forward return, XX = factor loadings, sector, size, liquidity, vol regime. DML estimates the signal’s effect net of everything the factor zoo would otherwise claim — answering “is there alpha after orthogonalising to all known exposures?” with ML-grade flexibility instead of a brittle linear factor regression.
  • Execution / treatment effects. TT = an execution choice (participation rate, order aggressiveness), YY = realised cost, XX = order and market state. DML recovers the causal cost of trading harder while flexibly controlling for the conditions under which you chose to trade harder.
  • Heterogeneous effects. Plain DML gives the average θ0\theta_0. Swap the final residual-on-residual regression for one with effect modifiers — or use a causal forest (DML’s local cousin) — to estimate θ0(Z)\theta_0(Z): how the effect varies with regime, size, or volatility. This is where “the signal works in high-vol names but not low-vol” becomes an estimated causal statement, not a data-mined subgroup.

Worked example. A signal’s raw long-short return is 5%5\% a year. A naive plug-in (signal plus factors in one boosted model) reports a causal effect of 4%4\% — suspiciously close to the raw number, because regularization bias left factor exposure leaking into it. Run proper DML: residualize forward returns on factors with one ML model (g^\hat g), residualize the signal on factors with another (m^\hat m), cross-fit with purged folds, regress residual-on-residual. The orthogonalised effect comes back at θ0=1.2%\theta_0 = 1.2\% with a confidence interval that excludes zero. Interpretation: 3.8%3.8\% of the raw 5%5\% was factor exposure the signal was proxying (a confounder you can buy cheaply with an index), and only 1.2%1.2\% is genuine, exposure-neutral causal alpha. The plug-in’s 4%4\% would have had you lever up a number that was almost entirely repackaged beta.

Warning:

DML needs overlap, and only adjusts for what you measured

Two assumptions are doing quiet work. Unconfoundedness: every common cause of TT and YY is in XX — violate it (a hidden confounder) and DML returns a precise, confident, biased number, with none of the warning signs. Overlap / positivity: at every confounder configuration the treatment must have genuine variation (the conditional variance of the treatment residual stays strictly positive); if XX predicts TT almost perfectly, m^(X)T\hat m(X) \approx T, the treatment residual collapses toward zero, and dividing by its near-zero variance produces an exploding, unstable θ^\hat\theta. DML relaxes functional form, not identification — when you fear unobserved confounding, go back to instruments, natural experiments, or RDD.

When to use it

Reach for DML when you can credibly list and measure your confounders but cannot credibly specify their functional form — the typical state of factor-heavy quant work, where you know the exposures but not how they nonlinearly map to returns. It is the right tool for “estimate this effect net of dozens of known, messy controls.” It is the wrong tool when the threat is a confounder you cannot observe (then you need an exogenous source of variation) or when overlap fails because the treatment is nearly deterministic in XX. Use DML to get expert-grade flexibility on the adjustment, and keep your identification honesty — observed-only, overlap-required — fully intact.

State DML's core limitation in one line.

Pick the right option for each blank, then check.

DML flexibly adjusts only for , so it remains biased by any hidden common cause and additionally requires overlap — variation in the treatment at every confounder configuration.

Recap

You walked in wanting to control for dozens of nonlinear confounders with the ML models you already trust, and learned why doing it the obvious way — one big model, read off the treatment — is biased, not noisy: regularization bias from the nuisance fit leaks into θ\theta and refuses to wash out. DML rescues the situation with three moves. Partialling-out (modern Frisch-Waugh-Lovell) residualizes both the outcome and the treatment against XX with arbitrary ML, then regresses the residuals — a contractor for the messy nuisance work and a clean univariate regression for the answer. Neyman orthogonality parks the estimator at the flat bottom of the bowl, where nuisance errors enter only through their product, so slow, biased ML nuisances still yield a n\sqrt{n}, normally-distributed θ\theta. Cross-fitting stops the nuisance from grading its own homework — and on time series it is purged, embargoed CV, because future leakage is just self-grading across the autocorrelation. The payoff is enormous and the limit is sharp: DML cancels observed confounders with ML-grade flexibility and demands overlap, but it is blind to the confounders you never measured. Unbiased, honest, and not magic.

Big picture

Double Machine Learning

  • Double Machine Learning
    • The plug-in trap
      • One model: read off the treatment
      • Regularization bias leaks into theta
      • Tighter CI, still wrong value
    • Partialling-out (FWL)
      • Residualize Y on X with g(X)
      • Residualize T on X with m(X)
      • Regress residual on residual = theta
    • Neyman orthogonality
      • Score derivative in nuisances = 0
      • Errors enter only as a product
      • Slow ML still gives root-n theta
    • Cross-fitting
      • Fit on one fold, score on another
      • Kills own-observation overfitting
      • Time series = purged + embargoed CV
    • Use and limits
      • Exposure-neutral alpha + execution effects
      • Heterogeneity: causal forests
      • Observed confounders only; needs overlap
Build the map: the plug-in trap, the three pillars (partialling-out, orthogonality, cross-fitting), and DML's honest limits.

Mixed check: can you orthogonalise without overfitting?

Question 1 of 50 correct

A colleague reports an unbiased causal effect from a single gradient-boosted model containing the treatment and 150 controls, citing a very tight confidence interval as proof. What is the flaw in that reasoning?

Check your answer to continue.

Mark lesson as complete