{"spec_id":"histogram-returns-distribution","library":"makie","language":"julia","code":"# anyplot.ai\n# histogram-returns-distribution: Returns Distribution Histogram\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 92/100 | Created: 2026-09-02\n\nusing CairoMakie\nusing Colors\nusing Random\nusing Statistics\nusing Printf\n\nRandom.seed!(42)\n\n# --- Theme tokens -------------------------------------------------------------\nconst THEME       = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG     = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst ELEVATED_BG = THEME == \"light\" ? colorant\"#FFFDF6\" : colorant\"#242420\"\nconst INK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst IMPRINT_PALETTE = [\n    colorant\"#009E73\", colorant\"#C475FD\", colorant\"#4467A3\", colorant\"#BD8233\",\n    colorant\"#AE3030\", colorant\"#2ABCCD\", colorant\"#954477\", colorant\"#99B314\",\n]\nconst ANYPLOT_AMBER = colorant\"#DDCC77\"  # warning — tail events beyond 2 std dev\nconst ANYPLOT_NEUTRAL = INK             # reference line — fitted normal curve\n\n# --- Data -----------------------------------------------------------------\n# One trading year of daily ETF returns (%). A minority of days carry a larger\n# negative shock, producing the fat left tail and mild negative skew typical\n# of real equity return series.\nn_days = 252\nbase_returns = 1.1 .* randn(n_days) .+ 0.05\nis_shock_day = rand(n_days) .< 0.07\ncrash_shocks = -abs.(2.6 .* randn(n_days))\ndaily_returns = ifelse.(is_shock_day, base_returns .+ crash_shocks, base_returns)\n\nmean_return = mean(daily_returns)\nstd_return = std(daily_returns)\nz_scores = (daily_returns .- mean_return) ./ std_return\nskewness = mean(z_scores .^ 3)\nexcess_kurtosis = mean(z_scores .^ 4) - 3\n\n# --- Histogram binning (manual, so tail bins can be recolored) ------------\nn_bins = 22\nlo, hi = minimum(daily_returns), maximum(daily_returns)\nedges = range(lo, hi; length = n_bins + 1)\nbin_width = step(edges)\ncounts = zeros(Int, n_bins)\nfor r in daily_returns\n    idx = clamp(Int(floor((r - lo) / bin_width)) + 1, 1, n_bins)\n    counts[idx] += 1\nend\nbin_centers = [edges[i] + bin_width / 2 for i in 1:n_bins]\ndensities = counts ./ (n_days * bin_width)  # density normalization\n\ntail_threshold = 2 * std_return\nis_tail_bin = [abs(c - mean_return) > tail_threshold for c in bin_centers]\n\n# Normal distribution fitted to the sample, for comparison\nnormal_xs = range(lo, hi; length = 200)\nnormal_pdf(x) = exp(-0.5 * ((x - mean_return) / std_return)^2) / (std_return * sqrt(2π))\nnormal_ys = normal_pdf.(normal_xs)\n\n# --- Plot -------------------------------------------------------------------\nfig = Figure(\n    resolution      = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title              = \"histogram-returns-distribution · julia · makie · anyplot.ai\",\n    titlesize          = 25,\n    titlecolor         = INK,\n    xlabel             = \"Daily Return (%)\",\n    ylabel             = \"Density\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelsize     = 12,\n    yticklabelsize     = 12,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    xminorgridvisible  = false,\n    yminorgridvisible  = false,\n)\n\nbarplot!(\n    ax, bin_centers[.!is_tail_bin], densities[.!is_tail_bin];\n    color = IMPRINT_PALETTE[1], width = bin_width, gap = 0.0,\n    label = \"Daily returns (|z| ≤ 2σ)\",\n)\nbarplot!(\n    ax, bin_centers[is_tail_bin], densities[is_tail_bin];\n    color = ANYPLOT_AMBER, width = bin_width, gap = 0.0,\n    label = \"Tail events (|z| > 2σ)\",\n)\nlines!(\n    ax, normal_xs, normal_ys;\n    color = ANYPLOT_NEUTRAL, linewidth = 3, linestyle = :dash, label = \"Normal fit\",\n)\n\n# Legend built declaratively from the axis's own labeled plot objects, rather\n# than hand-assembled proxy elements — Makie collects the legend entries for us.\nLegend(\n    fig[1, 2], ax;\n    framevisible = false,\n    labelcolor   = INK_SOFT,\n    labelsize    = 12,\n    backgroundcolor = PAGE_BG,\n)\n\nstats_text = @sprintf(\n    \"Mean: %.2f%%\\nStd Dev: %.2f%%\\nSkewness: %.2f\\nExcess Kurtosis: %.2f\",\n    mean_return, std_return, skewness, excess_kurtosis,\n)\npoly!(\n    ax, Rect2f(0.02, 0.79, 0.34, 0.17);\n    color = (ELEVATED_BG, 0.92), strokecolor = INK_SOFT, strokewidth = 1,\n    space = :relative,\n)\ntext!(\n    ax, 0.045, 0.935;\n    text = stats_text, space = :relative, align = (:left, :top),\n    color = INK, fontsize = 13, font = :bold,\n)\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}