Real-time Streaming

For live data, appendData() adds a bar (or updates the one currently forming) and refreshes the price candles, every active overlay and oscillator pane, the volume pane, and the x-axis incrementally, in O(active indicators x small tail) instead of the full teardown and rebuild that update() performs. Use it for tickers and any high-frequency feed.

Signature

apexStock.appendData(pointOrPoints, options)
  • pointOrPoints — one OHLC bar { x, y: [o, h, l, c], v } or an array of them for a batch. Malformed points are dropped, exactly like the constructor.
  • options.view"follow" (default) rides the right edge, shifting a zoomed window to include the new bar; "preserve" keeps the current zoom window unchanged.
  • options.maxPoints — a rolling-window cap: trims the oldest bars off the front so the buffer stays fixed-width.
  • options.updateLast — when the incoming x equals the last bar's x, replace that (forming) bar instead of appending.

It returns the instance, so calls can be chained.

Appending completed bars

When a bar closes, append it and ride the right edge:

apexStock.appendData({ x: t, y: [o, h, l, c], v }, { view: 'follow' })

To keep a fixed-width window (for example, the last 500 bars in a live ticker), pass maxPoints:

apexStock.appendData(bar, { maxPoints: 500 })

Running indicators keep their carried state when bars age out of the window, so their values reflect all history seen and do not jump when old bars are trimmed.

Updating a forming candle

Set updateLast: true to keep the in-progress bar live as ticks arrive, then start a new bar when the period rolls over:

let bar = null // the bar currently forming

function onTrade({ time, price, size }) {
  const bucket = Math.floor(time / 60000) * 60000 // 1-minute buckets
  if (!bar || bar.x !== bucket) {
    // New period: the previous bar closed; start a fresh forming bar.
    bar = { x: bucket, y: [price, price, price, price], v: size }
  } else {
    // Same period: fold the trade into the forming bar.
    bar.y[1] = Math.max(bar.y[1], price) // high
    bar.y[2] = Math.min(bar.y[2], price) // low
    bar.y[3] = price // close
    bar.v += size
  }
  apexStock.appendData(bar, { updateLast: true })
}

A forming bar's indicator values recompute from the last committed state each tick, and the bar's close commits in O(1), so indicators stay exact.

Follow vs preserve

  • "follow" (default) is what you usually want for a live feed: the newest bar stays visible even if the user has zoomed in.
  • "preserve" is right when the user is inspecting history and you do not want new bars to yank the viewport:
apexStock.appendData(bar, { view: 'preserve' })

Batching

Passing an array applies the whole batch in one pass, which is cheaper than calling appendData per bar when catching up after a reconnect:

apexStock.appendData(missedBars, { view: 'follow' })

Streaming and other features

  • Indicators update incrementally as bars arrive, see Technical Indicators.
  • Trading overlays are price-only (horizontal), so they are unaffected by appends, and their onCross callback is what fires when a newly-closed bar crosses a line, see Trading Overlays.
  • To build bars from a raw tick feed, see Time-frame Aggregation.