{"spec_id":"renko-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nrenko-basic: Basic Renko Chart\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\nfrom lets_plot import element_blank, element_line, element_rect, element_text, theme\nfrom lets_plot.export import ggsave\n\n\nLetsPlot.setup_html()\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nRULE = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\n# Okabe-Ito palette (bullish: position 1, bearish: position 2 for better accessibility)\nBULLISH = \"#009E73\"  # Okabe-Ito position 1\nBEARISH = \"#AE3030\"  # imprint red — bearish\n\n# Generate synthetic stock price data\nnp.random.seed(42)\nn_days = 200\ndates = pd.date_range(\"2024-01-01\", periods=n_days, freq=\"D\")\nreturns = np.random.normal(0.001, 0.02, n_days)\nprices = 100 * np.exp(np.cumsum(returns))\n\n# Renko brick calculation\nbrick_size = 2.0  # $2 brick size\nrenko_bricks = []\ncurrent_price = prices[0]\nbrick_base = (current_price // brick_size) * brick_size\ndirection = None\n\nfor price in prices:\n    while price >= brick_base + brick_size:\n        new_base = brick_base + brick_size\n        renko_bricks.append(\n            {\"brick_index\": len(renko_bricks), \"open\": brick_base, \"close\": new_base, \"direction\": \"bullish\"}\n        )\n        brick_base = new_base\n        direction = \"bullish\"\n\n    while price <= brick_base - brick_size:\n        new_base = brick_base - brick_size\n        renko_bricks.append(\n            {\"brick_index\": len(renko_bricks), \"open\": brick_base, \"close\": new_base, \"direction\": \"bearish\"}\n        )\n        brick_base = new_base\n        direction = \"bearish\"\n\n# Create DataFrame for plotting\ndf_renko = pd.DataFrame(renko_bricks)\n\n# Calculate brick positions for visualization\ndf_renko[\"x\"] = df_renko[\"brick_index\"]\ndf_renko[\"y_min\"] = df_renko[[\"open\", \"close\"]].min(axis=1)\ndf_renko[\"y_max\"] = df_renko[[\"open\", \"close\"]].max(axis=1)\ndf_renko[\"y_center\"] = (df_renko[\"y_min\"] + df_renko[\"y_max\"]) / 2\ndf_renko[\"height\"] = brick_size\n\n# Create Renko chart\nplot = (\n    ggplot(df_renko, aes(x=\"x\", y=\"y_center\", fill=\"direction\"))\n    + geom_tile(aes(height=\"height\"), width=0.85, color=\"white\", size=0.5)\n    + scale_fill_manual(\n        values={\"bullish\": BULLISH, \"bearish\": BEARISH}, name=\"Direction\"\n    )\n    + labs(x=\"Brick Index\", y=\"Price ($)\", title=\"renko-basic · letsplot · anyplot.ai\")\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_grid_major=element_line(color=INK, size=0.2),\n        panel_grid_minor=element_blank(),\n        axis_title=element_text(size=20, color=INK),\n        axis_text=element_text(size=16, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT),\n        plot_title=element_text(size=24, color=INK),\n        legend_background=element_rect(fill=PAGE_BG, color=INK_SOFT),\n        legend_text=element_text(size=16, color=INK_SOFT),\n        legend_title=element_text(size=18, color=INK),\n        legend_position=\"right\",\n    )\n    + ggsize(1600, 900)\n)\n\n# Save as PNG (scale 3x for 4800 × 2700 px)\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=3)\n\n# Save as HTML for interactive viewing\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}