Double Machine Learning : Estimer un Paramètre Causal au lieu de Prédire les Rendements
Chaque article de modélisation de ce blog jusqu'à présent pose la même forme de question : étant donné des caractéristiques, prédire un nombre, puis valider que la prédiction survit hors échantillon. Les modèles de spread prédisent le spread. Les modèles de remplissage prédisent la probabilité de remplissage. Tout l'appareil de validation — walk-forward purgé, Sharpe déflaté, taxonomie du look-ahead — existe pour vérifier si une prédiction est réelle.
Cet article pose une forme différente de question, et c'est la seule pièce de machinerie que le blog n'a jamais eue : estimer un seul paramètre scalaire qui a une interprétation causale, et attacher une erreur standard qui survit au fait qu'un modèle ML flexible a été utilisé pour y arriver.
Ce n'est pas une distinction rhétorique. "La position dans la file prédit la probabilité de remplissage" est trivialement vraie et opérationnellement inutile — bien sûr qu'elle le fait, les deux sont pilotés par la profondeur et la volatilité. "Avancer d'une position dans la file cause un changement de dans la probabilité de remplissage, l'état du marché étant fixé" est un nombre que vous pouvez mettre dans une politique de placement d'ordres. La première est un ajustement de régression. La seconde nécessite un estimateur qui n'existe pas dans la boîte à outils ML standard, car la régularisation et le surajustement dans une première étape flexible faussent exactement le coefficient qui vous intéresse.
Double Machine Learning (Chernozhukov, Chetverikov, Demirer, Duflo, Hansen, Newey & Robins, 2018) est l'estimateur qui résout ce problème. Tout trader quantitatif a entendu ceci : corrélation n'est pas causalité. DML est la partie qui vient après cette phrase.
Pourquoi la Régression Naïve Échoue

Posons la question sur le territoire propre du blog. Nous voulons l'effet causal de la position dans la file sur la probabilité de remplissage :
- : si l'ordre limite au repos à l'observation a été rempli dans l'horizon.
- : position dans la file au placement (normalisée par la taille du niveau).
- : les confondus — volatilité réalisée, spread coté, déséquilibre de profondeur, taille du niveau, heure de la journée, étiquette de régime. Ce sont les variables d'état du marché que le blog calcule déjà dans modélisation du spread avec le machine learning.
Le paramètre causal est dans
où capture la relation (potentiellement complexe, non linéaire) entre l'état du marché et le résultat de remplissage.
Le traitement n'est pas assigné aléatoirement. Vous êtes près du front de la file parce que le niveau était fin, ou parce que vous avez posté pendant une période calme, ou parce que le carnet était déséquilibré en votre faveur. Les mêmes conditions pilotent indépendamment si vous êtes rempli. C'est la confusion.
Approche 1 : Ignorer les confondus. Régresser sur seul. L'estimation absorbe l'effet de chaque confondu corrélé avec les deux. Biais de variable omise教科书 : les niveaux fins vous donnent à la fois une bonne place dans la file et un taux de remplissage élevé, donc vous exagérez la valeur de la place elle-même.
Approche 2 : Régression linéaire avec contrôles. Régresser sur et . Cela ne fonctionne que si est vraiment linéaire. La dynamique du carnet ne l'est pas — la relation remplissage/volatilité a des seuils, l'effet de déséquilibre de profondeur change de signe selon le régime. Spécifier mal réintroduit le biais.
Approche 3 : Prédiction ML. Ajuster un modèle gradient-boosted sur . Vous obtenez une bonne discrimination hors échantillon, et aucune interprétation causale whatsoever. Le modèle capture chaque motif prédictif, causal ou non ; la régularisation rétrécit la contribution du traitement de manière à biaiser ; et il n'y a pas d'erreur standard en laquelle vous pouvez avoir confiance.
C'est la tension centrale. ML est bon pour la prédiction, mais l'application naïve à un paramètre causal produit des estimations biaisées, non normales, non fiables.
Le Modèle Partiellement Linéaire

