Files
ramseshk 2f74e076b4 Live L2 Order Book + Trade Tape visualization (Bookmap-style)
New components:
  - hyperliquid-ws.ts: WebSocket hook for Hyperliquid L2 + trades
    - Auto-reconnect, ring buffer (500 trades)
    - Computes imbalance, total bid/ask volume, mid, spread
    - Type-safe interfaces: L2Snapshot, TradeTapeEntry

  - orderbook-depth-map.tsx: Dual-panel Canvas 2D visualization
    - Top panel (~55%): L2 volume profile histogram
      - Green bid bars (#00C853), red ask bars (#FF1744)
      - Yellow mid line (#FFEB3B) with floating price labels
      - Price axis, volume scale, orange mid marker
      - Quant overlay system: fair value, VWAP, signals
    - Bottom panel (~45%): Live trade tape
      - Amber trade path (#FFAB00)
      - Buy/sell markers (green/red dots sized by trade size)
      - Latest trade callout with side + price
    - Dark theme (#000000), monospace fonts, zero flicker

Integration:
  - Added to all strategy detail views (live tab only)
  - Renders below trade history table
  - WebSocket connects on mount, reconnects on error

Visual specification per user request:
  - Bid/ask bars: neon green/red on pure black
  - Mid line: yellow dashed with floating labels
  - Trade path: amber staircase with colored markers
  - No grid clutter, professional trading terminal aesthetic
2026-08-05 07:42:27 +00:00

1 line
14 KiB
HTML

<!DOCTYPE html><html lang="en" class="dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/cv/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/cv/_next/static/media/83afe278b6a6bb3c-s.p.2bn3s6zvc0dyp.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/cv/_next/static/chunks/3jf-3fbtd2x8h.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/cv/_next/static/chunks/3l04zcqx63h3y.js"/><script src="/cv/_next/static/chunks/3krunzhn7hds3.js" async=""></script><script src="/cv/_next/static/chunks/08ttfj81-47mu.js" async=""></script><script src="/cv/_next/static/chunks/turbopack-384ds9tgupq-y.js" async=""></script><script src="/cv/_next/static/chunks/3fntmmi971322.js" async="" crossorigin=""></script><script src="/cv/_next/static/chunks/0grysamdfk821.js" async="" crossorigin=""></script><title>FTDT Quant Lab</title><meta name="description" content="Professional quantitative trading dashboard — live testnet, paper mainnet, historical backtests"/><meta name="next-size-adjust" content=""/><script src="/cv/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body class="inter_5901b7c6-module__ec5Qua__variable jetbrains_mono_707233f-module__9hS9bG__variable antialiased"><div hidden=""><!--$--><!--/$--></div><div class="min-h-screen bg-background"><header class="sticky top-0 z-50 border-b border-border bg-background/80 backdrop-blur-xl"><div class="flex items-center justify-between px-6 py-3 max-w-[1440px] mx-auto"><div class="flex items-center gap-3"><span class="w-2 h-2 rounded-full bg-red-500"></span><div><h1 class="text-sm font-bold tracking-tight">FTDT Quant Lab</h1><p class="text-[10px] text-muted-foreground">Live Testnet · Equity $—</p></div></div><div data-slot="badge" class="inline-flex items-center justify-center rounded-md border px-2 py-0.5 font-medium w-fit whitespace-nowrap shrink-0 [&amp;&gt;svg]:size-3 gap-1 [&amp;&gt;svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden border-transparent bg-destructive text-destructive-foreground text-[10px] h-5">OFFLINE</div></div></header><div class="border-b border-border bg-background/80 backdrop-blur-xl sticky top-[49px] z-40"><div data-slot="tabs" class="flex flex-col max-w-[1440px] mx-auto px-6"><div data-slot="tabs-list" class="inline-flex items-center justify-center rounded-md text-muted-foreground h-10 bg-transparent border-0 gap-0 p-0"><button data-slot="tabs-trigger" data-state="active" class="inline-flex items-center justify-center whitespace-nowrap py-1.5 font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[state=active]:border-b-2 data-[state=active]:border-primary rounded-none px-5 text-xs h-10">Live<div data-slot="badge" class="inline-flex items-center justify-center rounded-md py-0.5 font-medium w-fit whitespace-nowrap shrink-0 [&amp;&gt;svg]:size-3 gap-1 [&amp;&gt;svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden ml-1.5 text-[9px] h-4 px-1.5 bg-amber-500/10 text-amber-400 border-0">Testnet</div></button><button data-slot="tabs-trigger" data-state="inactive" class="inline-flex items-center justify-center whitespace-nowrap py-1.5 font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[state=active]:border-b-2 data-[state=active]:border-primary rounded-none px-5 text-xs h-10">Paper<div data-slot="badge" class="inline-flex items-center justify-center rounded-md py-0.5 font-medium w-fit whitespace-nowrap shrink-0 [&amp;&gt;svg]:size-3 gap-1 [&amp;&gt;svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden ml-1.5 text-[9px] h-4 px-1.5 bg-purple-500/10 text-purple-400 border-0">$100K Mainnet</div></button><button data-slot="tabs-trigger" data-state="inactive" class="inline-flex items-center justify-center whitespace-nowrap py-1.5 font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm data-[state=active]:border-b-2 data-[state=active]:border-primary rounded-none px-5 text-xs h-10">Historical<div data-slot="badge" class="inline-flex items-center justify-center rounded-md py-0.5 font-medium w-fit whitespace-nowrap shrink-0 [&amp;&gt;svg]:size-3 gap-1 [&amp;&gt;svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden ml-1.5 text-[9px] h-4 px-1.5 bg-purple-500/10 text-purple-400 border-0">Real Data</div></button></div></div></div><main class="max-w-[1440px] mx-auto px-6 py-6"><div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-3 mb-6"></div><div data-slot="collapsible" class="flex flex-col gap-2 mb-6"><button data-slot="collapsible-trigger" class="font-medium [&amp;[data-state=open]&gt;svg]:rotate-180 flex items-center gap-2 text-xs text-muted-foreground hover:text-foreground transition-colors py-1" data-state="closed"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right w-3 h-3"><path d="m9 18 6-6-6-6"></path></svg>Open Positions &amp; Orders (<!-- -->0<!-- --> pos · <!-- -->0<!-- --> ord)</button></div><div class="grid grid-cols-1 md:grid-cols-3 gap-3 mb-6"><a href="https://ftdt.io" target="_blank" class="flex items-center gap-3 p-4 rounded-lg border border-border bg-card hover:border-primary/50 transition-colors"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-activity w-4 h-4 text-primary"><path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"></path></svg><div><p class="text-xs font-medium">ftdt.io</p><p class="text-[10px] text-muted-foreground">Main platform</p></div></a><a href="https://app.ftdt.io/quant-lab" target="_blank" class="flex items-center gap-3 p-4 rounded-lg border border-border bg-card hover:border-primary/50 transition-colors"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-trending-up w-4 h-4 text-chart-2"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"></polyline><polyline points="16 7 22 7 22 13"></polyline></svg><div><p class="text-xs font-medium">Quant Lab ↗</p><p class="text-[10px] text-muted-foreground">Web dashboard</p></div></a><a href="https://git.ftdt.io/rams/ftdt-quant-lab" target="_blank" class="flex items-center gap-3 p-4 rounded-lg border border-border bg-card hover:border-primary/50 transition-colors"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-database w-4 h-4 text-chart-3"><ellipse cx="12" cy="5" rx="9" ry="3"></ellipse><path d="M3 5V19A9 3 0 0 0 21 19V5"></path><path d="M3 12A9 3 0 0 0 21 12"></path></svg><div><p class="text-xs font-medium">Git Repo</p><p class="text-[10px] text-muted-foreground">rams/ftdt-quant-lab</p></div></a></div></main></div><!--$--><!--/$--><script src="/cv/_next/static/chunks/3l04zcqx63h3y.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"default\"]\n3:I[37457,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"default\"]\n4:I[47257,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"ClientPageRoot\"]\n5:I[52683,[\"/cv/_next/static/chunks/3fntmmi971322.js\",\"/cv/_next/static/chunks/0grysamdfk821.js\"],\"default\"]\n8:I[97367,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[97367,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"ViewportBoundary\"]\nd:I[97367,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"MetadataBoundary\"]\nf:I[68027,[\"/cv/_next/static/chunks/3fntmmi971322.js\"],\"default\",1]\n:HL[\"/cv/_next/static/chunks/3jf-3fbtd2x8h.css\",\"style\"]\n:HL[\"/cv/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/cv/_next/static/media/83afe278b6a6bb3c-s.p.2bn3s6zvc0dyp.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n0:{\"P\":null,\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/cv/_next/static/chunks/3jf-3fbtd2x8h.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/cv/_next/static/chunks/3fntmmi971322.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"dark\",\"children\":[\"$\",\"body\",null,{\"className\":\"inter_5901b7c6-module__ec5Qua__variable jetbrains_mono_707233f-module__9hS9bG__variable antialiased\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L4\",null,{\"Component\":\"$5\",\"serverProvidedParams\":{\"searchParams\":{},\"params\":{},\"promises\":[\"$@6\",\"$@7\"]}}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/cv/_next/static/chunks/0grysamdfk821.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,null]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lb\",null,{\"children\":\"$Lc\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Le\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/cv/_next/static/chunks/3jf-3fbtd2x8h.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"s3XEYXnsKqL1zh_R9lo0_\"}\n6:{}\n7:\"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params\"\nc:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\na:null\ne:[[\"$\",\"title\",\"0\",{\"children\":\"FTDT Quant Lab\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Professional quantitative trading dashboard — live testnet, paper mainnet, historical backtests\"}]]\n"])</script></body></html>