tf-inference 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.
- tf_inference-0.1.0/LICENSE +21 -0
- tf_inference-0.1.0/PKG-INFO +301 -0
- tf_inference-0.1.0/README.md +279 -0
- tf_inference-0.1.0/pyproject.toml +171 -0
- tf_inference-0.1.0/pyproject.toml.orig +90 -0
- tf_inference-0.1.0/src/tf_inference/__init__.py +55 -0
- tf_inference-0.1.0/src/tf_inference/calibration.py +228 -0
- tf_inference-0.1.0/src/tf_inference/cli.py +57 -0
- tf_inference-0.1.0/src/tf_inference/curve.py +195 -0
- tf_inference-0.1.0/src/tf_inference/data/calibrations.json +4 -0
- tf_inference-0.1.0/src/tf_inference/data/calibrations.parquet +0 -0
- tf_inference-0.1.0/src/tf_inference/probability.py +227 -0
- tf_inference-0.1.0/src/tf_inference/py.typed +0 -0
- tf_inference-0.1.0/src/tf_inference/tables.py +387 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gaurav Sood
|
|
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,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tf-inference
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Numerically constructed tF critical values for single-instrument IV inference
|
|
5
|
+
Keywords: instrumental variables,weak instruments,econometrics,inference,tF
|
|
6
|
+
Author: Gaurav Sood
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
13
|
+
Requires-Dist: numpy>=1.26
|
|
14
|
+
Requires-Dist: scipy>=1.12
|
|
15
|
+
Requires-Dist: pyarrow>=18
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Project-URL: Homepage, https://github.com/finite-sample/tf-inference
|
|
18
|
+
Project-URL: Repository, https://github.com/finite-sample/tf-inference
|
|
19
|
+
Project-URL: Issues, https://github.com/finite-sample/tf-inference/issues
|
|
20
|
+
Project-URL: Documentation, https://github.com/finite-sample/tf-inference#readme
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# tf-inference
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
[](https://github.com/finite-sample/tf-inference/actions/workflows/ci.yml)
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
tf-inference computes tF critical values and confidence intervals for
|
|
30
|
+
instrumental-variable (IV) models with one endogenous regressor and one
|
|
31
|
+
excluded instrument. It provides generated tables for common confidence
|
|
32
|
+
levels and numerical calibration for other levels.
|
|
33
|
+
|
|
34
|
+
The tF method and its theoretical results are due to David S. Lee,
|
|
35
|
+
Justin McCrary, Marcelo J. Moreira and Jack Porter, authors of [Valid
|
|
36
|
+
t-Ratio Inference for IV (2022)](https://doi.org/10.1257/aer.20211063).
|
|
37
|
+
This package provides an independent Python implementation of their
|
|
38
|
+
Appendix B.3 construction and reusable numerical tables. Critical values
|
|
39
|
+
depend on the first-stage F statistic and a two-sided significance
|
|
40
|
+
level. The code constructs the curve from its boundary expansion and
|
|
41
|
+
recurrence; the published rounded tables serve as test references.
|
|
42
|
+
|
|
43
|
+
This is an initial numerical implementation. Its calibration uses
|
|
44
|
+
deterministic integration, a finite nuisance-parameter grid and local
|
|
45
|
+
searches. These checks are documented and reproducible; they are not a
|
|
46
|
+
proof of a uniform size bound. The inferential framework is asymptotic
|
|
47
|
+
under the single-instrument IV model, not a finite-sample coverage
|
|
48
|
+
guarantee or a remedy for invalid instruments.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
Install with Python 3.12 or later:
|
|
53
|
+
|
|
54
|
+
python -m pip install tf-inference
|
|
55
|
+
|
|
56
|
+
NumPy, SciPy and PyArrow are required at runtime. No Stata, external data
|
|
57
|
+
download, API key or network access is needed to evaluate or generate
|
|
58
|
+
critical values.
|
|
59
|
+
|
|
60
|
+
## Use the generated tables
|
|
61
|
+
|
|
62
|
+
``` python
|
|
63
|
+
from tf_inference import critical_value, confidence_interval
|
|
64
|
+
|
|
65
|
+
critical_value([3.8, 3.9, 10, 1000], alpha=0.05)
|
|
66
|
+
# Approximately [inf, 30.93, 3.43035, 1.95996]
|
|
67
|
+
|
|
68
|
+
confidence_interval(coefficient=1, se=0.4, f_stat=10, alpha=0.05)
|
|
69
|
+
# Approximately [-0.37214, 2.37214]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`alpha` is the significance level: 0.05 means 95% confidence. The return
|
|
73
|
+
value of `critical_value` is the threshold for **absolute t**, not t
|
|
74
|
+
squared or a standard-error multiplier. Divide it by the normal
|
|
75
|
+
two-sided critical value to obtain the corresponding standard-error
|
|
76
|
+
multiplier for that alpha.
|
|
77
|
+
|
|
78
|
+
Inputs broadcast as NumPy arrays. Confidence intervals put lower and
|
|
79
|
+
upper bounds on the final axis. Complex inputs, nonfinite or negative F statistics,
|
|
80
|
+
nonfinite coefficients, and nonpositive standard errors are rejected.
|
|
81
|
+
|
|
82
|
+
The 95% boundary is about 3.84145882. F at or below the boundary returns
|
|
83
|
+
an infinite critical value; F strictly above it has a finite critical
|
|
84
|
+
value. There is no artificial cutoff at F=4. The boundary is computed
|
|
85
|
+
separately for each alpha as `scipy.special.ndtri(alpha / 2)**2`. Very
|
|
86
|
+
close to the boundary, rounding in the input F itself can materially
|
|
87
|
+
affect the result.
|
|
88
|
+
|
|
89
|
+
Bundled tables cover alpha values 0.0001, 0.0005, 0.001, 0.002, 0.005,
|
|
90
|
+
0.01, 0.02, 0.025, 0.03, 0.04, 0.05, 0.06, 0.075, 0.1, 0.125, 0.15, 0.2
|
|
91
|
+
and 0.25. Each contains at least 16,385 rows, concentrated near the
|
|
92
|
+
boundary. List the installed levels with `available_alphas()`. Tables
|
|
93
|
+
are never interpolated across alpha values.
|
|
94
|
+
|
|
95
|
+
The Python convenience functions and CLI default to `method="table"`. A
|
|
96
|
+
missing level raises an error; numerical calibration requires an
|
|
97
|
+
explicit `method="compute"` or a direct call to `calibrate`. The `auto`
|
|
98
|
+
method is not supported.
|
|
99
|
+
|
|
100
|
+
## Calculate an unconventional level
|
|
101
|
+
|
|
102
|
+
``` python
|
|
103
|
+
from tf_inference import calibrate
|
|
104
|
+
|
|
105
|
+
calibration = calibrate(alpha=0.037)
|
|
106
|
+
calibration.critical_value([4.5, 10, 100])
|
|
107
|
+
calibration.confidence_interval(1, 0.4, 10)
|
|
108
|
+
print(calibration.diagnostics)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The bundled Parquet dataset is read and validated once; interpolators are
|
|
112
|
+
cached per alpha and shared by `load_table`,
|
|
113
|
+
`critical_value` and `confidence_interval`. Repeated lookup does not
|
|
114
|
+
read files, verify checksums again or rebuild the interpolator. Explicit
|
|
115
|
+
`method="compute"` calls use a separate cache of up to 32 calibrations.
|
|
116
|
+
Direct `calibrate` calls always compute afresh. Tables loaded from a
|
|
117
|
+
custom directory are read and checksum-verified on each call so changes
|
|
118
|
+
are detected.
|
|
119
|
+
|
|
120
|
+
For large inputs, pass a NumPy array in one call. For repeated work at
|
|
121
|
+
one level, retain `load_table(alpha)` or the result of
|
|
122
|
+
`calibrate(alpha)` and call its methods directly.
|
|
123
|
+
|
|
124
|
+
The numerical alpha domain is \[0.0001, 0.25\]. It covers confidence
|
|
125
|
+
levels from 75% to 99.99%. This is an explicit implementation range, not
|
|
126
|
+
a theoretical limit of tF. Calculations outside it are rejected rather
|
|
127
|
+
than extrapolated.
|
|
128
|
+
|
|
129
|
+
`calibrate` accepts `epsilon`, `seeds`, `size_tolerance`,
|
|
130
|
+
`strength_limit`, `strengths` and `correlations`. Smaller initialization
|
|
131
|
+
epsilon and more seeds allow convergence checks. These settings are not
|
|
132
|
+
claims of certified error. Failed recurrence, integration or
|
|
133
|
+
optimization raises `ConvergenceError`. Inspect the returned diagnostics
|
|
134
|
+
when doing new calibrations, and validate beyond the search settings
|
|
135
|
+
before relying on an unconventional level for research.
|
|
136
|
+
|
|
137
|
+
## Generate constants for other software
|
|
138
|
+
|
|
139
|
+
The command-line interface exposes the same calculation:
|
|
140
|
+
|
|
141
|
+
tf-inference critical 3.9 10 100 --alpha 0.05
|
|
142
|
+
tf-inference critical 10 --alpha 0.037 --method compute
|
|
143
|
+
tf-inference generate --alpha 0.05 0.01 0.037 --output tables
|
|
144
|
+
|
|
145
|
+
The generator writes one `calibrations.parquet` dataset and a
|
|
146
|
+
`calibrations.json` manifest. Adding or replacing one alpha preserves the other
|
|
147
|
+
levels in that directory. The Parquet schema has three nonnullable float64
|
|
148
|
+
columns: `alpha`, `f_stat` and `regularized_squared`. Calibration settings,
|
|
149
|
+
plateaus and diagnostics are embedded as JSON in the Arrow schema metadata.
|
|
150
|
+
The schema-versioned manifest records the dataset's SHA-256 checksum.
|
|
151
|
+
Loading validates the checksum, schema, finite values, ordered grids,
|
|
152
|
+
boundary and plateau invariants, and agreement with the metadata.
|
|
153
|
+
|
|
154
|
+
`export_table(calibration, directory, points=16385)` and
|
|
155
|
+
`load_table(alpha, directory=directory)` provide the same operations in Python.
|
|
156
|
+
For a portable gzip CSV, add `--csv` to the generation command or pass
|
|
157
|
+
`include_csv=True` to `export_table`. CSV files are optional exports, not
|
|
158
|
+
packaged runtime data.
|
|
159
|
+
|
|
160
|
+
For accurate boundary evaluation, interpolate the regularized quantity
|
|
161
|
+
`Z(F) = (F - boundary) * critical(F)**2` using a monotone cubic interpolator.
|
|
162
|
+
It is the Parquet `regularized_squared` column (and the optional CSV's
|
|
163
|
+
`branch_regularized_squared` column). Then compute
|
|
164
|
+
`sqrt(Z(F) / (F - boundary))`. Cap F at the metadata's `plateau_f` before
|
|
165
|
+
evaluation and return infinity when F is at or below the boundary. The raw
|
|
166
|
+
branch extends to the Property (C) endpoint; at large F use the selected
|
|
167
|
+
plateau. The CSV's first critical value is infinite and must not be
|
|
168
|
+
interpolated as an ordinary finite row.
|
|
169
|
+
|
|
170
|
+
The export measures relative interpolation differences at every cell
|
|
171
|
+
midpoint against the computed curve, and rejects tables exceeding 1e-6
|
|
172
|
+
there. This is a measured check, not an interval-arithmetic error bound.
|
|
173
|
+
The shipped validation also compares randomly chosen F values against a
|
|
174
|
+
separately refined curve.
|
|
175
|
+
|
|
176
|
+
## How the calculation works
|
|
177
|
+
|
|
178
|
+
1. Compute the boundary q and initialize the squared critical value
|
|
179
|
+
near it using the expansion in Appendix B.3, step 1.
|
|
180
|
+
2. Apply the inverse map in step 2 to extend the decreasing curve. The
|
|
181
|
+
code interpolates Z(F), whose finite boundary limit is q cubed,
|
|
182
|
+
rather than interpolating a divergent critical value.
|
|
183
|
+
3. Locate the tangency that limits the decreasing segment under
|
|
184
|
+
Property (C). Its admissible plateau is also constrained to be at
|
|
185
|
+
least the normal two-sided critical value.
|
|
186
|
+
4. Integrate null rejection probabilities in the Gaussian weak-IV
|
|
187
|
+
experiment. Search the nuisance parameters and move the plateau
|
|
188
|
+
earlier if it over-rejects beyond the requested numerical tolerance.
|
|
189
|
+
|
|
190
|
+
The size search can change the plateau. For example, alpha=0.037
|
|
191
|
+
requires an adjustment to the first candidate. For alpha=0.01 the
|
|
192
|
+
plateau is about 2.72549, above the normal 99% critical value of about
|
|
193
|
+
2.57583. Replacing the 95% normal quantile with another quantile does
|
|
194
|
+
not implement general tF.
|
|
195
|
+
|
|
196
|
+
The default size search covers strength f0 from 0 to 80 and absolute
|
|
197
|
+
correlation rho from 0 to 1. Here E\[F\] = 1 + f0 squared; f0 is not F.
|
|
198
|
+
It includes singular rho=1 calculations, correlations approaching one,
|
|
199
|
+
and local searches between grid points. The strong-instrument limit is
|
|
200
|
+
checked separately by the normal critical-value constraint. The
|
|
201
|
+
unbounded nuisance domain is not exhaustively certified. The recorded
|
|
202
|
+
integration error does not include curve approximation or missed extrema
|
|
203
|
+
in the parameter search.
|
|
204
|
+
|
|
205
|
+
## Performance
|
|
206
|
+
|
|
207
|
+
Table lookup avoids numerical calibration. For large inputs, evaluate an array
|
|
208
|
+
in one call. `make benchmark` records separate timings for warm scalar and
|
|
209
|
+
array lookup, loading the complete Parquet dataset with empty package caches,
|
|
210
|
+
and fresh calibration. Imports and operating-system file-cache effects are
|
|
211
|
+
excluded. Results and environment details are in `benchmarks/results.json`;
|
|
212
|
+
`benchmarks/baseline.json` preserves the earlier implementation's measurements.
|
|
213
|
+
These are local observations, not CI timing assertions. Tests enforce that
|
|
214
|
+
default calls never calibrate and warm calls avoid file access and interpolator
|
|
215
|
+
construction.
|
|
216
|
+
|
|
217
|
+
## Validation and development
|
|
218
|
+
|
|
219
|
+
Install development dependencies and run the checks:
|
|
220
|
+
|
|
221
|
+
uv sync --all-groups
|
|
222
|
+
make ci
|
|
223
|
+
|
|
224
|
+
Tests cover the published rounded-table values and plateau landmarks,
|
|
225
|
+
initialization and grid refinement, the defining two-intersection
|
|
226
|
+
equations, monotonicity and the exact boundary, near-singular numerical
|
|
227
|
+
integration, independent Gaussian Monte Carlo calculations,
|
|
228
|
+
unconventional-alpha plateau adjustment, interval broadcasting, table
|
|
229
|
+
roundtrips and corrupted files, Parquet schema violations, complex inputs and
|
|
230
|
+
large-strength numerical stability. `make ci` runs Ruff, Pyright, pydoclint,
|
|
231
|
+
tests with a 90% coverage floor (including branch measurement), documentation
|
|
232
|
+
and distribution checks.
|
|
233
|
+
`preen check --strict` checks adoption of the shared py-canon standard.
|
|
234
|
+
|
|
235
|
+
`validation/validate.py` evaluates bundled tables against finer
|
|
236
|
+
recurrence calculations and held-out nuisance-parameter grids extending
|
|
237
|
+
to f0=160. `validation/results.json` records all cases and the
|
|
238
|
+
environment. Reproduce it:
|
|
239
|
+
|
|
240
|
+
uv run python validation/validate.py --output validation/results.json
|
|
241
|
+
|
|
242
|
+
Rebuild the bundled constants from scratch:
|
|
243
|
+
|
|
244
|
+
make tables
|
|
245
|
+
|
|
246
|
+
`make ci-docker` uses the standard `python:3.12` image. Documentation
|
|
247
|
+
includes this README directly; it is not maintained as a second copy.
|
|
248
|
+
|
|
249
|
+
## Scope and integration
|
|
250
|
+
|
|
251
|
+
This package takes summary quantities. It does not fit an IV model or
|
|
252
|
+
verify that an instrument is valid. For use with an estimator, require
|
|
253
|
+
one endogenous regressor and one excluded instrument, and use the
|
|
254
|
+
appropriate first-stage squared t statistic and compatible covariance
|
|
255
|
+
estimates. It supplies the numerical calibration; estimator-specific
|
|
256
|
+
eligibility checks belong in the calling package.
|
|
257
|
+
|
|
258
|
+
This implements the 2022 tF construction. VtF is a different procedure
|
|
259
|
+
using additional information and is outside the present implementation.
|
|
260
|
+
No generic p-value API is provided: numerical nesting across arbitrary
|
|
261
|
+
alpha levels would need separate validation before inverting the family
|
|
262
|
+
of tests.
|
|
263
|
+
|
|
264
|
+
## Citation and sources
|
|
265
|
+
|
|
266
|
+
Please cite the paper when using this package for research:
|
|
267
|
+
|
|
268
|
+
Lee, David S., Justin McCrary, Marcelo J. Moreira, and Jack Porter.
|
|
269
|
+
2022. [Valid t-Ratio Inference for
|
|
270
|
+
IV](https://doi.org/10.1257/aer.20211063). *American Economic Review*
|
|
271
|
+
112 (10): 3260-3290.
|
|
272
|
+
|
|
273
|
+
``` bibtex
|
|
274
|
+
@article{lee2022valid,
|
|
275
|
+
author = {Lee, David S. and McCrary, Justin and Moreira, Marcelo J. and Porter, Jack},
|
|
276
|
+
title = {Valid {t}-Ratio Inference for {IV}},
|
|
277
|
+
journal = {American Economic Review},
|
|
278
|
+
year = {2022},
|
|
279
|
+
volume = {112},
|
|
280
|
+
number = {10},
|
|
281
|
+
pages = {3260--3290},
|
|
282
|
+
doi = {10.1257/aer.20211063}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
The authors provide the construction and supporting materials:
|
|
287
|
+
|
|
288
|
+
- [Author manuscript with Appendix
|
|
289
|
+
B.3](https://eml.berkeley.edu/~jmccrary/LMMP_2_15_22.pdf), February
|
|
290
|
+
16, 2022.
|
|
291
|
+
- [Published supplemental
|
|
292
|
+
appendix](https://www.aeaweb.org/articles/materials/17480).
|
|
293
|
+
- [Data and code for the paper](https://doi.org/10.3886/E164502V1), the
|
|
294
|
+
authors' replication package.
|
|
295
|
+
- [Authors' supplementary
|
|
296
|
+
material](https://irs.princeton.edu/davidlee-supplementarytF) and
|
|
297
|
+
[Stata implementation](https://www.princeton.edu/~davidlee/wp/tf.ado).
|
|
298
|
+
|
|
299
|
+
AI assistance was used in this package's development and validation. The
|
|
300
|
+
numerical limitations and executed checks are recorded above and in the
|
|
301
|
+
repository's validation results.
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# tf-inference
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
[](https://github.com/finite-sample/tf-inference/actions/workflows/ci.yml)
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
tf-inference computes tF critical values and confidence intervals for
|
|
8
|
+
instrumental-variable (IV) models with one endogenous regressor and one
|
|
9
|
+
excluded instrument. It provides generated tables for common confidence
|
|
10
|
+
levels and numerical calibration for other levels.
|
|
11
|
+
|
|
12
|
+
The tF method and its theoretical results are due to David S. Lee,
|
|
13
|
+
Justin McCrary, Marcelo J. Moreira and Jack Porter, authors of [Valid
|
|
14
|
+
t-Ratio Inference for IV (2022)](https://doi.org/10.1257/aer.20211063).
|
|
15
|
+
This package provides an independent Python implementation of their
|
|
16
|
+
Appendix B.3 construction and reusable numerical tables. Critical values
|
|
17
|
+
depend on the first-stage F statistic and a two-sided significance
|
|
18
|
+
level. The code constructs the curve from its boundary expansion and
|
|
19
|
+
recurrence; the published rounded tables serve as test references.
|
|
20
|
+
|
|
21
|
+
This is an initial numerical implementation. Its calibration uses
|
|
22
|
+
deterministic integration, a finite nuisance-parameter grid and local
|
|
23
|
+
searches. These checks are documented and reproducible; they are not a
|
|
24
|
+
proof of a uniform size bound. The inferential framework is asymptotic
|
|
25
|
+
under the single-instrument IV model, not a finite-sample coverage
|
|
26
|
+
guarantee or a remedy for invalid instruments.
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
Install with Python 3.12 or later:
|
|
31
|
+
|
|
32
|
+
python -m pip install tf-inference
|
|
33
|
+
|
|
34
|
+
NumPy, SciPy and PyArrow are required at runtime. No Stata, external data
|
|
35
|
+
download, API key or network access is needed to evaluate or generate
|
|
36
|
+
critical values.
|
|
37
|
+
|
|
38
|
+
## Use the generated tables
|
|
39
|
+
|
|
40
|
+
``` python
|
|
41
|
+
from tf_inference import critical_value, confidence_interval
|
|
42
|
+
|
|
43
|
+
critical_value([3.8, 3.9, 10, 1000], alpha=0.05)
|
|
44
|
+
# Approximately [inf, 30.93, 3.43035, 1.95996]
|
|
45
|
+
|
|
46
|
+
confidence_interval(coefficient=1, se=0.4, f_stat=10, alpha=0.05)
|
|
47
|
+
# Approximately [-0.37214, 2.37214]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`alpha` is the significance level: 0.05 means 95% confidence. The return
|
|
51
|
+
value of `critical_value` is the threshold for **absolute t**, not t
|
|
52
|
+
squared or a standard-error multiplier. Divide it by the normal
|
|
53
|
+
two-sided critical value to obtain the corresponding standard-error
|
|
54
|
+
multiplier for that alpha.
|
|
55
|
+
|
|
56
|
+
Inputs broadcast as NumPy arrays. Confidence intervals put lower and
|
|
57
|
+
upper bounds on the final axis. Complex inputs, nonfinite or negative F statistics,
|
|
58
|
+
nonfinite coefficients, and nonpositive standard errors are rejected.
|
|
59
|
+
|
|
60
|
+
The 95% boundary is about 3.84145882. F at or below the boundary returns
|
|
61
|
+
an infinite critical value; F strictly above it has a finite critical
|
|
62
|
+
value. There is no artificial cutoff at F=4. The boundary is computed
|
|
63
|
+
separately for each alpha as `scipy.special.ndtri(alpha / 2)**2`. Very
|
|
64
|
+
close to the boundary, rounding in the input F itself can materially
|
|
65
|
+
affect the result.
|
|
66
|
+
|
|
67
|
+
Bundled tables cover alpha values 0.0001, 0.0005, 0.001, 0.002, 0.005,
|
|
68
|
+
0.01, 0.02, 0.025, 0.03, 0.04, 0.05, 0.06, 0.075, 0.1, 0.125, 0.15, 0.2
|
|
69
|
+
and 0.25. Each contains at least 16,385 rows, concentrated near the
|
|
70
|
+
boundary. List the installed levels with `available_alphas()`. Tables
|
|
71
|
+
are never interpolated across alpha values.
|
|
72
|
+
|
|
73
|
+
The Python convenience functions and CLI default to `method="table"`. A
|
|
74
|
+
missing level raises an error; numerical calibration requires an
|
|
75
|
+
explicit `method="compute"` or a direct call to `calibrate`. The `auto`
|
|
76
|
+
method is not supported.
|
|
77
|
+
|
|
78
|
+
## Calculate an unconventional level
|
|
79
|
+
|
|
80
|
+
``` python
|
|
81
|
+
from tf_inference import calibrate
|
|
82
|
+
|
|
83
|
+
calibration = calibrate(alpha=0.037)
|
|
84
|
+
calibration.critical_value([4.5, 10, 100])
|
|
85
|
+
calibration.confidence_interval(1, 0.4, 10)
|
|
86
|
+
print(calibration.diagnostics)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The bundled Parquet dataset is read and validated once; interpolators are
|
|
90
|
+
cached per alpha and shared by `load_table`,
|
|
91
|
+
`critical_value` and `confidence_interval`. Repeated lookup does not
|
|
92
|
+
read files, verify checksums again or rebuild the interpolator. Explicit
|
|
93
|
+
`method="compute"` calls use a separate cache of up to 32 calibrations.
|
|
94
|
+
Direct `calibrate` calls always compute afresh. Tables loaded from a
|
|
95
|
+
custom directory are read and checksum-verified on each call so changes
|
|
96
|
+
are detected.
|
|
97
|
+
|
|
98
|
+
For large inputs, pass a NumPy array in one call. For repeated work at
|
|
99
|
+
one level, retain `load_table(alpha)` or the result of
|
|
100
|
+
`calibrate(alpha)` and call its methods directly.
|
|
101
|
+
|
|
102
|
+
The numerical alpha domain is \[0.0001, 0.25\]. It covers confidence
|
|
103
|
+
levels from 75% to 99.99%. This is an explicit implementation range, not
|
|
104
|
+
a theoretical limit of tF. Calculations outside it are rejected rather
|
|
105
|
+
than extrapolated.
|
|
106
|
+
|
|
107
|
+
`calibrate` accepts `epsilon`, `seeds`, `size_tolerance`,
|
|
108
|
+
`strength_limit`, `strengths` and `correlations`. Smaller initialization
|
|
109
|
+
epsilon and more seeds allow convergence checks. These settings are not
|
|
110
|
+
claims of certified error. Failed recurrence, integration or
|
|
111
|
+
optimization raises `ConvergenceError`. Inspect the returned diagnostics
|
|
112
|
+
when doing new calibrations, and validate beyond the search settings
|
|
113
|
+
before relying on an unconventional level for research.
|
|
114
|
+
|
|
115
|
+
## Generate constants for other software
|
|
116
|
+
|
|
117
|
+
The command-line interface exposes the same calculation:
|
|
118
|
+
|
|
119
|
+
tf-inference critical 3.9 10 100 --alpha 0.05
|
|
120
|
+
tf-inference critical 10 --alpha 0.037 --method compute
|
|
121
|
+
tf-inference generate --alpha 0.05 0.01 0.037 --output tables
|
|
122
|
+
|
|
123
|
+
The generator writes one `calibrations.parquet` dataset and a
|
|
124
|
+
`calibrations.json` manifest. Adding or replacing one alpha preserves the other
|
|
125
|
+
levels in that directory. The Parquet schema has three nonnullable float64
|
|
126
|
+
columns: `alpha`, `f_stat` and `regularized_squared`. Calibration settings,
|
|
127
|
+
plateaus and diagnostics are embedded as JSON in the Arrow schema metadata.
|
|
128
|
+
The schema-versioned manifest records the dataset's SHA-256 checksum.
|
|
129
|
+
Loading validates the checksum, schema, finite values, ordered grids,
|
|
130
|
+
boundary and plateau invariants, and agreement with the metadata.
|
|
131
|
+
|
|
132
|
+
`export_table(calibration, directory, points=16385)` and
|
|
133
|
+
`load_table(alpha, directory=directory)` provide the same operations in Python.
|
|
134
|
+
For a portable gzip CSV, add `--csv` to the generation command or pass
|
|
135
|
+
`include_csv=True` to `export_table`. CSV files are optional exports, not
|
|
136
|
+
packaged runtime data.
|
|
137
|
+
|
|
138
|
+
For accurate boundary evaluation, interpolate the regularized quantity
|
|
139
|
+
`Z(F) = (F - boundary) * critical(F)**2` using a monotone cubic interpolator.
|
|
140
|
+
It is the Parquet `regularized_squared` column (and the optional CSV's
|
|
141
|
+
`branch_regularized_squared` column). Then compute
|
|
142
|
+
`sqrt(Z(F) / (F - boundary))`. Cap F at the metadata's `plateau_f` before
|
|
143
|
+
evaluation and return infinity when F is at or below the boundary. The raw
|
|
144
|
+
branch extends to the Property (C) endpoint; at large F use the selected
|
|
145
|
+
plateau. The CSV's first critical value is infinite and must not be
|
|
146
|
+
interpolated as an ordinary finite row.
|
|
147
|
+
|
|
148
|
+
The export measures relative interpolation differences at every cell
|
|
149
|
+
midpoint against the computed curve, and rejects tables exceeding 1e-6
|
|
150
|
+
there. This is a measured check, not an interval-arithmetic error bound.
|
|
151
|
+
The shipped validation also compares randomly chosen F values against a
|
|
152
|
+
separately refined curve.
|
|
153
|
+
|
|
154
|
+
## How the calculation works
|
|
155
|
+
|
|
156
|
+
1. Compute the boundary q and initialize the squared critical value
|
|
157
|
+
near it using the expansion in Appendix B.3, step 1.
|
|
158
|
+
2. Apply the inverse map in step 2 to extend the decreasing curve. The
|
|
159
|
+
code interpolates Z(F), whose finite boundary limit is q cubed,
|
|
160
|
+
rather than interpolating a divergent critical value.
|
|
161
|
+
3. Locate the tangency that limits the decreasing segment under
|
|
162
|
+
Property (C). Its admissible plateau is also constrained to be at
|
|
163
|
+
least the normal two-sided critical value.
|
|
164
|
+
4. Integrate null rejection probabilities in the Gaussian weak-IV
|
|
165
|
+
experiment. Search the nuisance parameters and move the plateau
|
|
166
|
+
earlier if it over-rejects beyond the requested numerical tolerance.
|
|
167
|
+
|
|
168
|
+
The size search can change the plateau. For example, alpha=0.037
|
|
169
|
+
requires an adjustment to the first candidate. For alpha=0.01 the
|
|
170
|
+
plateau is about 2.72549, above the normal 99% critical value of about
|
|
171
|
+
2.57583. Replacing the 95% normal quantile with another quantile does
|
|
172
|
+
not implement general tF.
|
|
173
|
+
|
|
174
|
+
The default size search covers strength f0 from 0 to 80 and absolute
|
|
175
|
+
correlation rho from 0 to 1. Here E\[F\] = 1 + f0 squared; f0 is not F.
|
|
176
|
+
It includes singular rho=1 calculations, correlations approaching one,
|
|
177
|
+
and local searches between grid points. The strong-instrument limit is
|
|
178
|
+
checked separately by the normal critical-value constraint. The
|
|
179
|
+
unbounded nuisance domain is not exhaustively certified. The recorded
|
|
180
|
+
integration error does not include curve approximation or missed extrema
|
|
181
|
+
in the parameter search.
|
|
182
|
+
|
|
183
|
+
## Performance
|
|
184
|
+
|
|
185
|
+
Table lookup avoids numerical calibration. For large inputs, evaluate an array
|
|
186
|
+
in one call. `make benchmark` records separate timings for warm scalar and
|
|
187
|
+
array lookup, loading the complete Parquet dataset with empty package caches,
|
|
188
|
+
and fresh calibration. Imports and operating-system file-cache effects are
|
|
189
|
+
excluded. Results and environment details are in `benchmarks/results.json`;
|
|
190
|
+
`benchmarks/baseline.json` preserves the earlier implementation's measurements.
|
|
191
|
+
These are local observations, not CI timing assertions. Tests enforce that
|
|
192
|
+
default calls never calibrate and warm calls avoid file access and interpolator
|
|
193
|
+
construction.
|
|
194
|
+
|
|
195
|
+
## Validation and development
|
|
196
|
+
|
|
197
|
+
Install development dependencies and run the checks:
|
|
198
|
+
|
|
199
|
+
uv sync --all-groups
|
|
200
|
+
make ci
|
|
201
|
+
|
|
202
|
+
Tests cover the published rounded-table values and plateau landmarks,
|
|
203
|
+
initialization and grid refinement, the defining two-intersection
|
|
204
|
+
equations, monotonicity and the exact boundary, near-singular numerical
|
|
205
|
+
integration, independent Gaussian Monte Carlo calculations,
|
|
206
|
+
unconventional-alpha plateau adjustment, interval broadcasting, table
|
|
207
|
+
roundtrips and corrupted files, Parquet schema violations, complex inputs and
|
|
208
|
+
large-strength numerical stability. `make ci` runs Ruff, Pyright, pydoclint,
|
|
209
|
+
tests with a 90% coverage floor (including branch measurement), documentation
|
|
210
|
+
and distribution checks.
|
|
211
|
+
`preen check --strict` checks adoption of the shared py-canon standard.
|
|
212
|
+
|
|
213
|
+
`validation/validate.py` evaluates bundled tables against finer
|
|
214
|
+
recurrence calculations and held-out nuisance-parameter grids extending
|
|
215
|
+
to f0=160. `validation/results.json` records all cases and the
|
|
216
|
+
environment. Reproduce it:
|
|
217
|
+
|
|
218
|
+
uv run python validation/validate.py --output validation/results.json
|
|
219
|
+
|
|
220
|
+
Rebuild the bundled constants from scratch:
|
|
221
|
+
|
|
222
|
+
make tables
|
|
223
|
+
|
|
224
|
+
`make ci-docker` uses the standard `python:3.12` image. Documentation
|
|
225
|
+
includes this README directly; it is not maintained as a second copy.
|
|
226
|
+
|
|
227
|
+
## Scope and integration
|
|
228
|
+
|
|
229
|
+
This package takes summary quantities. It does not fit an IV model or
|
|
230
|
+
verify that an instrument is valid. For use with an estimator, require
|
|
231
|
+
one endogenous regressor and one excluded instrument, and use the
|
|
232
|
+
appropriate first-stage squared t statistic and compatible covariance
|
|
233
|
+
estimates. It supplies the numerical calibration; estimator-specific
|
|
234
|
+
eligibility checks belong in the calling package.
|
|
235
|
+
|
|
236
|
+
This implements the 2022 tF construction. VtF is a different procedure
|
|
237
|
+
using additional information and is outside the present implementation.
|
|
238
|
+
No generic p-value API is provided: numerical nesting across arbitrary
|
|
239
|
+
alpha levels would need separate validation before inverting the family
|
|
240
|
+
of tests.
|
|
241
|
+
|
|
242
|
+
## Citation and sources
|
|
243
|
+
|
|
244
|
+
Please cite the paper when using this package for research:
|
|
245
|
+
|
|
246
|
+
Lee, David S., Justin McCrary, Marcelo J. Moreira, and Jack Porter.
|
|
247
|
+
2022. [Valid t-Ratio Inference for
|
|
248
|
+
IV](https://doi.org/10.1257/aer.20211063). *American Economic Review*
|
|
249
|
+
112 (10): 3260-3290.
|
|
250
|
+
|
|
251
|
+
``` bibtex
|
|
252
|
+
@article{lee2022valid,
|
|
253
|
+
author = {Lee, David S. and McCrary, Justin and Moreira, Marcelo J. and Porter, Jack},
|
|
254
|
+
title = {Valid {t}-Ratio Inference for {IV}},
|
|
255
|
+
journal = {American Economic Review},
|
|
256
|
+
year = {2022},
|
|
257
|
+
volume = {112},
|
|
258
|
+
number = {10},
|
|
259
|
+
pages = {3260--3290},
|
|
260
|
+
doi = {10.1257/aer.20211063}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
The authors provide the construction and supporting materials:
|
|
265
|
+
|
|
266
|
+
- [Author manuscript with Appendix
|
|
267
|
+
B.3](https://eml.berkeley.edu/~jmccrary/LMMP_2_15_22.pdf), February
|
|
268
|
+
16, 2022.
|
|
269
|
+
- [Published supplemental
|
|
270
|
+
appendix](https://www.aeaweb.org/articles/materials/17480).
|
|
271
|
+
- [Data and code for the paper](https://doi.org/10.3886/E164502V1), the
|
|
272
|
+
authors' replication package.
|
|
273
|
+
- [Authors' supplementary
|
|
274
|
+
material](https://irs.princeton.edu/davidlee-supplementarytF) and
|
|
275
|
+
[Stata implementation](https://www.princeton.edu/~davidlee/wp/tf.ado).
|
|
276
|
+
|
|
277
|
+
AI assistance was used in this package's development and validation. The
|
|
278
|
+
numerical limitations and executed checks are recorded above and in the
|
|
279
|
+
repository's validation results.
|