SPB Git forge

spb/market-atlas

Public
12commits 1branches 0releases
1.1 MBsize
maindefault branch
10 days agolast push
TypeScript 96.7% SQL 1.6% CSS 0.8% JavaScript 0.5%
1.9 KB · 40 lines tsx
Raw Blame History
1"use client";23import { formatBps, formatCompact, formatDuration, formatQuoteValue } from "@/lib/format";4import { useLiveQuote } from "@/lib/stream";5import type { Instrument, Quote } from "@/lib/types";67/** Key stats grid; bid/ask/volume follow the live stream, session values from the canonical quote. */8export function InstrumentStats({ instrument: i, quote: q }: { instrument: Instrument; quote: Quote | null }) {9  const live = useLiveQuote(i.id);10  const fresh = live && q && live.received >= Date.parse(q.updated_at);11  const f = (v: number | null | undefined) => formatQuoteValue(v, i.asset_class, q?.currency);12  const bid = fresh ? live!.bid : q?.bid;13  const ask = fresh ? live!.ask : q?.ask;14  const spreadBps = bid != null && ask != null && ask > 0 ? ((ask - bid) / ((ask + bid) / 2)) * 10_000 : null;15  const items: Array<[string, string]> = [16    ["Open", f(q?.open)],17    ["High", f(q?.high)],18    ["Low", f(q?.low)],19    ["Previous close", f(q?.previous_close)],20    ["Bid", f(bid)],21    ["Ask", f(ask)],22    ["Spread", formatBps(spreadBps)],23    ["Volume", formatCompact(fresh ? live!.volume : q?.volume)],24    ["Session high", f(q?.session_high)],25    ["Session low", f(q?.session_low)],26    ["Source dispersion", formatBps(q?.dispersion_bps)],27    ["Newest observation", q?.freshness_ms == null ? "—" : `${formatDuration(q.freshness_ms)} old at compute`],28  ];29  return (30    <dl className="grid grid-cols-2 gap-x-6 rounded-md border border-rule bg-surface px-4 py-2 sm:grid-cols-3 lg:grid-cols-4">31      {items.map(([k, v]) => (32        <div key={k} className="flex items-baseline justify-between gap-3 border-b border-rule py-1.5 text-sm last:border-0 sm:[&:nth-last-child(-n+3)]:border-0 lg:[&:nth-last-child(-n+4)]:border-0">33          <dt className="text-ink-3">{k}</dt>34          <dd className="mono truncate tnum">{v}</dd>35        </div>36      ))}37    </dl>38  );39}40