API Reference

Estimator

trop.estimator.TROP_TWFE_average(Y, W, treated_units, lambda_unit, lambda_time, lambda_nn, treated_periods=10, solver=None, verbose=False)[source]

Compute the TROP treatment effect with unit/time weighting and optional low-rank outcome model.

Parameters:
  • Y (array_like of shape (N, T)) – Outcome matrix.

  • W (array_like of shape (N, T)) – Treatment indicator (often binary). The estimator uses W as provided; treated_periods is used only to construct weights/masks, not to infer treatment timing.

  • treated_units (sequence of int) – Row indices of treated units used to form the reference (average) treated trajectory for unit-distance weighting.

  • lambda_unit (float) – Nonnegative decay parameter for unit weights: exp(-lambda_unit * dist_unit).

  • lambda_time (float) – Nonnegative decay parameter for time weights: exp(-lambda_time * dist_time).

  • lambda_nn (float) – Nuclear-norm penalty weight for the low-rank component L. Use np.inf to disable the low-rank adjustment (i.e., omit L).

  • treated_periods (int, default=10) – Number of final columns treated as the “post/tail block” for constructing (a) the pre-period mask (all but last treated_periods columns) used in unit distances, and (b) the time-distance center.

  • solver (str or None, default=None) – CVXPY solver name. If None, uses “SCS” when lambda_nn is finite and “OSQP” when lambda_nn is infinite.

  • verbose (bool, default=False) – Passed to cvxpy.Problem.solve.

Returns:

Estimated treatment-effect parameter tau from the weighted TWFE objective.

Return type:

float

Raises:
  • ValueError – If input shapes are inconsistent or tuning parameters are invalid.

  • RuntimeError – If the optimization fails to produce a finite tau.

Cross-validation

trop.cv.adaptive_TROP_cv(Y_control, treated_periods, *, init_ranges=((0.0, 1.0), (0.0, 1.0), (0.0, 1.0)), n_points=10, n_trials=200, n_jobs=-1, prefer='threads', expand_factor=1.0, max_expansions=6, zoom=True, zoom_factor=4.0, zoom_n_points=9, cv_sampling_method='resample', n_treated_units=1, K=None, random_seed=0, solver=None, verbose=False)[source]

Adaptive joint placebo cross-validation for (lambda_unit, lambda_time, lambda_nn).

Return type:

Tuple[float, float, float]

trop.cv.TROP_cv_single(Y_control, treated_periods, fixed_lambdas=(0.0, 0.0), lambda_grid=None, lambda_cv='unit', *, cv_sampling_method='resample', n_trials=200, n_treated_units=1, K=None, n_jobs=-1, prefer='threads', random_seed=0, solver=None, verbose=False)[source]

Tune one TROP tuning parameter by placebo cross-validation on a control-only panel.

For each candidate value in lambda_grid, this routine assigns placebo treatment in the final treated_periods columns, computes the corresponding TROP estimate, and selects the lambda minimizing the RMSE of placebo ATEs (targeting zero).

Parameters:
  • Y_control (array-like of shape (n_units, n_periods)) – Control-only outcome panel used for placebo cross-validation.

  • treated_periods (int) – Number of placebo treated (post) periods, taken as the final columns. Must satisfy 1 <= treated_periods <= n_periods - 1.

  • fixed_lambdas (tuple of float, default=(0.0, 0.0)) –

    Values held fixed for the two lambdas not being tuned. Interpretation depends on lambda_cv:

    • if lambda_cv="unit": (lambda_time, lambda_nn)

    • if lambda_cv="time": (lambda_unit, lambda_nn)

    • if lambda_cv="nn" : (lambda_unit, lambda_time)

  • lambda_grid (iterable of float or None, default=None) – Candidate values for the lambda being tuned. If None, uses np.arange(0.0, 2.0, 0.2).

  • lambda_cv ({"unit", "time", "nn"}, default="unit") – Which lambda to tune.

  • cv_sampling_method ({"resample", "kfold"}, default="resample") –

    Method used to construct placebo treated sets.

    • "resample": draw n_trials placebo sets, each containing n_treated_units units sampled without replacement.

    • "kfold": split units into K folds (after shuffling); treat each fold once.

    Placebo sets are generated once using random_seed and reused across all candidate lambdas.

  • n_trials (int, default=200) – Number of placebo trials when cv_sampling_method="resample". Required for "resample". Ignored for "kfold".

  • n_treated_units (int, default=1) – Number of placebo treated units per trial when cv_sampling_method="resample". Required for "resample". Ignored for "kfold".

  • K (int, default=None) – Number of folds when cv_sampling_method="kfold". Required for "kfold". Ignored for "resample".

  • n_jobs (int, default=-1) – Number of parallel jobs. -1 uses all available cores.

  • prefer ({"threads", "processes"}, default="threads") – Joblib backend preference.

  • random_seed (int, default=0) – Random seed used to generate placebo sets (and fold shuffling for kfold).

  • solver (str or None, default=None) – CVXPY solver passed to TROP_TWFE_average.

  • verbose (bool, default=False) – Verbosity flag passed to TROP_TWFE_average.

