diff_diff.StuteJointResult#

class diff_diff.StuteJointResult[source]#

Bases: object

Result of stute_joint_pretest() (joint Cramer-von Mises across horizons).

Aggregates the per-horizon Stute (1997) CvM statistic into a joint specification test: S_joint = sum_k S_k, where S_k is the single-horizon CvM on residuals eps_{g,k}. Inference is via Mammen (1993) wild bootstrap with a shared multiplier eta_g across horizons per unit (Delgado-Manteiga 2001; Hlavka-Huskova 2020) to preserve the unit-level dependence structure of the vector-valued empirical process.

Two nulls are supported via the thin wrappers joint_pretrends_test() (mean-independence: E[Y_t - Y_base | D] = mu_t, design matrix [1]) and joint_homogeneity_test() (linearity: E[Y_t - Y_base | D_t] = beta_{0,t} + beta_{fe,t} * D, design matrix [1, D]). Both wrappers accept a trends_lin: bool = False keyword-only flag (PR #392): when True, applies paper Eq 17 / Eq 18 linear-trend detrending before the joint CvM using per-group slope Y[g, F-1] - Y[g, F-2].

cvm_stat_joint#

Joint statistic S_joint = sum_k S_k. NaN on NaN-propagation.

Type:

float

p_value#

Bootstrap p-value (1 + sum(S*_b >= S_joint)) / (B + 1). NaN when the statistic is NaN. 1.0 when the per-horizon exact- linear short-circuit fires (all horizons machine-exact linear).

Type:

float

reject#

True iff p_value <= alpha. Always False on NaN.

Type:

bool

alpha#

Significance level.

Type:

float

horizon_labels#

Horizon identifiers as str(t) for each period. String identity only - NOT a chronological ordering key. Callers who need chronological order should preserve the original period values alongside (a downstream plotter sorting labels lexicographically will misorder e.g. ["2003-Q10", "2003-Q2", ...]).

Type:

list of str

per_horizon_stats#

{label: S_k} diagnostic. Per-horizon p-values are NOT exposed (decomposing the joint bootstrap into K independent loops is a K-fold memory/time cost; deferred). Callers who need per-horizon p-values can call stute_test() separately on each (period, residual) pair.

On NaN-propagation (any horizon has NaN input), this dict is preserved with {label: np.nan for label in horizon_labels}, NOT an empty dict, NOT a partial dict: the keys carry diagnostic value (which horizons were attempted), the NaN values signal non-propagation.

Type:

dict[str, float]

n_bootstrap#
Type:

int

n_obs#

Number of units G.

Type:

int

n_horizons#
Type:

int

seed#
Type:

int or None

null_form#

"mean_independence" (from joint_pretrends_test()) or "linearity" (from joint_homogeneity_test()). "custom" when called directly via stute_joint_pretest() without a wrapper.

Type:

str

exact_linear_short_circuited#

True when every horizon’s residual SSR to centered TSS ratio is below _EXACT_LINEAR_RELATIVE_TOL; bootstrap is skipped and p_value = 1.0. The per-horizon check ensures a single degenerate horizon does not collapse the joint test when other horizons have nontrivial residuals.

Type:

bool

Methods

__init__(cvm_stat_joint, p_value, reject, ...)

print_summary()

Print the summary to stdout.

summary()

Formatted summary table.

to_dataframe()

Return a one-row DataFrame of the top-level result fields.

to_dict()

Return results as a JSON-safe dict.

Attributes

__init__(cvm_stat_joint, p_value, reject, alpha, horizon_labels, per_horizon_stats, n_bootstrap, n_obs, n_horizons, seed, null_form, exact_linear_short_circuited)#
Parameters:
Return type:

None

classmethod __new__(*args, **kwargs)#