chc.estimators¶
Stability tier: evolving.
Pluggable causal-effect estimators: one Strategy interface, thin backend adapters.
CHC's identity is control + pessimism + benchmark on top of causal effects, not a home-grown
causal library. A controller only needs a scalar interventional slope d x_next / d u; this
module lets that number come from whichever backend is best, behind a single interface
(CausalEffectEstimator):
- built-ins (
BackdoorOLS,IV2SLS,DoubleML) — zero-dependency, thin wrappers overchc.causal; the default when you do not want extra installs; - adapters over mature libraries (
EconMLDoubleML-> EconML) — lazy-imported, never a hard dependency. EconML 0.17 installs besidepandas>=3on Python 3.12 and 3.14 (checked 2026-09-28), but it brings numba, sparse, statsmodels, shap and lightgbm with it, for one adapter over a pure-JAX core. DoWhy 0.14 declares<3.14. Install either yourself and pass the class in.
Richer backends may also return a heterogeneous cate(x) and diagnostics; the controller
ignores what it does not need, so every backend is swappable without touching the control code.
EffectEstimate
dataclass
¶
What a controller needs (effect), plus optional heterogeneity and diagnostics.
effect is the average interventional slope d x_next / d u consumed by
certainty-equivalent or MPC control. cate maps covariates to a per-unit effect where the
backend supplies it (EconML); diagnostics carries backend extras (t-stat, robustness, Qini).
CausalEffectEstimator
¶
Bases: Protocol
Estimate the interventional effect of treatment on outcome given covariates.
covariates is the conditioning set (backdoor adjustment set / DML nuisances / EconML X).
Every estimator here refuses, with ValueError, a column named in two roles -- the treatment
as the outcome or as a covariate, the outcome as a covariate, a covariate twice: read in both,
the treatment is partialled out of itself, or the outcome explained by itself.
BackdoorOLS
dataclass
¶
Backdoor adjustment: OLS of outcome on [treatment, *covariates] and an intercept.
IV2SLS
dataclass
¶
Two-stage least squares using instrument for a latent confounder (built-in).
Both stages condition on the column x, as chc.causal.estimate_effect_iv does, and
covariates is not read, so the treatment, the outcome and the instrument must each be a
column other than x. An instrument that does not move the treatment beyond what x
explains leaves the effect not identified, and is refused with ValueError.
diagnostics["instrument_relevance"], experimental, is the partial correlation of the
treatment and the instrument given x, in absolute value: how far the instrument moves the
treatment, which grades a weak instrument and is not a test.
DoubleML
dataclass
¶
Cross-fitted, Neyman-orthogonal Double ML with polynomial nuisances (built-in).
The nuisances are chc.causal.dml_point_and_se's, built on the centred and scaled
covariates with the intercept free of the ridge, so ridge reads the same in any units of
the covariates and at any level of them, of the treatment and of the outcome.
RLearner
dataclass
¶
Nie-Wager R-learner for heterogeneous effects tau(x) (built-in; continuous treatment).
Cross-fits nuisances m(x)=E[outcome|x] and e(x)=E[treatment|x] (polynomial-ridge), then
fits a linear-in-features tau minimising the R-loss sum (y_res - tau(x)*t_res)^2 on the
residualised data -- Neyman-orthogonal, so it recovers the CATE even under nonlinear
confounding where a naive treatment-on-outcome regression is biased. Returns the average effect
as effect and tau(x) as cate (call it on the covariate matrix). cate_degree=1 is
linear heterogeneity; raise it for nonlinear tau.
ridge reads the same in any units of the covariates and the treatment, and at any level of
the covariates, the treatment and the outcome: the nuisances and tau are built on the
centred and scaled covariates, the nuisances' intercept takes no ridge, and the ridge on each
coefficient of tau is scaled by its column's mean square in the R-loss, which has no
intercept. cate takes the covariates in the caller's units.
EconMLDoubleML
dataclass
¶
Adapter over econml.dml.LinearDML (lazy import; requires econml installed).
Pass a pre-constructed EconML estimator via model (e.g. CausalForestDML(...)) to use any
EconML DML variant; the default is LinearDML. Returns the ATE as effect and exposes
EconML's heterogeneous effect(X) as cate.
DoWhyEstimator
dataclass
¶
Adapter over DoWhy's identify -> estimate workflow (lazy import; requires dowhy installed).
Builds a CausalModel with common_causes = covariates, identifies the estimand, and
estimates it (backdoor linear regression by default). Pass another method_name for a
different DoWhy estimator (e.g. propensity-score matching / weighting).