Extracting Cyclical Components From Economic Time Series

with tags hp-filter hodrick-prescott baxter-king wavelet emd empirical-mode-decomposition -

The analysis of economic time series often requires the extraction of their cyclical components. This post presents some methods, which can be used to decompose time series into their different components. It is based on the chapter on business cycles by Stock and Watson (1999) in the Handbook of Macroeconomics, but also presents some more recent methods like Hamilton’s (2017) alternative to the HP-filter, wavelet filtering and empirical mode decomposition.

Data

I use quarterly data of US log real GDP from 1970Q1 to 2016Q4 for the illustration of the different methods. The time series is obtained via Quandl and its respectiv R-package. The original series can be downloaded from the FRED database.

# Load packages for data download and transformation
library(dplyr)
library(Quandl)
library(tidyr)

# Download data
data <- Quandl("FRED/GDPC1", order = "asc",
               start_date = "1970-01-01", end_date = "2016-10-01")  %>%
  rename(date = Date,
         gdp = Value) %>%
  mutate(lgdp = log(gdp)) # Take logs

To get an intuition about what it means to extract the cyclical component of a time series, look at the development of log real GDP over time in the following figure.

library(ggplot2)

ggplot(data, aes(x = date, y = lgdp)) +
  geom_line() +
  theme_classic() +
  labs(title = "Log real US GDP", x = "Quarter", y = "",
       caption = "Source: U.S. Bureau of Economic Analysis (GDPC1).\nRetrieved via Quandl.com.")

There is a clear increasing trend in the data, which appears to become gradually smaller up to the present. Additionally, the series seems to fluctuate around this trend in a more or less regular manner. There are relatively long lasting deviations from the trend, which could be considered to be cyclical fluctuations. The identification of those cyclical components is an important question in economics, because it might have serious implications for economic policy.

Deviation from a linear trend

A first approach to extract a trend from a series is to regress the variable of interest on a constant and a trend term and to obtain the fitted values. These are plotted in the following figure.

# Add a trend
data <- data %>%
  mutate(trend = 1:n())

# Estimate the model with a constant and a trend
time_detrend <- fitted(lm(lgdp ~ trend, data = data))
names(time_detrend) <- NULL

# Add series to main data frame
data <- data %>%
  mutate(lin_trend = time_detrend)

# Create data frame for the plot
temp <- data %>%
  select(date, lgdp, lin_trend) %>%
  gather(key = "Variable", value = "value", -date)

# Plot
ggplot(temp, aes(x = date, y = value, colour = Variable)) +
  geom_line() +
  theme_classic() +
  labs(title = "Residuals of a linear trend estimation",
       x = "Quarter", y = "")

This approach is relatively controversial, since it assumes that there is a constant, linear time trend. As we have seen above, this is not very likely given the steady decrease of the trend’s growth rate over time. However, it is still possible to assume a different functional form of the time trend, e.g. a quadratic term, to account for the specifities of a trend. A further disadvantage of this method is that it does only exlude the trend, but not the noise, i.e. the very small fluctuations in the series.

Hodrick-Prescott filter

Hodrick and Prescott (1981) developed a filter, which seprates a time series into a trend and cyclical component. In contrast to the linear trend the so-called HP filter estimates a trend, which changes over time. And the degree to which this trend is allowed to change, the smoothing parameter \(\lambda\), is determined manually by the researcher.

The hpfilter function is contained in the mFilter package and requires the time series and the smoothing parameter. The literature suggests a value of 1600 for quarterly data. However, it is possible to choose a much higher value as well. The follwoing figure plots the values of the cyclical component of real GDP obtained by the HP filter and compares it to the values of a linearly detrended series. The behaviour of both series appears to be quite similar at the beginning of the series.

# Load the package
library(mFilter)

# Run HP filter
hp_gdp <- hpfilter(data$lgdp, freq = 1600)

# Add the cyclical component of the HP filter and
# the linearly detrended sereis to the main data frame
data <- data %>%
  mutate(hp = hp_gdp$cycle,
         lin_cycle = lgdp - lin_trend)

# Create data frame for the plot
temp <- data %>%
  select(date, hp, lin_cycle) %>%
  gather(key = "Variable", value = "value", -date) %>%
  filter(!is.na(value)) %>%
  mutate(Variable = factor(Variable, levels = c("hp", "lin_cycle"),
                           labels = c("HP filter", "Residuals of\na linear trend\nestimation")))

# Plot
ggplot(temp, aes(x = date, y = value, colour = Variable)) +
  geom_hline(yintercept = 0, colour = "grey") +
  geom_line() +
  theme_classic() +
  labs(title = "HP filter",
       x = "Qurarter", y = "")

