*! version 1.0.1 04mar2026

help for tptestVersion 1.0.1 — 04mar2026

Title

tptest -- Universal Turning Point & Inflection Point Test
with Sasabuchi, Simonsohn Two-Lines, Bootstrap, Delta-Method, and Fieller Inference

Syntax

tptest x f(x) [f2(x)]
[, options]

where x is the linear term, f(x) is the second-order term
(x², 1/x, or [ln(x)]²), and f2(x) is the optional third-order
term (x³) for cubic models.

Functional Form
quadratic force quadratic: y = β₁·x + β₂·x²

cubic force cubic: y = β₁·x + β₂·x² + β₃·x³

inverse force inverse: y = β₁·x + β₂/x

logquadratic force log-quadratic: ln(y) = β₁·ln(x) + β₂·[ln(x)]²

Test Methods
delta delta-method SE and confidence interval for x*

fieller Fieller (1954) confidence interval for x*

twolines Simonsohn (2018) two-lines test

bootstrap parametric bootstrap confidence interval

breps(#) number of bootstrap replications; default is breps(1000)

Test Bounds & Level
min(#) use # as lower bound of interval (default: data minimum)

max(#) use # as upper bound of interval (default: data maximum)

inflection compute inflection point (cubic models only)

level(#) set confidence level; default is level(95)

Estimator Options
prefix(string) equation prefix in e(b), e.g., ECT

eq(string) equation name, e.g., LR, SR, ECT

tau(numlist) quantile(s) for multi-quantile turning point trajectory

Graph Options
graph produce publication-quality visualizations

nograph suppress graph output

saving(string) save graphs to files (base filename)

title(string) custom graph title

graphopt(string) pass-through twoway graph options

Description

tptest is a universal post-estimation command for testing turning points
(U-shaped or inverse U-shaped relationships) and inflection points. It provides
a comprehensive battery of modern inference methods for the extreme point x*
of fitted nonlinear relationships, integrating five distinct approaches:

1. Sasabuchi (1980) / Lind & Mehlum (2010) test.
The core hypothesis test for U-shape (or inverse U-shape) based on a composite
null. The test checks whether the slope is negative at the lower bound and
positive at the upper bound (U-shape), or vice versa (inverse U-shape).
The overall test statistic is the minimum of the absolute t-values at the
interval bounds.

2. Delta-method standard errors.
Asymptotic standard errors and confidence intervals for the turning point x*
derived via the delta method: Var(x*) = G' · V · G, where G is the gradient
vector and V = e(V) is the variance-covariance matrix.

3. Fieller (1954) confidence interval.
An exact confidence interval for the turning point based on the Fieller
method for ratios of normal random variables. Available for quadratic and
inverse specifications. Unlike the delta method, the Fieller CI has exact
coverage and does not rely on local linearity.

4. Simonsohn (2018) two-lines test.
A non-parametric robustness check that splits the data at x* and estimates
separate linear regressions on each segment. For a valid U-shape, the left
slope must be significantly negative and the right slope significantly positive.
The joint p-value is the maximum of the individual one-sided p-values. This
test is robust to misspecification of the functional form. When the original
model is a panel estimator (e.g., xtreg, fe), the two-lines test
automatically matches the estimation method for each segment.

5. Parametric bootstrap CI.
Confidence intervals obtained by drawing from the asymptotic distribution
N(β̂, V̂) of the estimated coefficients, computing x* for each draw, and
taking percentile-based intervals. Reports bootstrap SE, bias, and the
percentile CI. Useful when the delta-method normality approximation is
questionable.

tptest supports four functional forms (auto-detected or user-specified):

Quadratic y = β₁·x + β₂·x² → x* = −β₁/(2β₂)

Cubic y = β₁·x + β₂·x² + β₃·x³ → turning point + inflection point

Inverse y = β₁·x + β₂/x → x* = √(β₂/β₁)

Log-quadratic ln(y) = β₁·ln(x) + β₂·[ln(x)]² → x* = exp(−β₁/(2β₂))

Supported Estimators

tptest works as a post-estimation command after any Stata estimator.
It auto-detects the preceding command and adapts equation prefixes accordingly.
It has been tested and optimized for:

Cross-section regress, ardl, aardl, fbardl,
fbnardl, mtnardl, tnardl, qardl, fqardl,
qreg, ivregress

Panel xtreg (FE/RE), xtpmg, pnardl,
xtpqardl, areg

CS-Dependence xtdcce2, xtcce, xtcspqardl

Quantile qreg, sqreg, bsqreg, mmqreg,
xtqreg, xtqsh, xtmdqr, rifhdreg

For multi-equation models (xtpmg, xtdcce2, etc.), use
eq() or prefix() to specify the equation containing the
turning-point variables (e.g., eq(ECT) for the ECT equation in
xtpmg).

Options

Functional Form

quadratic forces interpretation as a quadratic specification:
y = β₁·x + β₂·x². If two variables are supplied and neither
quadratic, inverse, nor logquadratic is specified,
tptest auto-detects the form by comparing correlations with x² and 1/x.

cubic forces interpretation as a cubic specification:
y = β₁·x + β₂·x² + β₃·x³. Three variables must be supplied.
If three variables are supplied without cubic, the cubic form is
auto-detected.

inverse forces interpretation as an inverse specification:
y = β₁·x + β₂/x. The turning point is x* = √(β₂/β₁).

logquadratic forces log-quadratic interpretation:
ln(y) = β₁·ln(x) + β₂·[ln(x)]². The turning point is
x* = exp(−β₁/(2β₂)), reported in the original scale of x.

Test Methods

delta reports delta-method standard errors and confidence intervals
for the turning point x*. The SE is derived from the implicit function
theorem: SE(x*) = √(G'VG), where G = (∂x*/∂β₁, ∂x*/∂β₂, ...)'.

fieller computes the Fieller (1954) confidence interval for x*.
Available for quadratic and inverse specifications. The Fieller CI
provides exact coverage when the ratio estimator may be poorly approximated
by normality. Reports "bounded", "unbounded", or "entire real line"
depending on the precision of β₂.

twolines performs the Simonsohn (2018) two-lines test as a
robustness check. The data is split at the estimated turning point x*,
and separate linear regressions are estimated on each side:

Left: E[y | x ≤ x*] = α_L + β_L · x

Right: E[y | x > x*] = α_R + β_R · x

For a valid U-shape: β_L < 0 (significantly) and β_R > 0 (significantly).

Joint p-value = max(p_left, p_right) using one-sided tests.

For panel estimators (xtreg), the test automatically matches the
original estimation method (FE/RE) for each segment.

bootstrap computes parametric bootstrap confidence intervals for x*.
Draws B replications from N(β̂, V̂), computes x* for each draw, and reports
the bootstrap SE, bias (mean − point estimate), and percentile CI.
Available for quadratic, inverse, and log-quadratic specifications.

breps(#) specifies the number of bootstrap replications.
Default is breps(1000). Recommended: 2000 for publication.

Test Bounds & Level

min(#) sets the lower bound of the interval for the Sasabuchi test.
Default is the observed minimum of x in the data. Use this to test for
a turning point within a specific sub-range.

max(#) sets the upper bound of the interval for the Sasabuchi test.
Default is the observed maximum of x in the data.

inflection requests computation of the inflection point for cubic models.
The inflection point is x_ip = −β₂/(3β₃), with delta-method SE and CI.

level(#) sets the confidence level for all CIs. Default is 95.

Estimator Options

prefix(string) specifies the equation prefix used in e(b)
for multi-equation models. For example, after xtpmg, the ECT
equation coefficients may be stored with prefix "ECT:".

eq(string) specifies the equation name. This is equivalent to
prefix() but appends the colon automatically. Example:
eq(ECT) is equivalent to prefix(ECT:).

tau(numlist) activates multi-quantile mode. For each quantile τ
in the list, tptest extracts the coefficients from the corresponding
equation in e(b) (as stored by mmqreg, sqreg, or other
multi-quantile estimators), computes x*(τ), and reports a trajectory table.
With graph, produces a turning-point trajectory plot showing how
x* varies across quantiles.

Graph Options

graph produces publication-quality visualizations. The graphs
produced depend on the context:

Single-equation mode (no tau()): three graphs are produced:

(1) Fitted curve with 95% CI and markers for data range and turning point

(2) Slope function dy/dx with zero-crossing at x*

(3) Combined panel of both graphs

Multi-quantile mode (tau() specified): a trajectory plot
showing x*(τ) vs. τ with confidence bands and significance markers.
Filled markers indicate significant U/inverse-U shape (p < 0.05);
hollow markers indicate non-significance.

nograph suppresses all graph output.

saving(string) saves graph files using the specified base filename.
Three files are created: basename_curve.png, basename_slope.png,
and basename_combined.png. In multi-quantile mode, a single trajectory
plot is saved.

title(string) overrides the default graph title.

graphopt(string) passes additional options to the underlying
twoway graph command.

Methodology

Sasabuchi (1980) / Lind & Mehlum (2010) Test

Consider a quadratic relationship y = β₁x + β₂x² estimated on the
interval [x_L, x_U]. The marginal effect is dy/dx = β₁ + 2β₂x.

Test for U-shape:

H₀: The relationship is monotone or inverse U-shaped

H₁: The relationship is U-shaped (i.e., dy/dx < 0 at x_L and dy/dx > 0 at x_U)

Test for inverse U-shape:

H₀: The relationship is monotone or U-shaped

H₁: The relationship is inverse U-shaped (dy/dx > 0 at x_L and dy/dx < 0 at x_U)

The test statistics at the bounds are:

t_L = (β₁ + 2β₂x_L) / √[Var(β₁) + 4x_L²Var(β₂) + 4x_L·Cov(β₁,β₂)]

t_U = (β₁ + 2β₂x_U) / √[Var(β₁) + 4x_U²Var(β₂) + 4x_U·Cov(β₁,β₂)]

The overall test statistic is t = min(|t_L|, |t_U|). Under H₀, the test
has exact size α when using one-sided critical values.

Turning Point Formulae

Model Turning point x*

Quadratic x* = −β₁/(2β₂)

Cubic dy/dx = β₁ + 2β₂x + 3β₃x² = 0 (quadratic formula)

Inverse x* = √(β₂/β₁)

Log-quadratic x* = exp[−β₁/(2β₂)]

Delta-Method Standard Errors

For a turning point x* = g(β), the delta-method variance is:

Var(x*) = G' · V · G

where G = ∂g/∂β is the gradient vector and V = e(V). For example, for
the quadratic case x* = −β₁/(2β₂):

G₁ = ∂x*/∂β₁ = −1/(2β₂)

G₂ = ∂x*/∂β₂ = β₁/(2β₂²)

Fieller (1954) Confidence Interval

The Fieller method constructs a CI for the turning point (a ratio of
correlated normal random variables) without relying on the delta-method
linearization. The interval is obtained by inverting the t-test for
the numerator coefficient evaluated at hypothesized values of the ratio.
The CI can be bounded (standard), unbounded (when β₂ is imprecisely
estimated), or the entire real line (when H₀: β₂ = 0 cannot be rejected).

Simonsohn (2018) Two-Lines Test

A non-parametric robustness check for U-shaped relationships. Rather than
assuming a parametric functional form, the data is split at the estimated
turning point x*, and separate linear regressions are estimated:

Left segment (x ≤ x*): y = α_L + β_L · x

Right segment (x > x*): y = α_R + β_R · x

For a valid U-shape, both β_L < 0 and β_R > 0 must be individually
significant. The joint p-value equals max(p_L, p_R), where p_L and p_R
are one-sided p-values. This test protects against false positives
from misspecified quadratic models (e.g., an exponential mistaken for
a U-shape).

Parametric Bootstrap

The parametric bootstrap draws B replications β* ~ N(β̂, V̂) from the
asymptotic distribution, computes x*(β*) for each draw, and constructs:

Bootstrap SE = SD(x*₁, ..., x*_B)

Bootstrap bias = mean(x*_b) − x̂*

Percentile CI = [x*_{(α/2)}, x*_{(1−α/2)}]

Examples

Example 1: Basic quadratic test (comparable to utest)

. sysuse auto, clear

. gen mpg2 = mpg^2

. reg price mpg mpg2

. tptest mpg mpg2

Example 2: Full inference suite — all five methods

. sysuse auto, clear

. gen mpg2 = mpg^2

. reg price mpg mpg2

. tptest mpg mpg2, delta fieller twolines bootstrap breps(2000) graph saving("mytest")

Example 3: Custom interval bounds and confidence level

. reg price mpg mpg2

. tptest mpg mpg2, min(15) max(35) level(90) delta fieller

Example 4: Inverse model

. gen mpg_inv = 1/mpg

. reg price mpg mpg_inv

. tptest mpg mpg_inv, inverse delta fieller twolines bootstrap

Example 5: Log-quadratic (Environmental Kuznets Curve)

. gen lnprice = ln(price)

. gen lnmpg = ln(mpg)

. gen lnmpg2 = lnmpg^2

. reg lnprice lnmpg lnmpg2

. tptest lnmpg lnmpg2, logquadratic delta twolines bootstrap breps(2000)

Example 6: Cubic model with inflection point

. gen mpg3 = mpg^3

. reg price mpg mpg2 mpg3

. tptest mpg mpg2 mpg3, cubic inflection delta graph saving("cubic_test")

Example 7: Panel fixed effects (EKC-style)

. webuse nlswork, clear

. gen ttl_exp2 = ttl_exp^2

. xtreg ln_wage ttl_exp ttl_exp2 tenure, fe

. tptest ttl_exp ttl_exp2, delta fieller twolines bootstrap breps(2000)

Example 8: Panel random effects

. xtreg ln_wage ttl_exp ttl_exp2 tenure, re

. tptest ttl_exp ttl_exp2, delta twolines bootstrap

Example 9: Panel ARDL (xtpmg) — long-run turning point

. xtpmg D.y L.y L.x L.x2, lr(L.y x x2) ec(ECT)

. tptest x x2, eq(ECT) delta graph

Example 10: Cross-sectional dependence (xtdcce2)

. xtdcce2 y x x2, cr(x x2)

. tptest x x2, delta graph

Example 11: Quantile regression — multi-quantile trajectory

. sysuse auto, clear

. gen mpg2 = mpg^2

. mmqreg price mpg mpg2, q(10 25 50 75 90)

. tptest mpg mpg2, tau(.10 .25 .50 .75 .90) delta graph saving("qtrajectory")

Example 12: IV regression

. gen weight2 = weight^2

. ivregress 2sls price (mpg mpg2 = weight weight2 length)

. tptest mpg mpg2, delta

Example 13: With control variables

. reg price mpg mpg2 weight length foreign

. tptest mpg mpg2, delta fieller twolines

Example 14: Robust standard errors

. reg price mpg mpg2, robust

. tptest mpg mpg2, delta fieller twolines bootstrap breps(2000)

Stored results

tptest stores the following in r():

Scalars — Core

r(tp) turning point estimate x*

r(extr) extreme point (= turning point)

r(t) overall t-value (Sasabuchi test)

r(p) overall p-value (one-sided)

r(x_l) lower bound of test interval

r(x_u) upper bound of test interval

r(s_l) slope at lower bound

r(s_u) slope at upper bound

r(t_l) t-value at lower bound

r(t_u) t-value at upper bound

Scalars — Delta-method (with delta)

r(tp_se) delta-method standard error

r(tp_ci_lo) lower CI bound (delta-method)

r(tp_ci_hi) upper CI bound (delta-method)

Scalars — Fieller (with fieller)

r(fieller_lo) Fieller CI lower bound

r(fieller_hi) Fieller CI upper bound

Scalars — Two-lines test (with twolines)

r(tl_slope_l) left-segment slope (β_L)

r(tl_slope_r) right-segment slope (β_R)

r(tl_t_l) left-segment t-value

r(tl_t_r) right-segment t-value

r(tl_p_l) left-segment p-value (two-sided)

r(tl_p_r) right-segment p-value (two-sided)

r(tl_p_joint) joint p-value (Simonsohn test)

r(tl_n_l) N in left segment

r(tl_n_r) N in right segment

Scalars — Bootstrap (with bootstrap)

r(bs_se) bootstrap standard error

r(bs_bias) bootstrap bias

r(bs_ci_lo) bootstrap CI lower bound (percentile)

r(bs_ci_hi) bootstrap CI upper bound (percentile)

Scalars — Cubic (with cubic)

r(ip) inflection point

r(ip_se) inflection point SE (delta-method)

Macros

r(shape) detected shape: "U shape" or "Inverse U shape"

r(model) functional form: "quad", "cubic", "inv", "logquad"

r(spec) specification label: "Quadratic", "Cubic", etc.

r(cmd_used) name of the preceding estimation command

Matrices — Multi-quantile (with tau())

r(tp_trajectory) matrix of (τ, x*, SE, t, p) per quantile

r(n_tau) number of quantiles

Comparison with utest

tptest is fully backward-compatible with utest for quadratic
and inverse specifications. The table below summarizes the differences:

Feature utest tptest

Quadratic ✓ ✓

Inverse ✓ ✓

Cubic / Inflection point ✓

Log-quadratic ✓

Auto-detect functional form ✓

Delta-method SE & CI ✓

Fieller CI ✓ ✓

Simonsohn (2018) two-lines ✓

Parametric bootstrap CI ✓

Multi-quantile tau() ✓

Publication-quality graphs ✓

Auto-detect 20+ estimators ✓

Panel FE/RE support ✓

xtpmg/xtdcce2/xtcspqardl ✓

References

Lind, J.T. and H. Mehlum (2010).
With or without U? The appropriate test for a U-shaped relationship.
Oxford Bulletin of Economics and Statistics, 72(1): 109-118.
https://doi.org/10.1111/j.1468-0084.2009.00569.x

Sasabuchi, S. (1980).
A test of a multivariate normal mean with composite hypotheses determined by linear inequalities.
Biometrika, 67(2): 429-439.
https://doi.org/10.1093/biomet/67.2.429

Simonsohn, U. (2018).
Two lines: A valid alternative to the invalid testing of U-shaped relationships with quadratic regressions.
Advances in Methods and Practices in Psychological Science, 1(4): 538-555.
https://doi.org/10.1177/2515245918805755

Fieller, E.C. (1954).
Some problems in interval estimation.
Journal of the Royal Statistical Society, Series B, 16(2): 175-185.
https://doi.org/10.1111/j.2517-6161.1954.tb00159.x

Efron, B. and R.J. Tibshirani (1993).
An Introduction to the Bootstrap.
Chapman & Hall/CRC.

Requirements

Stata 14 or later.

Author

Dr. Merwan Roudane

Email: merwanroudane920@gmail.com

Please cite this package as:

Roudane, M. (2026). TPTEST: Stata module for universal turning point and
inflection point testing. Statistical Software Components, Boston College
Department of Economics.

Also see

utest, nlcom, margins, test, regress,
xtreg, qreg, mmqreg