Forêts causales pour effets de traitement hétérogènes dans le trading
Chaque modèle prédictif sur ce blog estime le même objet : une moyenne conditionnelle . L'ingénierie de caractéristiques, le gradient boosting, les intervalles conformes, la validation walk-forward — tout cela sert un seul estimand. Cet article traite d'un estimand différent et de la machinerie qui change lorsque vous le remplacez.
L'objet est l'effet de traitement moyen conditionnel :
la différence entre deux résultats potentiels pour la même unité — dont vous n'observez jamais l'un. Vous ne pouvez pas faire de régression dessus, car il n'est pas dans vos données. Les forêts causales (Athey et Imbens 2016; Wager et Athey 2018) l'estiment de manière non paramétrique et, remarquablement, vous donnent un intervalle de confiance valide autour.
Trois choses rendent cela possible et aucune n'existe dans une forêt aléatoire standard : un critère de division qui maximise la variance de l'effet de traitement au lieu de minimiser l'erreur de prédiction, une contrainte d'honnêteté qui interdit d'utiliser les mêmes observations pour choisir une division et estimer l'effet à l'intérieur, et une relecture de la forêt comme un noyau adaptatif qui transforme la co-occurrence des feuilles en poids d'estimation. Ces trois choses, plus le test de calibration qui vous dit si l'hétérogénéité que vous avez trouvée est un signal, sont le contenu de cet article.
Des effets moyens aux effets hétérogènes

