{"spec_id":"histogram-returns-distribution","library":"bokeh","language":"python","code":"\"\"\" anyplot.ai\nhistogram-returns-distribution: Returns Distribution Histogram\nLibrary: bokeh 3.9.0 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-20\n\"\"\"\n\nimport os\nimport sys\nimport time\nfrom pathlib import Path\n\n\n# Remove the current directory from sys.path to avoid shadowing the bokeh package\nsys.path = [p for p in sys.path if p not in (\"\", \".\", os.getcwd(), os.path.dirname(__file__))]\n\nimport numpy as np\nfrom bokeh.io import output_file, save\nfrom bokeh.models import BoxAnnotation, ColumnDataSource, HoverTool, Label\nfrom bokeh.plotting import figure\nfrom selenium import webdriver\nfrom selenium.webdriver.chrome.options import Options\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Data\nnp.random.seed(42)\nn_days = 252\ndaily_returns = np.random.normal(loc=0.0005, scale=0.015, size=n_days) * 100\n\nmean_return = np.mean(daily_returns)\nstd_return = np.std(daily_returns)\nn = len(daily_returns)\nskewness = np.sum(((daily_returns - mean_return) / std_return) ** 3) / n\nkurtosis = np.sum(((daily_returns - mean_return) / std_return) ** 4) / n - 3\n\nn_bins = 30\nhist, edges = np.histogram(daily_returns, bins=n_bins, density=True)\n\nx_norm = np.linspace(daily_returns.min() - std_return, daily_returns.max() + std_return, 200)\ny_norm = (1 / (std_return * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x_norm - mean_return) / std_return) ** 2)\n\nlower_tail = mean_return - 2 * std_return\nupper_tail = mean_return + 2 * std_return\n\nbar_colors = [\n    \"#C475FD\" if (edges[i] < lower_tail or edges[i + 1] > upper_tail) else \"#009E73\" for i in range(len(hist))\n]\n\nhist_source = ColumnDataSource(\n    data={\n        \"top\": hist,\n        \"left\": edges[:-1],\n        \"right\": edges[1:],\n        \"bottom\": [0] * len(hist),\n        \"color\": bar_colors,\n        \"bin_left\": [f\"{edges[i]:.2f}\" for i in range(len(hist))],\n        \"bin_right\": [f\"{edges[i + 1]:.2f}\" for i in range(len(hist))],\n        \"density\": [f\"{h:.4f}\" for h in hist],\n    }\n)\n\nnorm_source = ColumnDataSource(data={\"x\": x_norm, \"y\": y_norm})\n\n# Plot\np = figure(\n    width=3200,\n    height=1800,\n    title=\"histogram-returns-distribution · python · bokeh · anyplot.ai\",\n    x_axis_label=\"Daily Returns (%)\",\n    y_axis_label=\"Density\",\n    toolbar_location=None,\n    min_border_bottom=160,\n    min_border_left=180,\n    min_border_top=110,\n    min_border_right=50,\n)\n\np.add_layout(BoxAnnotation(right=lower_tail, fill_alpha=0.10, fill_color=\"#C475FD\"))\np.add_layout(BoxAnnotation(left=upper_tail, fill_alpha=0.10, fill_color=\"#C475FD\"))\n\nbars = p.quad(\n    top=\"top\",\n    bottom=\"bottom\",\n    left=\"left\",\n    right=\"right\",\n    fill_color=\"color\",\n    line_color=PAGE_BG,\n    fill_alpha=0.80,\n    line_width=1,\n    source=hist_source,\n)\n\nhover = HoverTool(renderers=[bars], tooltips=[(\"Range\", \"@bin_left% – @bin_right%\"), (\"Density\", \"@density\")])\np.add_tools(hover)\n\np.line(x=\"x\", y=\"y\", source=norm_source, line_color=\"#4467A3\", line_width=5, legend_label=\"Normal Distribution\")\n\nstats_text = f\"Mean: {mean_return:.3f}%\\nStd Dev: {std_return:.3f}%\\nSkewness: {skewness:.3f}\\nKurtosis: {kurtosis:.3f}\"\nstats_label = Label(\n    x=210,\n    y=1180,\n    x_units=\"screen\",\n    y_units=\"screen\",\n    text=stats_text,\n    text_font_size=\"30pt\",\n    text_color=INK,\n    background_fill_color=ELEVATED_BG,\n    background_fill_alpha=0.90,\n    border_line_color=INK_SOFT,\n    border_line_width=2,\n)\np.add_layout(stats_label)\n\n# Style\np.background_fill_color = PAGE_BG\np.border_fill_color = PAGE_BG\np.outline_line_color = None\n\np.title.text_font_size = \"50pt\"\np.title.text_color = INK\n\np.xaxis.axis_label_text_font_size = \"42pt\"\np.yaxis.axis_label_text_font_size = \"42pt\"\np.xaxis.axis_label_text_color = INK\np.yaxis.axis_label_text_color = INK\n\np.xaxis.major_label_text_font_size = \"34pt\"\np.yaxis.major_label_text_font_size = \"34pt\"\np.xaxis.major_label_text_color = INK_SOFT\np.yaxis.major_label_text_color = INK_SOFT\n\np.xaxis.axis_line_color = INK_SOFT\np.yaxis.axis_line_color = INK_SOFT\np.xaxis.major_tick_line_color = INK_SOFT\np.yaxis.major_tick_line_color = INK_SOFT\n\np.xgrid.grid_line_color = None\np.ygrid.grid_line_color = INK\np.ygrid.grid_line_alpha = 0.10\n\np.legend.location = \"top_right\"\np.legend.label_text_font_size = \"34pt\"\np.legend.background_fill_color = ELEVATED_BG\np.legend.border_line_color = None\np.legend.label_text_color = INK_SOFT\n\n# Save\noutput_file(f\"plot-{THEME}.html\")\nsave(p)\n\nW, H = 3200, 1800\nopts = Options()\nfor arg in (\n    \"--headless=new\",\n    \"--no-sandbox\",\n    \"--disable-dev-shm-usage\",\n    \"--disable-gpu\",\n    f\"--window-size={W},{H}\",\n    \"--hide-scrollbars\",\n):\n    opts.add_argument(arg)\ndriver = webdriver.Chrome(options=opts)\ndriver.execute_cdp_cmd(\n    \"Emulation.setDeviceMetricsOverride\", {\"width\": W, \"height\": H, \"deviceScaleFactor\": 1, \"mobile\": False}\n)\ndriver.get(f\"file://{Path(f'plot-{THEME}.html').resolve()}\")\ntime.sleep(3)\ndriver.save_screenshot(f\"plot-{THEME}.png\")\ndriver.quit()\n"}