Returns:

best_lambda – Selected lambda value minimizing the placebo RMSE.

Return type:

float

Raises:
  • ValueError – If inputs are invalid (panel shape, treated_periods bounds, empty grid, or inconsistent CV sampling arguments).

  • RuntimeError – If all placebo trials/folds fail or return non-finite ATEs for a candidate lambda (e.g., solver failures).

trop.cv.TROP_cv_cycle(Y_control, treated_periods, unit_grid, time_grid, nn_grid, lambdas_init=None, *, max_iter=50, cv_sampling_method='resample', n_trials=200, n_treated_units=1, K=None, n_jobs=-1, prefer='threads', random_seed=0, solver=None, verbose=False)[source]

Tune (lambda_unit, lambda_time, lambda_nn) by coordinate-descent placebo cross-validation.

Iteratively updates one tuning parameter at a time using TROP_cv_single while holding the other two fixed, until the selected triplet stops changing or max_iter is reached. Each coordinate update selects the lambda minimizing the RMSE of placebo ATEs on a control-only panel (targeting zero placebo effects).

Parameters:
  • Y_control (array-like of shape (n_units, n_periods)) – Control-only outcome panel used for placebo cross-validation.

  • treated_periods (int) – Number of placebo treated (post) periods, taken as the final columns. Must satisfy 1 <= treated_periods <= n_periods - 1.

  • unit_grid (sequence of float) – Candidate values for lambda_unit (unit-distance decay).

  • time_grid (sequence of float) – Candidate values for lambda_time (time-distance decay).

  • nn_grid (sequence of float) – Candidate values for lambda_nn (nuclear-norm penalty).

  • lambdas_init (tuple of float or None, default=None) – Initial values (lambda_unit, lambda_time, lambda_nn). If None, each parameter is initialized to the mean of its grid.

  • max_iter (int, default=50) – Maximum number of coordinate-descent iterations.

  • cv_sampling_method ({"resample", "kfold"}, default="resample") –

    Method used to construct placebo treated sets for each coordinate update.

    • "resample": draw n_trials placebo sets, each containing n_treated_units units sampled without replacement.

    • "kfold": split units into K folds (after shuffling); treat each fold once.

    Placebo sets are generated using random_seed for each call to TROP_cv_single (so each coordinate uses the same placebo assignments across its grid).

  • n_trials (int, default=200) – Number of placebo trials when cv_sampling_method="resample". Ignored when cv_sampling_method="kfold".

  • n_treated_units (int, default=1) – Number of placebo treated units per trial when cv_sampling_method="resample". Ignored when cv_sampling_method="kfold".

  • K (int, default=None) – Number of folds when cv_sampling_method="kfold". Required for "kfold". Ignored when cv_sampling_method="resample".

  • n_jobs (int, default=-1) – Number of parallel jobs. -1 uses all available cores.

  • prefer ({"threads", "processes"}, default="threads") – Joblib backend preference.

  • random_seed (int, default=0) – Random seed used for placebo-set generation (and fold shuffling for kfold).

  • solver (str or None, default=None) – CVXPY solver passed to TROP_TWFE_average.

  • verbose (bool, default=False) – Verbosity flag passed to TROP_TWFE_average.

Return type:

Tuple[float, float, float]

Returns:

  • lambda_unit (float) – Selected value for lambda_unit.

  • lambda_time (float) – Selected value for lambda_time.

  • lambda_nn (float) – Selected value for lambda_nn.

Raises:

RuntimeError – If the procedure does not converge (no fixed point) within max_iter.

trop.cv.TROP_cv_joint(Y_control, treated_periods, unit_grid, time_grid, nn_grid, *, cv_sampling_method='resample', n_trials=200, n_treated_units=1, K=None, n_jobs=-1, prefer='threads', random_seed=0, solver=None, verbose=False)[source]

Select (lambda_unit, lambda_time, lambda_nn) by joint placebo cross-validation.

Performs a full grid search over unit_grid × time_grid × nn_grid. For each candidate triple, repeatedly assigns placebo treatment to a subset of units and computes the corresponding TROP estimate. The selected triple is the one minimizing the root-mean-square error (RMSE) of placebo ATEs (targeting zero).

Parameters:
  • Y_control (array-like of shape (n_units, n_periods)) – Control-only outcome panel used for placebo cross-validation.

  • treated_periods (int) – Number of placebo treated (post) periods, taken as the final columns. Must satisfy 1 <= treated_periods <= n_periods - 1.

  • unit_grid (sequence of float) – Candidate values for lambda_unit (unit-distance decay).

  • time_grid (sequence of float) – Candidate values for lambda_time (time-distance decay).

  • nn_grid (sequence of float) – Candidate values for lambda_nn (nuclear-norm penalty).

  • cv_sampling_method ({"resample", "kfold"}, default="resample") –

    Method used to construct placebo treated sets.

    • "resample": draw n_trials placebo sets, each containing n_treated_units units sampled without replacement.

    • "kfold": split units into K folds (after shuffling); treat each fold once.

    Placebo sets are generated once using random_seed and reused across all candidate triples.

  • n_trials (int, default=200) – Number of placebo trials when cv_sampling_method="resample". Ignored when cv_sampling_method="kfold".

  • n_treated_units (int, default=1) – Number of placebo treated units per trial when cv_sampling_method="resample". Ignored when cv_sampling_method="kfold".

  • K (int, default=None) – Number of folds when cv_sampling_method="kfold". Required for "kfold". Ignored when cv_sampling_method="resample".

  • n_jobs (int, default=-1) – Number of parallel jobs. -1 uses all available cores.

  • prefer ({"threads", "processes"}, default="threads") – Joblib backend preference.

  • random_seed (int, default=0) – Random seed used to generate placebo sets (and fold shuffling for kfold).

  • solver (str or None, default=None) – CVXPY solver passed to TROP_TWFE_average.

  • verbose (bool, default=False) – Verbosity flag passed to TROP_TWFE_average.

