chart

Docs › Chart types

Candlestick and OHLC charts with volume and moving averages

@82chart/stock: candlesticks and OHLC bars with a volume pane, SMA/EMA, Korean or global colors, realtime ticks, zoom, keyboard access and SSR. Free, MIT.

A candlestick chart draws the open, high, low and close of each period (a day, a minute) as one candle, showing how a price moved. A candle that closes above its open is rising, one that closes below is falling, and the thin wicks reach the high and the low. An OHLC chart draws the same four values as a vertical line with short ticks to the left and right.

Stock charts in 82chart come as a separate package on top of the core, @82chart/stock: candlesticks and OHLC bars, a volume pane and moving averages of the close (SMA, EMA). Tooltips, keyboard, zoom, realtime, export and server rendering work as on any other 82chart. The default colors follow Korean brokerage apps, red up and blue down; colors: 'global' switches to green and red.

npm i @82chart/core @82chart/stock
import { createStockChart } from '@82chart/stock';
import '@82chart/core/styles.css';

createStockChart('#chart', {
  title: 'ACME',
  data: { series: [{ name: 'ACME', data: bars }] }, // { x, open, high, low, close, volume }
  stock: { ma: [5, 20, 60] },
});

// with the core createChart, register the types once
import { createChart, use } from '@82chart/core';
import { stock } from '@82chart/stock';
use(stock); // 'candlestick', 'ohlc'
createChart('#chart', { type: 'candlestick', data });

The example below is 60 trading days of a made-up share. Hover, or focus the chart and use ← →: the tooltip shows close, open, high, low, volume, the change from the previous close and the moving averages. Drag to zoom.

Live example

Code for this example

createChart('#chart', {
  type: 'candlestick',
  title: '82 Electronics (sample)',
  subtitle: 'Daily bars, 60 trading days',
  zoom: true,
  stock: { ma: [5, 20] },
  data: {
    series: [{
      name: '82 Elec.',
      data: Array.from({ length: 60 }, (_, i) => {
        // Mon–Fri, 60 trading days (2026-07-27 to 10-16)
        const day = new Date(Date.UTC(2026, 6, 27 + Math.floor(i / 5) * 7 + (i % 5)));
        const base = 70000 + Math.sin(i / 7) * 4000 + i * 60;
        const open = Math.round((base + Math.sin(i * 1.3) * 700) / 100) * 100;
        const close = Math.round((base + Math.sin(i * 2.1 + 1) * 900) / 100) * 100;
        return {
          x: day.toISOString().slice(0, 10),
          open,
          high: Math.max(open, close) + 100 + ((i * 37) % 5) * 100,
          low: Math.min(open, close) - 100 - ((i * 53) % 5) * 100,
          close,
          volume: 1200000 + ((i * 7919) % 900) * 1000,
        };
      }),
    }],
  },
});

Data format

  • A bar is an object { x, open, high, low, close, volume } or a tuple straight from an API, [date, open, high, low, close, volume]. Volume is optional.
  • x is a date string ('2026-10-21'), a time ('2026-10-21T09:01'), a Date or epoch milliseconds.
  • The x axis is the list of bars, so weekends and holidays leave no gaps. Date labels sit where the month changes.
  • A bar is rising when the close is above the open and falling when below; a bar that closes at its open compares with the previous close.
  • The first series is the price; further line series are drawn on the price scale (your own indicator lines, for example).

OHLC bars and global colors

type: 'ohlc' draws the same data as OHLC bars. For readers outside Korea use colors: 'global' (green up, red down). This one has no volume pane and a 20-day exponential moving average.

Live example

Code for this example

createChart('#chart', {
  type: 'ohlc',
  title: 'OHLC bars, global colors',
  stock: { colors: 'global', volume: false, ma: [{ period: 20, type: 'ema' }] },
  data: {
    series: [{
      name: '82 Elec.',
      data: Array.from({ length: 60 }, (_, i) => {
        // the same 60 trading days
        const day = new Date(Date.UTC(2026, 6, 27 + Math.floor(i / 5) * 7 + (i % 5)));
        const base = 70000 + Math.sin(i / 7) * 4000 + i * 60;
        const open = Math.round((base + Math.sin(i * 1.3) * 700) / 100) * 100;
        const close = Math.round((base + Math.sin(i * 2.1 + 1) * 900) / 100) * 100;
        return {
          x: day.toISOString().slice(0, 10),
          open,
          high: Math.max(open, close) + 100 + ((i * 37) % 5) * 100,
          low: Math.min(open, close) - 100 - ((i * 53) % 5) * 100,
          close,
          volume: 1200000 + ((i * 7919) % 900) * 1000,
        };
      }),
    }],
  },
});

