Skip to contents

Why “experimental” is a real, load-bearing label here

Most of exuber’s methods implement a peer-reviewed paper’s own procedure and pass the package’s standard validation pass (formula-exact check against a brute-force reimplementation, published-table lookup, Monte Carlo size, power against a genuine alternative). radf_recovery() and datestamp(option = "svadf") both run that same pass and both come back genuinely useful – but each has one specific, disclosed gap that keeps it below that bar. They print and emit a caveat message at call time for exactly that reason; treat their output as directional, not as calibrated as the rest of the package.

radf_recovery(): dating a collapse and a recovery

Phillips & Shi (2014)’s reverse-regression idea: reverse the series in time, run the same BSADF recursion radf() already computes, and map the crossing dates back. A collapse-then-recovery episode, reversed, turns the collapse into an explosive regime and the recovery into its unwind – so the existing forward machinery, run backwards, dates both.

set.seed(2)
n1 <- 40; n2 <- 25; n3 <- 35
expansion <- 100 * 1.03^(1:n1) + cumsum(rnorm(n1, sd = 1))
collapse <- expansion[n1] * 0.5^((1:n2) / n2) + cumsum(rnorm(n2, sd = 1))
recovery <- collapse[n2] + cumsum(rnorm(n3, sd = 1)) + (1:n3) * 0.5
y <- c(expansion, collapse, recovery) # expansion -> collapse -> recovery
res <- radf_recovery(y, minw = 15, nrep = 200, seed = 1)
res
#> 
#> ── radf_recovery (n = 100, minw = 15, level = 95%) ─────────────────────────────
#> 
#>  Experimental. f_c and the overall false-detection rate are exploratory pending further validation; see ?radf_recovery, Caveats section.
#> 
#>    series  f_c  f_r  detected  censored
#>   series1   35   62      TRUE     FALSE

f_c (crisis onset) lands near the true collapse start (40) and f_r (recovery) after it (62), in the right order – by construction, since the down-crossing search only ever starts at the up-crossing. The disclosed gap: f_c and the overall false-detection rate are exploratory pending further validation (see ?radf_recovery, Caveats section) – the date-ordering property is solid, the false-alarm calibration is not yet.

datestamp(option = "svadf"): a non-peer-reviewed preprint

Sarkar & Wells (2026, arXiv, not yet peer reviewed) – flagged explicitly because that is a different evidentiary bar than every other paper this package implements. Its statistic turns out to be exactly radf()’s own badf sequence compared against two closed-form, sample-size-only thresholds from the paper’s own applied methodology (no new estimation machinery needed), which is why it was cheap to add – as a datestamp() option rather than a separate entry point, despite the preprint caveat.

res <- radf(sim_data, lag = 0)
datestamp(res, option = "svadf", min_duration = psy_ds(nrow(sim_data)))
#> 
#> ── Datestamp (min_duration = 5) ──────────────── SV-ADF (Sarkar & Wells 2026) ──
#> 
#>  Experimental. Sarkar & Wells (2026) is a non-peer-reviewed preprint; see ?datestamp, Caveats section.
#> 
#> psy1 :
#>   Start Peak End Duration   Signal Ongoing
#> 1    48   48  49        1 positive   FALSE
#> 
#> psy2 :
#>   Start Peak End Duration   Signal Ongoing
#> 1    23   23  24        1 positive   FALSE

psy1 and psy2 get clean origination/collapse dates; evans, div and blan don’t cross the threshold on this panel at all – again a realistic, not cherry-picked, mixed result.

Using them responsibly

Both are worth using – radf_recovery()’s date ordering result and datestamp(option = "svadf")’s point statistic are both solid – but neither should be the sole basis for a claim about false-alarm rates or exact calibration. Prefer radf()/datestamp() or one of the peer-reviewed alternatives in vignette("alternative-tests")/vignette("dating-methods") when that matters, and treat these two as a second opinion rather than the primary one until their own caveats are resolved (tracked in docs/enhancements/dating-and-root-inference.md and volatility-robustness.md).