localproj 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ # Changelog
2
+
3
+ All notable changes to LocalProj are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-07-12
11
+
12
+ Initial alpha release of LocalProj.
13
+
14
+ ### Added
15
+
16
+ - A single `localproj.lp()` entry point and a common result contract for supported estimators.
17
+ - Horizon-specific and common samples with explicit observation-origin alignment.
18
+ - Formula-based regular OLS and IV local projections with fixed effects, generated leads and
19
+ lags, multiple outcomes, and multiple shocks.
20
+ - IID, heteroskedasticity-robust, HAC/Newey-West, and clustered pointwise covariance
21
+ estimators, with HC1 as the regular-LP default.
22
+ - Cross-horizon covariance, Gaussian sup-t and Scheffé bands, and path-specific Wald tests for
23
+ common-sample regular OLS projections.
24
+ - Wild residual bootstrap inference with percentile, basic, normal, and sup-t intervals.
25
+ - Panel fixed-effects estimation and split-panel jackknife bias correction.
26
+ - Herbst–Johannsen analytical finite-sample bias correction for observed-shock time-series LPs.
27
+ - Barnichon–Brownlees B-spline smooth local projections, including cross-validated smoothing and
28
+ single-endogenous-shock smooth IV.
29
+ - Adamek–Smeekes–Wilms high-dimensional local projections using desparsified lasso and
30
+ Newey–West inference.
31
+ - Observed-shock Bayesian SU-LPs with hierarchical GP/Normal-Gamma shrinkage and optional ArviZ
32
+ integration.
33
+ - Plotnine impulse-response plots in the standard installation.
34
+ - Focused literature replications covering regular, panel, bias-corrected, smooth,
35
+ high-dimensional, and Bayesian estimators.
36
+
37
+ [Unreleased]: https://github.com/whoisnnamdi/localproj/compare/v0.1.0...HEAD
38
+ [0.1.0]: https://github.com/whoisnnamdi/localproj/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nnamdi Iregbulem and LocalProj contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,313 @@
1
+ Metadata-Version: 2.4
2
+ Name: localproj
3
+ Version: 0.1.0
4
+ Summary: Composable local projections for Python
5
+ Keywords: econometrics,local projections,impulse responses,time series,panel data
6
+ Author: LocalProj contributors
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Requires-Dist: formulaic>=1.0
23
+ Requires-Dist: numpy>=1.26
24
+ Requires-Dist: pandas>=2.0
25
+ Requires-Dist: plotnine==0.15.3
26
+ Requires-Dist: pyfixest>=0.50.1
27
+ Requires-Dist: scipy>=1.11
28
+ Requires-Dist: arviz>=0.17 ; extra == 'bayes'
29
+ Requires-Dist: pytest>=8.0 ; extra == 'dev'
30
+ Requires-Dist: ruff>=0.8 ; extra == 'dev'
31
+ Requires-Python: >=3.11
32
+ Project-URL: Homepage, https://github.com/whoisnnamdi/localproj
33
+ Project-URL: Repository, https://github.com/whoisnnamdi/localproj
34
+ Project-URL: Issues, https://github.com/whoisnnamdi/localproj/issues
35
+ Project-URL: Changelog, https://github.com/whoisnnamdi/localproj/blob/main/CHANGELOG.md
36
+ Provides-Extra: bayes
37
+ Provides-Extra: dev
38
+ Description-Content-Type: text/markdown
39
+
40
+ # LocalProj
41
+
42
+ [![CI](https://github.com/whoisnnamdi/localproj/actions/workflows/ci.yml/badge.svg)](https://github.com/whoisnnamdi/localproj/actions/workflows/ci.yml)
43
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](pyproject.toml)
44
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
45
+
46
+ `LocalProj` is a Python library for estimating local projections (LPs). The current `0.1.0` implementation includes regular time-series LPs, LP-IV, high-dimensional desparsified-lasso LPs, panel fixed effects and split-panel jackknife estimates, Herbst–Johannsen finite-sample bias correction, smooth LPs, wild-bootstrap and simultaneous inference, and observed-shock Bayesian SU-LPs.
47
+
48
+ > **Project status:** `0.1.0` is an alpha release. The public API may evolve as the package gains broader production use.
49
+
50
+ ## Installation
51
+
52
+ ```bash
53
+ uv add localproj
54
+ ```
55
+
56
+ Plotting is included in the standard installation. Bayesian diagnostics are available as an extra:
57
+
58
+ ```bash
59
+ uv add "localproj[bayes]"
60
+ ```
61
+
62
+ ## Quick start
63
+
64
+ ```python
65
+ import localproj as lp
66
+
67
+ fit = lp.lp(
68
+ "y ~ shock + l(y, 1:4) + l(shock, 1:4)",
69
+ data=df,
70
+ shock="shock",
71
+ horizons=range(0, 13),
72
+ outcome="level", # also: "cumulative" or "diff"
73
+ sample="horizon", # or "common"
74
+ vcov="hc1",
75
+ )
76
+
77
+ print(fit.tidy())
78
+ print(fit.coef())
79
+ print(fit.confint())
80
+ print(fit.summary())
81
+ ```
82
+
83
+ The formula preprocessor supports `l(var, periods)` and `f(var, periods)` helpers. `horizons=12` means horizons `0..12`; an explicit iterable is also accepted. Regular LPs use HC1 covariance when `vcov` is omitted; HAC/Newey–West remains available explicitly with `vcov="hac"` or a fixed lag specification.
84
+
85
+ ## Supported estimators and inference
86
+
87
+ | Area | Current support |
88
+ |---|---|
89
+ | Regular LP | Horizon-by-horizon PyFixest OLS; multiple outcomes and shocks |
90
+ | Outcome transforms | Level, cumulative/long difference, period difference, custom callable |
91
+ | Samples | Horizon-specific or common complete-case sample |
92
+ | Covariance | Regular LPs: IID, HC1–HC3, HAC/Newey-West, and PyFixest cluster specifications; smooth LPs also support HC0 |
93
+ | LP-IV | PyFixest/`feols`-style IV formulas and first-stage diagnostics |
94
+ | Panel LP | Group-aware leads/lags, fixed effects, clustered covariance |
95
+ | Bias correction | Split-panel jackknife for panels; Herbst–Johannsen analytical BC/BCC for observed-shock time-series LPs |
96
+ | Smooth LP | B-spline ridge smoothing, contiguous-fold CV, HC0/NW inference, multiple responses, and single-shock smooth IV |
97
+ | High-dimensional LP | Adamek–Smeekes–Wilms desparsified lasso with unpenalized shock coefficients, plug-in tuning, reused nodewise regressions, and Newey–West inference |
98
+ | Joint inference | Gaussian sup-t and Scheffé bands, plus cross-horizon Wald tests, for common-sample regular OLS LPs |
99
+ | Bootstrap | Wild residual bootstrap with pointwise and sup-t intervals for regular OLS LPs |
100
+ | Bayesian | Observed-shock SU-LP with hierarchical GP/Normal-Gamma shrinkage |
101
+ | Plotting | Plotnine IRF plots, selection, and outcome/shock faceting |
102
+
103
+ ## Multiple outcomes and shocks
104
+
105
+ ```python
106
+ fit = lp.lp(
107
+ "gdp + cpi ~ mp_shock + fp_shock + l(gdp, 1:4) + l(cpi, 1:4)",
108
+ data=df,
109
+ shock=["mp_shock", "fp_shock"],
110
+ horizons=range(0, 13),
111
+ )
112
+
113
+ fit.tidy() # one row per (outcome, shock, horizon)
114
+ fit.coef(outcome="gdp", shock="mp_shock")
115
+ fit.plot(facet_by=["outcome", "shock"])
116
+ ```
117
+
118
+ ## Simultaneous and bootstrap inference
119
+
120
+ Regular LP simultaneous bands require an aligned common sample:
121
+
122
+ ```python
123
+ joint_fit = lp.lp(
124
+ "y ~ shock + l(y, 1:4) + l(shock, 1:4)",
125
+ data=df,
126
+ shock="shock",
127
+ horizons=range(0, 13),
128
+ sample="common",
129
+ vcov="hc1",
130
+ )
131
+
132
+ joint_fit.confint(band="sup-t")
133
+ joint_fit.confint(band="scheffe")
134
+ joint_fit.wald(horizons=range(0, 13), null=0)
135
+ ```
136
+
137
+ Joint inference supports IID and HC1–HC3 covariance directly. HAC joint inference requires an explicit common lag count, such as `vcov={"type": "hac", "lags": 4}`; an omitted HAC lag remains valid for pointwise fits but does not produce joint covariance because its defaults vary by horizon.
138
+
139
+ Wild-bootstrap inference is available for regular PyFixest OLS LPs:
140
+
141
+ ```python
142
+ boot = joint_fit.bootstrap(reps=999, weights="rademacher", seed=123)
143
+ boot.confint(interval="percentile")
144
+ boot.confint(band="sup-t")
145
+ ```
146
+
147
+ Bootstrap support currently excludes IV, fixed effects, panels, clustered/HAC covariance, SPJ, and smooth LPs. See [`docs/bootstrap_inference.md`](docs/bootstrap_inference.md).
148
+
149
+ ## LP-IV and panel LPs
150
+
151
+ PyFixest/`feols`-style formula parts are passed through horizon by horizon:
152
+
153
+ ```python
154
+ iv_fit = lp.lp(
155
+ "y ~ controls | 0 | shock ~ instrument",
156
+ data=df,
157
+ shock="shock",
158
+ horizons=range(0, 13),
159
+ )
160
+
161
+ iv_fit.iv_diagnostics()
162
+ ```
163
+
164
+ Panel leads and lags are built within groups. Fixed effects and clustered covariance are delegated to PyFixest:
165
+
166
+ ```python
167
+ panel_fit = lp.lp(
168
+ "y ~ shock + l(y, 1:2) | unit + time",
169
+ data=panel,
170
+ groupby="unit",
171
+ time="time",
172
+ shock="shock",
173
+ horizons=range(0, 9),
174
+ vcov={"CRV1": "unit"},
175
+ )
176
+
177
+ spj_fit = lp.lp(
178
+ "y ~ shock | unit",
179
+ data=panel,
180
+ groupby="unit",
181
+ time="time",
182
+ shock="shock",
183
+ horizons=range(0, 9),
184
+ estimator="spj",
185
+ vcov={"CRV1": "unit"},
186
+ )
187
+ ```
188
+
189
+ SPJ currently supports one-way fixed effects matching `groupby`; two-way FE and multiway-cluster SPJ are not yet implemented. See [`docs/iv_lp.md`](docs/iv_lp.md) and [`docs/panel_lp.md`](docs/panel_lp.md) for assumptions, diagnostics, sampling, and inference details.
190
+
191
+ ## Herbst–Johannsen finite-sample correction
192
+
193
+ For a time-series LP with one directly observed iid shock and predetermined controls, use the recursive Herbst–Johannsen BCC estimator:
194
+
195
+ ```python
196
+ hj_fit = lp.lp(
197
+ "y ~ shock + l(y, 1:4)",
198
+ data=df,
199
+ shock="shock",
200
+ horizons=range(0, 13),
201
+ time="date",
202
+ estimator="herbst_johannsen", # `"hj"` also works
203
+ vcov="hc1",
204
+ )
205
+ ```
206
+
207
+ The default recursively plugs corrected lower-horizon estimates into the analytical bias expression (equation 11 in Herbst & Johannsen). Use `hj={"plugin": "ols"}` for their one-step BC estimator (equation 10). Horizons must be ordered, contiguous, and start at zero. The current implementation supports one observed shock, no IV/fixed effects/panels, and a contiguous complete time-series sample. It retains the original OLS covariance for first-order asymptotic inference; the correction can still increase finite-sample variance. Diagnostics and horizon-specific correction terms are in `hj_fit.metadata["bias_correction"]`. See [`docs/herbst_johannsen.md`](docs/herbst_johannsen.md).
208
+
209
+ ## Smooth LPs
210
+
211
+ ```python
212
+ smooth_fit = lp.lp(
213
+ "y ~ shock + l(y, 1:4) + l(shock, 1:4)",
214
+ data=df,
215
+ shock="shock",
216
+ horizons=range(0, 21),
217
+ estimator="smooth",
218
+ smooth={"lambda": "cv", "r": 2, "vcov": "nw"},
219
+ )
220
+ ```
221
+
222
+ Smooth LPs support multiple outcomes and observed shocks. Smooth IV supports one outcome and one endogenous shock:
223
+
224
+ ```python
225
+ smooth_iv = lp.lp(
226
+ "y ~ l(y, 1:4) + l(shock, 1:4) | 0 | shock ~ instrument",
227
+ data=df,
228
+ shock="shock",
229
+ horizons=range(0, 21),
230
+ estimator="smooth",
231
+ smooth={"lambda": "cv", "vcov": "nw"},
232
+ )
233
+ ```
234
+
235
+ Fixed effects and grouped/panel smooth LPs remain unsupported. See [`docs/smooth_lp.md`](docs/smooth_lp.md) for the estimand, tuning options, uncertainty, and smooth-IV scope.
236
+
237
+ ## High-dimensional desparsified-lasso LPs
238
+
239
+ Use `estimator="debiased_lasso"` (aliases: `"desparsified_lasso"` and `"hdlp"`) when the formula contains many controls, potentially more than observations:
240
+
241
+ ```python
242
+ hdlp_fit = lp.lp(
243
+ "y ~ shock + l(y, 1:12) + l(shock, 1:12) + "
244
+ + " + ".join(macro_controls),
245
+ data=df,
246
+ shock="shock",
247
+ horizons=range(0, 25),
248
+ time="date",
249
+ estimator="debiased_lasso",
250
+ vcov="hac",
251
+ hdlp={"plugin_constant": 0.8, "random_state": 123},
252
+ )
253
+ ```
254
+
255
+ The named shock coefficients are left unpenalized. Other formula columns are selected with the iterative plug-in lasso. Nodewise regressions use the longest outcome-independent source sample with a valid RHS design; its scaling and desparsifying state are reused only when exact Origins, columns, and evaluated design values align. Inference uses Origin Order to construct the authors' Newey–West covariance with an Andrews data-driven bandwidth by default. Explicit non-HAC requests are rejected. A fixed maximum lag can be requested with `vcov={"type": "hac", "lags": 4}`; excessive lags are rejected rather than truncated, and automatic Andrews selection requires at least four observations and defined score innovations. Exact own-response impact is returned as the normalized coefficient `1` with zero covariance; normalized-only requests skip nuisance fitting entirely.
256
+
257
+ The current scope is observed-shock time-series LPs without IV, fixed effects, or panel grouping. Data are demeaned and standardized internally. `hdlp` diagnostics record selected controls, initial and nodewise penalties, nodewise reuse, and bandwidths. See [`docs/high_dimensional_lasso.md`](docs/high_dimensional_lasso.md).
258
+
259
+ ## Bayesian SU-LP
260
+
261
+ ```python
262
+ bayes_fit = lp.lp(
263
+ "y ~ shock + l(y, 1:2)",
264
+ data=df,
265
+ shock="shock",
266
+ horizons=range(0, 9),
267
+ estimator="bayesian_sulp",
268
+ sample="common",
269
+ sulp={"draws": 1000, "burnin": 1000, "chains": 2, "seed": 123},
270
+ )
271
+
272
+ bayes_fit.tidy(level=0.9)
273
+ bayes_fit.plot(level=0.9, include_gp=True)
274
+ bayes_fit.posterior_draws
275
+ ```
276
+
277
+ The Bayesian estimator currently supports one outcome, one or more observed shocks, simple additive RHS terms, and contiguous horizons starting at zero. IV/proxy measurement equations, panels, multiple outcomes, missing-lead imputation, and stochastic volatility are deferred. See [`docs/bayesian_sulp.md`](docs/bayesian_sulp.md).
278
+
279
+ ## Documentation
280
+
281
+ - [`docs/api_design.md`](docs/api_design.md) — current API and proposed extensions
282
+ - [`docs/architecture.md`](docs/architecture.md) — current implementation and target architecture
283
+ - [`CONTEXT.md`](CONTEXT.md) — local-projection domain language
284
+ - [`docs/mvp_plan.md`](docs/mvp_plan.md) — implementation status and roadmap
285
+ - [`docs/technique_inventory.md`](docs/technique_inventory.md) — literature-driven method inventory
286
+ - [`docs/outcome_transform_examples.md`](docs/outcome_transform_examples.md) — outcome transformations
287
+ - [`docs/multiple_response_examples.md`](docs/multiple_response_examples.md) — multi-response plotting
288
+ - [`docs/bootstrap_inference.md`](docs/bootstrap_inference.md) — bootstrap workflow and scope
289
+ - [`docs/iv_lp.md`](docs/iv_lp.md) — instrumental-variable LP assumptions, diagnostics, and examples
290
+ - [`docs/panel_lp.md`](docs/panel_lp.md) — fixed-effect panel LP and split-panel jackknife workflows
291
+ - [`docs/herbst_johannsen.md`](docs/herbst_johannsen.md) — Herbst–Johannsen BC/BCC workflow and scope
292
+ - [`docs/smooth_lp.md`](docs/smooth_lp.md) — smooth observed-shock and smooth-IV workflows
293
+ - [`docs/bayesian_sulp.md`](docs/bayesian_sulp.md) — Bayesian SU-LP workflow and scope
294
+ - [`docs/high_dimensional_lasso.md`](docs/high_dimensional_lasso.md) — high-dimensional desparsified-lasso workflow and scope
295
+ - [`docs/replications/`](docs/replications/) — literature replications
296
+ - [`literature/`](literature/README.md) — literature references and selected figures
297
+ - [`CHANGELOG.md`](CHANGELOG.md) — notable changes by release
298
+
299
+ ## License
300
+
301
+ The LocalProj source code and original documentation are available under the [MIT License](LICENSE).
302
+ Third-party datasets and published figures retain their original rights and are not covered by
303
+ this license; see [`literature/README.md`](literature/README.md).
304
+
305
+ ## Development
306
+
307
+ ```bash
308
+ uv run --extra dev --extra bayes pytest -q
309
+ uv run --extra dev ruff check .
310
+ uv build
311
+ ```
312
+
313
+ The test suite covers the core estimator, formulas, Horizon Samples, high-dimensional lasso inference, panel/SPJ and Herbst–Johannsen estimation, smooth LPs, IV diagnostics, simultaneous bands, bootstrap inference, Bayesian SU-LP, plotting, and sample handling.
@@ -0,0 +1,274 @@
1
+ # LocalProj
2
+
3
+ [![CI](https://github.com/whoisnnamdi/localproj/actions/workflows/ci.yml/badge.svg)](https://github.com/whoisnnamdi/localproj/actions/workflows/ci.yml)
4
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-blue.svg)](pyproject.toml)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
+
7
+ `LocalProj` is a Python library for estimating local projections (LPs). The current `0.1.0` implementation includes regular time-series LPs, LP-IV, high-dimensional desparsified-lasso LPs, panel fixed effects and split-panel jackknife estimates, Herbst–Johannsen finite-sample bias correction, smooth LPs, wild-bootstrap and simultaneous inference, and observed-shock Bayesian SU-LPs.
8
+
9
+ > **Project status:** `0.1.0` is an alpha release. The public API may evolve as the package gains broader production use.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ uv add localproj
15
+ ```
16
+
17
+ Plotting is included in the standard installation. Bayesian diagnostics are available as an extra:
18
+
19
+ ```bash
20
+ uv add "localproj[bayes]"
21
+ ```
22
+
23
+ ## Quick start
24
+
25
+ ```python
26
+ import localproj as lp
27
+
28
+ fit = lp.lp(
29
+ "y ~ shock + l(y, 1:4) + l(shock, 1:4)",
30
+ data=df,
31
+ shock="shock",
32
+ horizons=range(0, 13),
33
+ outcome="level", # also: "cumulative" or "diff"
34
+ sample="horizon", # or "common"
35
+ vcov="hc1",
36
+ )
37
+
38
+ print(fit.tidy())
39
+ print(fit.coef())
40
+ print(fit.confint())
41
+ print(fit.summary())
42
+ ```
43
+
44
+ The formula preprocessor supports `l(var, periods)` and `f(var, periods)` helpers. `horizons=12` means horizons `0..12`; an explicit iterable is also accepted. Regular LPs use HC1 covariance when `vcov` is omitted; HAC/Newey–West remains available explicitly with `vcov="hac"` or a fixed lag specification.
45
+
46
+ ## Supported estimators and inference
47
+
48
+ | Area | Current support |
49
+ |---|---|
50
+ | Regular LP | Horizon-by-horizon PyFixest OLS; multiple outcomes and shocks |
51
+ | Outcome transforms | Level, cumulative/long difference, period difference, custom callable |
52
+ | Samples | Horizon-specific or common complete-case sample |
53
+ | Covariance | Regular LPs: IID, HC1–HC3, HAC/Newey-West, and PyFixest cluster specifications; smooth LPs also support HC0 |
54
+ | LP-IV | PyFixest/`feols`-style IV formulas and first-stage diagnostics |
55
+ | Panel LP | Group-aware leads/lags, fixed effects, clustered covariance |
56
+ | Bias correction | Split-panel jackknife for panels; Herbst–Johannsen analytical BC/BCC for observed-shock time-series LPs |
57
+ | Smooth LP | B-spline ridge smoothing, contiguous-fold CV, HC0/NW inference, multiple responses, and single-shock smooth IV |
58
+ | High-dimensional LP | Adamek–Smeekes–Wilms desparsified lasso with unpenalized shock coefficients, plug-in tuning, reused nodewise regressions, and Newey–West inference |
59
+ | Joint inference | Gaussian sup-t and Scheffé bands, plus cross-horizon Wald tests, for common-sample regular OLS LPs |
60
+ | Bootstrap | Wild residual bootstrap with pointwise and sup-t intervals for regular OLS LPs |
61
+ | Bayesian | Observed-shock SU-LP with hierarchical GP/Normal-Gamma shrinkage |
62
+ | Plotting | Plotnine IRF plots, selection, and outcome/shock faceting |
63
+
64
+ ## Multiple outcomes and shocks
65
+
66
+ ```python
67
+ fit = lp.lp(
68
+ "gdp + cpi ~ mp_shock + fp_shock + l(gdp, 1:4) + l(cpi, 1:4)",
69
+ data=df,
70
+ shock=["mp_shock", "fp_shock"],
71
+ horizons=range(0, 13),
72
+ )
73
+
74
+ fit.tidy() # one row per (outcome, shock, horizon)
75
+ fit.coef(outcome="gdp", shock="mp_shock")
76
+ fit.plot(facet_by=["outcome", "shock"])
77
+ ```
78
+
79
+ ## Simultaneous and bootstrap inference
80
+
81
+ Regular LP simultaneous bands require an aligned common sample:
82
+
83
+ ```python
84
+ joint_fit = lp.lp(
85
+ "y ~ shock + l(y, 1:4) + l(shock, 1:4)",
86
+ data=df,
87
+ shock="shock",
88
+ horizons=range(0, 13),
89
+ sample="common",
90
+ vcov="hc1",
91
+ )
92
+
93
+ joint_fit.confint(band="sup-t")
94
+ joint_fit.confint(band="scheffe")
95
+ joint_fit.wald(horizons=range(0, 13), null=0)
96
+ ```
97
+
98
+ Joint inference supports IID and HC1–HC3 covariance directly. HAC joint inference requires an explicit common lag count, such as `vcov={"type": "hac", "lags": 4}`; an omitted HAC lag remains valid for pointwise fits but does not produce joint covariance because its defaults vary by horizon.
99
+
100
+ Wild-bootstrap inference is available for regular PyFixest OLS LPs:
101
+
102
+ ```python
103
+ boot = joint_fit.bootstrap(reps=999, weights="rademacher", seed=123)
104
+ boot.confint(interval="percentile")
105
+ boot.confint(band="sup-t")
106
+ ```
107
+
108
+ Bootstrap support currently excludes IV, fixed effects, panels, clustered/HAC covariance, SPJ, and smooth LPs. See [`docs/bootstrap_inference.md`](docs/bootstrap_inference.md).
109
+
110
+ ## LP-IV and panel LPs
111
+
112
+ PyFixest/`feols`-style formula parts are passed through horizon by horizon:
113
+
114
+ ```python
115
+ iv_fit = lp.lp(
116
+ "y ~ controls | 0 | shock ~ instrument",
117
+ data=df,
118
+ shock="shock",
119
+ horizons=range(0, 13),
120
+ )
121
+
122
+ iv_fit.iv_diagnostics()
123
+ ```
124
+
125
+ Panel leads and lags are built within groups. Fixed effects and clustered covariance are delegated to PyFixest:
126
+
127
+ ```python
128
+ panel_fit = lp.lp(
129
+ "y ~ shock + l(y, 1:2) | unit + time",
130
+ data=panel,
131
+ groupby="unit",
132
+ time="time",
133
+ shock="shock",
134
+ horizons=range(0, 9),
135
+ vcov={"CRV1": "unit"},
136
+ )
137
+
138
+ spj_fit = lp.lp(
139
+ "y ~ shock | unit",
140
+ data=panel,
141
+ groupby="unit",
142
+ time="time",
143
+ shock="shock",
144
+ horizons=range(0, 9),
145
+ estimator="spj",
146
+ vcov={"CRV1": "unit"},
147
+ )
148
+ ```
149
+
150
+ SPJ currently supports one-way fixed effects matching `groupby`; two-way FE and multiway-cluster SPJ are not yet implemented. See [`docs/iv_lp.md`](docs/iv_lp.md) and [`docs/panel_lp.md`](docs/panel_lp.md) for assumptions, diagnostics, sampling, and inference details.
151
+
152
+ ## Herbst–Johannsen finite-sample correction
153
+
154
+ For a time-series LP with one directly observed iid shock and predetermined controls, use the recursive Herbst–Johannsen BCC estimator:
155
+
156
+ ```python
157
+ hj_fit = lp.lp(
158
+ "y ~ shock + l(y, 1:4)",
159
+ data=df,
160
+ shock="shock",
161
+ horizons=range(0, 13),
162
+ time="date",
163
+ estimator="herbst_johannsen", # `"hj"` also works
164
+ vcov="hc1",
165
+ )
166
+ ```
167
+
168
+ The default recursively plugs corrected lower-horizon estimates into the analytical bias expression (equation 11 in Herbst & Johannsen). Use `hj={"plugin": "ols"}` for their one-step BC estimator (equation 10). Horizons must be ordered, contiguous, and start at zero. The current implementation supports one observed shock, no IV/fixed effects/panels, and a contiguous complete time-series sample. It retains the original OLS covariance for first-order asymptotic inference; the correction can still increase finite-sample variance. Diagnostics and horizon-specific correction terms are in `hj_fit.metadata["bias_correction"]`. See [`docs/herbst_johannsen.md`](docs/herbst_johannsen.md).
169
+
170
+ ## Smooth LPs
171
+
172
+ ```python
173
+ smooth_fit = lp.lp(
174
+ "y ~ shock + l(y, 1:4) + l(shock, 1:4)",
175
+ data=df,
176
+ shock="shock",
177
+ horizons=range(0, 21),
178
+ estimator="smooth",
179
+ smooth={"lambda": "cv", "r": 2, "vcov": "nw"},
180
+ )
181
+ ```
182
+
183
+ Smooth LPs support multiple outcomes and observed shocks. Smooth IV supports one outcome and one endogenous shock:
184
+
185
+ ```python
186
+ smooth_iv = lp.lp(
187
+ "y ~ l(y, 1:4) + l(shock, 1:4) | 0 | shock ~ instrument",
188
+ data=df,
189
+ shock="shock",
190
+ horizons=range(0, 21),
191
+ estimator="smooth",
192
+ smooth={"lambda": "cv", "vcov": "nw"},
193
+ )
194
+ ```
195
+
196
+ Fixed effects and grouped/panel smooth LPs remain unsupported. See [`docs/smooth_lp.md`](docs/smooth_lp.md) for the estimand, tuning options, uncertainty, and smooth-IV scope.
197
+
198
+ ## High-dimensional desparsified-lasso LPs
199
+
200
+ Use `estimator="debiased_lasso"` (aliases: `"desparsified_lasso"` and `"hdlp"`) when the formula contains many controls, potentially more than observations:
201
+
202
+ ```python
203
+ hdlp_fit = lp.lp(
204
+ "y ~ shock + l(y, 1:12) + l(shock, 1:12) + "
205
+ + " + ".join(macro_controls),
206
+ data=df,
207
+ shock="shock",
208
+ horizons=range(0, 25),
209
+ time="date",
210
+ estimator="debiased_lasso",
211
+ vcov="hac",
212
+ hdlp={"plugin_constant": 0.8, "random_state": 123},
213
+ )
214
+ ```
215
+
216
+ The named shock coefficients are left unpenalized. Other formula columns are selected with the iterative plug-in lasso. Nodewise regressions use the longest outcome-independent source sample with a valid RHS design; its scaling and desparsifying state are reused only when exact Origins, columns, and evaluated design values align. Inference uses Origin Order to construct the authors' Newey–West covariance with an Andrews data-driven bandwidth by default. Explicit non-HAC requests are rejected. A fixed maximum lag can be requested with `vcov={"type": "hac", "lags": 4}`; excessive lags are rejected rather than truncated, and automatic Andrews selection requires at least four observations and defined score innovations. Exact own-response impact is returned as the normalized coefficient `1` with zero covariance; normalized-only requests skip nuisance fitting entirely.
217
+
218
+ The current scope is observed-shock time-series LPs without IV, fixed effects, or panel grouping. Data are demeaned and standardized internally. `hdlp` diagnostics record selected controls, initial and nodewise penalties, nodewise reuse, and bandwidths. See [`docs/high_dimensional_lasso.md`](docs/high_dimensional_lasso.md).
219
+
220
+ ## Bayesian SU-LP
221
+
222
+ ```python
223
+ bayes_fit = lp.lp(
224
+ "y ~ shock + l(y, 1:2)",
225
+ data=df,
226
+ shock="shock",
227
+ horizons=range(0, 9),
228
+ estimator="bayesian_sulp",
229
+ sample="common",
230
+ sulp={"draws": 1000, "burnin": 1000, "chains": 2, "seed": 123},
231
+ )
232
+
233
+ bayes_fit.tidy(level=0.9)
234
+ bayes_fit.plot(level=0.9, include_gp=True)
235
+ bayes_fit.posterior_draws
236
+ ```
237
+
238
+ The Bayesian estimator currently supports one outcome, one or more observed shocks, simple additive RHS terms, and contiguous horizons starting at zero. IV/proxy measurement equations, panels, multiple outcomes, missing-lead imputation, and stochastic volatility are deferred. See [`docs/bayesian_sulp.md`](docs/bayesian_sulp.md).
239
+
240
+ ## Documentation
241
+
242
+ - [`docs/api_design.md`](docs/api_design.md) — current API and proposed extensions
243
+ - [`docs/architecture.md`](docs/architecture.md) — current implementation and target architecture
244
+ - [`CONTEXT.md`](CONTEXT.md) — local-projection domain language
245
+ - [`docs/mvp_plan.md`](docs/mvp_plan.md) — implementation status and roadmap
246
+ - [`docs/technique_inventory.md`](docs/technique_inventory.md) — literature-driven method inventory
247
+ - [`docs/outcome_transform_examples.md`](docs/outcome_transform_examples.md) — outcome transformations
248
+ - [`docs/multiple_response_examples.md`](docs/multiple_response_examples.md) — multi-response plotting
249
+ - [`docs/bootstrap_inference.md`](docs/bootstrap_inference.md) — bootstrap workflow and scope
250
+ - [`docs/iv_lp.md`](docs/iv_lp.md) — instrumental-variable LP assumptions, diagnostics, and examples
251
+ - [`docs/panel_lp.md`](docs/panel_lp.md) — fixed-effect panel LP and split-panel jackknife workflows
252
+ - [`docs/herbst_johannsen.md`](docs/herbst_johannsen.md) — Herbst–Johannsen BC/BCC workflow and scope
253
+ - [`docs/smooth_lp.md`](docs/smooth_lp.md) — smooth observed-shock and smooth-IV workflows
254
+ - [`docs/bayesian_sulp.md`](docs/bayesian_sulp.md) — Bayesian SU-LP workflow and scope
255
+ - [`docs/high_dimensional_lasso.md`](docs/high_dimensional_lasso.md) — high-dimensional desparsified-lasso workflow and scope
256
+ - [`docs/replications/`](docs/replications/) — literature replications
257
+ - [`literature/`](literature/README.md) — literature references and selected figures
258
+ - [`CHANGELOG.md`](CHANGELOG.md) — notable changes by release
259
+
260
+ ## License
261
+
262
+ The LocalProj source code and original documentation are available under the [MIT License](LICENSE).
263
+ Third-party datasets and published figures retain their original rights and are not covered by
264
+ this license; see [`literature/README.md`](literature/README.md).
265
+
266
+ ## Development
267
+
268
+ ```bash
269
+ uv run --extra dev --extra bayes pytest -q
270
+ uv run --extra dev ruff check .
271
+ uv build
272
+ ```
273
+
274
+ The test suite covers the core estimator, formulas, Horizon Samples, high-dimensional lasso inference, panel/SPJ and Herbst–Johannsen estimation, smooth LPs, IV diagnostics, simultaneous bands, bootstrap inference, Bayesian SU-LP, plotting, and sample handling.