Lattice Grid Buy a licence

demo D261

Starter kit: trading terminal

One market feed fans to a quotes grid and a movers grid narrowed by its own route, plus a price chart

createDataRouter · attach filter · priceFeed

Building…
Loading a live grid…

The configuration

'starter-trading-terminal': () => ({
  rows: [],
  config: {},
  foot: [
    'one market feed, fanned to a quotes grid and a movers grid',
    'the movers route narrows and sorts before a row reaches the grid',
    'the mock socket runs it with no backend; one line points it at real market data',
  ],
  mount: (el: HTMLElement, LG: any) => {
    const money = { style: 'currency', currency: 'USD', decimals: 2 } as const;
    const upDown = [
      { id: 'up', when: { op: 'gt', value: 0 }, style: { color: '#3ddc97' } },
      { id: 'down', when: { op: 'lt', value: 0 }, style: { color: '#ff6b6b' } },
    ];
    const cols = [
      { field: 'symbol', title: 'Symbol', layout: { width: 84, pin: 'start' } },
      { field: 'last', title: 'Last', type: 'number', format: money },
      { field: 'chg', title: 'Chg', type: 'number', format: { decimals: 2 } },
      { field: 'bid', title: 'Bid', type: 'number', format: money },
      { field: 'ask', title: 'Ask', type: 'number', format: money },
    ];
    const strip = document.createElement('div');
    strip.style.cssText = 'display:grid;grid-template-columns:1fr 1fr;gap:12px';
    el.append(strip);
    const quotesEl = panel(strip, 'Quotes');
    const moversEl = panel(strip, 'Biggest moves');
    const chartEl = chartHost(el, 220);
    const quotes = LG.createGrid(quotesEl, {
      rowKey: 'symbol', theme: 'dark', highlightOnChange: { duration: 350 },
      formatting: { chg: upDown }, columns: cols,
    });
    const movers = LG.createGrid(moversEl, {
      rowKey: 'symbol', theme: 'dark', highlightOnChange: { duration: 350 },
      formatting: { chg: upDown }, columns: cols,
    });
    let chart: any, socket: any;
    Promise.all([loadDataRouter(), loadCharts(), loadMockSocket()])
      .then(([dr, ch, ms]: any[]) => {
        const router = dr.createDataRouter({ key: 'type', rowKey: 'symbol', overlap: true });
        router.attach(quotes, 'price');
        router.attach(movers, 'price', {
          filter: (row: any) => Math.abs(row.chg) >= 0.4,
          sort: { key: 'chg', dir: 'desc' },
        });
        chart = ch.createChart({ grid: quotes, container: chartEl, type: 'bar', x: 'symbol', y: 'last', title: 'Last price by symbol' });
        socket = new ms.MockWebSocket({ feed: ms.priceFeed({ seed: 7 }), rate: 260 });
        pipe(socket, router);
      })
      .catch((err) => console.error('[starter-trading-terminal]', err));
    return () => {
      socket?.close?.();
      chart?.destroy?.();
      quotes?.destroy?.(); movers?.destroy?.();
    };
  },
})