DML opère dans un cadre structurel. Le cheval de labour est la régression partiellement linéaire (PLR) :
- est le paramètre causal d'intérêt.
- est une fonction de nuisance — la partie du résultat expliquée par l'état du marché.
- est une autre fonction de nuisance — l'espérance conditionnelle du traitement étant donné l'état du marché (la "propensity" dans un cadre de traitement continu).
- et sont des résidus structurels.
L'insight clé : est de basse dimension, mais et peuvent être arbitrairement complexes. Nous voulons que ML gère les fonctions de nuisance tout en délivrant encore une inférence valide sur le scalaire.
Pourquoi "Double" ?
Deux modèles ML, pas un seul :
- Modèle de résultat : — prédire le résultat à partir de l'état du marché seul.
- Modèle de traitement : — prédire le traitement à partir de l'état du marché seul.
Former les résidus
et estimer en régressant sur :
C'est Frisch-Waugh-Lovell aux stéroïdes : partial out les confondus avec ML au lieu d'une projection linéaire, puis lire l'effet du traitement à partir de la variation résiduelle.
Orthogonalité de Neyman : Pourquoi Ça Marche
L'approche de partial-out naïve (estimer , soustraire, régresser) échoue car les erreurs d'estimation ML dans se propagent directement dans . Le score DML est construit pour être Neyman orthogonal — insensible aux petites perturbations dans les fonctions de nuisance.
Le score orthogonal pour PLR :
où . La condition d'orthogonalité est
Intuitivement, le score n'utilise que la variation dans et qui est indépendante de , et les erreurs dans une fonction de nuisance sont compensées par l'autre. Si sur-prédit légèrement le traitement, est légèrement trop petit, mais l'erreur correspondante dans d'avoir mal estimé pousse dans une direction compensatoire. Le biais devient du second ordre — le produit de deux erreurs de première étape — plutôt que du premier ordre.
Formellement, si les deux estimateurs de nuisance convergent au taux (doux ; la plupart des méthodes ML raisonnables satisfont cela), alors
donc converge au taux paramétrique et est asymptotiquement normal.
Cross-Fitting : Pourquoi C'est Obligatoire Ici
L'orthogonalité seule ne suffit pas. Si les modèles de nuisance sont ajustés sur les mêmes lignes utilisées pour estimer , le surajustement de première étape contamine la deuxième étape — et le dommage spécifique vaut la peine d'être énoncé précisément, car ce n'est pas le dommage auquel vous êtes habitué. Ailleurs, le surajustement se manifeste comme un score de validation gonflé : vous le remarquez, vous le rabattez, vous continuez. Ici, il se manifeste comme une estimation de point décalée pour , avec un intervalle de confiance toujours étroit et toujours centré sur le mauvais nombre. Il n'y a pas de score dont être soupçonneux. L'estimateur ment simplement tranquillement.
Le cross-fitting brise la dépendance : les prédictions de nuisance de chaque observation viennent d'un modèle entraîné sans elle, et est estimé à partir des résidus held-out regroupés. La mécanique est la machinerie K-fold ordinaire, couverte dans modélisation du spread avec le machine learning ; ce qui compte en bas est quels folds vous lui donnez.
L'Algorithme DML Étape par Étape
Entrée : données , méthodes ML et , folds .
Étape 1 — Partition : diviser en folds disjoints.
Étape 2 — Cross-fit les modèles de nuisance : pour , entraîner et sur le complément du fold , puis calculer et pour .
Étape 3 — Estimation :
Étape 4 — Inférence :
avec intervalles .
L'intervalle de confiance est valide pour exactement une question
C'est la réserve qui décide si un résultat DML vaut quelque chose, et c'est là que la plupart des usages appliqués de la méthode s'effondrent silencieusement.
La normalité asymptotique ci-dessus est une déclaration sur un traitement prédéfini, un ensemble de confondus prédéfini, un score prédéfini. Fixez ceux à l'avance, exécutez l'estimateur une fois, et l'intervalle signifie ce qu'il dit. Essayez trois traitements candidats, ou quatre ensembles de confondus, ou swappez les learners jusqu'à ce que la p-value ait l'air mieux, et vous ne faites plus d'inférence — vous exécutez une recherche, et la p-value rapportée est la p-value d'un maximum, pas d'un tirage.
Le blog a déjà mesuré ce que cela fait. Dans l'étude du Sharpe ratio déflaté, les recherches sur du bruit pur avec zéro avantage réel produisent un taux de fausse découverte naïf de 1,000 — le test non ajusté se déclenche à chaque fois — alors que la p-value naïve médiane du gagnant s'assoit près de 0,0007. Rien dans l'orthogonalité de Neyman ne vous protège de cela. L'orthogonalité corrige le biais de l'estimation de nuisance ; elle ne dit rien du biais de la recherche de spécification. Une p-value DML de 1e-05 obtenue après avoir essayé six spécifications mérite exactement le même traitement Bonferroni/Holm/BHY que tout autre gagnant tiré d'une grille, avec réglé au nombre de spécifications que vous avez réellement exécutées.
Cela a une conséquence pratique directe pour les fonctionnalités de commodité des outils. DoubleMLData accepte une liste dans d_cols et retournera avec plaisir trois effets de traitement dans un seul tableau récapitulatif :
dml_data_multi = dml.DoubleMLData(
df, y_col='filled', d_cols=['queue_pos', 'toxicity', 'spread_at_post'],
x_cols=confounder_cols,
)
Trois lignes, trois p-values, et un problème de tests multiples que le tableau récapitulatif ne mentionne pas. Si vous lisez les trois, ajustez les trois. Si seulement un était la question préenregistrée, dites-le, et traitez les deux autres explicitement comme exploratoires.
Cross-Fitting sur Séries Temporelles : Purge, Embargo, Folds Personnalisés