Return type:

Tuple[float, float, float]

Returns:

  • lambda_unit (float) – Selected value for lambda_unit.

  • lambda_time (float) – Selected value for lambda_time.

  • lambda_nn (float) – Selected value for lambda_nn.

Raises:
  • ValueError – If inputs are invalid (panel shape, treated_periods bounds, empty grids, or inconsistent CV sampling arguments).

  • RuntimeError – If all parameter combinations fail (e.g., all placebo evaluations return non-finite ATEs due to solver failures).

Inference

class trop.inference.BootstrapResult(estimate, se, ci, estimates, n_failed, alpha)[source]

Bases: object

Output of bootstrap().

estimate

Estimate on the original (non-resampled) panel.

Type:

float

se

Bootstrap standard error: standard deviation of the finite bootstrap draws.

Type:

float

ci

Percentile confidence interval (lower, upper) at level 1 - alpha.

Type:

tuple of float

estimates

All bootstrap draws; NaN where the estimator failed.

Type:

ndarray of shape (n_bootstrap,)

n_failed

Number of draws where the estimator raised or returned a non-finite value.

Type:

int

alpha

Significance level used for ci.

Type:

float

estimate: float
se: float
ci: Tuple[float, float]
estimates: ndarray
n_failed: int
alpha: float
property n_bootstrap: int
trop.inference.bootstrap(Y, W, treated_units, treated_periods, estimator=None, *, lambdas=None, n_bootstrap=1000, resample='controls', scale='absolute', alpha=0.05, n_jobs=-1, prefer='processes', random_state=None)[source]

Unit-level bootstrap standard errors and confidence intervals for a panel estimator.

Each draw resamples units (rows of Y/W) with replacement, re-applies the estimator with its tuning parameters held fixed, and records the estimate. The standard error is the standard deviation of the draws; the confidence interval is the percentile interval.

Parameters:
  • Y (array_like of shape (N, T)) – Outcome matrix.

  • W (array_like of shape (N, T)) – Treatment indicator matrix.

  • treated_units (sequence of int) – Row indices of treated units.

  • treated_periods (int) – Number of final columns treated as the post-treatment block; passed to the estimator.

  • estimator (callable or None, default=None) – estimator(Y, W, treated_units, treated_periods) -> float, the same signature as the entries of trop.default_estimator_suite(). If None, TROP with fixed lambdas is used.

  • lambdas (tuple of float or None, default=None) – (lambda_unit, lambda_time, lambda_nn) for the default TROP estimator, typically selected beforehand by cross-validation on the original panel. Required when estimator is None; must be None otherwise.

  • n_bootstrap (int, default=1000) – Number of bootstrap draws.

  • resample ({"controls", "stratified"}, default="controls") – "controls": keep the treated units fixed and resample control units with replacement. Suitable with a single (or few) treated unit(s). "stratified": resample treated and control units separately, each with replacement, keeping the number of each fixed.

  • scale ({"absolute", "relative"}, default="absolute") – "absolute": effects in outcome units. "relative": effects as a fraction of the counterfactual mean, tau / (mean(Y[W > 0]) - tau); multiply by 100 for a percentage change. Applied to the full-sample estimate and to every draw.

  • alpha (float, default=0.05) – Significance level for the percentile confidence interval.

  • n_jobs (int, default=-1) – Number of parallel jobs. -1 uses all available cores.

  • prefer ({"processes", "threads"}, default="processes") – Joblib backend preference. Processes are usually much faster for the cvxpy-based estimators, whose problem setup holds the GIL.

  • random_state (int or None, default=None) – Seed for reproducible draws. Draws are seeded individually, so results do not depend on n_jobs.

Return type:

BootstrapResult

Raises:
  • ValueError – If inputs are invalid.

  • RuntimeError – If every bootstrap draw fails.

Warns:

RuntimeWarning – If some (but not all) draws fail; they are excluded from se and ci.

Examples

>>> lambdas = trop.TROP_cv_cycle(np.delete(Y, 0, axis=0), treated_periods,
...                              unit_grid, time_grid, nn_grid)
>>> res = trop.bootstrap(Y, W, [0], treated_periods, lambdas=lambdas, random_state=0)
>>> res.estimate, res.se, res.ci