{"spec_id":"candlestick-volume","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\ncandlestick-volume: Stock Candlestick Chart with Volume\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 91/100 | Created: 2026-05-16\n\"\"\"\n\nimport sys\n\n\n# Remove the current directory from sys.path to avoid shadowing the installed plotnine package\nwhile \"\" in sys.path:\n    sys.path.remove(\"\")\ncwd = __file__[: __file__.rfind(\"/\")]\nwhile cwd in sys.path:\n    sys.path.remove(cwd)\n\n# Now import plotnine\nimport os\n\nimport numpy as np\nimport pandas as pd\n\nfrom plotnine import (\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    facet_grid,\n    geom_col,\n    geom_rect,\n    geom_segment,\n    ggplot,\n    ggsave,\n    labs,\n    scale_color_manual,\n    scale_fill_manual,\n    theme,\n    theme_minimal,\n)\n\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\"\n\n# imprint semantic anchors: Up (green), Down (red)\nUP_COLOR = \"#009E73\"\nDOWN_COLOR = \"#AE3030\"\n\n# Generate realistic OHLC data\nnp.random.seed(42)\nn_periods = 60\ndates = pd.date_range(\"2024-01-01\", periods=n_periods, freq=\"D\")\n\n# Create price movement with realistic patterns\nreturns = np.random.normal(0.001, 0.02, n_periods)\nclose_prices = 100 * np.exp(np.cumsum(returns))\nopen_prices = close_prices * (1 + np.random.normal(0, 0.01, n_periods))\nhigh_prices = np.maximum(open_prices, close_prices) + np.abs(np.random.normal(0, 0.5, n_periods))\nlow_prices = np.minimum(open_prices, close_prices) - np.abs(np.random.normal(0, 0.5, n_periods))\nvolumes = np.random.exponential(1e6, n_periods)\n\n# Create main dataframe\ndf = pd.DataFrame(\n    {\n        \"date\": dates,\n        \"open\": open_prices,\n        \"high\": high_prices,\n        \"low\": low_prices,\n        \"close\": close_prices,\n        \"volume\": volumes,\n    }\n)\n\n# Add direction (up/down) and position columns for rectangles\ndf[\"direction\"] = df[\"close\"] >= df[\"open\"]\ndf[\"direction_label\"] = df[\"direction\"].map({True: \"Up\", False: \"Down\"})\ndf[\"x_min\"] = df[\"date\"] - pd.Timedelta(hours=12)\ndf[\"x_max\"] = df[\"date\"] + pd.Timedelta(hours=12)\n\n# Create separate dataframes for faceting\ndf_price = df.copy()\ndf_price[\"pane\"] = \"Price (OHLC)\"\n\ndf_volume = df.copy()\ndf_volume[\"pane\"] = \"Trading Volume\"\n\n# Create the faceted plot\nplot = (\n    ggplot()\n    # Candlestick wicks (high-low lines)\n    + geom_segment(\n        aes(x=\"date\", y=\"low\", xend=\"date\", yend=\"high\", color=\"direction_label\"),\n        data=df_price,\n        size=0.8,\n        show_legend=False,\n    )\n    # Candlestick bodies (open-close rectangles)\n    + geom_rect(\n        aes(xmin=\"x_min\", xmax=\"x_max\", ymin=\"open\", ymax=\"close\", fill=\"direction_label\"),\n        data=df_price,\n        show_legend=False,\n    )\n    # Volume bars\n    + geom_col(aes(x=\"date\", y=\"volume\", fill=\"direction_label\"), data=df_volume, show_legend=False)\n    # Facet with free y-scales for price and volume\n    + facet_grid(\"pane ~ .\", scales=\"free_y\")\n    # Color scales\n    + scale_color_manual(values=[DOWN_COLOR, UP_COLOR])\n    + scale_fill_manual(values=[DOWN_COLOR, UP_COLOR])\n    # Labels and title\n    + labs(title=\"candlestick-volume · plotnine · anyplot.ai\", x=\"Date\", y=\"\")\n    # Theme\n    + theme_minimal()\n    + theme(\n        figure_size=(16, 9),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_border=element_rect(color=INK_SOFT, fill=None, size=0.3),\n        axis_title=element_text(size=20, color=INK),\n        axis_text=element_text(size=16, color=INK_SOFT),\n        plot_title=element_text(size=24, color=INK, weight=\"medium\"),\n        strip_text_y=element_text(size=18, color=INK),\n        panel_grid_major_y=element_line(color=INK_SOFT, size=0.3, alpha=0.15),\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n    )\n)\n\n# Save with theme-suffixed filename to script directory\nscript_dir = __file__[: __file__.rfind(\"/\")]\nggsave(plot, f\"{script_dir}/plot-{THEME}.png\", dpi=300)\n"}