DML standard suppose des observations i.i.d. Les données de carnet ne le sont pas, et le mode d'échec est celui que le blog a déjà documenté en détail : les lignes adjacentes partagent des fenêtres forward qui se chevauchent, donc un TimeSeriesSplit ordinaire fuite encore la réponse à travers la limite du fold. Voir modélisation du spread avec le machine learning pour l'implémentation walk-forward purgée et embarguée et la raison pour laquelle un écart d'au moins horizon lignes est requis, et la taxonomie du biais de look-ahead pour le catalogue complet des fuites et leurs grandeurs mesurées.
La partie vraiment spécifique à DML est comment vous remettez des folds purgés à l'estimateur, car set_sample_splitting a un contrat qui fait trébucher les gens :
import numpy as np
import doubleml as dml
def purged_folds(n: int, n_splits: int, horizon: int):
"""Folds à fenêtre expansive avec un écart purge/embargo de `horizon` lignes.
Même construction que le CV walk-forward purgé dans l'article de
modélisation du spread : l'écart élimine le chevauchement entre la fenêtre
forward d'une ligne d'entraînement et une ligne de validation.
"""
fold_size = n // (n_splits + 1)
for k in range(1, n_splits + 1):
train_end = fold_size * k
val_start = train_end + horizon
val_end = val_start + fold_size
if val_end > n:
break
yield np.arange(0, train_end - horizon), np.arange(val_start, val_end)
folds = list(purged_folds(len(df), n_splits=5, horizon=HORIZON))
dml_plr = dml.DoubleMLPLR(dml_data, ml_l=ml_l, ml_m=ml_m)
dml_plr.set_sample_splitting([folds])
dml_plr.fit()
Deux choses à savoir, aucune d'entre elles évidente à partir des docs de la bibliothèque :
- Les folds walk-forward purgés ne couvrent pas chaque ligne. Les écarts de purge et le bloc d'entraînement initial ne sont jamais le fold de test de personne, donc est estimé à partir de strictement moins de résidus. C'est un comportement correct, pas un bug, mais cela signifie que le effectif dans la formule de variance est le nombre de lignes de test regroupées — vérifiez-le plutôt que de le supposer.
- Les répétitions
n_repne sont pas gratuites ici. Avec K-fold aléatoire, répéter le cross-fitting et moyenner est une réduction de variance bon marché. Avec un split déterministe ordonné dans le temps, il n'y a qu'un seul split, doncn_repn'achète rien et ne cache rien ; la stabilité doit venir de la réexécution sur différentes fenêtres de données à la place.
Pour les structures de panel (plusieurs symboles sur la même période), DoubleML prend en charge les erreurs standard robustes en grappe — grouper sur symbole, pas sur temps, et voir validation multi-symboles pour la position du blog sur quand un résultat cross-instrument est réellement établi.
Le Cas Mesuré : Position dans la File et Probabilité de Remplissage

