Vela, our next-generation charting platform, is live at vela.luxalgo.com.
LuxAlgo

Examples

Static charts over your own bars and live, provider-backed charts, plus the in-repo playground.

View as Markdown

These snippets cover the two ways to run Vela™: static, over offline OHLCV you pass as data — no network, no API key, so it runs anywhere out of the box — and live, over a provider-backed market. The repository also ships an interactive playground.

These snippets import from the npm package @luxalgo/vela (see Installation).

Orientation snippet

The shape of every example is the same: create a chart over offline data, register a scripting engine, add an indicator. Vela™ ships no engine — these examples use the Pine addon (npm i @luxalgo/vela-pinets pinets; see Scripting engines).

import { Vela } from '@luxalgo/vela';
import { PineEngine } from '@luxalgo/vela-pinets';

const chart = new Vela('#chart', { data: myBars, timeframe: '1h', live: false, theme: 'dark' });
chart.registerEngine('pine', new PineEngine());

chart.addIndicator(`//@version=5
indicator("EMA", overlay=true)
plot(ta.ema(close, input.int(20, "Length")), "EMA", color.orange)`);

With offline data, timeframe only drives bar spacing and axis labels; there is no fetch.

Everything in one place — a provider-backed, live chart with a custom theme, the GPU backend, drawing tools, a scripting indicator, runtime tweaks, and events. Swap symbol for data: myBars (and drop live) to run the same thing offline.

Construct with the full option set:

import { Vela } from '@luxalgo/vela';
import { PineEngine } from '@luxalgo/vela-pinets';
import { BinanceProvider } from '@luxalgo/vela/providers/binance';

// A full custom theme — all seven fields are required.
const theme = {
  background:  '#0b0e14',
  textColor:   '#c9d1d9',
  gridColor:   '#1c2230',
  borderColor: '#30363d',
  upColor:     '#26a69a',
  downColor:   '#ef5350',
  fontFamily:  'Inter, system-ui, sans-serif',
};

const chart = new Vela('#chart', {
  // market — provider-backed; the `binance:` prefix pins the venue (use `data: myBars` instead to run offline)
  symbol: 'binance:BTCUSDT',
  timeframe: '1h',
  bars: 1000,
  live: true,
  // appearance
  theme,
  upColor: '#26a69a',           // candle colors live at the TOP level (the theme's up/down don't reach the candles)
  downColor: '#ef5350',
  priceStyle: 'candles',        // candles | bars | line | area | baseline
  currentPriceLine: true,
  logScale: false,
  glow: 0.4,                    // WebGL2 only
  // backend + motion
  nativeBackend: 'webgl2',      // auto | canvas2d | webgl2
  animations: { zoom: true, pan: false },
  // interactive layers
  drawings: { toolbar: true, tools: ['trendline', 'hline', 'ray', 'box', 'text'] },
  // scripting
  defaultLanguage: 'pine',
});

Wire up the provider, engine, an indicator, runtime tweaks, and events:

// Neither a provider nor an engine is bundled; registerEngine is chainable.
chart.data.registerProvider('binance', new BinanceProvider());
chart.registerEngine('pine', new PineEngine());

await chart.data.ready(); // provider symbol index settled
await chart.ready();      // chart painted and interactive

// A Pine indicator in its own pane — the handle is usable synchronously.
const rsi = chart.addIndicator(
  `//@version=5
indicator("RSI")
plot(ta.rsi(close, input.int(14, "Length")), "RSI", color.purple)`,
  { pane: 'new', title: 'RSI (14)' }, // AddIndicatorOptions: id / language / inputs / props / overlay / pane / title
);
rsi.on('ready', () => console.log(rsi.title, '→', rsi.inputs.length, 'inputs'));
rsi.on('error', ({ error }) => console.error('RSI failed:', error.message));


// Chart-level events.
chart.on('bar', (bar) => { /* the forming bar updated or a new bar appended */ });
chart.on('indicator:error', ({ id, error }) => console.error(id, error.message));

// Runtime appearance — no rebuild, no indicator re-run.
if (chart.renderer.supports('glow')) chart.renderer.set('glow', 0.6);
chart.renderer.set({ logScale: true, gridlines: true, timezone: 'America/New_York' });

// Frame a preset range, then read the exact window back.
chart.setVisibleRangePreset('3M');
const range = chart.getVisibleRange(); // { from, to } in epoch-ms (non-null after ready)

// Programmatic drawing + JSON round-trip.
if (range && chart.drawings.supported) {
  chart.drawings.add('trendline', {
    paneId: 'price',
    anchors: [{ time: range.from, price: 30000 }, { time: range.to, price: 40000 }],
  });
  const saved = chart.drawings.toJSON(); // chart.drawings.fromJSON(saved) restores it
}

// Export a PNG snapshot; tear everything down when done.
const png = chart.renderer.screenshot(); // PNG data URL, or null if unsupported
// chart.destroy();

Every option above is documented in Options; every method and event in API reference.

Static or live

ModeWhat it shows
StaticHistory only: candles plus indicators over the offline bars you pass as data, with live left off.
LiveA provider-backed symbol with live: true: the forming candle updates on each real tick, a new candle appends when the interval rolls over, and indicators recompute. Observe ticks with chart.on('bar', …).

Bars you pass as data never move on their own. From Vela™ 0.8.4, they are shown exactly as given, even with live: true. To stream real updates onto your own bars, register a data provider that implements subscribe, and load its symbol instead of passing data.

On Vela™ 0.8.3 or earlier, leave live off for bars you pass as data. Those versions fill that combination in with simulated ticks: the last candle moves at random by up to 0.15% and made-up candles are appended, so real data shows price movement that never happened. Upgrade to 0.8.4 or later to remove them.

Adding drawings from code

The drawing toolbar is interactive by default; you can also place drawings programmatically and round-trip them through JSON:

chart.drawings.add('trendline', {
    paneId: 'price',
    anchors: [
        { time: myBars[10].time, price: myBars[10].low },
        { time: myBars[40].time, price: myBars[40].high },
    ],
});

const saved = chart.drawings.toJSON(); // persist this however you like
chart.drawings.fromJSON(saved);        // …and restore it later

See Drawing Tools for the full tool catalogue and toolbar UX.

Playground

The in-repo playground (npm run playground) mounts the full single-chart shell against live Binance data straight from the source (open /widget.html from the index) — edit playground/widget.ts to try options, providers, or your own indicator manifest. Press ? in the shell for the shortcut list.

Next steps

On this page