Setup and Data Preparation

— FIX: Explicitly read the data from the file —

The uploaded file ‘sp500_sampled data_2020_2024.txt’ is a CSV file.

sp500_data_raw <- read.csv(“sp500_sampled data_2020_2024.txt”, header = TRUE, sep = “,”) # — The original error (object ‘data_object’ not found) is now resolved. —

— Task 1: Data Wrangling (The “Pivot”) —

1. Pivot ROE columns from wide to long format

2. Extract the year from the ROE column name for the ‘Year’ column

sp500_data_long <- sp500_data_raw %>% pivot_longer( cols = starts_with(“ROE_”), # Select all columns starting with “ROE_” names_to = “Year_Col”, # Name for the new column holding the original column names values_to = “ROE” # Name for the new column holding the values ) %>% # Create a clean ‘Year’ column mutate( Year = as.integer(str_remove(Year_Col, “ROE_”)) # Remove “ROE_” and convert to integer ) %>% select(-Year_Col) # Remove the temporary column

— Task 2: Financial Logic Calculation —

1. Calculate the ‘Growth_Status’ based on EPS_2024 vs. EPS_2020

sp500_data_final <- sp500_data_raw %>% # Handle NA values in PE_Current for the scatter plot # Calculate 5-Year EPS Growth Rate and Growth Status mutate( # Simple label: “Growing” if EPS is higher in 2024 vs 2020 Growth_Status = ifelse( EPS_2024 > EPS_2020, “Growing”, “Declining” ), # Calculate 5-Year EPS Growth for the scatter plot # Use absolute value of EPS_2020 to handle negative starting earnings EPS_Growth_5Y = (EPS_2024 - EPS_2020) / abs(EPS_2020) )

Separate datasets for clarity in plotting

roe_data_for_plot <- sp500_data_long scatter_data_for_plot <- sp500_data_final # UI for the Shiny app fluidPage( titlePanel(“Value Investing Stock Screener: Compounders Dashboard”),

sidebarLayout( sidebarPanel( # Dropdown to select a specific company selectInput( “selected_company”, “Select Company for Trend Analysis:”, choices = unique(roe_data_for_plot$Company), selected = “Apple Inc.” # Default selection ), h5(“Objective: Identify ‘Compounders’ - stocks with Growing Earnings and stable/growing ROE.”), h5(paste0(“Total Companies Analyzed:”, nrow(sp500_data_final))) ),

mainPanel(
  # Main Panel (Top): ROE Trend Line Chart
  h3("5-Year Return on Equity (ROE) Trend"),
  plotOutput("roe_trend_plot"),

  hr(), # Horizontal rule to separate the plots

  # Main Panel (Bottom): PE vs. EPS Growth Scatter Plot
  h3("Valuation vs. Growth: P/E Ratio vs. 5-Year EPS Growth"),
  plotOutput("pe_growth_scatter")
)

) ) # Server logic for the Shiny app function(input, output) {

# Reactive subset for the ROE Line Chart company_roe_data <- reactive({ roe_data_for_plot %>% filter(Company == input$selected_company) })

# Render the ROE Trend Line Chart (Main Panel Top) output$roe_trend_plot <- renderPlot({

# Get the data for the selected company
data <- company_roe_data()

# Fetch the calculated growth status for labeling
growth_status <- scatter_data_for_plot %>%
  filter(Company == input$selected_company) %>%
  pull(Growth_Status)

# Create the ggplot line chart
ggplot(data, aes(x = Year, y = ROE)) +
  geom_line(color = "dodgerblue4", size = 1.2) +
  geom_point(color = "dodgerblue4", size = 3) +
  geom_text(aes(label = paste0(round(ROE*100, 1), "%")), vjust = -1) +
  labs(
    title = paste("ROE Trend for", input$selected_company),
    subtitle = paste("EPS Growth Status (2020-2024):", growth_status),
    x = "Fiscal Year",
    y = "Return on Equity (ROE)"
  ) +
  theme_minimal() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(breaks = unique(data$Year))

})

# Render the P/E vs. EPS Growth Scatter Plot (Main Panel Bottom) output$pe_growth_scatter <- renderPlot({

# Determine the color based on 'Growth_Status'
color_scheme <- c("Growing" = "darkgreen", "Declining" = "firebrick")

# Define a variable for the selected company for highlighting
scatter_data_for_plot_viz <- scatter_data_for_plot %>%
  mutate(
    Highlight = ifelse(Company == input$selected_company, input$selected_company, "Other")
  ) %>%
  # Remove rows where PE_Current is NA (e.g., Boeing)
  filter(!is.na(PE_Current))


# Create the ggplot scatter plot
ggplot(scatter_data_for_plot_viz, aes(x = EPS_Growth_5Y, y = PE_Current, color = Growth_Status, size = abs(EPS_Growth_5Y))) +
  geom_point(alpha = 0.7) +
  # Highlight the selected company
  geom_point(data = filter(scatter_data_for_plot_viz, Highlight != "Other"),
             aes(x = EPS_Growth_5Y, y = PE_Current),
             color = "black", size = 5, shape = 21, stroke = 1.5) +

  # Add company labels for the selected one
  geom_text(data = filter(scatter_data_for_plot_viz, Highlight != "Other"),
            aes(label = Symbol),
            vjust = 2, hjust = 0.5, color = "black", size = 4) +

  labs(
    title = "P/E Ratio vs. 5-Year EPS Growth",
    subtitle = "Identify potential 'Compounders' (Growing Status, Low/Stable P/E)",
    x = "5-Year EPS Growth Rate (%) (2020 to 2024)",
    y = "Current P/E Ratio"
  ) +
  scale_color_manual(values = color_scheme) +
  scale_x_continuous(labels = scales::percent) +
  scale_size_continuous(guide = "none") + # Hide the size legend
  theme_classic() +
  # Add vertical line at 0 for growth
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray50")

}) }