{"spec_id":"histogram-returns-distribution","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' histogram-returns-distribution: Returns Distribution Histogram\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 92/100 | Created: 2026-05-20\n\nlibrary(ggplot2)\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\"\nIMPRINT   <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                 \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data - 2 years of daily returns for a diversified equity portfolio\nn     <- 504\nmu    <- 0.10 / 252        # 10% annual return (daily)\nsigma <- 0.18 / sqrt(252)  # 18% annual volatility (daily)\n\nbase_returns          <- rnorm(n, mean = mu, sd = sigma)\nfat_idx               <- sample(n, 14)\nbase_returns[fat_idx] <- base_returns[fat_idx] * 2.6\nreturns_pct           <- base_returns * 100\n\n# Summary statistics\nmean_ret <- mean(returns_pct)\nsd_ret   <- sd(returns_pct)\nskew_ret <- mean((returns_pct - mean_ret)^3) / sd_ret^3\nkurt_ret <- mean((returns_pct - mean_ret)^4) / sd_ret^4 - 3\n\n# Pre-compute histogram for per-bin tail coloring\nh       <- hist(returns_pct, breaks = 40, plot = FALSE)\nbin_w   <- diff(h$breaks)[1]\ndf_hist <- data.frame(\n  mid     = h$mids,\n  density = h$density,\n  tail    = abs(h$mids - mean_ret) > 2 * sd_ret\n)\n\n# Normal distribution overlay\nx_seq   <- seq(min(h$breaks), max(h$breaks), length.out = 500)\ndf_norm <- data.frame(x = x_seq, y = dnorm(x_seq, mean = mean_ret, sd = sd_ret))\n\n# Statistics annotation (top-right, above the tail region)\nstats_txt <- sprintf(\n  \"Mean:      %+.3f%%\\nStd Dev:    %.3f%%\\nSkewness: %+.2f\\nEx. Kurt:  %+.2f\",\n  mean_ret, sd_ret, skew_ret, kurt_ret\n)\nann_x <- max(h$mids)\nann_y <- max(h$density) * 0.93\n\n# Plot\np <- ggplot(df_hist, aes(x = mid, y = density, fill = tail)) +\n  geom_col(width = bin_w * 0.90, color = PAGE_BG, linewidth = 0.2, alpha = 0.85) +\n  scale_fill_manual(\n    values = c(\"FALSE\" = IMPRINT[1], \"TRUE\" = IMPRINT[2]),\n    labels = c(\"FALSE\" = \"Within ±2σ\", \"TRUE\" = \"Beyond ±2σ\"),\n    name   = NULL\n  ) +\n  geom_line(\n    data = df_norm, aes(x = x, y = y), inherit.aes = FALSE,\n    color = IMPRINT[3], linewidth = 1.2\n  ) +\n  geom_vline(\n    xintercept = c(mean_ret - 2 * sd_ret, mean_ret + 2 * sd_ret),\n    color      = IMPRINT[2], linewidth = 0.7, linetype = \"dashed\", alpha = 0.7\n  ) +\n  annotate(\"label\",\n    x = ann_x, y = ann_y,\n    label         = stats_txt,\n    hjust         = 1, vjust = 1,\n    color         = INK,\n    fill          = ELEVATED_BG,\n    label.padding = unit(0.45, \"lines\"),\n    label.size    = 0.3,\n    size          = 3.9\n  ) +\n  scale_x_continuous(labels = function(x) paste0(x, \"%\")) +\n  labs(\n    title = \"histogram-returns-distribution · r · ggplot2 · anyplot.ai\",\n    x     = \"Daily Return (%)\",\n    y     = \"Density\"\n  ) +\n  theme_minimal(base_size = 8) +\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  = element_line(color = INK_SOFT, linewidth = 0.15),\n    panel.grid.minor  = element_blank(),\n    panel.border      = element_blank(),\n    axis.line         = element_line(color = INK_SOFT, linewidth = 0.4),\n    axis.ticks        = element_blank(),\n    axis.title        = element_text(color = INK,      size = 10),\n    axis.text         = element_text(color = INK_SOFT, size = 8),\n    plot.title        = element_text(color = INK,      size = 12, hjust = 0),\n    legend.background = element_rect(fill = ELEVATED_BG, color = NA, linewidth = 0),\n    legend.text       = element_text(color = INK_SOFT, size = 8),\n    legend.position   = \"bottom\",\n    legend.key.size   = unit(0.5, \"cm\"),\n    plot.margin       = margin(0.5, 0.7, 0.3, 0.5, \"cm\")\n  )\n\n# Save\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot     = p,\n  device   = ragg::agg_png,\n  width    = 8,\n  height   = 4.5,\n  units    = \"in\",\n  dpi      = 400\n)\n"}