Skip to contents

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_effective is now the exposure-robust F of the shock-level first stage ( on the residualised shocks, exposure weights, HC1) – the first-stage F ivreg2/reg report after ssaggregate. 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 fields pi_shock, se_shock, n_shocks, route; new shock_cluster argument.
  • 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 fields coef_shock, se_shock, p_shock, n_shocks, level_used; new shock_cluster argument.
  • ssb_estimate() now reports the route-appropriate first-stage F in its fstat attribute (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 / akm0 are 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 of NA rows. The note column 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 uses exogenous = "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.

Terminology (point 5)

  • Remaining references to the top-Rotemberg-weight shocks in the format() / plot() methods of ssb_rotemberg, ssb_drop_top, the leave-one-out plot axis and the README now say share instruments / sectors.

Minor

  • ssb_aggregate() no longer produces NaN for 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(): exogenous is 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() (and ssb_placebo(), ssb_drop_top()): the default methods now follow the route – conventional ehw (+ cluster when a cluster variable is set) on the share route, exposure-robust akm / akm0 on the shift route. Explicit methods = 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() and plot() 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 their alpha. (Point 4.)

Methodology fixes

  • Exposure-robust (shock-level) variances in ssb_shock_iv(), ssb_first_stage() and ssb_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 BHJ ssaggregate workflow (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() gains demean = 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 headline se / 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’s sector_cvar and 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.