
Recursively Demeaned Sign-Based Bubble Test (s-bar-PWY / s-bar-PSY)
Source:R/radf_sign.R
radf_sign_dm.Rdradf_sign_dm computes the second sign-based analogue of the recursive
right-tailed unit root test of Harvey, Leybourne & Zu (2020), which the paper
denotes \(\bar{s}PWY\)/\(\bar{s}PSY\). The construction is the same as in
radf_sign, but it is built on a recursively (expanding-window)
demeaned cumulated-sign series, Ctilde_t = sum_{i=2}^{t}
(sign(diff(y)_i) - mean(sign(diff(y)_{2:i}))), and not on the raw cumulated
sign that radf_sign uses.
Arguments
- data
A univariate or multivariate numeric time series object, a numeric vector or matrix, or a data.frame. A column may have leading or trailing
NAvalues, which describes an unbalanced panel in which series enter or exit the sample at different times. Those periods are filled withNAinbadfandbsadfand excluded from theadf,sadfandgsadfof that series. InteriorNAvalues (a gap in the middle of a series) are not supported. When any series is padded in this way, the panel statistics (bsadf_panelandgsadf_panel) are not available, and the function returnsNAfor them with a warning.- minw
A positive integer. The minimum window size (default = \((0.01 + 1.8/\sqrt{T})T\), where T denotes the sample size).
Value
An object of class radf_sign_dm_obj/radf_obj. It is the same
adf/badf/sadf/bsadf/gsadf list as for
radf, and it pairs with radf_sign_dm_cv.
Details
Harvey, Leybourne, Tatlow & Zu (2025) show that this statistic shares the
asymptotic level-shift robustness of radf_sign (see the
Level-shift robustness section of that function). It does not need
Assumption 2 of the underlying HLZ (2020) theory, that the median of the
innovations is zero, which is a strictly weaker requirement than the one
radf_sign needs for its own invariance result. Their finite-sample
simulations also find that the recursive demeaning tends to reduce the size
distortion under level shifts further than radf_sign does, although both
are asymptotically robust to level shifts under the same condition.
Note
The test needs the critical values from radf_sign_dm_cv, and
radf_sign_cv does not apply, because it is calibrated to the
non-demeaned radf_sign statistic. The statistic is pivotal like
radf_sign, so no bootstrap is needed for each dataset.
The result carries the radf_obj class. Since 2026-08-18 the full
summary(), datestamp, tidy and autoplot
pipeline works, with the same fix as for radf_sign:
radf_sign_dm_cv() now also computes badf_cv and bsadf_cv,
and not only the three scalar critical values. See
vignette("naming-and-analysis", package = "exuber").
References
Harvey, D. I., Leybourne, S. J., & Zu, Y. (2020). Sign-based unit root tests for explosive financial bubbles in the presence of deterministically time-varying volatility. Econometric Theory, 36(1), 122-169.
Harvey, D. I., Leybourne, S. J., Tatlow, D., & Zu, Y. (2025). Unit root tests for explosive financial bubbles in the presence of deterministic level shifts. Oxford Bulletin of Economics and Statistics, 87(5), 879-901. doi:10.1111/obes.12668
See also
radf_sign_dm_cv for critical values, and
radf_sign for the non-demeaned sign-based analogue.
Other volatility-robust tests:
cusum_test(),
radf_kp(),
radf_sbz(),
radf_sbz_union(),
radf_sign(),
radf_tt(),
ssu_test()
Examples
# \donttest{
# Volatility triples half-way through the sample. This is the case of
# non-stationary volatility that this test is built for, and plain radf()
# over-rejects here
y <- sim_psy1(n = 200, seed = 1, e = sim_vol_break(199))
res <- radf_sign_dm(y, minw = 20)
print(res)
#>
#> ── radf_sign_dm (minw = 20) ────────────────────────────────────────────────────
#>
#> series adf sadf gsadf
#> series1 -0.03298 2.492 6.081
#>
cv <- radf_sign_dm_cv(n = 200, minw = 20)
summary(res, cv = cv)
#>
#> ── Summary (minw = 20, lag = 0) ───── Sign-Based MC (demeaned) (nboot = 2000) ──
#>
#> series1 :
#> # A tibble: 3 × 5
#> stat tstat `90` `95` `99`
#> <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 adf -0.0330 0.853 1.28 2.09
#> 2 sadf 2.49 2.45 2.80 3.46
#> 3 gsadf 6.08 3.32 3.66 4.58
#>
tidy(res, cv = cv)
#> # A tibble: 1 × 4
#> id adf sadf gsadf
#> <fct> <dbl> <dbl> <dbl>
#> 1 series1 -0.0330 2.49 6.08
datestamp(res, cv = cv)
#>
#> ── Datestamp (min_duration = 0) ──────────────────── Sign-Based MC (demeaned) ──
#>
#> series1 :
#> Start Peak End Duration Signal Ongoing
#> 1 91 103 115 24 positive FALSE
#> 2 156 157 158 2 negative FALSE
#> 3 159 160 161 2 negative FALSE
#>
autoplot(res, cv = cv)
# }