cleverly.sensitivity.omitted_variable_bounds#

cleverly.sensitivity.omitted_variable_bounds(result: TMLEResult, estimand: str = 'ate', *, cf_y: float | None = None, cf_d: float | None = None, rho: float = 1.0, level: float = 0.95, null_hypothesis: float = 0.0, nu2_estimator: str = 'auto', benchmark: BenchmarkResult | None = None) → SensitivityBounds[source]#

Bias-adjusted bounds and robustness values for one estimand.

Defaults follow the convention of assuming a confounder with cf_y = cf_d = 0.03, with worst-case alignment (rho = 1). Prefer reading SensitivityBounds.robustness_value, which needs no assumption at all. benchmark= takes the strengths from a benchmark() of this fit instead. Its gain statistics are the published proxies for the two shares (Chernozhukov et al., arXiv:2112.13398v6, Appendix E.5, Remark 8), so they enter the bound unchanged.

Parameters:
resultTMLEResult

A fitted result.

estimandstr

Alias to bound.

cf_yfloat or None

Assumed share of residual outcome variation the confounder explains, in [0, 1]. None means 0.03, or the benchmark’s cf_y with benchmark=.

cf_dfloat or None

Assumed share of the Riesz representer’s second moment that only the confounder adds, in [0, 1). For the ATE it is the gain in precision of the treatment model. None means 0.03, or the benchmark’s cf_d with benchmark=.

rhofloat

How adversarially the two are aligned. 1.0 is the worst case. A benchmark does not set it. Pass rho=benchmark.rho to use the benchmark’s alignment.

levelfloat

Coverage level of the reported limits.

null_hypothesisfloat

Value the robustness values are measured against.

nu2_estimator{“auto”, “doubly_robust”, “plugin”}

Which estimator of the Riesz second moment to use.

benchmarkBenchmarkResult or None

A benchmark of this fit and this estimand. Its cf_y and cf_d become the assumed strengths, so cf_y= and cf_d= must be omitted.

Returns:
SensitivityBounds

Adjusted bounds, their confidence limits, and the robustness values. Under nu2_estimator="plugin" the bounds, max_bias and the point robustness value are reported, and the one-sided limits and the confidence-limit robustness value refuse when read, because no derivation in a source this package cites gives their standard error (docs/roadmap.md F26). A zero bias scale also leaves the point bounds available but refuses the limits, whose square-root derivative is undefined. An unreachable robustness threshold is None.

Raises:
ValueError

If nu2_estimator is not one of NU2_ESTIMATORS, if cf_y lies outside [0, 1] or cf_d outside [0, 1), if |rho| exceeds one, or if level lies outside [0.5, 1). With benchmark=, also if cf_y= or cf_d= is passed, or if the benchmark is of another estimand or another fit.

CapabilityError

On every refusal sensitivity_elements() raises: a fit the rule table refuses, an estimand the bound does not cover, or a doubly robust estimate of nu^2 that is not positive.

Notes

A fit made with treatment_adjustment= (treatment_covariates= in cleverly.TMLE.fit()) lets the treatment mechanism read a subset of the adjustment set. The Riesz representer of the bound uses that fitted mechanism. So the bound reads the statistical-model restriction that the fit’s summary prints, and it is claimed only under that restriction. Collaborative fits stay refused. If a later release admits a collaborative fit that selects nothing, the same statement covers it.