Module 3 Discussion

Author

Kevin Rusu

1 Import Packages

library(fpp3)
Registered S3 method overwritten by 'tsibble':
  method               from 
  as_tibble.grouped_df dplyr
── Attaching packages ──────────────────────────────────────────── fpp3 1.0.2 ──
✔ tibble      3.3.0     ✔ tsibble     1.1.6
✔ dplyr       1.1.4     ✔ tsibbledata 0.4.1
✔ tidyr       1.3.1     ✔ feasts      0.4.2
✔ lubridate   1.9.4     ✔ fable       0.4.1
✔ ggplot2     4.0.0     
── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
✖ lubridate::date()    masks base::date()
✖ dplyr::filter()      masks stats::filter()
✖ tsibble::intersect() masks base::intersect()
✖ tsibble::interval()  masks lubridate::interval()
✖ dplyr::lag()         masks stats::lag()
✖ tsibble::setdiff()   masks base::setdiff()
✖ tsibble::union()     masks base::union()
library(fredr)
fredr_set_key(Sys.getenv("FRED_API_KEY"))

2 Are the time series stationary? If not, tell us what condition is violated. Please confirm this with any a formal test.

2.1 Real GDP

gdp <- fredr("GDPC1",
             observation_start = as.Date("1990-01-01"),
             observation_end = as.Date("2024-12-31")) |>
  mutate(Quarter = yearquarter(date)) |>
  as_tsibble(index = Quarter) |>
  select(Quarter, value)

gdp
# A tsibble: 140 x 2 [1Q]
   Quarter  value
     <qtr>  <dbl>
 1 1990 Q1 10047.
 2 1990 Q2 10084.
 3 1990 Q3 10091.
 4 1990 Q4  9999.
 5 1991 Q1  9952.
 6 1991 Q2 10030.
 7 1991 Q3 10080.
 8 1991 Q4 10115.
 9 1992 Q1 10236.
10 1992 Q2 10347.
# ℹ 130 more rows

2.1.1 GDP Graph

gdp |> autoplot(value) +
  labs(title = "US Real GDP",
       y = "Billions of 2017 USD",
       x = "Quarter")

2.1.2 KPSS Test #1

gdp |> 
  features(value, unitroot_kpss)
# A tibble: 1 × 2
  kpss_stat kpss_pvalue
      <dbl>       <dbl>
1      2.83        0.01

Result: The null hypothesis of the KPSS test is that the series is stationary. The test returned a p-value of 0.01, which is below the 0.05 significance level. Therefore we reject the null hypothesis and conclude that the series is non-stationary.

2.2 Federal Funds Rate

fedfunds <- fredr("FEDFUNDS",
                  observation_start = as.Date("1990-01-01"),
                  observation_end = as.Date("2025-10-31")) |>
  mutate(Month = yearmonth(date)) |>
  as_tsibble(index = Month) |>
  select(Month, value)

fedfunds
# A tsibble: 430 x 2 [1M]
      Month value
      <mth> <dbl>
 1 1990 Jan  8.23
 2 1990 Feb  8.24
 3 1990 Mar  8.28
 4 1990 Apr  8.26
 5 1990 May  8.18
 6 1990 Jun  8.29
 7 1990 Jul  8.15
 8 1990 Aug  8.13
 9 1990 Sep  8.2 
10 1990 Oct  8.11
# ℹ 420 more rows

2.2.1 FEDFUNDS Graph

fedfunds |> autoplot(value) +
  labs(title = "Federal Funds Rate",
       y = "Percent",
       x = "Month")

2.2.2 KPSS Test #2

fedfunds |> 
  features(value, unitroot_kpss)
# A tibble: 1 × 2
  kpss_stat kpss_pvalue
      <dbl>       <dbl>
1      2.82        0.01

Result: Fedfunds is non-stationary. The test returned a p-value of 0.01, which is below the 0.05 significance level. Therefore we reject the null hypothesis and conclude that the series is non-stationary.

2.3 CPI Index

cpi <- fredr("CPIAUCSL",
                  observation_start = as.Date("1990-01-01"),
                  observation_end = as.Date("2025-09-30")) |>
  mutate(Month = yearmonth(date)) |>
  as_tsibble(index = Month) |>
  select(Month, value)

cpi
# A tsibble: 429 x 2 [1M]
      Month value
      <mth> <dbl>
 1 1990 Jan  128.
 2 1990 Feb  128 
 3 1990 Mar  129.
 4 1990 Apr  129.
 5 1990 May  129.
 6 1990 Jun  130.
 7 1990 Jul  130.
 8 1990 Aug  132.
 9 1990 Sep  132.
10 1990 Oct  133.
# ℹ 419 more rows

2.3.1 CPI Graph

cpi |> autoplot(value) +
  labs(title = "Consumer Price Index",
       y = "Index (1982-1984 = 100",
       x = "Month")

2.3.2 KPSS Test #3

cpi |> 
  features(value, unitroot_kpss)
# A tibble: 1 × 2
  kpss_stat kpss_pvalue
      <dbl>       <dbl>
1      6.96        0.01

CPI is non-stationary. The test returned a p-value of 0.01, which is below the 0.05 significance level. Therefore we reject the null hypothesis and conclude that the series is non-stationary.

