{"spec_id":"ohlc-bar","library":"makie","language":"julia","code":"# anyplot.ai\n# ohlc-bar: OHLC Bar Chart\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 89/100 | Created: 2026-09-02\n\nusing CairoMakie\nusing Colors\nusing Dates\nusing Random\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 INK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst UP_COLOR    = colorant\"#009E73\"  # Imprint position 1 — bullish (close >= open)\nconst DOWN_COLOR  = colorant\"#AE3030\"  # Imprint semantic anchor — bearish (close < open)\n\n# --- Data: 45 trading sessions of a fictional robotics stock (SLRA) ---------\nstart_date = Date(2024, 3, 1)\ncalendar_days = start_date:Day(1):(start_date + Day(90))\ntrading_dates = filter(d -> dayofweek(d) <= 5, collect(calendar_days))[1:45]\n\nn_days = length(trading_dates)\nopen_prices = zeros(n_days)\nhigh_prices = zeros(n_days)\nlow_prices = zeros(n_days)\nclose_prices = zeros(n_days)\n\nprice = 185.0\nfor i in 1:n_days\n    # Sessions 20-27 simulate an earnings-reaction stretch with wider ranges\n    vol_mult = (20 <= i <= 27) ? 2.6 : 1.0\n    open_prices[i] = price\n    close_prices[i] = max(price + randn() * 2.2 * vol_mult, 5.0)\n    high_prices[i] = max(open_prices[i], close_prices[i]) + abs(randn()) * 1.6 * vol_mult\n    low_prices[i] = min(open_prices[i], close_prices[i]) - abs(randn()) * 1.6 * vol_mult\n    global price = close_prices[i]\nend\n\nbar_up = close_prices .>= open_prices\nbar_colors = [up ? UP_COLOR : DOWN_COLOR for up in bar_up]\n\npeak_idx = argmax(high_prices)\ntrough_idx = argmin(low_prices)\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              = \"ohlc-bar · julia · makie · anyplot.ai\",\n    titlesize          = 25,\n    titlecolor         = INK,\n    xlabel             = \"2024 Trading Sessions\",\n    ylabel             = \"SLRA Share Price (USD)\",\n    xlabelsize         = 14,\n    ylabelsize         = 14,\n    xlabelcolor        = INK,\n    ylabelcolor        = INK,\n    xticklabelsize     = 11,\n    yticklabelsize     = 12,\n    xticklabelcolor    = INK_SOFT,\n    yticklabelcolor    = INK_SOFT,\n    xticklabelrotation = pi / 6,\n    xtickcolor         = INK_SOFT,\n    ytickcolor         = INK_SOFT,\n    backgroundcolor    = PAGE_BG,\n    topspinevisible    = false,\n    rightspinevisible  = false,\n    leftspinecolor     = INK_SOFT,\n    bottomspinecolor   = INK_SOFT,\n    xgridvisible       = false,\n    ygridcolor         = RGBAf(INK.r, INK.g, INK.b, 0.15),\n)\n\ntick_width = 0.32\nxs = Float32.(1:n_days)\n\nopen_points = Point2f[]\nclose_points = Point2f[]\nfor i in 1:n_days\n    x = xs[i]\n    push!(open_points, Point2f(x - tick_width, open_prices[i]), Point2f(x, open_prices[i]))\n    push!(close_points, Point2f(x, close_prices[i]), Point2f(x + tick_width, close_prices[i]))\nend\ntick_colors = repeat(bar_colors, inner = 2)\n\nrangebars!(ax, xs, low_prices, high_prices; color = bar_colors, linewidth = 2.5)\nlinesegments!(ax, open_points; color = tick_colors, linewidth = 2.5)\nlinesegments!(ax, close_points; color = tick_colors, linewidth = 2.5)\n\ntext!(\n    ax, xs[peak_idx], high_prices[peak_idx];\n    text = \"Swing high\", align = (:center, :bottom), offset = (0, 6),\n    fontsize = 11, color = INK_SOFT,\n)\ntext!(\n    ax, xs[trough_idx], low_prices[trough_idx];\n    text = \"Swing low\", align = (:center, :top), offset = (0, -6),\n    fontsize = 11, color = INK_SOFT,\n)\n\ntick_step = 5\ntick_positions = collect(1:tick_step:n_days)\nax.xticks = (Float32.(tick_positions), [Dates.format(trading_dates[i], \"u dd\") for i in tick_positions])\nxlims!(ax, 0, n_days + 1)\nylims!(ax, minimum(low_prices) - 6, maximum(high_prices) + 6)\n\nlegend_elements = [\n    LineElement(color = UP_COLOR, linewidth = 2.5),\n    LineElement(color = DOWN_COLOR, linewidth = 2.5),\n]\naxislegend(\n    ax, legend_elements, [\"Up (close ≥ open)\", \"Down (close < open)\"];\n    position = :lt, framevisible = false, labelcolor = INK_SOFT, labelsize = 12,\n)\n\n# --- Save ---------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}