Exciting Update: Version 1.0.0 is now available, introducing high-performance technical indicators and custom drawing tools. Read more
Version: 1.0.0

Custom Series Types

By registering a Custom Series Type, you can override how candlesticks or lines are painted. You can define custom render functions to handle alternate pricing models (like Renko, hollow candles, or custom range bars).

Registering a Custom Series

Custom series renderers are registered on the window.ChartingAPI namespace using the registerCandleType method. You pass a unique identifier string and a rendering callback function:

window.ChartingAPI.registerCandleType(name, rendererFunc);

Renderer Callback Arguments

The renderer function receives the following arguments from the chart rendering cycle:

  • ctx

    The 2D HTML5 Canvas rendering context.

  • visibleBars

    An array of bar data currently visible in the viewport: [{{ time, open, high, low, close, volume }}].

  • slot / bodyW

    slot is the total width allocated per candle (including gaps). bodyW is the calculated candle body width.

  • priceToY(price)

    A coordinate utility function to convert numeric stock price values to Y positions on the canvas.

  • xOffset

    The starting X offset on the canvas corresponding to the first visible bar.

Example: Custom Orange Candle Renderer

Below is the registration of an orange custom candlestick series that renders hollow candle bodies for bullish bars:

window.ChartingAPI.registerCandleType('orange_hollow', function(ctx, visibleBars, slot, bodyW, chartH, priceToY, themeColors, xOffset) {
  ctx.save();
  ctx.strokeStyle = '#ff9800';
  ctx.lineWidth = 1.5;

  visibleBars.forEach((bar, index) => {
    const x = xOffset + index * slot + slot / 2;
    const yOpen = priceToY(bar.open);
    const yClose = priceToY(bar.close);
    const yHigh = priceToY(bar.high);
    const yLow = priceToY(bar.low);

    // Draw wicks
    ctx.beginPath();
    ctx.moveTo(x, yHigh); ctx.lineTo(x, yLow);
    ctx.stroke();

    // Draw body
    if (bar.close >= bar.open) {
      // Bullish hollow body
      ctx.strokeRect(x - bodyW / 2, Math.min(yOpen, yClose), bodyW, Math.max(1, Math.abs(yClose - yOpen)));
    } else {
      // Bearish filled body
      ctx.fillStyle = '#ff9800';
      ctx.fillRect(x - bodyW / 2, Math.min(yOpen, yClose), bodyW, Math.max(1, Math.abs(yClose - yOpen)));
    }
  });
  ctx.restore();
});