OHLC Bar Chart — Apache ECharts

An OHLC (Open-High-Low-Close) bar chart displays financial price data using vertical bars with horizontal tick marks. Each bar shows the price range from high to low as a thin vertical line, with a left tick indicating the opening price and a right tick indicating the closing price. Unlike candlestick charts that use colored bodies, OHLC bars provide a cleaner, less cluttered view favored by technical analysts who prefer to focus on price levels rather than visual patterns.

OHLC Bar Chart rendered with Apache ECharts

Renders

JavaScript source (Apache ECharts)

// anyplot.ai
// ohlc-bar: OHLC Bar Chart
// Library: echarts 6.1.0 | JavaScript 22.23.2
// Quality: 93/100 | Created: 2026-09-02

const t = window.ANYPLOT_TOKENS;
const UP_COLOR = t.palette[0]; // #009E73 brand green — profit/up semantic
const DOWN_COLOR = t.palette[4]; // #AE3030 matte red — loss/down semantic

// --- Data: 45 trading days of a fictional stock's OHLC prices --------------
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"];
const NUM_DAYS = 45;

function seededRandom(seed) {
  let s = seed;
  return function () {
    s = (s * 1103515245 + 12345) & 0x7fffffff;
    return s / 0x7fffffff;
  };
}
const rand = seededRandom(42);

const dateLabels = [];
const cursor = new Date(2024, 0, 2); // Tue Jan 2 2024
while (dateLabels.length < NUM_DAYS) {
  const weekday = cursor.getDay();
  if (weekday !== 0 && weekday !== 6) {
    dateLabels.push(`${MONTHS[cursor.getMonth()]} ${cursor.getDate()}`);
  }
  cursor.setDate(cursor.getDate() + 1);
}

const ohlcRows = [];
let lastClose = 182;
for (let i = 0; i < NUM_DAYS; i++) {
  const open = lastClose + (rand() - 0.5) * 3;
  const drift = (rand() - 0.47) * 6; // slight upward drift over the period
  const close = open + drift;
  const high = Math.max(open, close) + rand() * 2.6;
  const low = Math.min(open, close) - rand() * 2.6;
  ohlcRows.push([i, +open.toFixed(2), +high.toFixed(2), +low.toFixed(2), +close.toFixed(2)]);
  lastClose = close;
}

// --- Find the steepest single-day move for the storytelling callout --------
let extremeIndex = 0;
let extremeMove = ohlcRows[0][4] - ohlcRows[0][1];
for (const [xIndex, open, , , close] of ohlcRows) {
  const move = close - open;
  if (Math.abs(move) > Math.abs(extremeMove)) {
    extremeMove = move;
    extremeIndex = xIndex;
  }
}

// --- Custom render: I-beam OHLC bars ----------------------------------------
// Bearish bars use a dashed stroke in addition to red, so the up/down signal
// survives for red-green color-vision-deficient viewers, not just via hue.
function renderOhlcBar(params, api) {
  const xIndex = api.value(0);
  const openPoint = api.coord([xIndex, api.value(1)]);
  const highPoint = api.coord([xIndex, api.value(2)]);
  const lowPoint = api.coord([xIndex, api.value(3)]);
  const closePoint = api.coord([xIndex, api.value(4)]);
  const tickLength = api.size([1, 0])[0] * 0.32;
  const isUp = api.value(4) >= api.value(1);
  const lineStyle = isUp
    ? { stroke: UP_COLOR, lineWidth: 2.6 }
    : { stroke: DOWN_COLOR, lineWidth: 2.6, lineDash: [6, 3] };

  return {
    type: "group",
    children: [
      {
        type: "line",
        shape: { x1: highPoint[0], y1: highPoint[1], x2: lowPoint[0], y2: lowPoint[1] },
        style: lineStyle,
      },
      {
        type: "line",
        shape: { x1: openPoint[0] - tickLength, y1: openPoint[1], x2: openPoint[0], y2: openPoint[1] },
        style: lineStyle,
      },
      {
        type: "line",
        shape: { x1: closePoint[0], y1: closePoint[1], x2: closePoint[0] + tickLength, y2: closePoint[1] },
        style: lineStyle,
      },
    ],
  };
}

// --- Init + option -----------------------------------------------------------
const chart = echarts.init(document.getElementById("container"));