Although widely used in economics, the HP filter is also heavily criticised for some features. See, for example, a good overview in a Bruegel blog post by Jérémie Cohen-Setton and Yury Yatsynovich and here for the working paper version of a critique by James Hamilton.

A regression based alternative to the HP filter

Hamilton (forthcoming) also proposes an alternative approach to the HP filter, which boils down to a simple regression model, where the hth lead of the times series is regressed on the most recent p values of the time series. As recommended in the paper I use \(h = 8\) and \(p = 4\) in the following example.

# Set lead and lags
p <- 4
h <- 8

# Get the series
y <- data$lgdp

# Obtain lags
temp <- y
for (i in h + 0:(p - 1)) {
  temp <- cbind(temp, lag(y, i))
}

temp <- as.data.frame(na.omit(temp))

# Estimate the model
lm_temp <- lm(temp ~ . , data = temp)

# Obtain residuals
residuals <- c(rep(NA,  p + h - 1), residuals(lm_temp))
names(residuals) <- NULL

# Add residuals to the main data frame
data <- data %>%
  mutate(hamilton = residuals)

# Prepare dataset for plot
temp <- data %>%
  select(date, hamilton, hp) %>%
  gather(key = "Variable", value = "value", -date) %>%
  filter(!is.na(value)) %>%
  mutate(Variable = factor(Variable,
                           levels = c("hp", "hamilton"),
                           labels = c("HP filter", "Hamilton's\nalternative\nto the HP-filter")))

# Plot
ggplot(temp, aes(x = date, y = value, colour = Variable)) +
  geom_hline(yintercept = 0, colour = "grey") +
  geom_line() +
  theme_classic() +
  labs(title = "Hamilton's alternative to the HP filter",
       x = "Qurarter", y = "", 
       caption = "Source: Hamilton (Forthcoming).")

Baxter King filter

Baxter and King (1994, 1999) proposed a filter, which yields very similar results as the HP filter. Additionally, it takes out the noise from the time series, so that a smooth estimate of the cyclical component can be obtained. The function bkfilter is also contained in the mFilter package. It requires the series, a lower and an upper bound of the amount of periods, where cycles are assumed to occur (pl and pu), and a smoothing factor nfix. The literature (e.g. NBER, Stock and Watson (1999)) suggests that business cycles last from 6 to 32 months. These values were used to specify the lower and upper bound of the cycle periodicity. The results of the BK filter are shown in the following figure. A relatively serious drawback of this method is that the smoothing factor leads to the loss of observations at the beginning and the end of the series. This might be a problem with small samples and when the current state of the economy is of interest.

# Run BK filter
bk_gdp <- bkfilter(data$lgdp, pl = 6, pu = 32, nfix = 12)

# Add cyclical component to the main data frame
data <- data %>%
  mutate(bk = bk_gdp$cycle[, 1])

# Create data frame for the plot
temp <- data %>%
  select(date, hp, bk) %>%
gather(key = "Variable", value = "value", -date) %>%
  filter(!is.na(value)) %>%
  mutate(Variable = factor(Variable,
                           levels = c("hp", "bk"),
                           labels = c("HP filter", "BK filter")))

# Plot
ggplot(temp, aes(x = date, y = value, colour = Variable)) +
  geom_hline(yintercept = 0, colour = "grey") +
  geom_line() +
  theme_classic() +
  labs(title = "Baxter-King filter",
       x = "Qurarter", y = "")

Wavelet filter

Yogo (2008) proposed to use wavelet filters to extract business cycles from time series data. The advantage of this method is that the function does not only allow to extract the trend, cycle and noise of a series, but also to become more specific about the periods within which cycles occur. However, there is not full freedom in that, since the technique can only capture periodicities of a power of two, i.e. 2, 4, 8, 16, 32 and so on.

The methods implementation in R is also neat, but requires some additional data transformation before it can be used. A useful function is contained in the waveslim package and is called mra (“multiresolution analysis”). It requires a differenced version of the time series and the depth of the decomposition.

# Load package
library(waveslim)

# Calculate first difference of log GDP
data <- data %>%
  mutate(dlgdp = lgdp - lag(lgdp, 1))

# Get data
y <- na.omit(data$dlgdp)

# Run the filter
wave_gdp <- mra(y, J = 5)

# Transform mra-output to data frame
wave_gdp <- as_tibble(wave_gdp)

# Create data frame for plotting
temp <- wave_gdp %>%
  gather(key = "imf", value = "value") %>%
  group_by(imf) %>%
  mutate(date = data$date[-1])

# Plot mra output
ggplot(temp, aes(x = date, y = value)) +
  geom_line() +
  facet_wrap( ~ imf, scales = "free") +
  labs(title = "Wavelets",
       x = "Quarter", y = "")

