# clp: curvilinear local projections for Stata

Version 1.2.0, 9 October 2026.

`clp` fits quadratic local projections at user-specified horizons, using within least squares or Poisson pseudo-maximum likelihood with absorbed fixed effects. It reports coefficients, endpoint slopes, intersection-union tests for U or inverted-U shapes, stationary points with delta-method intervals and Fieller sets, and curvature changes across horizons. The existing 29-column `r(table)` is retained; the additional `r(fieller)` matrix identifies every computed Fieller set type and its endpoints.

## Installation

Install from the independent CLP project:

```stata
net install clp, from("https://clp-stata.pages.dev") replace
help clp
```

The declared minimum is Stata 16. The development test environment uses Stata 19.5; the version declaration does not establish that the release has been run on Stata 16. The default `estimator(ppml)` uses `ppmlhdfe`, with its `reghdfe` and `ftools` dependencies. Install missing dependencies with:

```stata
ssc install ftools
ssc install reghdfe
ssc install ppmlhdfe
```

`estimator(linear)` uses built-in `xtreg, fe` with time indicators when `absorb()` contains the panel and time variables declared by `xtset`. Internally encoded time indicators support negative event-time values without changing the declared time variable. Other absorbed-effect specifications use `reghdfe`.

## Syntax

```stata
clp depvar dosevar [controls] [if] [in], horizons(numlist) absorb(absvars) ///
    [estimator(ppml|linear) transform(none|asinh|log) cumulative ///
     outcomes(varlist) vce(vcetype) support(lo hi) shape(auto|invu|u) ///
     level(#) reference(#) graph graphoptions(string) ///
     saving(filename[, replace]) estore(name) noprint verbose estimator_options]
```

The data must be declared with `xtset panelvar timevar`. The outcome and dose must be plain numeric variables; controls may use factor-variable and time-series notation. `horizons()` specifies integer horizons, and `absorb()` specifies the fixed effects.

- `estimator(ppml)` is the default; `estimator(linear)` selects within least squares.
- `transform(asinh)` or `transform(log)` transforms the outcome for linear estimation. The default is `transform(none)`; the log transformation excludes nonpositive outcomes.
- `cumulative` sums outcomes from the current period through each horizon before any requested transformation. Horizons must be nonnegative.
- `outcomes()` supplies one outcome variable per horizon instead of constructing leads. With `cumulative`, horizons must be consecutive from zero.
- `vce()` passes the variance specification to the estimator, including clustered standard errors.
- `support()` sets the interval used for endpoint tests and graphs. Its default is the observed dose range across the estimation samples.
- `shape()` chooses the inverted-U or U alternative. The default, `auto`, uses the sign of the quadratic coefficient.
- `reference()` selects the horizon used for curvature comparisons; its default is the first specified horizon. `level()` defaults to 95.
- `graph`, `saving()`, and `estore()` produce profile plots, a results dataset, and stored horizon-specific estimates. `noprint` suppresses summary tables; `verbose` displays estimator output. Other options are passed to the estimator.
- `graphoptions(name(myprofile, replace))` names the combined profile graph. Without a name option, the default is `name(clp, replace)`. Temporary component graphs preserve unrelated existing graphs.
- Every name generated by `estore()`, including the horizon suffix, must be a valid Stata name with at most 32 characters. Invalid names are rejected before fitting any horizon. Stored estimates support coefficient tables; native residual prediction is unsupported because generated horizon outcomes or time-effect indicators may no longer exist after the command returns.

Slopes and curvature refer to the log mean under PPML and to the mean of the projected outcome under linear estimation. Linear coefficient and endpoint-test p-values and Fieller sets use the estimator's residual degrees of freedom when available; otherwise the normal reference distribution is used. PPML uses the normal reference distribution. Stationary-point Wald intervals and profile bands use normal critical values under both estimators. See `help clp` for formulas, references, and all returned results.

## Fieller sets and saved results

`r(fieller)` has one row per horizon and six columns: `h type lb ub gap_lb gap_ub`. Its `type` values are:

| Type | Confidence set | Relevant endpoints |
|---|---|---|
| `0` | Entire real line | None |
| `1` | Bounded interval, including a singleton | `[lb, ub]` |
| `2` | Two exterior intervals | `(-inf, gap_lb]` and `[gap_ub, +inf)` |
| `3` | Left half-line | `(-inf, ub]` |
| `4` | Right half-line | `[lb, +inf)` |
| `5` | Empty set | None |
| `.` | Not computable from the available inputs | None |

Unused endpoints are missing. `r(table)` retains its original columns and order. Its `fl_lb` or `fl_ub` may now carry a finite half-line endpoint when `fl_bounded` is zero. Use the explicit set type rather than inferring the entire real line from missing gap endpoints. Missing endpoint standard errors yield missing intersection-union p-values.

`saving()` writes the original 29 result variables plus `fl_type`, preserving numeric precision. Dataset characteristics record the outcome, dose, absorbed effects, variance specification, support, confidence level, reference horizon, estimator, transformation, accumulation, controls, shape alternative, supplied outcomes, command line, horizons and package version. Their names use the `clp_` prefix; `help clp` lists them individually.

## Simulated example

The example creates a simulated firm-year panel and requires no external dataset. Run it in a Stata session where clearing the current data is appropriate:

```stata
net get clp, from("https://clp-stata.pages.dev") replace
do clp_example.do
```

The example estimates several horizons, reports shape statistics, draws profile plots, saves temporary results, and stores estimates. It uses the PPML dependencies listed above.

## Deterministic self-test

Retrieve the ancillary scripts, change to the directory containing them, and run:

```stata
net get clp, from("https://clp-stata.pages.dev") replace
do clp_selftest.do
```

Run the self-test in a fresh session: **it clears the current data** and constructs a deterministic synthetic panel. The full suite requires `ftools`, `reghdfe` and `ppmlhdfe`; it uses no external research dataset. It checks the command's numerical and interface behavior rather than reproducing a manuscript's empirical results.

The test procedure adopts the AER-Skills reproducibility practices of a fixed seed, relative paths, recorded dependency versions and named numerical assertions. Check the test log and its completion status; a process starting successfully is not a passing test. These practices do not constitute AEA certification, an editorial reproducibility review or manuscript acceptance. Exact dependency versions must be recorded because `ssc install` by itself does not pin a version.

## Methodological sources

The command combines local projections, quadratic endpoint intersection-union inference, inversion of the Fieller inequality and absorbed-effect estimation. The help file cites the methodological sources and defines the statistics and reference distributions. The software tests concern this implementation and do not establish causal identification for a particular application. Changes in this release are listed in [CHANGELOG.md](CHANGELOG.md).

## Package files

`clp.pkg` and `stata.toc` describe the package. `net install` installs `clp.ado` and `clp.sthlp`; `net get` retrieves the ancillary `clp_example.do` and `clp_selftest.do`. The license is included as `clp_license.txt`. This package contains no research data or manuscript files.

## License

MIT License. Copyright (c) 2026 CLP. See [clp_license.txt](clp_license.txt). The package installs this license alongside its command and help files.