chart.setOption({
  animation: false,
  backgroundColor: "transparent",
  title: {
    text: "Aurora Robotics · ohlc-bar · javascript · echarts · anyplot.ai",
    left: "center",
    top: 24,
    textStyle: { color: t.ink, fontSize: 22, fontWeight: 500 },
  },
  legend: {
    data: ["Bullish (close > open)", "Bearish (close < open)"],
    top: 78,
    textStyle: { color: t.inkSoft, fontSize: 16 },
    itemWidth: 26,
    itemHeight: 3,
  },
  grid: { left: 130, right: 60, top: 150, bottom: 110 },
  xAxis: {
    type: "category",
    data: dateLabels,
    boundaryGap: true,
    axisLabel: { color: t.inkSoft, fontSize: 14, interval: 3 },
    axisLine: { lineStyle: { color: t.inkSoft } },
    axisTick: { show: false },
    splitLine: { show: false },
  },
  yAxis: {
    type: "value",
    scale: true,
    name: "Price (USD)",
    nameLocation: "middle",
    nameGap: 44,
    nameRotate: 90,
    nameTextStyle: { color: t.inkSoft, fontSize: 14 },
    axisLabel: { color: t.inkSoft, fontSize: 14, formatter: (v) => `$${v}` },
    axisLine: { show: false },
    splitLine: { lineStyle: { color: t.grid } },
  },
  series: [
    {
      name: "Bullish (close > open)",
      type: "line",
      data: [],
      symbol: "none",
      itemStyle: { color: UP_COLOR },
      lineStyle: { color: UP_COLOR, width: 2.6 },
    },
    {
      name: "Bearish (close < open)",
      type: "line",
      data: [],
      symbol: "none",
      itemStyle: { color: DOWN_COLOR },
      lineStyle: { color: DOWN_COLOR, width: 2.6, type: "dashed" },
    },
    {
      name: "OHLC",
      type: "custom",
      renderItem: renderOhlcBar,
      encode: { x: 0, y: [1, 2, 3, 4] },
      data: ohlcRows,
    },
  ],
});

// --- Storytelling callout: annotate the steepest single-day move -----------
const extremeRow = ohlcRows[extremeIndex];
const anchorPrice = extremeMove >= 0 ? extremeRow[2] : extremeRow[3]; // high : low
const anchorPixel = chart.convertToPixel({ xAxisIndex: 0, yAxisIndex: 0 }, [
  dateLabels[extremeIndex],
  anchorPrice,
]);
const calloutLabel =
  extremeMove >= 0
    ? `Steepest rally: +$${extremeMove.toFixed(2)}`
    : `Steepest drawdown: -$${Math.abs(extremeMove).toFixed(2)}`;
const labelOffset = extremeMove >= 0 ? -38 : 38;
const labelY = anchorPixel[1] + labelOffset;

chart.setOption({
  graphic: {
    elements: [
      {
        type: "group",
        children: [
          {
            type: "line",
            shape: {
              x1: anchorPixel[0],
              y1: anchorPixel[1],
              x2: anchorPixel[0],
              y2: labelY + (extremeMove >= 0 ? 14 : -14),
            },
            style: { stroke: t.inkSoft, lineWidth: 1 },
          },
          {
            type: "text",
            x: anchorPixel[0],
            y: labelY,
            style: {
              text: calloutLabel,
              fill: t.ink,
              font: "600 13px sans-serif",
              textAlign: "center",
              textVerticalAlign: extremeMove >= 0 ? "bottom" : "top",
            },
          },
        ],
      },
    ],
  },
});

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/ohlc-bar/echarts/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "ohlc-bar",
  "language": "javascript",
  "library": "echarts",
  "page": "https://anyplot.ai/ohlc-bar/javascript/echarts",
  "hub": "https://anyplot.ai/ohlc-bar",
  "code_json": "https://api.anyplot.ai/specs/ohlc-bar/echarts/code",
  "spec_json": "https://api.anyplot.ai/specs/ohlc-bar",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/javascript/echarts/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/javascript/echarts/plot-dark.png",
  "interactive_light_html": "https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/javascript/echarts/plot-light.html",
  "interactive_dark_html": "https://storage.googleapis.com/anyplot-images/plots/ohlc-bar/javascript/echarts/plot-dark.html",
  "quality_score": 93.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of OHLC Bar Chart on anyplot.ai.

Other implementations