Realtime ticks

With realtime on, append() takes trades { x, price, volume }: when x is the last bar's, that bar's high, low, close and volume move; a new x opens a new bar. A finished bar { x, open, high, low, close, volume } replaces the bar with the same x or is added. For minute bars, put times in x.

Live example

Code for this example

const chart = createChart('#chart', {
  type: 'candlestick',
  title: 'Live trades (sample)',
  realtime: { window: 40 },
  zoom: true,
  stock: { ma: [5] },
  data: {
    series: [{
      name: '82 Elec.',
      data: Array.from({ length: 60 }, (_, i) => {
        // the window keeps the latest 40 bars (realtime.window)
        const day = new Date(Date.UTC(2026, 6, 27 + Math.floor(i / 5) * 7 + (i % 5)));
        const base = 70000 + Math.sin(i / 7) * 4000 + i * 60;
        const open = Math.round((base + Math.sin(i * 1.3) * 700) / 100) * 100;
        const close = Math.round((base + Math.sin(i * 2.1 + 1) * 900) / 100) * 100;
        return {
          x: day.toISOString().slice(0, 10),
          open,
          high: Math.max(open, close) + 100 + ((i * 37) % 5) * 100,
          low: Math.min(open, close) - 100 - ((i * 53) % 5) * 100,
          close,
          volume: 1200000 + ((i * 7919) % 900) * 1000,
        };
      }),
    }],
  },
});
// each trade moves the last bar (high, low, close, volume); every 10th opens the next trading day
let day = Date.UTC(2026, 9, 16);
let price = 72000;
let n = 0;
setInterval(() => {
  if (++n % 10 === 0) day += 86400000 * (new Date(day).getUTCDay() === 5 ? 3 : 1);
  price = Math.max(1000, Math.round((price + (Math.random() - 0.5) * 600) / 100) * 100);
  chart.append({ x: new Date(day).toISOString().slice(0, 10), price, volume: Math.round(Math.random() * 40000) });
}, 600);

Options (stock)

OptionDefaultWhat it does
ma–Moving averages of the close: [5, 20] or [{ period: 20, type: 'ema', color, name }], in fixed colors that are neither red nor blue
volumeon when bars have volumefalse hides the pane; { height: 0.3 } sets its share of the plot
colors'korea''korea': red up, blue down. 'global': green up, red down
priceFormat'comma'Price labels (71,500); prices are never shortened to 만/억. unit, prefix and decimals apply
lastPricetrueThe last close as a tag on the price axis with a dotted line

Other options (title, theme, zoom, realtime, height, language, …) work as on any chart. The helpers sma(values, period) and ema(values, period) return the averages (null until there are enough values) and toBar(datum) reads one bar.

What comes with it

  • Keyboard: focus the chart, ← → step one bar, Home and End jump to the ends. Screen readers hear a summary with the change over the period, the high and the low.
  • Export: PNG, SVG, CSV and Excel (xlsx); CSV and xlsx have date, open, high, low, close and volume columns.
  • Server rendering: use(stock) with renderToSVG from @82chart/core/server makes candle SVGs without a DOM.
  • Script tag: load 82chart-stock.min.js after 82chart.min.js, then Chart82.createChart(el, { type: 'candlestick', … }) (CDN).
  • Size: the lite entry with candlesticks is about 30.7 KB gzipped; the extra CDN file about 5.9 KB (Import only the charts you use).

Frequently asked questions

Why is up red?

It is the Korean convention (brokerage apps and HTS show rising bars red, falling bars blue). For other audiences use stock: { colors: 'global' }: green up, red down.

Does it take minute bars and ticks?

Yes. Put times (ISO strings or epoch milliseconds) in x, turn on realtime and pass trades to chart.append({ x, price, volume }): the last bar moves, and a new time opens a new bar.

Are there indicators such as RSI or MACD?

0.5 has moving averages (SMA, EMA) and volume. Add other indicators as line series computed with sma, ema or your own code; they are drawn on the price scale.

Is this stock chart library free for commercial use?

Yes. @82chart/stock is MIT like the core: free in commercial products, with no key, watermark or attribution requirement.