3 Generate and interpret the ACF and PACF graphs for each of the three different times series.

3.1 GDP (stationary)

gdp_diff <- gdp |>
  mutate(diff_value = difference (value))

gdp_diff |> autoplot(diff_value) + 
  labs(title = "Change in US Real GDP (First Difference)",
       y = "Billions of 2017 USD",
       x = "Quarter")
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).

3.1.1 GDP ACF and PACF

gdp_diff |>
  gg_tsdisplay(diff_value, plot_type = "partial") +
  labs(title = "ACF and PACF of Differenced GDP")
Warning: `gg_tsdisplay()` was deprecated in feasts 0.4.2.
ℹ Please use `ggtime::gg_tsdisplay()` instead.
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

Interpretation: The ACF of differenced GDP shows one significant negative spike at lag 1 that cuts off quickly. The PACF also shows a significant spike at lag 1. This pattern is consistent with an MA(1) process, which suggests that quarterly GDP changes are influenced primarily by the shock from the previous quarter.

3.2 Fedfunds (stationary)

fedfunds_diff <- fedfunds |>
  mutate(diff_value = difference(value))

fedfunds_diff |> autoplot(diff_value) +
  labs(title = "Change iN FedFunds Rate (First Difference)",
       y = "Percentage Point Change",
       x = "Month")
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).

3.2.1 FedFunds ACF and PACF

fedfunds_diff |> 
  gg_tsdisplay(diff_value, plot_type = "partial") +
  labs(title =  "ACF & PACF of Differenced FedFunds Rate")
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

Interpretation: The ACF of the differenced Federal Funds Rate shows a slow gradual decay across many lags, while the PACF cuts off sharply after lag 1. This pattern is consistent with an AR(1) process, suggesting that monthly changes in the Federal Funds Rate are strongly predicted by the change in the previous month, reflecting the Fed’s tendency to adjust rates gradually over time.

3.3 CPI -> Inflation (stationary)

cpi_inflation <- cpi |>
  mutate(inflation = difference(log(value)) * 100)

cpi_inflation |> autoplot(inflation) + 
  labs(title = "Monthly Inflation Rate (CPI)",
       y = "Percent Change",
       x = "Month")
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).

3.3.1 Inflation ACF and PACF

cpi_inflation |>
  gg_tsdisplay(inflation, plot_type = "partial") + 
  labs(title = "ACF and PACF of CPI Inflation Rate")
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_line()`).
Warning: Removed 1 row containing missing values or values outside the scale range
(`geom_point()`).

Interpretation: The ACF of the CPI inflation rate shows one significant spike at lag 1 that cuts off sharply, while the PACF also cuts off after lag 1. This pattern is consistent with an MA(1) process, suggesting that monthly inflation is primarily driven by the shock from the previous month

4 Apply decomposition methods on all three time series. What do the graphs tell you/are your key takeaways?

4.1 GDP Decomposition

gdp |>
  model(STL(value ~ season(window = 13),
            robust = TRUE)) |>
  components() |>
  autoplot()

Interpretation: There is a clear upward trend for GDP which is smooth and persistent. This is why the original data is non-stationary. In addition, there the decomposition shows a quarterly seasonal pattern, which repeats ever year. For the remainder, it mostly looks like random noise fluctuating around zero, which is good. However, there is a massive spike down around 2020 Q2 because of the Covid pandemic.

4.2 FedFunds Decomposition

fedfunds |>
  model(STL(value ~ season(window = 13),
            robust = TRUE)) |>
  components() |>
  autoplot()

Interpretation: There is no clear trend in the fedfunds data. It shows high rates in the early 1990s, a gradual decline through the 2000s, near zero values from 2008 to around 2015, and a small increase around 2018/19. Then there is new drop to zero in 2020 because of covid, and a sharp rise in 2022/23. There is a small seasonal pattern, but it’s extremely weak and almost disappears after 2000 (values are between -0.2 and 0.15). The month of the year is not really important for the Fed for lowering or increasing rats. The remainder shows that it is much noisier than GDP with spikes around 2001, 2008 and 2020. The Federal Funds Rate shifts between different average levels across distinct monetary policy regimes, with no consistent long-run mean, which is the primary reason for its non-stationarity.

4.3 CPI Decomposition

cpi |>
  model(STL(value ~ season(window = 13),
            robust = TRUE)) |>
  components() |>
  autoplot()

Interpretation: The trend is smooth and upward trending. CPI roughly doubles from 1990 to 2024, reflecting cumulative inflation. The trend accelerates slightly after 2020, which is the post-covid inflation surge. The CPI has a small seasonal pattern that becomes more after 2020, which is likely due to covid-related supply chain disruptions and energy price volatility. The remainder is stable but has upward spikes in 2008 and 2020. The strong upward trend is the dominant cause of non-stationarity. The variance also appears to increase slightly over time.

This is a random in-text citation and this journa talks about Arima Models (Shumway and Stoffer 2017)

References

Shumway, Robert H., and David S. Stoffer. 2017. ARIMA Models.” In Time Series Analysis and Its Applications, by Robert H. Shumway and David S. Stoffer, 75–163. Cham: Springer International Publishing. https://doi.org/10.1007/978-3-319-52452-8_3.