{"spec_id":"depth-order-book","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\ndepth-order-book: Order Book Depth Chart\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 83/100 | Created: 2026-06-15\n\"\"\"\n\nimport os\nimport sys\n\nimport numpy as np\n\n\n# Prevent the local pygal.py from shadowing the installed pygal package\n_script_dir = os.path.dirname(os.path.abspath(__file__))\nif _script_dir in sys.path:\n    sys.path.remove(_script_dir)\n\nimport pygal\nfrom pygal.style import Style\n\n\n# Theme\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\n# Imprint palette — semantic: green for bids (buy), red for asks (sell)\nBID_COLOR = \"#009E73\"\nASK_COLOR = \"#AE3030\"\n\n# Data — synthetic BTC/USD order book snapshot, mid price $60,000\nnp.random.seed(42)\nn_levels = 50\ntick = 10\n\nbid_prices = np.array([59_995 - i * tick for i in range(n_levels)])\nask_prices = np.array([60_005 + i * tick for i in range(n_levels)])\n\nbid_qtys = np.random.exponential(scale=2.5, size=n_levels) + 0.3\nask_qtys = np.random.exponential(scale=2.5, size=n_levels) + 0.3\n\n# Order walls at key price levels\nbid_qtys[9] *= 6\nbid_qtys[24] *= 8\nbid_qtys[38] *= 5\nask_qtys[11] *= 7\nask_qtys[27] *= 9\nask_qtys[41] *= 4\n\n# Cumulative volume from best price outward\nbid_cum = np.cumsum(bid_qtys)\nask_cum = np.cumsum(ask_qtys)\n\n# Reverse bids for left-to-right layout (worst → best price, descending cumulative)\nbid_px = bid_prices[::-1]\nbid_cq = bid_cum[::-1]\nask_px = ask_prices\nask_cq = ask_cum\n\n# Max cumulative volume and mid-price annotation data\nmax_vol = max(float(bid_cq[0]), float(ask_cq[-1]))\nmid_price = 60_000\nmid_line = [(mid_price, 0.0), (mid_price, max_vol * 1.05)]\n\n# Biggest bid wall: bid_qtys[24] *= 8 at price 59755.\n# Visual step (drop) appears at bid_px[26]=59765; top of the step is bid_cq[25]=bid_cum[24].\nbid_wall_price = int(bid_px[26])  # 59765\nbid_wall_vol = float(bid_cq[25])  # bid_cum[24] — height at the top of the 8× drop\n\n# Biggest ask wall: ask_qtys[27] *= 9 at price 60275.\n# Visual step (rise) at ask_px[27]=60275; peak is ask_cq[27]=ask_cum[27].\nask_wall_price = int(ask_px[27])  # 60275\nask_wall_vol = float(ask_cq[27])  # ask_cum[27] — height at the top of the 9× rise\n\n# Build bid staircase (descending from left/worst to right/best, close to zero at mid)\nbid_step = [(int(bid_px[0]), float(bid_cq[0]))]\nfor i in range(1, len(bid_px)):\n    bid_step.append((int(bid_px[i]), float(bid_cq[i - 1])))\n    bid_step.append((int(bid_px[i]), float(bid_cq[i])))\nbid_step.append((int(bid_px[-1]) + 1, 0.0))\n\n# Build ask staircase (ascending from left/best to right/worst, open from zero at mid)\nask_step = [(int(ask_px[0]) - 1, 0.0), (int(ask_px[0]), 0.0), (int(ask_px[0]), float(ask_cq[0]))]\nfor i in range(1, len(ask_px)):\n    ask_step.append((int(ask_px[i]), float(ask_cq[i - 1])))\n    ask_step.append((int(ask_px[i]), float(ask_cq[i])))\n\n# Title — 67 chars → no scaling needed\ntitle = \"BTC/USD Order Book · depth-order-book · python · pygal · anyplot.ai\"\nn_chars = len(title)\nratio = 67 / n_chars if n_chars > 67 else 1.0\ntitle_fontsize = max(44, round(66 * ratio))\n\n# Style — 5 colors: Bids, Asks, Mid-price line, Bid Wall dot, Ask Wall dot\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=(BID_COLOR, ASK_COLOR, INK_MUTED, BID_COLOR, ASK_COLOR),\n    opacity=0.5,\n    opacity_hover=0.85,\n    title_font_size=title_fontsize,\n    label_font_size=56,\n    major_label_font_size=44,\n    legend_font_size=44,\n    value_font_size=36,\n    stroke_width=3.0,\n    dots_size=12,\n)\n\n# Chart\nchart = pygal.XY(\n    width=3200,\n    height=1800,\n    fill=True,\n    show_dots=False,\n    show_x_guides=False,\n    show_y_guides=True,\n    x_label_rotation=30,\n    style=custom_style,\n    title=title,\n    x_title=\"Price (USD)\",\n    y_title=\"Cumulative Volume (BTC)\",\n)\n\nchart.add(\"Bids\", bid_step)\nchart.add(\"Asks\", ask_step)\n# Dashed vertical line at mid price — highlights the bid-ask spread gap\nchart.add(\n    \"Mid $60,000 · Spread $10\",\n    mid_line,\n    fill=False,\n    show_dots=False,\n    stroke_style={\"width\": 3, \"dasharray\": \"12,6\", \"linecap\": \"round\"},\n)\n# Dot callouts at the largest liquidity walls for storytelling\nchart.add(\n    \"8× Bid Wall\", [{\"value\": (bid_wall_price, bid_wall_vol), \"label\": \"8×\"}], fill=False, show_dots=True, stroke=False\n)\nchart.add(\n    \"9× Ask Wall\", [{\"value\": (ask_wall_price, ask_wall_vol), \"label\": \"9×\"}], fill=False, show_dots=True, stroke=False\n)\n\n# Save\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}