Introduction

Understanding the dynamics of the U.S. economy requires both national and localized perspectives. This study constructs a diffusion index using data on employment, industrial production, and consumer sentiment. By capturing the proportion of improving economic indicators, the diffusion index provides insights into trends in economic activity. It is then compared with the Chicago Fed National Activity Diffusion Index (CFNAIDIFF) to identify patterns of growth and contraction over time. This comparison highlights alignments and deviations, offering a comprehensive view of economic performance and its underlying drivers. The analysis serves as a tool to assess broader economic trends and localized conditions.

Data selection and Diffusion Index Construction.

The diffusion index reflects economic expansion and contraction based on pulling data for three selected variables. Here selected variables are Employment, industrial production, and housing starts.

suppressWarnings({
  suppressPackageStartupMessages({
    library(tidyverse)
    library(quantmod)
    library(tsbox)
    library(zoo)
  })
})

options(digits = 3, scipen = 99999)
graphics.off()
# Load economic variables
getSymbols(c("PAYEMS", "INDPRO", "HOUST"),
           src = "FRED", return.class = 'xts', 
           from = "2010-01-01", to = Sys.Date())
## [1] "PAYEMS" "INDPRO" "HOUST"

Comparison of Custom Diffusion Index and CFNAIDIFF

# Data preprocessing
employment <- PAYEMS
industrial_production <- INDPRO
housing  <- HOUST

employment_ss <- employment["2010-01-31/2024-09-01"] |> ts_ts()
industrial_ss <- industrial_production["2010-01-31/2024-09-01"] |> ts_ts()
housing_ss <- housing["2010-01-31/2024-09-01"] |> ts_ts()

mydata <- cbind.data.frame(employment_ss, industrial_ss, housing_ss)

mydf <- mydata %>%
  mutate(
    emp_diff = tsibble::difference(employment_ss, differences = 1),
    ind_diff = tsibble::difference(industrial_ss, differences = 1),
    house_diff = tsibble::difference(housing_ss, differences = 1)
  ) %>%
  dplyr::select(emp_diff, ind_diff, house_diff) %>%
  na.omit()

Visual Observations (First Plot):

# Construct diffusion index
mydf_mat <- apply(mydf, 2, sign)
pos <- apply(mydf_mat, 1, function(row) sum(row > 0))
neg <- apply(mydf_mat, 1, function(row) sum(row < 0))
tot <- pos + neg
index <- (pos / tot - neg / tot) * 100
ma_index <- rollmean(index, 7, align = "right", na.pad = TRUE)

Date <- seq.Date(from = as.Date("2010-05-01"), length.out = length(index), by = "month")
diffusion_df <- cbind.data.frame(Date, index, ma_index)

ggplot(diffusion_df, aes(x = Date, y = index)) +
  # Line for the diffusion index
  geom_line(color = "pink", size = 0.8) +
  # Smoothed trend line with transparency
  geom_smooth(color = "orange", fill = "blue", alpha = 0.3, size = 1.2) +
  # Adding labels to key points
  geom_text(data = diffusion_df[c(1, nrow(diffusion_df)), ],
            aes(label = paste0(round(index, 2), "%")), 
            vjust = -1, size = 3.5, fontface = "bold", color = "yellow") +
  # Adding a horizontal reference line
  geom_hline(yintercept = 0, linetype = "dashed", color = "black", size = 0.8) +
  # Vertical line for a key event (e.g., COVID-19)
  geom_vline(xintercept = as.Date("2020-03-01"), linetype = "dotted", color = "green", size = 1) +
  annotate("text", x = as.Date("2020-03-01"), y = -90, 
           label = "COVID-19", color = "green", size = 4, hjust = 0, angle = 90) +
  # Title, subtitle, and axis labels
  labs(
    title = "U.S. Economic Diffusion Index Over Time",
    subtitle = "Analyzing economic trends",
    x = "Year",
    y = "Diffusion Index (%)"
  ) +
  # Adjust y-axis limits to zoom out
  scale_y_continuous(limits = c(-120, 120)) +
  # Enhance visual appearance with themes
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(size = 20, face = "bold", hjust = 0.5, color = "brown"),
    plot.subtitle = element_text(size = 14, face = "italic", hjust = 0.5, color = "darkblue"),
    axis.title.x = element_text(size = 14, face = "bold", color = "black"),
    axis.title.y = element_text(size = 14, face = "bold", color = "black"),
    axis.text = element_text(size = 12, color = "black"),
    panel.grid.major = element_line(color = "gray", size = 0.5),
    panel.grid.minor = element_blank(),
    legend.position = "none",
    plot.background = element_rect(fill = "white", color = "white")
  )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## 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'

Long-Term Trend in Diffusion Index

# Load CFNAIDIFF
getSymbols("CFNAIDIFF", src = "FRED", return.class = 'xts', from = "2010-01-01")
## [1] "CFNAIDIFF"
cfnaidiff_ss <- CFNAIDIFF["2010-05-01/2024-09-01"] |> ts_ts()
min_length <- min(length(ma_index), length(cfnaidiff_ss))
ma_index <- ma_index[1:min_length]
cfnaidiff_ss <- cfnaidiff_ss[1:min_length]
Date <- Date[1:min_length]

# Prepare the comparison data frame
compare_df <- cbind.data.frame(Date, diffusion_index = ma_index, CFNAIDIFF = cfnaidiff_ss)

correlation <- cor(compare_df$diffusion_index, compare_df$CFNAIDIFF, use = "complete.obs")

# Enhanced comparison plot with interactivity
plotly::ggplotly(
  ggplot() +
    geom_line(data = compare_df, aes(x = Date, y = diffusion_index, color = "Diffusion Index"), size = 1.2) +
    geom_line(data = compare_df, aes(x = Date, y = CFNAIDIFF * 100, color = "CFNAIDIFF"), size = 1.2, linetype = "dashed") +
    scale_color_manual(
      values = c("Diffusion Index" = "violet", "CFNAIDIFF" = "red")
    ) +
    labs(
      title = "Comparison of Diffusion Index and CFNAIDIFF",
      x = "Year",
      y = "Index Value",
      color = "Legend"
    ) +
    theme_minimal(base_size = 8) +
    theme(
      plot.title = element_text(size = 10, face = "bold", hjust = 0.5),
      legend.position = "bottom"
    )
)

Key Economic Insights

Recent Economic Conditions (Post-September 2024)

Conclusion

The Diffusion Index reveals significant economic fluctuations, recently driven by declines in employment, industrial production, and consumer sentiment. In contrast, the CFNAIDIFF exhibits steadier national activity with lower volatility. A weak correlation of 0.157 underscores their differing focuses: the Diffusion Index is more responsive to localized economic shifts, while CFNAIDIFF reflects broader national trends. This divergence suggests that the Diffusion Index signals regional or sectoral weaknesses, whereas CFNAIDIFF indicates a stable national economy with no widespread contraction. Together, these indexes provide complementary insights, highlighting localized vulnerabilities against a backdrop of steady national economic conditions.