The function gives multiple series, which have to be cumulated with cumsum to translate them back into the level data. Maybe not surprisingly, the wavelet filter yields a similar result as the BK filter, since the upper bound of cycle periods is equal in both and the lower bound differs only by two - \(2^3 = 8\) compared to the \(6\) in the BK filter.

data <- data %>%
  mutate(wave = c(NA, cumsum(wave_gdp$D3 + wave_gdp$D4 + wave_gdp$D5)))

temp <- data %>%
  select(date, bk, wave) %>%
  gather(key = "Variable", value = "value", -date) %>%
  filter(!is.na(value)) %>%
  mutate(Variable = factor(Variable, levels = c("bk", "wave"),
                           labels = c("BK filter", "Wavelets")))

ggplot(temp, aes(x = date, y = value, colour = Variable)) +
  geom_hline(yintercept = 0, colour = "grey") +
  geom_line() +
  theme_classic() +
  labs(title = "Wavelets",
       x = "Quarter", y = "")

Empirical mode decomposition (EMD)

Kozic and Sever (2014) propose empirical mode decomposition as a further method of business cycle extraction as presented in Huang et al. (1998). The emd function can be found in the EMD package and requires a differenced time series, a boundary condition and a rule that specifies, at which point the iterative algorithm can stop. The results of this filter method are relatively different from the HP, BK and wavelet filter. It is the task of every researching to assess, whether working with this method is justified or not.

library(EMD)

y <- na.omit(data$lgdp)

# Run EMD
emd_gdp <- emd(xt = y, boundary = "none")

# Exctract the intrinsic mode functions
emd_gdp <- as_tibble(emd_gdp$imf)

# Create a data frame for plotting
temp <- emd_gdp %>%
  gather(key = "imf", value = "value") %>%
  group_by(imf) %>%
  mutate(date = data$date)

# Plot the EMD output
ggplot(temp, aes(x = date, y = value)) +
  geom_line() +
  facet_wrap( ~ imf) +
  labs(title = "Empirical mode decomposition",
       x = "Quarter", y = "")

# Add EMD output to main data frame
data <- data %>%
  mutate(emd = emd_gdp$V2)

# Create data frame for plotting
temp <- data %>%
  select(date, hp, emd) %>%
  gather(key = "Variable", value = "value", -date) %>%
  filter(!is.na(value)) %>%
  mutate(Variable = factor(Variable, levels = c("hp", "emd"),
                           labels = c("HP filter", "EMD")))

# Plot
ggplot(temp, aes(x = date, y = value, colour = Variable)) +
  geom_hline(yintercept = 0, colour = "grey") +
  geom_line() +
  theme_classic() +
  labs(title = "Empirical mode decomposition",
       x = "Qurarter", y = "")

References

Balcilar, M. (2018). mFilter: Miscellaneous Time Series Filters. R package version 0.1-4. https://CRAN.R-project.org/package=mFilter

Baxter, M., & King, R. O. (1999). Measuring Business Cycles: Approximate Band-Pass Filters for Economic Time Series. Review of Economics & Statistics, 81(4), 575–593.

Hamilton, J. D. (Forthcoming), Why you should never use the Hodrick-Prescott filter. Review of Economics and Statistics.

Kim, D. and Oh, H.-S. (2014). EMD: Empirical Mode Decomposition and Hilbert Spectral Analysis. R package version 1.5.7.

Kožić, I., & Sever, I. (2014). Measuring business cycles: Empirical Mode Decomposition of economic time series. Economics Letters, 123(3), 287–290. doi:10.1016/j.econlet.2014.03.009

McTaggart, R., Daroczi, G., & Leung, C. (2018). Quandl: API Wrapper for Quandl.com. R package version 2.9.1. https://CRAN.R-project.org/package=Quandl

Stock, J. H., & Watson, M. W. (1999). Business Cycle Fluctuations in US Macroeconomic Time Series. In J. B. Taylor & M. Woodford (Eds.), Handbook of Macroeconomics. Handbook of Macroeconomics (pp. 3–64). Elsevier.

Whitcher, B. (2015). waveslim: Basic wavelet routines for one-, two- and three-dimensional signal processing. R package version 1.7.5. https://CRAN.R-project.org/package=waveslim

Wickham, H. (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York.

Wickham, H., François, R., Henry, L., & Müller, K. (2018). dplyr: A Grammar of Data Manipulation. R package version 0.7.8. https://CRAN.R-project.org/package=dplyr

Yogo, M. (2008). Measuring business cycles: A wavelet analysis of economic time series. Economics Letters, 100(2), 208–212. doi:10.1016/j.econlet.2008.01.008