{"spec_id":"renko-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' renko-basic: Basic Renko Chart\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 82/100 | Created: 2026-05-17\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(ragg)\n\nset.seed(42)\n\n# --- Theme tokens -----------------------------------------------------------\nTHEME       <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG     <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK         <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT    <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\n\n# Color palette\nBULL        <- \"#009E73\"  # Okabe-Ito position 1 (green)\nBEAR        <- \"#AE3030\"  # imprint red — bearish\n\n# --- Data generation --------------------------------------------------------\n# Generate synthetic stock price data\nn <- 250\ndates <- seq.Date(as.Date(\"2024-01-01\"), length.out = n, by = \"day\")\nprices <- 100 + cumsum(rnorm(n, 0, 0.8))\n\ndf_prices <- data.frame(date = dates, close = prices)\n\n# --- Renko brick calculation -----------------------------------------------\nbrick_size <- 2.0\n\ncalculate_renko <- function(prices, brick_size) {\n  bricks <- list()\n  brick_count <- 0\n  current_level <- floor(prices[1] / brick_size) * brick_size\n  direction <- 0  # 0 = start, 1 = up, -1 = down\n\n  for (i in seq_along(prices)) {\n    price <- prices[i]\n\n    while (price >= current_level + brick_size) {\n      brick_count <- brick_count + 1\n      new_direction <- 1\n      if (direction == 1) {\n        bricks[[brick_count]] <- list(\n          brick_num = brick_count,\n          open = current_level,\n          close = current_level + brick_size,\n          direction = \"up\"\n        )\n      } else {\n        bricks[[brick_count]] <- list(\n          brick_num = brick_count,\n          open = current_level,\n          close = current_level + brick_size,\n          direction = \"up\"\n        )\n      }\n      direction <- 1\n      current_level <- current_level + brick_size\n    }\n\n    while (price <= current_level - brick_size) {\n      brick_count <- brick_count + 1\n      if (direction == -1) {\n        bricks[[brick_count]] <- list(\n          brick_num = brick_count,\n          open = current_level,\n          close = current_level - brick_size,\n          direction = \"down\"\n        )\n      } else {\n        bricks[[brick_count]] <- list(\n          brick_num = brick_count,\n          open = current_level,\n          close = current_level - brick_size,\n          direction = \"down\"\n        )\n      }\n      direction <- -1\n      current_level <- current_level - brick_size\n    }\n  }\n\n  do.call(rbind, lapply(bricks, function(x) {\n    data.frame(\n      brick_num = x$brick_num,\n      open = x$open,\n      close = x$close,\n      direction = x$direction,\n      stringsAsFactors = FALSE\n    )\n  }))\n}\n\nrenko_bricks <- calculate_renko(df_prices$close, brick_size)\n\n# Calculate dimensions for visualization\nrenko_bricks <- renko_bricks %>%\n  mutate(\n    x_min = brick_num - 0.4,\n    x_max = brick_num + 0.4,\n    y_min = pmin(open, close),\n    y_max = pmax(open, close)\n  )\n\n# --- Plot -------------------------------------------------------------------\np <- ggplot(renko_bricks, aes(fill = direction)) +\n  geom_rect(\n    aes(xmin = x_min, xmax = x_max, ymin = y_min, ymax = y_max),\n    color = INK_SOFT,\n    linewidth = 0.3\n  ) +\n  scale_fill_manual(\n    values = c(\"up\" = BULL, \"down\" = BEAR),\n    guide = \"none\"\n  ) +\n  labs(\n    title = \"renko-basic · ggplot2 · anyplot.ai\",\n    x = \"Brick Index\",\n    y = \"Price ($)\"\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 = element_line(color = INK, linewidth = 0.3),\n    panel.grid.minor = element_blank(),\n    panel.border = element_rect(color = INK_SOFT, fill = NA, linewidth = 0.5),\n    axis.title = element_text(color = INK, size = 20),\n    axis.text = element_text(color = INK_SOFT, size = 16),\n    plot.title = element_text(color = INK, size = 24, face = \"plain\"),\n    legend.position = \"none\"\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"}