{"spec_id":"histogram-returns-distribution","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nhistogram-returns-distribution: Returns Distribution Histogram\nLibrary: letsplot 4.10.0 | Python 3.13.13\nQuality: 88/100 | Updated: 2026-05-20\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import *\nfrom lets_plot.export import ggsave\nfrom scipy import stats\n\n\nLetsPlot.setup_html()\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\"\nGRID_COLOR = \"#D9D8D1\" if THEME == \"light\" else \"#3A3A37\"\n\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\"]\n\n# Data\nnp.random.seed(42)\nn_days = 252\n\n# Simulate realistic daily stock returns with slight fat tails\nbase_returns = np.random.normal(loc=0.0003, scale=0.012, size=n_days)\noutlier_mask = np.random.random(n_days) < 0.05\noutliers = np.random.normal(loc=0, scale=0.035, size=n_days)\nreturns = np.where(outlier_mask, outliers, base_returns)\n\n# Calculate statistics\nmean_ret = np.mean(returns) * 100\nstd_ret = np.std(returns) * 100\nskewness = stats.skew(returns)\nkurtosis = stats.kurtosis(returns)\n\n# Create DataFrame for plotting (convert to percentage)\ndf = pd.DataFrame({\"returns\": returns * 100})\n\n# Define tail thresholds (beyond 2 standard deviations)\nlower_tail = mean_ret - 2 * std_ret\nupper_tail = mean_ret + 2 * std_ret\n\ndf[\"region\"] = np.where(\n    df[\"returns\"] < lower_tail,\n    \"Tail (beyond ±2σ)\",\n    np.where(df[\"returns\"] > upper_tail, \"Tail (beyond ±2σ)\", \"Normal Range (±2σ)\"),\n)\n\n# Generate normal distribution curve for overlay\nx_min, x_max = df[\"returns\"].min(), df[\"returns\"].max()\nx_range = np.linspace(x_min - 0.5, x_max + 0.5, 200)\nnormal_pdf = stats.norm.pdf(x_range, loc=mean_ret, scale=std_ret)\ndf_normal = pd.DataFrame({\"x\": x_range, \"density\": normal_pdf})\n\n# Statistics text for annotation\nstats_text = f\"Mean: {mean_ret:.3f}%\\nStd Dev: {std_ret:.3f}%\\nSkewness: {skewness:.2f}\\nKurtosis: {kurtosis:.2f}\"\n\n# Build theme\nanyplot_theme = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG),\n    panel_grid_major_y=element_line(color=GRID_COLOR, size=0.5),\n    panel_grid_major_x=element_blank(),\n    panel_grid_minor=element_blank(),\n    panel_border=element_blank(),\n    axis_title=element_text(color=INK, size=12),\n    axis_text=element_text(color=INK_SOFT, size=10),\n    axis_line=element_line(color=INK_SOFT),\n    axis_ticks=element_line(color=INK_SOFT),\n    plot_title=element_text(color=INK, size=16),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n    legend_text=element_text(color=INK_SOFT, size=10),\n    legend_title=element_text(color=INK, size=10),\n    legend_position=[0.15, 0.85],\n)\n\n# Plot — histogram with tail highlighting and lets-plot hover tooltips (LF-01)\nplot = (\n    ggplot(df, aes(x=\"returns\", fill=\"region\"))\n    + geom_histogram(\n        aes(y=\"..density..\"),\n        bins=30,\n        alpha=0.85,\n        color=PAGE_BG,\n        size=0.5,\n        tooltips=layer_tooltips().line(\"@region\").line(\"Density: @{..density..|.4f}\"),\n    )\n    + geom_line(\n        data=df_normal,\n        mapping=aes(x=\"x\", y=\"density\"),\n        color=INK,\n        size=1.5,\n        linetype=\"dashed\",\n        inherit_aes=False,\n    )\n    + geom_vline(xintercept=lower_tail, color=IMPRINT[1], size=1, linetype=\"dotted\", alpha=0.8)\n    + geom_vline(xintercept=upper_tail, color=IMPRINT[1], size=1, linetype=\"dotted\", alpha=0.8)\n    + scale_fill_manual(\n        values={\"Normal Range (±2σ)\": IMPRINT[0], \"Tail (beyond ±2σ)\": IMPRINT[1]}, name=\"Region\"\n    )\n    + labs(\n        x=\"Daily Returns (%)\", y=\"Density\", title=\"histogram-returns-distribution · python · letsplot · anyplot.ai\"\n    )\n    + theme_minimal()\n    + anyplot_theme\n    + ggsize(800, 450)\n    + geom_label(\n        x=upper_tail + 2.5,\n        y=normal_pdf.max() * 0.90,\n        label=stats_text,\n        size=10,\n        hjust=0.5,\n        fill=ELEVATED_BG,\n        color=INK,\n        alpha=0.9,\n        label_padding=0.5,\n        label_size=0.3,\n    )\n)\n\n# Save PNG (scale 4x → 3200 × 1800 px)\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=4)\n\n# Save HTML (lets-plot interactive hover tooltips work natively in the HTML output)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}