This vignette uses the datasets::EuStockMarkets data,
which contain the daily closing prices of four major European stock
indices: the German DAX, the Swiss SMI, the French CAC and the UK FTSE
(see ?EuStockMarkets). The data are sampled in business
time, so weekends and holidays are omitted. We want weekly observations,
so we aggregate to a weekly frequency, which reduces the sample from
1860 to 372 observations.
stocks <- aggregate(EuStockMarkets, nfrequency = 52, mean)Estimation
We estimate the recursive augmented Dickey-Fuller test on these series with one lag.
est_stocks <- radf(stocks, lag = 1)Analysis
summary() prints the test statistics together with the
critical values at the 10%, 5% and 1% significance levels. A critical
value is the threshold a statistic must exceed before we reject the null
hypothesis of a unit root in favor of explosive behavior. When
cv is omitted, summary(),
diagnostics(), datestamp() and
autoplot() fetch precomputed Monte Carlo critical values
for the relevant (n, lag) from a shared store. The store
covers lags 0 to 4 and samples of up to 4000 observations. The first
fetch needs network access, and later calls read from the disk cache.
Here we simulate the critical values locally with
radf_mc_cv() and pass the result through cv to
every downstream call. This offline route is also the one to use for
other lags or larger samples.
cv_stocks <- radf_mc_cv(NROW(stocks), lag = 1)
summary(est_stocks, cv = cv_stocks)
#>
#> ── Summary (minw = 38, lag = 1) ────────────────── Monte Carlo (nboot = 1000) ──
#>
#> DAX :
#> # A tibble: 3 × 5
#> stat tstat `90` `95` `99`
#> <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 adf 1.45 -0.440 -0.0429 0.537
#> 2 sadf 4.95 1.23 1.54 2.06
#> 3 gsadf 5.18 2.13 2.38 3.00
#>
#> SMI :
#> # A tibble: 3 × 5
#> stat tstat `90` `95` `99`
#> <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 adf 1.77 -0.440 -0.0429 0.537
#> 2 sadf 4.28 1.23 1.54 2.06
#> 3 gsadf 4.49 2.13 2.38 3.00
#>
#> CAC :
#> # A tibble: 3 × 5
#> stat tstat `90` `95` `99`
#> <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 adf 0.987 -0.440 -0.0429 0.537
#> 2 sadf 2.91 1.23 1.54 2.06
#> 3 gsadf 2.97 2.13 2.38 3.00
#>
#> FTSE :
#> # A tibble: 3 × 5
#> stat tstat `90` `95` `99`
#> <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 adf 0.194 -0.440 -0.0429 0.537
#> 2 sadf 2.56 1.23 1.54 2.06
#> 3 gsadf 2.67 2.13 2.38 3.00All four stocks appear to show exuberant behavior, and
diagnostics() confirms this by reporting which series
reject the null. It is most useful when there are many series.
diagnostics(est_stocks, cv = cv_stocks)
#>
#> ── Diagnostics (option = gsadf) ───────────────────────────────── Monte Carlo ──
#>
#> DAX: Rejects H0 at the 1% significance level
#> SMI: Rejects H0 at the 1% significance level
#> CAC: Rejects H0 at the 5% significance level
#> FTSE: Rejects H0 at the 5% significance levelTo find out when the exuberance occurred, we use
datestamp(), which takes the same arguments as
summary() and diagnostics().
# Minimum duration of an explosive period
rot <- psy_ds(stocks) # log(n) ~ rule of thumb
dstamp_stocks <- datestamp(est_stocks, cv = cv_stocks, min_duration = rot)
dstamp_stocks
#>
#> ── Datestamp (min_duration = 6) ───────────────────────────────── Monte Carlo ──
#>
#> DAX :
#> Start Peak End Duration Signal Ongoing
#> 1 1997-02-10 1997-08-05 1997-11-04 38 positive FALSE
#> 2 1998-01-27 1998-07-22 1998-08-19 29 positive FALSE
#>
#> SMI :
#> Start Peak End Duration Signal Ongoing
#> 1 1993-12-02 1994-02-03 1994-02-17 11 positive FALSE
#> 2 1997-04-14 1997-07-15 1997-09-02 20 positive FALSE
#> 3 1997-09-09 1997-10-07 1997-11-04 8 positive FALSE
#> 4 1997-11-25 1998-04-07 1998-08-19 39 positive TRUE
#>
#> CAC :
#> Start Peak End Duration Signal Ongoing
#> 1 1997-07-08 1997-08-05 1997-08-19 6 positive FALSE
#> 2 1998-03-10 1998-07-15 1998-08-12 22 positive FALSE
#>
#> FTSE :
#> Start Peak End Duration Signal Ongoing
#> 1 1997-07-08 1997-08-12 1997-09-02 8 positive FALSE
#> 2 1997-09-23 1997-10-07 1997-11-04 6 positive FALSE
#> 3 1998-02-10 1998-04-14 1998-06-24 19 positive FALSEWe can also extract the datestamp as a dummy variable, where 1 marks exuberance and 0 marks its absence.
dummy <- attr(dstamp_stocks, "dummy")
tail(dummy)
#> DAX SMI CAC FTSE
#> 367 1 1 1 1
#> 368 1 1 1 1
#> 369 1 1 1 1
#> 370 1 1 1 0
#> 371 1 1 0 0
#> 372 0 1 0 0datestamp() is not the only way to obtain dates, but the
other two approaches answer different questions rather than the same
one. The dating_*() family
(vignette("dating-methods")) fits an explicit regime model
to date a bubble that you already believe is there, and it does not test
whether one exists. The monitor() and
monitor_*() family (vignette("monitoring"))
detects bubbles in real time by watching new observations one at a time,
instead of dating a finished sample.
vignette("naming-and-analysis") shows how every function in
the package relates to datestamp().
Plotting
autoplot() returns a faceted ggplot2 object for all the
series that reject the null hypothesis at the 5% significance level.
autoplot(est_stocks, cv = cv_stocks)
Finally, we can plot only the periods of exuberance. Plotting the datestamp object is useful when there are many series and we want to see the explosive episodes in all of them.

