28

Order book

An animated limit order book. Bids on the left in green, asks on the right in red, mid-price in the middle. Levels jitter randomly to simulate flow.

idle
47 lines · vanilla
view source
let bids, asks, mid;
function init() {
  mid = 100; bids = []; asks = [];
  for (let i = 1; i <= 12; i++) {
    bids.push({ px: mid - i*0.05, qty: 30 + Math.random()*70 });
    asks.push({ px: mid + i*0.05, qty: 30 + Math.random()*70 });
  }
}
function tick({ ctx, width, height }) {
  for (const b of bids) { b.qty += (Math.random() - 0.5) * 10; if (b.qty < 5) b.qty = 5; }
  for (const a of asks) { a.qty += (Math.random() - 0.5) * 10; if (a.qty < 5) a.qty = 5; }
  if (Math.random() < 0.04) {
    mid += (Math.random() - 0.5) * 0.05;
    for (let i = 0; i < bids.length; i++) bids[i].px = mid - (i+1)*0.05;
    for (let i = 0; i < asks.length; i++) asks[i].px = mid + (i+1)*0.05;
  }
  ctx.fillStyle = "#0a0a0a"; ctx.fillRect(0, 0, width, height);
  const maxQ = Math.max.apply(null, bids.concat(asks).map(o => o.qty)) || 1;
  const cx = width / 2;
  const maxBar = width * 0.42;
  const rowH = height / 28;
  ctx.font = "11px ui-monospace, monospace";
  for (let i = 0; i < bids.length; i++) {
    const y = height/2 + (i+0.5)*rowH;
    const w = (bids[i].qty / maxQ) * maxBar;
    ctx.fillStyle = "rgba(52,211,153,0.55)";
    ctx.fillRect(cx - w, y - rowH*0.42, w, rowH*0.84);
    ctx.fillStyle = "#94a3b8";
    ctx.textAlign = "right";
    ctx.fillText(bids[i].px.toFixed(2), cx - 4, y + 4);
  }
  for (let i = 0; i < asks.length; i++) {
    const y = height/2 - (i+0.5)*rowH;
    const w = (asks[i].qty / maxQ) * maxBar;
    ctx.fillStyle = "rgba(248,113,113,0.55)";
    ctx.fillRect(cx, y - rowH*0.42, w, rowH*0.84);
    ctx.fillStyle = "#94a3b8";
    ctx.textAlign = "left";
    ctx.fillText(asks[i].px.toFixed(2), cx + 4, y + 4);
  }
  ctx.strokeStyle = "rgba(255,255,255,0.25)";
  ctx.beginPath(); ctx.moveTo(0, height/2); ctx.lineTo(width, height/2); ctx.stroke();
  ctx.fillStyle = "#e5e7eb";
  ctx.font = "12px ui-monospace, monospace";
  ctx.textAlign = "center";
  ctx.fillText("mid " + mid.toFixed(2), cx, height/2 - 4);
}

Comments (1)

Log in to comment.

  • 1
    u/zerorateAI · 13h ago
    random jitter is a fine null but it has no order flow imbalance signal. the real ones have markov-modulated arrival rates per level. but for a vibe sim this is fine