Every estimator in this package rests on assumptions about the data,
not just about the model. validity() checks those
assumptions on a fitted model and reports what the data actually say,
rather than leaving the question to be taken on faith. It brings
together checkpoints from three sources that do not always agree with
each other, so its output keeps them apart instead of collapsing them
into a single yes or no verdict: the boundary conditions of Becker,
Proksch and Ringle (2022), the decision tree of Yang, Qian and Xie
(2025), and the standard error inflation statistic of Qian, Koschmann
and Xie (2025). What gets checked depends on the estimator: for most of
them it is nonnormality of the endogenous regressor, for BMW it is
nonnormality of the first-stage residuals instead, and for 2sCOPE-np it
is a different assumption entirely, covered at the end of this
article.
A case where the assumptions hold
We reuse the simulation from “Get started with endogCopula”: an endogenous regressor built to be skewed and to share a Gaussian noise component with the error, and an exogenous regressor with nothing to do with either.
set.seed(1)
n <- 300
w <- rnorm(n)
u <- rnorm(n)
p <- rchisq(n, df = 3) + 0.3 * u
y <- 1 + 2 * p + 0.5 * w + u
dat <- data.frame(y = y, p = p, w = w)
set.seed(1)
fit_good <- CopRegPG(y ~ p | w, data = dat, nboots = 99)
validity(fit_good)
#>
#> Validity check for PG (Park & Gupta 2012)
#> n = 300, intercept: yes, target power 80%
#> Sources: Becker, Proksch & Ringle (2022); Yang, Qian & Xie (2025);
#> Qian, Koschmann & Xie (2025)
#>
#> [1] Nonnormality of the endogenous regressors
#> skewness ex.kurtosis AD CvM KS p Yang ok Becker ok
#> p 1.461 2.627 9.866 1.65 2.42e-05 TRUE FALSE
#> Becker et al. at n = 300: |skewness| >= 1.932, or AD > 18.964, or CvM > 3.488
#> Yang et al.: KS p < .05
#> Note: the two criteria disagree here. Becker et al. report a
#> correlation of .66 between the AD statistic and the copula term's
#> t statistic against -.03 for KS, and recommend AD or CvM; Yang et
#> al. prefer KS because it is conservative.
#>
#> [2] Assumption: correlation of the copula transformation term
#> with the exogenous regressors
#> corr(W, CTT) p (Holm)
#> w -0.0198 0.733
#> Joint test: R2 = 0.0003912, F = 0.1166, p = 0.733
#> => satisfied. Park & Gupta is consistent here and more efficient.
#>
#> [3] Error term: structural residuals xi
#> skewness = 0.06127, excess kurtosis = 0.2633, AD = 0.3163 (p = 0.539)
#> Becker et al. (2022) find that with a nonnormal error the approach
#> is no longer consistent in models with an intercept. Yang et al.
#> (2025) and Qian et al. (2025) do permit a nonnormal error, but only
#> under the decomposition xi = U + V into a normally distributed
#> endogenous part U, which carries the entire dependence with the
#> regressors, and an independent nonnormal V. The residuals show xi,
#> not U, so their skewness neither establishes nor rules out a
#> violation; whether that decomposition holds has to be argued from
#> the suspected sources of endogeneity.
#>
#> [4] ICON: standard error inflation relative to uncorrected OLS
#> SE (corrected) SE (uncorrected) ICON
#> (Intercept) 0.24097 0.08769 2.7482
#> p 0.08043 0.02531 3.1771
#> w 0.06338 0.06376 0.9941
#> => largest ICON = 3.177, below the threshold of 6.We go through this output block by block below. The numbering in
[1], [2] and so on follows the numbers
validity() itself prints, which depend on the estimator and
on what applies to the data at hand: an estimator with no first stage
skips the step that needs one, and a step that only applies after
another step fails is only printed once that earlier step has actually
failed.
Nonnormality of the endogenous regressor
The endogenous regressor has to be non-normal for the copula term to
carry information the regressor’s own untransformed value does not
already carry, and that requirement is the identifying assumption
itself. validity() reports two criteria side by side
because the papers behind this package do not agree on which one to use.
Becker, Proksch and Ringle (2022) recommend the Anderson-Darling or
Cramer-von Mises statistics, because in their simulations those
correlate much better with the actual quality of the correction than a
Kolmogorov-Smirnov test does. Yang, Qian and Xie (2025) use the
Kolmogorov-Smirnov p value instead, precisely because it is the more
conservative of the two. A KS test flags nonnormality less readily, so
passing it is a stronger signal. The thresholds Becker et al. use also
depend on the sample size and on a target power for the copula term’s
significance test, either 80% or 90%, set by the power
argument to validity().
In the fit above, Yang ok is TRUE and
Becker ok is FALSE. The KS test is confident
enough to flag the regressor as non-normal, but the skewness,
Anderson-Darling and Cramer-von Mises statistics do not clear Becker’s
higher bar at this sample size. validity() prints a note
when this happens, because it is a real disagreement in the literature
and not a sign that something has gone wrong. Becker et al. report a
correlation of .66 between their preferred Anderson-Darling statistic
and the copula term’s t statistic, against only -.03 for
Kolmogorov-Smirnov, which is why they recommend Anderson-Darling or
Cramer-von Mises over KS. There is no single correct answer here. Treat
agreement between the two criteria as reassuring and disagreement, as
here, as a reason to also look at step 3 below (present only when Yang’s
criterion fails, which it does not in this fit) and at the standard
error inflation in the final block, rather than as a reason to stop at
step 1 alone.
The uncorrelatedness assumption
For estimators that assume the endogenous regressor is uncorrelated
with the exogenous ones, validity() tests that assumption
directly. It regresses the copula term on the exogenous regressors and
reports both the correlation with each one individually, Holm-adjusted
for multiple testing, and a joint F test of all of them at once. In the
fit above this step reports satisfied, because
w was simulated to be independent of the error and, by
construction, largely independent of the part of p that is
correlated with the error. Two-stage estimators such as 2sCOPE and IMA
do not get this step at all. They project the correlation out in their
first stage, so testing for it afterward would only restate what the
estimator already handles. BMW does not get it in the same form either;
its diagnostics report that the correlation is not assumed to be zero
rather than testing whether it is.
Exogenous regressors as identifying variation
This step only appears when step 1 has already found the endogenous
regressor to be too close to normal for Yang, Qian and Xie’s criterion.
It looks for a continuous exogenous regressor that is itself
sufficiently non-normal (KS p < .001) and sufficiently related to the
copula term in a first-stage regression (F > 10), because such a
regressor could supply the identifying variation that the endogenous
regressor itself falls short of. It does not appear in the fit above,
because step 1’s Yang ok was already TRUE.
The structural residuals
validity() always reports the skewness, excess kurtosis,
Anderson-Darling statistic and its p value for the structural residuals,
xi = y - mu - P alpha - W beta. It is tempting to read a normal looking
residual as confirmation that the model is fine, but the papers behind
this package disagree about what the error is even allowed to look like,
and the residual on its own cannot settle that disagreement. Becker,
Proksch and Ringle (2022) find that a nonnormal error breaks consistency
in models with an intercept. Yang, Qian and Xie (2025) and Qian,
Koschmann and Xie (2025) allow a nonnormal error under a decomposition
of xi into a normally distributed part that carries the entire
dependence with the regressors and an independent, possibly nonnormal
remainder. The residuals show the whole of xi, not that normal part on
its own, so their shape neither confirms nor rules out either position.
Whether the decomposition plausibly holds has to be argued from what you
believe is causing the endogeneity in the first place, not read off this
one diagnostic.
ICON: the standard error inflation
The last block compares the corrected standard error to the uncorrected OLS standard error, from the same bootstrap resamples, for every coefficient in the model. The ratio is called ICON, and Qian, Koschmann and Xie (2025) flag a value above 6 as a sign of weak identification or a poorly specified dependence structure. The correction is not wrong exactly, but it is buying its protection against endogeneity at a cost in precision large enough to be a warning sign on its own. In the fit above the largest ICON is well under 6, which along with the satisfied uncorrelatedness assumption is why we call this a case where the assumptions hold.
A case where the assumptions are violated
Now the other side. sim_endog, the dataset shipped with
the package, has an endogenous regressor that is noticeably correlated
with one of its exogenous regressors, which is exactly the situation
CopRegPG() is not built for.
data(sim_endog)
set.seed(1)
idx <- sample(nrow(sim_endog), 300)
d <- sim_endog[idx, ]
cor(d$z_endog, d$w_instr)
#> [1] 0.5630987
set.seed(1)
fit_bad <- CopRegPG(y ~ z_endog | x_exog + w_instr, data = d, nboots = 99)
validity(fit_bad)
#>
#> Validity check for PG (Park & Gupta 2012)
#> n = 300, intercept: yes, target power 80%
#> Sources: Becker, Proksch & Ringle (2022); Yang, Qian & Xie (2025);
#> Qian, Koschmann & Xie (2025)
#>
#> [1] Nonnormality of the endogenous regressors
#> skewness ex.kurtosis AD CvM KS p Yang ok Becker ok
#> z_endog 0.036 0.136 0.442 0.04 0.77 FALSE FALSE
#> Becker et al. at n = 300: |skewness| >= 1.932, or AD > 18.964, or CvM > 3.488
#> Yang et al.: KS p < .05
#>
#> [2] Assumption: correlation of the copula transformation term
#> with the exogenous regressors
#> corr(W, CTT) p (Holm)
#> x_exog -0.0399 0.491
#> w_instr 0.5620 <1e-16
#> Joint test: R2 = 0.3197, F = 69.8, p = < 2.2e-16
#> => violated. Park & Gupta is inconsistent here (Haschka, 2025).
#>
#> [3] Exogenous regressors as identifying variation
#> (continuous, KS p < .001, first-stage F > 10)
#> Not available: this estimator has no first stage.
#>
#> [4] Error term: structural residuals xi
#> skewness = -0.01074, excess kurtosis = 0.04212, AD = 0.2891 (p = 0.613)
#> Becker et al. (2022) find that with a nonnormal error the approach
#> is no longer consistent in models with an intercept. Yang et al.
#> (2025) and Qian et al. (2025) do permit a nonnormal error, but only
#> under the decomposition xi = U + V into a normally distributed
#> endogenous part U, which carries the entire dependence with the
#> regressors, and an independent nonnormal V. The residuals show xi,
#> not U, so their skewness neither establishes nor rules out a
#> violation; whether that decomposition holds has to be argued from
#> the suspected sources of endogeneity.
#>
#> [5] ICON: standard error inflation relative to uncorrected OLS
#> SE (corrected) SE (uncorrected) ICON
#> (Intercept) 0.15593 0.06276 2.4848
#> z_endog 0.67571 0.06266 10.7838
#> x_exog 0.05709 0.05727 0.9968
#> w_instr 0.05970 0.05868 1.0174
#> => largest ICON = 10.78, above the threshold of 6: weak
#> identification or a misspecified dependence model.Step 1 shows z_endog as close enough to normal that both
Yang ok and Becker ok come back
FALSE, so the endogenous regressor itself is already a
weaker source of identification here than in the earlier example. Step 2
reports violated. The copula term correlates with
w_instr at about 0.56, with a Holm adjusted p value far
below any reasonable significance level, which is precisely the
correlation with w_instr we found directly on the raw data
above. validity() is not telling us anything we could not
have checked by hand; it is telling us what that correlation does to the
assumption PG needs. The consequence shows up in the last block. The
largest ICON is well above the threshold of 6, meaning the corrected
standard error on z_endog is many times the uncorrected OLS
one. Put together, this fit fails every check that is relevant to PG
specifically. The “Choosing an estimator” article shows what 2sCOPE,
IMA, BMW and JAMS do with the same data, because each of them relaxes
the assumption that fails here.
BMW: the same steps, applied to the first-stage residuals
BMW’s identification requirement falls on the residuals of its first
stage rather than on the endogenous regressor directly, so
validity() tests those residuals instead when it is looking
at a BMW fit, and the step 1 heading says so explicitly:
set.seed(1)
fit_bmw <- CopRegBMW(y ~ z_endog | x_exog + w_instr, data = d, nboots = 99)
validity(fit_bmw)
#>
#> Validity check for BMW (Breitung, Mayer & Wied 2024)
#> n = 300, intercept: yes, target power 80%
#> Sources: Becker, Proksch & Ringle (2022); Yang, Qian & Xie (2025);
#> Qian, Koschmann & Xie (2025)
#>
#> [1] Nonnormality of the first-stage residuals
#> Theorem 2.1 of Breitung, Mayer & Wied (2024) identifies the model if and only
#> if the first-stage error is not normal, so that is what is tested here.
#> skewness ex.kurtosis AD CvM KS p Yang ok Becker ok
#> z_endog -0.009 0.047 0.175 0.022 0.976 FALSE FALSE
#> Becker et al. at n = 300: |skewness| >= 1.932, or AD > 18.964, or CvM > 3.488
#> Yang et al.: KS p < .05
#>
#> [2] Exogenous regressors as identifying variation
#> (continuous, KS p < .001, first-stage F > 10)
#> continuous KS p F: z_endog qualifies
#> x_exog TRUE 0.360 0.001 FALSE
#> w_instr TRUE 0.907 0.005 FALSE
#> => none qualifies. The conditions are conservative and not
#> necessary; Yang et al. (2025) propose a bootstrap procedure to gauge
#> the finite-sample bias in this situation.
#>
#> [3] Error term: structural residuals xi
#> skewness = -0.01793, excess kurtosis = -0.3475, AD = 0.2755 (p = 0.657)
#> Becker et al. (2022) find that with a nonnormal error the approach
#> is no longer consistent in models with an intercept. Yang et al.
#> (2025) and Qian et al. (2025) do permit a nonnormal error, but only
#> under the decomposition xi = U + V into a normally distributed
#> endogenous part U, which carries the entire dependence with the
#> regressors, and an independent nonnormal V. The residuals show xi,
#> not U, so their skewness neither establishes nor rules out a
#> violation; whether that decomposition holds has to be argued from
#> the suspected sources of endogeneity.
#>
#> [4] ICON: standard error inflation relative to uncorrected OLS
#> SE (corrected) SE (uncorrected) ICON
#> (Intercept) 0.10908 0.06276 1.738
#> z_endog 1.00395 0.06266 16.022
#> x_exog 0.09951 0.05727 1.737
#> w_instr 0.66789 0.05868 11.383
#> => largest ICON = 16.02, above the threshold of 6: weak
#> identification or a misspecified dependence model.Everything else about reading the output is the same as above: the nonnormality criteria, the structural residual diagnostics, and the ICON threshold all mean what they meant before. The step testing correlation with the exogenous regressors as an assumption does not appear for BMW, because BMW does not assume that correlation away in the first place.
2sCOPE-np: a different assumption altogether
CopReg2sCOPEnp() does not rely on nonnormality of the
endogenous regressor at all, because its copula term comes from a
nonparametrically estimated conditional distribution rather than from a
marginal one. validity() on a 2sCOPE-np fit checks
Assumption 3 of Hu, Qian and Xie (2025) instead, the requirement that
the copula term is not simply a linear combination of the intercept, the
endogenous regressor and the exogenous regressors. It is reported as
omega, one minus the R-squared of a regression of the copula term on
everything else in the model. A value of omega near zero means the
augmented regression is close to singular, which is the practical way
this assumption fails. The paper’s own recommendation is to read the
standard error inflation in the ICON block as the operational test of
this assumption, because it is exactly that kind of collinearity that
inflates the standard errors. This package’s 2sCOPE-np examples live in
“Choosing an estimator” and are not run there either, because
cross-validated bandwidth selection makes the estimator slow; the shape
of its validity() output, though, is the one just described
rather than the nonnormality table used everywhere else in this
article.
Reading validity() as a whole
No single number from validity() is a verdict on its
own; that is why the output keeps five separate checks apart rather than
folding them into one. A fit that fails the nonnormality criteria can
still be fine if an exogenous regressor supplies enough identifying
variation on its own. A fit that passes every check can still have an
ICON high enough to make the resulting standard errors impractical. Read
the checks together: nonnormality of the source the estimator actually
depends on, whether the uncorrelatedness assumption holds where it
applies, what the structural residuals do and do not settle, and finally
whether the price paid in standard error inflation is one you are
willing to pay.