L'effet de traitement moyen
La configuration : un traitement binaire (un événement s'est produit ou non), un résultat (un rendement), des covariables . L'Effet de Traitement Moyen est
l'impact moyen sur toutes les unités. Pour le trading, c'est presque inutile — vous ne tradez pas la moyenne. Si un événement pousse la moitié de l'univers vers le haut et la moitié vers le bas, l'ATE est zéro et l'opportunité est maximale.
L'effet de traitement moyen conditionnel
Le CATE conditionne sur les caractéristiques. Étant donné une pièce avec une capitalisation boursière spécifique, une volatilité réalisée, un historique de funding et une profondeur du carnet, quel est l'impact de rendement attendu de cet événement sur cet actif ? Le CATE est une fonction sur l'espace des covariables, et estimer cette fonction sans imposer sa forme est ce que font les forêts causales.
Pourquoi ne pas utiliser simplement des modèles d'interaction linéaire ?
L'alternative du manuel est une régression saturée :
où porte l'interaction. Cela suppose que l'interaction est linéaire. C'est rarement le cas : la sensibilité à un changement de funding est convexe dans l'effet de levier, pas linéaire ; la profondeur interagit multiplicativement avec la capitalisation boursière ; le régime de volatilité verrouille tout le reste. Les forêts causales n'imposent rien de cela — elles partitionnent l'espace des covariables de manière adaptative et laissent la structure d'hétérogénéité émerger des données.
Forêts causales : L'algorithme

Une forêt causale est une forêt aléatoire reconstruite autour de l'estimand d'effet de traitement. Chaque arbre est un arbre causal qui partitionne l'espace des covariables pour maximiser l'hétérogénéité de l'effet de traitement.
Arbres causaux
À chaque nœud interne, l'algorithme choisit une variable de division et un point de division . La différence clé avec un arbre de régression : le critère maximise la variance de l'effet de traitement estimé parmi les enfants plutôt que de minimiser l'erreur de prédiction au carré.
Pour un nœud avec des données , l'estimation de l'effet au niveau du nœud est la différence des moyennes de groupe :
et le score de division est
avec les tailles d'échantillon dans l'enfant gauche, l'enfant droit et le parent. C'est exactement la variance inter-groupe des effets de traitement : une division est bonne quand les deux enfants ne sont pas d'accord sur l'effet, pas quand ils prédisent bien le résultat. Une covariable qui prédit fortement mais est orthogonale à la façon dont agit ne sera jamais sélectionnée.
Estimation honnête
L'innovation critique est l'honnêteté. Les données utilisées pour déterminer la structure de l'arbre doivent être disjointes des données utilisées pour estimer les effets des feuilles :
- Divisez les données en et
- Construisez l'arbre en utilisant seulement pour choisir les variables et points de division
- Estimez les effets des feuilles en utilisant seulement , en laissant tomber ces observations dans l'arbre déjà fixé
Sans cela, l'arbre triche : il sculpte des feuilles dont les effets extrêmes sont du bruit dans le même échantillon utilisé pour les trouver, puis rapporte ce bruit comme l'estimation. C'est le même échec de sélection adaptative que la probabilité de sur-ajustement de backtest mesure au niveau de la stratégie, sauf qu'ici il est défendu contre à l'intérieur de l'estimateur plutôt que diagnostiqué après coup. L'honnêteté achète l'absence de biais asymptotique :
Le prix est l'efficacité de l'échantillon — la moitié de vos données construit une structure qui ne peut ensuite être utilisée pour la remplir.
Des arbres aux forêts
Une forêt causale agrège arbres causaux, chacun sur un sous-échantillon aléatoire de taille avec un sous-ensemble de covariables aléatoire à chaque division :
La façon la plus utile d'écrire ceci est comme une moyenne pondérée des résultats :
avec des poids adaptifs fixés par la fréquence à laquelle l'observation atterrit dans la même feuille que :
où est la feuille contenant dans l'arbre . C'est la vue de forêt aléatoire généralisée (Athey, Tibshirani et Wager 2019) : une forêt causale est un estimateur de noyau localement adaptatif. Il apprend sa propre notion de "similaire", définie par les covariables qui comptent réellement pour l'hétérogénéité de l'effet, plutôt que par la distance euclidienne dans un espace où vous deviez choisir l'échelle à la main.
Théorie asymptotique
Sous des conditions de régularité (Wager et Athey 2018) l'estimateur est cohérent, , et asymptotiquement normal :
donnant des intervalles ponctuels . La variance provient du jackknife infinitésimal (ou bootstrap-de-petits-sacs), calculé à partir de la même structure de sous-échantillon que la forêt a déjà construite — aucune boucle bootstrap externe.
Il vaut la peine d'être précis sur ce que garantit cette garantie et ce qu'elle ne garantit pas. Elle est asymptotique et ponctuelle, et tient pour le CATE. Les intervalles de prédiction conforme utilisés ailleurs sur ce blog sont d'échantillon fini et sans distribution, mais marginaux, et couvrent un résultat. Différent estimand, différente garantie ; ils ne sont pas substituts.
La connexion Double Machine Learning
Lorsque le traitement n'est pas assigné aléatoirement, la forêt causale est ajustée sur des données résiduelles : un modèle de résultat et un modèle de propension sont estimés par ajustement croisé, et la forêt fonctionne sur contre . L'orthogonalité de Neyman est ce qui rend cela sûr : l'erreur d'estimation de nuisance n'entre que comme un produit, donc et peuvent chacun converger à et converge encore à .
Ce cadre — résidualisation, ajustement croisé, l'argument d'orthogonalité, implications de taille d'échantillon — est le sujet de son propre article, Double Machine Learning pour Signaux de Trading Causaux. Lisez-le d'abord ; tout ci-dessous le suppose et couvre seulement ce qui change quand l'estimand est au lieu de .
Application de trading : Hétérogénéité de l'impact des événements

Configuration
Le domaine naturel pour ce blog est l'univers des pièces perpétuelles, où les événements sont fréquents, horodatés et observables sans un feed de fournisseur.
- Unités : observations pièce-événement sur l'univers perp tradable
- Traitement : si l'événement s'est produit pour la pièce — un changement de signe de taux de funding, une inscription spot, ou une cascade de liquidation traversant le seuille supercritique décrit dans cascades de liquidation comme signal de trading — et pour les fenêtres non-événement correspondantes
- Résultat : = le rendement anormal sur la fenêtre d'événement, pas le rendement brut. Ajustez un modèle de marché sur une fenêtre d'estimation précédant l'événement, puis prenez le rendement anormal cumulatif. La spécification exacte — fenêtre d'estimation, régression de modèle de marché, construction de CAR et sa statistique t — est travaillée dans la section d'étude d'événement de minage d'alpha LLM à partir des appels de résultats; réutilisez-le tel quel. Cette étape n'est pas optionnelle : un résultat brut close-to-close laisse le mouvement à l'échelle du marché entrer dans , et puisque le mouvement du marché est commun à toutes les unités traitées, il ressemble exactement à un effet de traitement
- Covariables : capitalisation boursière, volatilité réalisée, historique de funding, profondeur du carnet d'ordres, ratio intérêt ouvert à capitalisation
- Confondeurs : variables de régime qui déplacent à la fois la probabilité d'événement et les rendements
Le signal de trading
La surface CATE se mappe sur un dimensionneur de position exactement comme toute estimation d'incertitude calibrée : dimensionnez par relatif à la largeur de l'intervalle, et ne tradez pas quand l'intervalle chevauche zéro. Cette règle de décision — dimensionnement de largeur inverse, le ratio d'edge , le filtre no-trade, la variante consciente des coûts, et l'argument pour pourquoi vous ne devriez pas le multiplier dans une fraction Kelly — est dérivé dans Prédiction Conforme pour Dimensionnement de Position Conscient du Risque. Réutilisez-le avec à la place de et l'intervalle de forêt causale à la place du conforme. Équilibrez les jambes longues et courtes et le livre est neutre au marché par construction.
Implémentation Python avec EconML
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingRegressor, GradientBoostingClassifier
from econml.dml import CausalForestDML
def fit_causal_forest(Y, T, X, W, n_estimators=1000):
"""
CausalForestDML: residualize against (X, W), then fit a causal
forest on the residuals.
Y: abnormal returns over the event window (CAR, market-model adjusted)
T: event indicator
X: effect modifiers -- only these drive heterogeneity
W: confounders -- enter the nuisance models only
"""
cf = CausalForestDML(
model_y=GradientBoostingRegressor(
n_estimators=200, max_depth=5, learning_rate=0.05
),
model_t=GradientBoostingClassifier(
n_estimators=200, max_depth=5, learning_rate=0.05
),
n_estimators=n_estimators,
min_samples_leaf=20,
max_depth=None,
criterion="het", # heterogeneity-based splitting
honest=True, # honest estimation
inference=True, # infinitesimal-jackknife intervals
cv=5, # cross-fitting folds for DML
random_state=42,
)
cf.fit(Y=Y, T=T, X=X, W=W)
return cf
def summarize_cate(cf, X, feature_names):
"""Distribution of the CATE and what drives its heterogeneity."""
tau_hat = cf.effect(X)
tau_lo, tau_hi = cf.effect_interval(X, alpha=0.05)
print(f"Mean CATE: {tau_hat.mean():.4f}")
print(f"Std CATE: {tau_hat.std():.4f}")
print(f"Range: [{tau_hat.min():.4f}, {tau_hat.max():.4f}]")
print(f"% CI excl. 0: {((tau_lo > 0) | (tau_hi < 0)).mean():.1%}")
for idx in np.argsort(cf.feature_importances_)[::-1]:
print(f" {feature_names[idx]:>20s}: {cf.feature_importances_[idx]:.4f}")
return tau_hat, tau_lo, tau_hi
Interpréter la surface CATE
Les graphiques d'effet marginal montrent comment l'effet de traitement se déplace le long d'une covariable avec le reste maintenu à sa médiane :
def plot_cate_by_feature(cf, X, feature_idx, n_points=50):
x_grid = np.linspace(X[:, feature_idx].min(),
X[:, feature_idx].max(), n_points)
X_eval = np.tile(np.median(X, axis=0), (n_points, 1))
X_eval[:, feature_idx] = x_grid
tau = cf.effect(X_eval)
tau_lo, tau_hi = cf.effect_interval(X_eval, alpha=0.05)
return x_grid, tau, tau_lo, tau_hi
Lisez ceux-ci comme descriptions de la surface ajustée, pas comme des courbes dose-réponse causales — maintenir les autres covariables à leur médiane peut vous placer dans une région de l'espace des covariables sans support.
Hypothèses clés et diagnostics

Violatez celles-ci et vous obtenez des effets confiants, précis, faux.
1. Absence de confusion (Sélection sur observables)
L'assignation de traitement doit être indépendante des résultats potentiels étant donné les covariables observées. Pour un événement défini mécaniquement c'est défendable ; pour un événement qui est lui-même une réaction de marché — une annonce d'inscription, le moteur de liquidation d'un échange se déclenchant — ce n'est pas le cas, car le même flux non observé qui a déclenché l'événement déplace aussi le rendement.
Testez-le avec l'analyse de sensibilité de Rosenbaum : si un non observé peut déplacer les cotes de traitement jusqu'à un facteur ,
à quel point doit-il être grand avant que l'effet estimé ne change de signe ? Un design qui casse à n'est pas une découverte.
2. Chevauchement (Positivité)
Chaque unité a besoin d'une probabilité positive d'apparaître dans les deux bras. Vérifiez les scores de propension et rogez :
propensity = cf.models_t[0][0].predict_proba(np.hstack([X, W]))[:, 1]
print(f"Propensity range: [{propensity.min():.3f}, {propensity.max():.3f}]")
valid = (propensity > 0.05) & (propensity < 0.95)
print(f"Retained after trimming: {valid.mean():.1%}")
Le rogna n'est pas gratuit — il redéfinit la population que votre décrit. Rapportez quelle fraction a survécu.
3. SUTVA (Hypothèse de Valeur de Traitement d'Unité Stable)
Le traitement d'une unité ne doit pas affecter le résultat d'une autre. Dans la crypto, c'est la plus faible des trois : une cascade de liquidation dans un perp se propage à travers le collatéral partagé et l'inventaire des market makers dans chaque paire corrélé, ce qui est de l'interférence par définition. Regrouper les erreurs standard par groupe de corrélation y répond partiellement ; rien ne le fait complètement.
Au-delà des traitements binaires
Les forêts causales s'étendent aux traitements continus à travers la même machinerie DML — estimant combien la magnitude d'un choc, pas seulement son occurrence, déplace les actifs différemment :
où est, disons, la taille du changement de taux de funding en points de base. Maintenant est un effet par point de base.
cf_continuous = CausalForestDML(
model_y=GradientBoostingRegressor(n_estimators=200),
model_t=GradientBoostingRegressor(n_estimators=200), # regression, not classifier
discrete_treatment=False,
n_estimators=1000,
honest=True,
inference=True,
)
cf_continuous.fit(Y=car, T=funding_change_bps, X=asset_features, W=controls)
effects_25bp = cf_continuous.effect(X_test, T0=0, T1=25)
Considérations pratiques
L'hétérogénéité est-elle réelle ?
C'est la question à laquelle les forêts causales répondent et rien d'autre sur ce blog ne fait, et elle mérite un véritable test plutôt qu'une règle empirique. L'honnêteté protège contre les divisions fallacieuses à l'intérieur de l'estimateur ; l'évaluation hors échantillon sur des événements retenus (pas des actifs retenus) est standard et couverte dans l'optimisation walk-forward et Sharpe dégonflé et tests multiples. Aucun ne vous dit si varie avec du tout.
Le test du Meilleur Prédicteur Linéaire le fait. Régressez le résultat résiduel sur le traitement résiduel et son interaction avec l'estimation CATE décentrée :
Les deux coefficients répondent à deux questions différentes. est l'effet moyen : y a-t-il quelque chose ici du tout ? est la pente de calibration sur vos propres prédictions : quand votre forêt dit que l'effet est plus grand, est-il vraiment plus grand ? Sous l'hypothèse nulle d'absence d'hétérogénéité . Sous calibration parfaite . Un significativement au-dessus de zéro mais loin de un signifie que la forêt a trouvé un ordre réel mais a exagéré sa dispersion — vous pouvez trader le classement, pas les magnitudes.
Le RScorer d'EconML donne un score de sélection de modèle accompagnateur :
from econml.score import RScorer
scorer = RScorer(
model_y=GradientBoostingRegressor(n_estimators=100),
model_t=GradientBoostingClassifier(n_estimators=100),
discrete_treatment=True,
cv=5,
)
scorer.fit(Y_val, T_val, X=X_val, W=W_val)
print(f"R-score: {scorer.score(cf):.4f}")
Ajustez le scorer sur une division de validation que la forêt n'a jamais vue, puis utilisez-le pour comparer les modèles CATE candidats les uns contre les autres et contre une ligne de base à effet constant. Une forêt qui ne peut pas battre le modèle à effet constant sur le R-score n'a trouvé aucune hétérogénéité worth trading, quoi que disent ses importances dans l'échantillon.
Taille d'échantillon
Les forêts causales ont besoin de plus de données qu'un modèle de résultat, car l'estimand est une différence et les deux bras doivent être peuplés à l'intérieur de chaque feuille. La discipline générale données-vs-paramètres — combien de points hors échantillon par paramètre libre, et la correction Bonferroni une fois que vous comparez des configurations — est dans la section des exigences de données de l'optimisation walk-forward. La réponse spécifique à la forêt causale est empirique, pas une règle empirique : ajustez la forêt sur des sous-échantillons imbriqués et tracez la largeur d'intervalle médiane contre ; la taille d'échantillon utilisable est là où la largeur tombe sous les tailles d'effet que vous avez l'intention de trader.
Walk-Forward, avec deux nuances
Le protocole d'évaluation est walk-forward ancré ordinaire — réajustez sur tous les événements jusqu'à , tradez l'événement — et le traitement complet, incluant le purging, l'embargo, le ratio d'efficacité walk-forward et le taux de dégradation, est dans l'optimisation walk-forward. Deux choses sont spécifiques à cet estimateur.
Premièrement, les fenêtres d'événements se chevauchent. Si la fenêtre de covariables précédant l'événement contient la fenêtre de résultat de l'événement , les folds partagent des observations et le résultat hors échantillon est contaminé. Purgez les fenêtres qui se chevauchent avant de compter un seul chiffre PnL ; avec un traitement fréquemment mécanique comme un flip de funding, cela peut retirer une part substantielle d'événements.
Deuxièmement, la division honnête doit être redessinée à chaque réajustement. Porter la même partition / à travers les folds réintroduit exactement la fuite de sélection de structure que l'honnêteté existe pour empêcher, car les événements nouvellement ajoutés atterrissent dans une partition qui a été choisie avec connaissance des anciens.
Puis exécutez le PnL hors échantillon au niveau événement à travers les portes habituelles — PBO et le ratio de Sharpe dégonflé — avant de croire quoi que ce soit.
Coûts
Un signal CATE est priced comme tout autre signal événementiel : soustrayez le demi-spread attendu de avant le filtre no-trade, et dimensionnez vers le bas dans les livres minces. Les versions quantitatives — la loi d'impact racine carrée et les courbes de coût ajustées dans modèles de coût de slippage, le filtre no-trade conscient des coûts dans prédiction conforme, et la comptabilité d'exécution dans implementation shortfall et TCA — tous se transfèrent sans changement.
La seule chose qui ne se transfère pas : la durée de vie d'un signal CATE est limitée par la fenêtre d'événement, donc le coût est amorti sur une période de détention fixe courte plutôt que sur une période ouverte. Un signal détenu en continu paie le spread une fois et gagne tant que l'edge persiste ; celui-ci le paie à chaque événement. Si l'edge survit à cela est une question empirique sur votre événement spécifique et votre univers spécifique, et c'est la première chose à vérifier, car cela peut tuer la stratégie avant que toute machinerie causale ne compte.
Conclusion
Les forêts causales estiment un objet différent du reste de la boîte à outils de ce blog. Pas "que rendra cet actif", mais "combien cet événement a-t-il déplacé cet actif, relatif au contrefactuel où il ne s'est pas produit". La machinerie qui rend cela estimable — les divisions maximisant l'hétérogénéité, l'estimation honnête, la représentation de poids de noyau adaptatif et les intervalles jackknife infinitésimal — n'a pas d'analogue dans l'apprentissage supervisé ordinaire, et les hypothèses dont il a besoin (absence de confusion, chevauchement, SUTVA) sont assez fortes pour qu'elles doivent être testées plutôt qu'affirmées.
Ce que cet article n'a pas est un résultat. Chaque nombre ci-dessus est un espace réservé. Contre la norme établie par le négatif honnête et Sharpe dégonflé, une méthode sans distribution CATE mesurée, un BLP avec une valeur p, un diagnostic de chevauchement et PnL hors échantillon protégé par DSR/PBO est un tutoriel, pas une découverte. Ces nombres sont le prochain travail ; un résultat négatif vaut la peine d'être publié.
Références
- Athey, S., Imbens, G.W. "Recursive Partitioning for Heterogeneous Causal Effects." PNAS, 113(27), 7353-7360 (2016).
- Wager, S., Athey, S. "Estimation and Inference of Heterogeneous Treatment Effects using Random Forests." JASA, 113(523), 1228-1242 (2018). arXiv:1510.04342
- Athey, S., Tibshirani, J., Wager, S. "Generalized Random Forests." Annals of Statistics, 47(2), 1148-1178 (2019).
- Chernozhukov, V., et al. "Double/Debiased Machine Learning for Treatment and Structural Parameters." The Econometrics Journal, 21(1), C1-C68 (2018).
- Chernozhukov, V., Demirer, M., Duflo, E., Fernandez-Val, I. "Generic Machine Learning Inference on Heterogeneous Treatment Effects in Randomized Experiments." (2018). arXiv:1712.04802
- Battocchi, K., et al. "EconML: A Python Package for ML-Based Heterogeneous Treatment Effects Estimation." Microsoft Research (2019). GitHub
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.