{"spec_id":"indicator-sma","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' indicator-sma: Simple Moving Average (SMA) Indicator Chart\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 86/100 | Created: 2026-05-19\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(tidyr)\nlibrary(scales)\nlibrary(ragg)\n\nset.seed(42)\n\n# Theme tokens\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nELEVATED_BG <- if (THEME == \"light\") \"#FFFDF6\" else \"#242420\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\n\nIMPRINT <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n               \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data: 500 trading days of simulated stock prices\nn_days <- 700L\nall_dates <- seq(as.Date(\"2022-01-03\"), by = \"day\", length.out = n_days)\ntrading_dates <- all_dates[!weekdays(all_dates) %in% c(\"Saturday\", \"Sunday\")]\ntrading_dates <- trading_dates[seq_len(500L)]\n\ndaily_returns <- rnorm(500L, mean = 0.0004, sd = 0.016)\nclose_price   <- 148.0 * cumprod(1 + daily_returns)\n\n# Rolling SMA helper\nsma <- function(x, k) {\n  out <- rep(NA_real_, length(x))\n  for (i in seq(k, length(x))) {\n    out[i] <- mean(x[(i - k + 1L):i])\n  }\n  out\n}\n\ndf <- data.frame(\n  date      = trading_dates,\n  Price     = close_price,\n  `SMA 20`  = sma(close_price, 20L),\n  `SMA 50`  = sma(close_price, 50L),\n  `SMA 200` = sma(close_price, 200L),\n  check.names = FALSE\n)\n\ndf_long <- tidyr::pivot_longer(df, cols = -date, names_to = \"series\", values_to = \"value\")\ndf_long$series <- factor(df_long$series, levels = c(\"Price\", \"SMA 20\", \"SMA 50\", \"SMA 200\"))\n\nseries_colors <- setNames(IMPRINT[1:4], c(\"Price\", \"SMA 20\", \"SMA 50\", \"SMA 200\"))\nseries_widths <- c(\"Price\" = 1.4, \"SMA 20\" = 1.0, \"SMA 50\" = 1.0, \"SMA 200\" = 1.0)\n\n# Plot\np <- ggplot(df_long, aes(x = date, y = value, color = series, linewidth = series)) +\n  geom_line(na.rm = TRUE) +\n  scale_color_manual(values = series_colors) +\n  scale_linewidth_manual(values = series_widths) +\n  scale_x_date(date_breaks = \"3 months\", date_labels = \"%b %Y\") +\n  scale_y_continuous(labels = scales::dollar_format(prefix = \"$\", accuracy = 1)) +\n  guides(linewidth = \"none\") +\n  labs(\n    title = \"Daily Close Price · indicator-sma · r · ggplot2 · anyplot.ai\",\n    x     = \"Date\",\n    y     = \"Price (USD)\",\n    color = NULL\n  ) +\n  theme_minimal(base_size = 14) +\n  theme(\n    plot.background    = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background   = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major.y = element_line(color = INK_SOFT, linewidth = 0.25),\n    panel.grid.major.x = element_blank(),\n    panel.grid.minor   = element_blank(),\n    axis.title         = element_text(color = INK,      size = 20),\n    axis.text          = element_text(color = INK_SOFT, size = 16),\n    axis.text.x        = element_text(angle = 30, hjust = 1),\n    axis.line.x        = element_line(color = INK_SOFT, linewidth = 0.4),\n    axis.line.y        = element_line(color = INK_SOFT, linewidth = 0.4),\n    plot.title         = element_text(color = INK,      size = 22, face = \"bold\"),\n    legend.background  = element_rect(fill = ELEVATED_BG, color = INK_SOFT, linewidth = 0.4),\n    legend.text        = element_text(color = INK_SOFT, size = 16),\n    legend.key         = element_rect(fill = NA),\n    legend.position    = \"top\",\n    legend.direction   = \"horizontal\"\n  )\n\n# Save\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 16,\n  height   = 9,\n  units    = \"in\",\n  dpi      = 300\n)\n"}