Guide
Getting started
Install exuber in R, Python or C++, run a bubble test on simulated data, and read the result. The next two pages explain what the test does and which settings change it.
Install
R (exuber)
install.packages("exuber") # CRAN release
devtools::install_github("kvasilopoulos/exuber") # development versionThe methods beyond the original PSY test (dating, volatility-robust tests, monitoring and multivariate methods) will reach CRAN with exuber 2.0.0. Until then they are in the development version.
Python (pyexuber)
pip install pyexuber
# or, to build from source:
git clone https://github.com/kvasilopoulos/pyexuber
cd pyexuber
uv sync --devVersion 0.1.0 is on PyPI with prebuilt wheels for Linux, macOS and Windows (Python 3.10 or later), so pip needs no compiler. A source build needs a C++17 compiler, CMake ≥ 3.16 and a system Armadillo (apt install libarmadillo-dev, brew install armadillo, or vcpkg). The package is imported as exuber.
C++ (exubercore)
git clone https://github.com/kvasilopoulos/exubercore
cd exubercore
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildThis needs a system Armadillo with BLAS/LAPACK. The library provides the statistic only. Critical values, dating and simulation are in the R and Python packages.
A first run
The example tests a series, calibrates the critical values and date-stamps the result. The
R and Python versions differ only in spelling. In Python the data can be a numpy array, a
one-dimensional sequence, or anything with a .to_numpy() method
(such as a pandas or polars column).
library(exuber)
rsim <- radf(sim_data) # adf, badf, sadf, gsadf, bsadf, ...
cv <- radf_mc_cv(n = NROW(sim_data)) # simulated 90/95/99% thresholds
summary(rsim, cv) # rejects/does not reject H0 per series, per statistic
autoplot(rsim, cv) # bsadf vs. its threshold, explosive spans shaded
datestamp(rsim, cv) # a Start/End/Duration row per detected episode import numpy as np
import exuber
data = np.cumsum(np.random.randn(200))
result = exuber.radf(data) # RadfResult: .adf .badf .sadf .gsadf .bsadf
cv = exuber.radf_mc_cv(n=len(data)) # RadfCv: simulated 90/95/99% thresholds
result.adf, result.sadf, result.gsadf
exuber.datestamp(result, cv) # list[Episode]: one per detected explosive span #include <exubercore/radf.hpp>
arma::vec y = arma::cumsum(arma::randn(200));
auto result = exubercore::radf(y, /* min_win = */ 20);
// arma::vec: badf, then adf, sadf, gsadf, then the bsadf sequence --
// see the reference entry for the exact layout and offsets. Reading the output
summary(): reports, for each series and statistic (ADF, SADF, GSADF), whether the null hypothesis of a unit root is rejected at 90, 95 and 99%.autoplot(): plots the BSADF sequence against its critical value and shades the explosive spans.datestamp(): returns one Start / Peak / End / Duration row for each detected episode.
Next, read about what ADF, SADF, GSADF and BSADF test.
Which method do I need?
The test above is the right starting point for most series. The packages also cover a number of situations it was not designed for. Each guide page below runs a short example and says when to prefer one function over another.
- Is the variance of my series changing over time? Volatility-robustness tests.
- I already believe there is a bubble. When did it start and end, and how fast did it grow? Dating and root inference.
- I want to be alerted as new data arrive. Real-time monitoring.
- Do two series bubble together, or does one spill into the other? Multivariate bubble tests.
- I want a test that does not rely on the recursive ADF. Alternative paradigms.
- I want to study the size or power of a test, or generate example data. Simulating bubbles.
Validation notes, the formulas behind each method and the scripts that reproduce the published numbers are kept in the replication record for readers who want to check the work.
exuber