Skip to content

Real-Time Data

ChartGPU is designed for live streaming. The recommended API is connectStream, which handles append-vs-update logic automatically.

connectStream

Pass a WebSocket or any AsyncIterable<Candle>. The chart decides whether to append or update based on the incoming timestamp:

  • Same timestamp as last candle → updates in place (tick update while candle is forming)
  • Newer timestamp → appends as a new candle
  • Older timestamp → ignored
ts
// WebSocket
const ws = new WebSocket('wss://feed.example.com/candles');
const disconnect = chart.connectStream(ws);

// Async iterable (custom generator, EventSource wrapper, etc.)
const disconnect2 = chart.connectStream(myAsyncGenerator());

// Stop streaming
disconnect();
// or: chart.disconnectStream();

chart.destroy() calls disconnectStream automatically.

WebSocket Example (Binance)

Binance kline stream sends JSON where the candle fields are nested under k. Wrap the WebSocket with a transform to map to the Candle shape:

ts
async function* binanceStream(symbol: string, tf: string): AsyncGenerator<Candle> {
  const ws = new WebSocket(`wss://stream.binance.com:9443/ws/${symbol}@kline_${tf}`);
  for await (const event of wsMessages(ws)) {
    const { k } = JSON.parse(event.data);
    yield {
      open:      parseFloat(k.o),
      high:      parseFloat(k.h),
      low:       parseFloat(k.l),
      close:     parseFloat(k.c),
      timestamp: k.t,
      volume:    parseFloat(k.v),
    };
  }
}

chart.connectStream(binanceStream('btcusdt', '1m'));

appendCandle

For manual control without connectStream:

ts
chart.appendCandle({
  open:      103.5,
  high:      105.2,
  low:       102.8,
  close:     104.1,
  timestamp: Date.now(),
  volume:    85000,
});

If the viewport is at the trailing edge, the chart advances automatically to keep the latest candle in view.

Updating the Last Candle

For manual tick-level updates:

ts
const candles = chart.getCandles();
candles[candles.length - 1] = updatedCandle;
chart.setCandles(candles);

connectStream handles this automatically — prefer it over manual updates.

Timeframe Switching

When the user changes the timeframe, fetch new candle data and reset:

ts
chart.setTimeframe('5m');
chart.setCandles(await fetchCandles('5m'));

setTimeframe fires the timeframeChange event which you can subscribe to:

ts
chart.on('timeframeChange', (tf) => {
  console.log('New timeframe:', tf);
});

Events

ts
chart.on('viewportChange', (viewport) => {
  // viewport.start, viewport.end changed (pan/zoom)
});

chart.on('timeframeChange', (tf) => {
  // User switched timeframe
});

Released under the MIT License.