── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ tsibble::interval() masks lubridate::interval()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Visually, all three datasets do not display stationarity. All three graphs don’t have a constant mean. Federal Funds and Crude Oil Prices don’t have constant variance, and all three graphs have trends, breaking the covariance independent of time requirement.
Formal (KPSS test)
I used kpss test for stationarity, which checks the null hypothesis that our graphs are stationary and returns a p-value. We can reject stationarity if our p-value is below .05.
Given a p-value of .01 was returned, stationarity can be rejected for all three datasets and differencing can be applied (as I will show later) to fix this.
III. ACF/PACF tests
Differencing the Data
To set up ACF and PACF tests, the data must first be differenced. I’ll first use the ndiffs() command to determine the number of differences needed for each dataset.
op |>features(value, unitroot_ndiffs)
# A tibble: 1 × 1
ndiffs
<int>
1 1
ur |>features(value, unitroot_ndiffs)
# A tibble: 1 × 1
ndiffs
<int>
1 1
ff |>features(value, unitroot_ndiffs)
# A tibble: 1 × 1
ndiffs
<int>
1 1
Given a return of 1, I will difference once and reapply kpss tests to confirm, as seen below.
op |>mutate(diff_value =difference(value)) |>features(diff_value, unitroot_kpss)
After differencing once each, our p-value has climbed to 0.1 for each dataset, indicating that each dataset is stationary. Before beginning the tests, I’ll run one more check for seasonal differencing that may be required. See the below code:
op |>features(value, unitroot_nsdiffs)
# A tibble: 1 × 1
nsdiffs
<int>
1 0
ur |>features(value, unitroot_nsdiffs)
# A tibble: 1 × 1
nsdiffs
<int>
1 0
ff |>features(value, unitroot_nsdiffs)
# A tibble: 1 × 1
nsdiffs
<int>
1 0
With no seasonal differencing required, I’ll now begin the ACF/PACF tests.
ACF/PACF
Oil Price
op |>mutate(diff_value =difference(value)) |>ACF(diff_value) |>autoplot() +labs(subtitle ="ACF of differenced crude oil prices")
op |>mutate(diff_value =difference(value)) |>PACF(diff_value) |>autoplot() +labs(subtitle ="PACF of differenced crude oil prices")
ACF here spikes at the first lag, and although the second lag is above the threshold, it may not be significant enough to encourage MA(2), although both will be tested.
PACF also spikes at the first lag and then dips below the threshold, indicating MA(1) would be strongest here. Because this cut off is cleaner, we might expect AR(1) to perform stronger than MA(1).
Unemployment Rate
ur |>mutate(diff_value =difference(value)) |>ACF(diff_value) |>autoplot() +labs(subtitle ="ACF of differenced unemployment rate")
ur |>mutate(diff_value =difference(value)) |>PACF(diff_value) |>autoplot() +labs(subtitle ="PACF of differenced unemployment rate")
Both the ACF and PACF show significant negative spikes in the first few lags, indicating higher p and q values respectively. As both charts look similar in terms of cutoffs, p and q values of 3 and 4 will be tested.
Federal Funds Rate
ff |>mutate(diff_value =difference(value)) |>ACF(diff_value) |>autoplot() +labs(subtitle ="ACF of differenced federal funds rate")
ff |>mutate(diff_value =difference(value)) |>PACF(diff_value) |>autoplot() +labs(subtitle ="PACF of differenced federal funds rate")
ACF here spikes at the first lag but is consistently present throughout, indicating ARMA(p,q) may be the strongest model here, with similar p and q values. PACF spikes in the first two lags, first positive, then negative. However, PACF spikes throughout, similarly to ACF. ARMA and ARIMA may be strongest here.
IV. Decomposition
Now, I’ll apply decomposition to each dataset. I’ll use the stl() function and then interpret the graphs in terms of stationarity.
op_dcmp <- op %>%model(stl =STL(value ~season(window =7))) %>%components()autoplot(op_dcmp) +xlab("Year")
ur_dcmp <- ur %>%model(stl =STL(value ~season(window =7))) %>%components()autoplot(ur_dcmp) +xlab("Year")
The first graph displayed decomposes the oilprices dataset. The trend here is strongly increasing, seasonality does not appear to show a clear pattern, and the remainder is large in recent years. This volatility and the large trend shift indicate non-stationarity.
The second graph displayed decomposes the unemployment rate dataset. The trend here captures a cycle, while seasonality and the remainder are quite small until recent years, but they appear to be returning to form. This would imply that non-stationarity here is driven by the economic business cycles in the U.S.
The third and final graph displayed decomposes the Federal funds rate dataset. The trend here shows regime changes in the 1980s, while seasonality and remainder are flat after the early 1980s. Clearly the non-stationarity here is driven by policy changes in earlier regimes.