C'est la seule question causale dans l'article où le projet a déjà les données, et elle devrait être exécutée plutôt que posée. L'analyse de position dans la file couvre déjà l'estimation de position, la mécanique FIFO, les taux de drainage et le temps-à-remplissage sur de vraies données de carnet ; la simulation de remplissage couvre la modélisation de probabilité de remplissage et la boucle d'étalonnage contre les remplissages en direct. Les deux produisent un modèle prédictif de remplissages. DML transforme les mêmes entrées en une estimation causale.
La spécification, préenregistrée avant de regarder l'estimation :
- Résultat : rempli dans
HORIZONsnapshots (binaire). - Traitement : position dans la file normalisée au placement.
- Confondus : volatilité réalisée 1s, spread coté en bps, déséquilibre de profondeur, taille de niveau au post, distance du mid en ticks, encodage de l'heure de la journée, étiquette de régime.
from sklearn.ensemble import GradientBoostingRegressor
import doubleml as dml
confounder_cols = [
'rv_1s', 'spread_bps', 'depth_imbalance', 'level_size',
'dist_from_mid_ticks', 'tod_sin', 'tod_cos', 'regime',
]
dml_data = dml.DoubleMLData(
df, y_col='filled', d_cols='queue_pos_norm', x_cols=confounder_cols,
)
ml_l = GradientBoostingRegressor(n_estimators=300, max_depth=5)
ml_m = GradientBoostingRegressor(n_estimators=300, max_depth=5)
dml_plr = dml.DoubleMLPLR(dml_data, ml_l=ml_l, ml_m=ml_m, score='partialling out')
dml_plr.set_sample_splitting([folds])
dml_plr.fit()
print(dml_plr.summary)
dml_plr.sensitivity_analysis()
print(dml_plr.sensitivity_summary)
Le résultat à rapporter est une comparaison à quatre colonnes, pas un seul coefficient : l'estimation naïve OLS de sur seul, l'estimation de contrôle linéaire de sur et , l'estimation DML avec son erreur standard, et la valeur de robustesse de l'analyse de sensibilité — à quel point un confondu non observé devrait être fort pour annuler l'effet. L'écart entre les colonnes naïves et DML est la quantité d'intérêt réel : c'est combien de la valeur apparente de la position dans la file était de l'état du marché déguisé.
Un nul ou négatif ici est un résultat publiable et correspond mieux à ce blog qu'un positif propre. Si l'effet causal de la position dans la file s'effondre une fois la volatilité et la taille de niveau partiellement éliminées, c'est un résultat direct sur la politique de placement d'ordres : la place n'est pas ce qui gagne le remplissage, les conditions dans lesquelles vous avez obtenu la place le sont.
Analyse de Facteur Causal
L'approche standard à l'investissement factoriel est associatif : trier par une caractéristique, former des portefeuilles long-court, observer que les rendements diffèrent. DML permet un test différent — estimer l'effet causal direct d'une caractéristique sur les rendements, nettoyant les effets de confusion des autres caractéristiques. Si l'effet disparaît sous DML, le facteur n'est pas indépendamment causal ; c'est un proxy.
C'est une deuxième, forme indépendante de scepticisme factoriel, et cela vaut la peine d'être explicite sur la façon dont cela se rapporte à celui que le blog publie déjà. Le Sharpe ratio déflaté attaque le zoo de facteurs du côté de la sélection : avec suffisamment d'essais, un facteur peut paraître significatif purement parce que vous avez regardé plusieurs fois. DML l'attaque du côté de la confusion : un facteur peut paraître significatif sur un seul test honnête et être toujours un proxy pour autre chose dans l'ensemble de conditionnement. Un facteur doit survivre aux deux pour être intéressant, et les deux modes d'échec sont indépendants — en passer un ne vous dit rien sur l'autre.
Ce Que DML Ne Peut Pas Faire
-
Il exige que les confondus soient observés. Si une variable non observée pilote à la fois le traitement et le résultat, DML est biaisé, et aucune sophistication ML ne corrige un problème d'identification. L'analyse de sensibilité borne le risque ; elle ne l'élimine pas.
-
Il estime un effet moyen. Si l'effet de la position dans la file varie fortement à travers les régimes, l'estimation de point est la moyenne sur le mix de régimes de votre échantillon. Pour l'hétérogénéité, utilisez le Interactive Regression Model (
DoubleMLIRM) ou une forêt causale. -
Il suppose un modèle structurel. La spécification partiellement linéaire exige que le traitement entre dans l'équation de résultat d'une manière particulière. Si le vrai processus est fondamentalement différent, DML est confiantément faux.
-
Il ne découvre pas de structure causale. DML estime l'effet d'un traitement prédéfini. Il ne vous dit pas quelles variables sont des causes.
-
Il ne vous exempte pas des tests multiples. Répéter le point ci-dessus parce que c'est le plus souvent sauté : l'orthogonalité de-biaise l'estimation de nuisance, pas la recherche de spécification.
Notes Pratiques
Taille d'échantillon. DML exige que les modèles de nuisance convergent à , ce qui en pratique signifie suffisamment de lignes pour que les modèles ML approximent et du tout. Plutôt que de faire confiance à des seuils de nombres ronds, établissez l'adéquation empiriquement de la manière dont la validation multi-symboles le fait — vérifiez si l'estimation tient à travers les instruments et les sous-périodes, et traitez l'instabilité comme le signal qu'elle est.
Choix du learner. Le fait spécifique à DML est étroit mais utile : étant donné la convergence , le learner affecte l'efficacité de (largeur d'intervalle), pas sa cohérence. Quels learners valent la peine d'atteindre sur les données de marché tabulaires, et pourquoi le gradient boosting est le défaut, est déjà couvert dans modélisation du spread avec le machine learning. Si se déplace matériellement à travers les learners, ce n'est pas un menu à choisir — c'est la preuve que les fonctions de nuisance sont mal estimées, et par la section ci-dessus, choisir le plus convivial transforme l'exercice en une recherche.
Conclusion
DML donne au blog quelque chose qu'il n'avait pas : un moyen d'énoncer une réclamation de microstructure de marché comme un paramètre causal avec une erreur standard défendable, plutôt que comme une prédiction avec un bon score de validation.
Les trois idées porteuses sont :
- Orthogonalisez le score pour que les erreurs de première étape se compensent au second ordre.
- Cross-fit, avec des folds purgés et embargués sur les données de séries temporelles, pour que le surajustement de première étape ne puisse pas déplacer .
- Prédéfinissez, pour que l'intervalle que vous rapportez est l'intervalle que vous avez réellement gagné.
L'estimateur est la partie facile. Les parties difficiles restent inchangées : décider quels confondus importent, plaider que les hypothèses d'identification tiennent, et résister à l'envie d'exécuter la spécification une fois de plus.
Références
La lignée de DML est courte et vaut une ligne : c'est le modèle partiellement linéaire de Robinson (1988) avec ML remplaçant les estimateurs de noyau, atteignant la borne d'efficience semi-paramétrique, avec une condition d'orthogonalité remontant au test C() de Neyman et un proche cousin dans la littérature de l'apprentissage ciblé (TMLE). La contribution de Chernozhukov et al. était de montrer que cela pouvait être rendu opérationnel avec des learners ML arbitraires tout en retenant l'inférence -cohérente, asymptotiquement normale.
- Chernozhukov, V., Chetverikov, D., Demirer, M., Duflo, E., Hansen, C., Newey, W., & Robins, J. (2018). Double/Debiased Machine Learning for Treatment and Structural Parameters. The Econometrics Journal, 21(1), C1-C68.
- Robinson, P. M. (1988). Root-N-Consistent Semiparametric Regression. Econometrica, 56(4), 931-954.
- Bach, P., Chernozhukov, V., Kurz, M. S., & Spindler, M. (2022). DoubleML — An Object-Oriented Implementation of Double Machine Learning in Python. Journal of Machine Learning Research, 23(53), 1-6.
- Facure, M. (2022). Causal Inference for the Brave and True. Chapter 22: Debiased/Orthogonal Machine Learning.
- Cahan, E., Bai, J., & Ng, S. (2024). Causal Factor Investing. Quantitative Finance.
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.