Overview

In this post, we will calculate a Diffusion Index for the U.S. economy using three key economic indicators:

  1. Average Hourly Earnings (AHE)
  2. Total Nonfarm Employment (CTNA)
  3. Business Applications (BUSAPP)

We will compare this Diffusion Index with the Chicago Federal Reserve’s National Activity Index (CFNAIDIFF) to evaluate the current economic situation and make predictions about future trends.

Environment Setup

First, we will load the required libraries and set up our working environment.

Retrieving Economic Data

To construct the Diffusion Index, we will download the following economic data series from FRED (Federal Reserve Economic Data):

# Fetch the relevant economic data from FRED
getSymbols(c("BUSAPPWNSACT", "CTNA", "SMU09000000500000003"), 
           freq = "monthly", 
           src = "FRED", return.class = 'xts',
           index.class  = 'Date', 
           from = "2010-01-01", 
           to = Sys.Date(), 
           periodicity = "monthly")
## [1] "BUSAPPWNSACT"         "CTNA"                 "SMU09000000500000003"
# Display the first few rows of the datasets
head(SMU09000000500000003, 3)
##            SMU09000000500000003
## 2010-01-01                27.75
## 2010-02-01                28.22
## 2010-03-01                28.03
head(CTNA, 3)
##              CTNA
## 2010-01-01 1601.0
## 2010-02-01 1601.8
## 2010-03-01 1603.7
head(BUSAPPWNSACT, 3)
##            BUSAPPWNSACT
## 2010-01-02          320
## 2010-01-09          320
## 2010-01-16          590

Data Preparation

We will process the data by extracting monthly values for each of the economic variables and computing their first differences (monthly changes).

# Extract monthly values for each variable
biz = to.monthly(BUSAPPWNSACT)[,4]
## Warning in to.period(x, "months", indexAt = indexAt, name = name, ...): missing
## values removed from data
ct_ctna = CTNA
us_emp = SMU09000000500000003

# Limit the data range for visual clarity
biz_ss <- biz["2010-01-31/2024-09-01"] |> ts_ts()
us_ss <- us_emp["2010-01-31/2024-09-01"] |> ts_ts()
ctna_ss <- ct_ctna["2010-01-31/2024-09-01"] |> ts_ts()

# Combine the data into a data frame
mydata = cbind.data.frame(biz_ss, us_ss, ctna_ss)

# Compute first differences (monthly changes)
mydf = mydata %>% 
  mutate(bizD1 = tsibble::difference(biz_ss, differences = 1),
         usD1 = tsibble::difference(us_ss, differences = 1),
         ctD1 = tsibble::difference(ctna_ss, differences = 1)
  ) %>% dplyr::select(c(bizD1, usD1, ctD1)) |> na.omit()
## Registered S3 method overwritten by 'tsibble':
##   method               from 
##   as_tibble.grouped_df dplyr
# Inspect the first differences
head(mydf, 3)
##   bizD1  usD1 ctD1
## 2    80 -0.19  1.9
## 3    20  0.40  9.2
## 4   -30  0.00  8.9

Constructing the Diffusion Index

The next step is to calculate the Diffusion Index. For each time period, we classify the change in each variable as either “up” (positive change), “down” (negative change), or “no change” (zero change). The Diffusion Index is then computed as the difference between the proportion of variables showing an upward trend and those showing a downward trend.

# Convert first differences into "up", "down", or "no change"
mydf_mat = apply(mydf, 2, sign)

# Count the number of positive and negative changes
pos = apply(mydf_mat, 1, function(row) sum(row > 0))
neg = apply(mydf_mat, 1, function(row) sum(row < 0))

# Total number of changes
tot = pos + neg

# Calculate the Diffusion Index
index = (pos / tot - neg / tot) * 100

# Visualize the Diffusion Index
plot(index, type = "l", main = "U.S. Economic Diffusion Index", 
     ylab = "Index Value", xlab = "Time")
abline(h = 0, col = "darkred")

Smoothing the Diffusion Index

To better observe the overall trends, we apply a 7-month moving average to the Diffusion Index.

# Apply 7-month moving average
ma_index = zoo::rollmean(index, 7, align = "right")

# Create a date sequence for plotting
Date <- seq.Date(from = as.Date("2010-05-01"), length.out = 175, by = "month")

# Combine Date and Diffusion Index into a data frame
data <- data.frame(Date = Date, Index = index)

# Plot the Diffusion Index with the smoothed trend
ggplot(data, aes(x = Date, y = Index)) + 
  geom_line() + 
  geom_smooth(colour = "blue") +  # Smoothed trend line
  labs(title = "U.S. Economic Diffusion Index", 
       x = "Months", 
       y = "Index Value") + 
  theme(axis.line.x = element_line(size = 0.75, colour = "red"),
        axis.line.y = element_line(size = 0.75, colour = "red"),
        legend.position = "bottom", 
        legend.direction = "horizontal") + 
  theme_tufte()
## Warning: The `size` argument of `element_line()` is deprecated as of ggplot2 3.4.0.
## ℹ Please use the `linewidth` argument instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Comparison with the Chicago Fed National Activity Index (CFNAIDIFF)

To assess how the Diffusion Index aligns with a well-established economic indicator, we will compare it with the Chicago Fed National Activity Index (CFNAIDIFF).

# Download CFNAIDIFF data from FRED
getSymbols("CFNAIDIFF", src = "FRED", from = "2010-01-01", to = Sys.Date())
## [1] "CFNAIDIFF"
# Extract CFNAIDIFF and limit the date range
cfna_diff = CFNAIDIFF["2010-01-01/2024-09-01"] |> ts_ts()

# Trim the Date sequence to match the length of CFNAIDIFF
Date_trimmed <- seq.Date(from = as.Date("2010-01-01"), length.out = length(coredata(cfna_diff)), by = "month")

# Adjust the Diffusion Index to match CFNAIDIFF's length
index_trimmed <- index[1:length(coredata(cfna_diff))]

# Create a comparison data frame
df_comparison = data.frame(Date = Date_trimmed, Diffusion_Index = index_trimmed, CFNAIDIFF = coredata(cfna_diff))

# Plot both the Diffusion Index and CFNAIDIFF
ggplot(df_comparison, aes(x = Date)) +
  geom_line(aes(y = Diffusion_Index, color = "Diffusion Index")) + 
  geom_line(aes(y = CFNAIDIFF, color = "CFNAIDIFF")) + 
  labs(title = "Diffusion Index vs CFNAIDIFF", 
       x = "Date", 
       y = "Index Value") +
  scale_color_manual(values = c("Diffusion Index" = "green", "CFNAIDIFF" = "red")) + 
  theme_minimal()
## Warning: Removed 2 rows containing missing values or values outside the scale range
## (`geom_line()`).

# Calculate and display the correlation between the two indices
cor(index_trimmed, coredata(cfna_diff), use = "complete.obs")
## [1] 0.008485195

Conclusion

The Diffusion Index provides a useful measure of the U.S. economy’s broad trends. By comparing it with the Chicago Fed National Activity Index (CFNAIDIFF), we observe similar patterns, suggesting that the Diffusion Index can be a valuable tool for assessing economic activity. The correlation between the two indices offers further insight into how well the Diffusion Index reflects national economic conditions.

Based on the latest data, both indices suggest that the U.S. economy is stabilizing, indicating a period of steady economic performance.

References