Changelog
Source:NEWS.md
ssBartik 0.2.1
Follow-up to the 0.2.0 review fixes, after re-checking each point against ShiftShareSE and the BHJ ssaggregate workflow.
Alignment with ssaggregate (review point 7)
-
ssb_first_stage():F_effectiveis now the exposure-robust F of the shock-level first stage ( on the residualised shocks, exposure weights, HC1) – the first-stage Fivreg2/regreport afterssaggregate. The previous version was the AKM- of the location-level first stage, a different regression whose F can differ substantially.print()leads with the route-appropriate statistic (the conventional F on the share route, the shock-level F on the shift route). New fieldspi_shock,se_shock,n_shocks,route; newshock_clusterargument. -
ssb_pretrend(): on the shift route the headline is now the shock-level regression of the exposure-weighted pre-period outcome on the residualised shocks (BHJ’s balance/pre-trend regression), with HC1 or shock-clustered SEs. The location-level reduced form is still returned (coef_loc,se_ehw,se_cluster,p_ehw); its location-level AKM SE (se_akm,p_akm,conf.low_akm/conf.high_akm) is no longer reported. New fieldscoef_shock,se_shock,p_shock,n_shocks,level_used; newshock_clusterargument. -
ssb_estimate()now reports the route-appropriate first-stage F in itsfstatattribute (conventional HC1 on the share route, shock-level exposure-robust on the shift route), labelled in the printed / formatted tables (fstat_label). (Point 1.) - Documentation now states precisely when the native shock-level SEs equal ShiftShareSE’s AKM: exactly when the location controls lie in the span of the shares (an intercept with complete shares, period fixed effects), and up to finite-sample differences in how the shocks are residualised otherwise (both are consistent exposure-robust variances). The 0.2.0 wording (“match … exactly”) was too strong for designs with other controls.
Route guardrails (points 1, 2)
-
ssb_estimate(): when is not installed (or fails),akm/akm0are computed natively from the BHJ shock-level scores (HC0 SE; AKM0 by inverting the shock-level Anderson-Rubin test, with the same disjoint / unbounded-set conventions as ShiftShareSE), so the shift route always delivers exposure-robust inference instead ofNArows. Thenotecolumn records which engine produced the row. -
ssb_ri()warns when called on a share-route design (permuting the shocks is a shift-route tool); its example now usesexogenous = "shift". - README walkthrough now keeps a share-route design (
d) and a shift-route design (d2) apart and calls each tool on the route it belongs to.
Minor
-
ssb_aggregate()no longer producesNaNfor shock-cells with zero total exposure (they get zero weight). - An unbounded AKM0 set is now annotated as the Anderson-Rubin test rejecting no
beta(typical with few effective shocks) rather than as a “weak instrument”, since it can occur with a large Wald first-stage F.
ssBartik 0.2.0
Changes
-
ssb_design()/ssbartik():exogenousis now required (no default). The identification route fixes the automatic controls, the standard errors and the diagnostics, so it must be chosen deliberately. -
ssb_estimate()(andssb_placebo(),ssb_drop_top()): the defaultmethodsnow follow the route – conventionalehw(+clusterwhen a cluster variable is set) on the share route, exposure-robustakm/akm0on the shift route. Explicitmethods = c(...)still overrides, and the printed table names the route. (Review point 1.) -
ssb_overid()now reports a Sargan–Hansen J from efficient two-step GMM with a robust (or cluster-robust) weight matrix, replacing the precision-weighted Cochran Q, which treated the mutually correlated just-identified estimates as independent. Estimators of the common coefficient:"2sls", efficient"gmm", and the many-instrument-robust"liml"/"jive"("auto"picks between 2SLS and LIML by K/n). Collinear residualised shares are pruned automatically (complete designs use K−1 instruments, df = K−2). Output fields changed accordingly;ssb_plot_overid(),format()andplot()methods updated. (Point 3.) -
ssb_pipeline()reports only route-appropriate statistics: Rotemberg weights / weight summary / overidentification / share balance on the share route; equivalence / shock summary / shock balance on the shift route. Arguments belonging to the other route are skipped with a message. (Point 2.) -
ssb_share_balance()now tests the sectors with the largest |Rotemberg weight| (the shares that drive the estimate), not the largest average exposure, and returns theiralpha. (Point 4.)
Methodology fixes
- Exposure-robust (shock-level) variances in
ssb_shock_iv(),ssb_first_stage()andssb_pretrend()now use the shocks residualised on the shock-level controls (a constant, plus period fixed effects in panels) with exposure weights, instead of the raw shocks. Point estimates are unchanged; standard errors are corrected and now match the BHJssaggregateworkflow (verified in the test suite; see 0.2.1 for the precise relation to ShiftShareSE’s AKM variance). (Point 7.) - Shift-route panels now automatically control the sum of exposure shares interacted with period fixed effects (reducing to period FE under complete shares); controlling only the overall sum is not sufficient in panels. Auto columns are pruned of anything the user’s controls already span, and the location-/shock-level equivalence is now exact in panels. (Point 6.)
-
ssb_rotemberg()gainsdemean = TRUE: shocks are demeaned with exposure weights (within periods in panels) whenever the corresponding constant directions are absorbed by the controls, resolving the normalisation non-uniqueness of the decomposition; the weights are now invariant to adding constants to the shocks. β̂, the per-instrument estimates and Fs are unaffected. (Point 5.) -
ssb_pretrend()is route-aware: the headlinese/p/ interval are exposure-robust on the shift route and conventional (cluster / EHW) on the share route, with all three SEs still reported. (Point 2.)
Verification, wording, docs
-
ssb_estimate(shock_cluster = )was verified to genuinely cluster the shocks: it reaches ShiftShareSE’ssector_cvarand matches a hand-computed cluster-robust shock-level regression; a regression test pins this down.ssb_shock_iv(cluster = )now also accepts a shocks-table column name. (Point 8.) -
ssb_ri()documents (and prints) that randomization inference requires shocks to be exchangeable within blocks – a stronger assumption than BHJ as-good-as-random, which allows heteroskedastic shocks. (Point 9.) - Shock-balance output no longer states that a non-significant test shows shocks are “unrelated to observables”; it reports that the null of balance is not rejected. (Point 10.)
- Terminology: high-weight share instruments (sectors), not “shocks”, across
ssb_weight_summary(),ssb_loo(),ssb_drop_top()output and plots. (Point 5.)
ssBartik 0.1.1
CRAN release: 2026-07-19
First release. An end-to-end toolkit for shift-share (Bartik) instrumental variables, spanning both identification routes (exogenous shares and exogenous shocks) from instrument construction through estimation, inference, and credibility diagnostics.
- Estimation:
ssb_design(),ssbartik(), andssb_estimate(), reporting a panel of confidence intervals (IID, EHW, and exposure-robust AKM / AKM0 by default; cluster and two-way available on request). - Rotemberg / GPSS diagnostics:
ssb_rotemberg(),ssb_weight_summary(),ssb_loo(),ssb_drop_top(). - Shock-level (Borusyak-Hull-Jaravel) tools:
ssb_aggregate(),ssb_shock_iv(),ssb_equivalence(),ssb_recenter(). - Credibility checks:
ssb_first_stage(),ssb_overid(),ssb_share_balance(),ssb_shock_balance(),ssb_pretrend(),ssb_placebo(),ssb_ri(). - Output:
autoplot()/ssb_plot_*()figures (including thessb_plot_ci()interval comparison), and paste-ready tables viaformat(x, "latex" / "markdown")and a renderedplot()for the Rotemberg table.