{"spec_id":"candlestick-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' candlestick-basic: Basic Candlestick Chart\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 91/100 | Created: 2026-05-30\n\nlibrary(ggplot2)\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\n# Imprint palette — semantic finance mapping (position 1: gain, position 5: loss)\nBULL_COLOR <- \"#009E73\"  # bullish / gain\nBEAR_COLOR <- \"#AE3030\"  # bearish / loss\n\n# --- Data --------------------------------------------------------------------\n# NovaTech Corp (NVTK) — 40 trading days, Jan–Mar 2024\nall_dates   <- seq(as.Date(\"2024-01-02\"), by = \"day\", length.out = 60)\ntrade_dates <- all_dates[!weekdays(all_dates) %in% c(\"Saturday\", \"Sunday\")]\ntrade_dates <- head(trade_dates, 40)\nn           <- length(trade_dates)\n\nprice  <- 148.0\nopens  <- numeric(n)\nhighs  <- numeric(n)\nlows   <- numeric(n)\ncloses <- numeric(n)\n\nfor (i in seq_len(n)) {\n    daily_range <- runif(1, 1.5, 4.5)\n    open_i      <- price + rnorm(1, 0, 0.5)\n    close_i     <- open_i + rnorm(1, 0.2, daily_range * 0.45)\n    high_i      <- max(open_i, close_i) + runif(1, 0.2, daily_range * 0.35)\n    low_i       <- min(open_i, close_i) - runif(1, 0.2, daily_range * 0.35)\n    opens[i]    <- open_i\n    highs[i]    <- high_i\n    lows[i]     <- low_i\n    closes[i]   <- close_i\n    price       <- close_i\n}\n\ndf <- data.frame(\n    date      = trade_dates,\n    x         = seq_len(n),\n    open      = opens,\n    high      = highs,\n    low       = lows,\n    close     = closes\n)\ndf$direction   <- ifelse(df$close >= df$open, \"up\", \"down\")\ndf$body_top    <- pmax(df$open, df$close)\ndf$body_bottom <- pmin(df$open, df$close)\ndf$xmin        <- df$x - 0.38\ndf$xmax        <- df$x + 0.38\n\n# Closing price trend line (linear fit) for visual storytelling\ntrend_fit <- lm(close ~ x, data = df)\ntrend_y   <- fitted(trend_fit)\n\n# --- X-axis breaks -----------------------------------------------------------\nbreak_idx    <- seq(1, n, by = 5)\nbreak_labels <- format(trade_dates[break_idx], \"%b %d\")\n\n# --- Plot --------------------------------------------------------------------\np <- ggplot(df) +\n    # High-low wicks\n    geom_segment(\n        aes(x = x, xend = x, y = low, yend = high, color = direction),\n        linewidth = 0.45, show.legend = FALSE\n    ) +\n    # Subtle trend overlay (closing prices)\n    geom_line(\n        data = data.frame(x = df$x, close = trend_y),\n        aes(x = x, y = close),\n        color = INK_SOFT, linewidth = 0.5, linetype = \"dashed\",\n        inherit.aes = FALSE, alpha = 0.55\n    ) +\n    # Open-close bodies\n    geom_rect(\n        aes(xmin = xmin, xmax = xmax, ymin = body_bottom, ymax = body_top,\n            fill = direction, color = direction),\n        linewidth = 0.2\n    ) +\n    scale_color_manual(\n        values = c(\"up\" = BULL_COLOR, \"down\" = BEAR_COLOR),\n        guide  = \"none\"\n    ) +\n    scale_fill_manual(\n        values = c(\"up\" = BULL_COLOR, \"down\" = BEAR_COLOR),\n        labels = c(\"up\" = \"Bullish\", \"down\" = \"Bearish\"),\n        breaks = c(\"up\", \"down\"),\n        name   = NULL\n    ) +\n    scale_x_continuous(\n        breaks = break_idx,\n        labels = break_labels,\n        expand = expansion(mult = c(0.02, 0.02))\n    ) +\n    scale_y_continuous(\n        labels = label_dollar(accuracy = 0.01),\n        expand = expansion(mult = c(0.03, 0.04))\n    ) +\n    labs(\n        title = \"NovaTech Corp (NVTK) · candlestick-basic · r · ggplot2 · anyplot.ai\",\n        x     = NULL,\n        y     = \"Price (USD)\"\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.y = element_line(color = INK_SOFT,   linewidth = 0.2),\n        panel.grid.major.x = element_blank(),\n        panel.grid.minor   = element_blank(),\n        axis.title         = element_text(color = INK,        size = 10),\n        axis.text          = element_text(color = INK_SOFT,   size = 8),\n        axis.text.x        = element_text(angle = 40, hjust = 1),\n        axis.line          = element_line(color = INK_SOFT,   linewidth = 0.3),\n        axis.ticks         = element_line(color = INK_SOFT,   linewidth = 0.3),\n        plot.title         = element_text(color = INK,        size = 12,\n                                          margin = margin(b = 8)),\n        legend.background  = element_rect(fill = ELEVATED_BG, color = INK_SOFT,\n                                          linewidth = 0.3),\n        legend.text        = element_text(color = INK_SOFT,   size = 8),\n        legend.key.size    = unit(0.9, \"lines\"),\n        legend.position    = \"top\",\n        legend.direction   = \"horizontal\",\n        plot.margin        = margin(t = 10, r = 14, b = 8, l = 8)\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"}