Skip to content

Composite Indicator Panes

Render multi-layer trading indicators (histogram, lines, bands, markers) as native chart series. Use inside createStackedChart or any standalone createChart pane.

Import

typescript
import {
  buildIndicatorPane,
  buildIndicatorSeries,
  detectIndicatorMarkers,
  type IndicatorData,
  type IndicatorLineColorZones,
} from 'velo-plot/full';

Quick Example (Stacked Pane)

typescript
import { createStackedChart, buildIndicatorPane, detectIndicatorMarkers } from 'velo-plot/full';

const markers = detectIndicatorMarkers(x, fastLine, 4);

const wavePane = buildIndicatorPane({
  id: 'wave',
  height: 0.24,
  label: 'Wave',
  yRange: [-80, 80],
  tickCount: 5,
  data: {
    x,
    histogram: {
      y: histogram,
      positiveColor: '#26a69a',
      negativeColor: '#ef5350',
    },
    lines: [
      {
        id: 'fast',
        y: fastLine,
        width: 2,
        colorZones: {
          ref: 'slow',
          aboveColor: '#26a69a',  // buy / bullish
          belowColor: '#ef5350',  // sell / bearish
        },
      },
      { id: 'slow', y: slowLine, color: 'rgba(224, 64, 251, 0.55)', width: 1.5 },
    ],
    fills: [{
      upper: upperBand,
      lower: lowerBand,
      color: 'rgba(80, 60, 140, 0.35)',
    }],
    markers,
    referenceLines: [
      { y: 60, color: 'rgba(198, 40, 40, 0.45)' },
      { y: -60, color: 'rgba(38, 166, 154, 0.45)' },
    ],
  },
});

const stack = createStackedChart({
  container,
  masterPaneId: 'price',
  panes: [pricePane, volumePane, wavePane],
});

buildIndicatorPane

Returns a StackedPaneConfig ready for createStackedChart.

High-level presets (Stage 2)

typescript
import { createChart, buildIndicatorPaneFromPreset } from 'velo-plot/trading';

// Single chart — overlay or inline layers
await chart.addIndicator('bollinger', { period: 20, sourceSeriesId: 'candles' });
await chart.addIndicator('rsi', { period: 14, id: 'rsi' });

// Stacked chart — build pane at creation time
const rsiPane = await buildIndicatorPaneFromPreset('rsi', x, closePrices, {
  id: 'rsi',
  label: 'RSI (14)',
  height: 0.24,
});

const stack = createStackedChart({
  container,
  panes: [pricePane, volumePane, rsiPane],
});
PresetPlacementNotes
rsioscillator paneReference lines at 70 / 30
macdoscillator paneHistogram + MACD + signal
bollingerprice overlayBand fill + middle line
ema, smaprice overlaySingle line on source series Y axis
stochasticoscillator pane%K / %D lines with overbought/oversold refs

Calculations use the Stage 1 worker pool when available (indicatorsAsync).

typescript
function buildIndicatorPane(options: BuildIndicatorPaneOptions): StackedPaneConfig
PropertyTypeDefaultDescription
idstringrequiredPane id
dataIndicatorDatarequiredComposite indicator payload
heightnumber | string0.25Flex ratio inside stack
labelstring'Indicator'Y-axis label
yRange[number, number] | 'auto''auto'Lock Y range for oscillators
tickCountnumber5Y-axis tick count
showXAxisbooleanOverride X axis visibility
styleIndicatorStyleBaseline and marker styling
seriesIdstring{id}-indicatorRoot id for expanded series

buildIndicatorSeries

Lower-level expansion into native SeriesOptions[] (bar, line, band, scatter):

typescript
function buildIndicatorSeries(options: IndicatorSeriesOptions): SeriesOptions[]

Use when adding indicators to an existing chart:

typescript
const series = buildIndicatorSeries({
  id: 'macd',
  type: 'indicator',
  data: {
    x,
    histogram: { y: macdHist },
    lines: [{ y: signalLine, color: '#ff9800' }],
  },
});

for (const s of series) chart.addSeries(s);

IndicatorData Layers

LayerRenders asDescription
histogram2 bar series (pos/neg)Signed histogram split at zero
linesline seriesOne or more indicator lines
fillsband seriesUpper/lower envelope shading
markersscatter seriesPeak/trough markers
baselinedashed lineOptional reference at Y (e.g. 0 for MACD histogram)
referenceLineshorizontal linesFixed Y levels (overbought, etc.)

Histogram

typescript
histogram: {
  y: Float32Array,           // signed values
  positiveColor?: string,    // default '#26a69a'
  negativeColor?: string,    // default '#ef5350'
  opacity?: number,
  barWidth?: number,         // omit for time-axis auto width
}

Lines with Buy/Sell Colors (colorZones)

Split one logical line into colored segments at crossings with a reference:

typescript
lines: [{
  id: 'fast',
  y: fastLine,
  width: 2,
  colorZones: {
    ref: 'zero',              // 'zero' | number | another line id
    aboveColor: '#26a69a',
    belowColor: '#ef5350',
  },
}]
ref valueMeaning
'zero' or omittedCompare against Y = 0
numberConstant threshold (e.g. 60 for RSI)
stringId of another line in the same lines array

Example — color relative to a signal line:

typescript
{ id: 'signal', y: slowLine, color: '#888', width: 1.5 },
{
  id: 'fast',
  y: fastLine,
  colorZones: { ref: 'signal', aboveColor: '#00e5ff', belowColor: '#e040fb' },
}

Fills

typescript
fills: [{
  upper: Float32Array,
  lower: Float32Array,
  color?: string,
  opacity?: number,
}]

Markers

typescript
// Manual
markers: [{ x: 100, y: 42, kind: 'peak' }, { x: 200, y: -30, kind: 'trough' }]

// Auto-detect local extrema
import { detectIndicatorMarkers } from 'velo-plot/full';
const markers = detectIndicatorMarkers(x, y, 3); // window = 3

Indicator panes with histogram + lines use free Y pan/zoom (full canvas movement). Pure bar panes (volume) keep Y anchored at zero. See Stacked Chart — Interaction.

Known limitations

  • Bundle entry — pick velo-plot, velo-plot/trading, velo-plot/scientific, or velo-plot/full. See Bundle Architecture.
  • WebGPU renderer (renderer: 'webgpu') requires an extended bundle entry and is experimental — use WebGL (default) for production.
  • SVG export (exportSVG()) is unavailable on core-only imports and partial elsewhere; see Stage 6 SVG parity.
  • See Plugin status registry for plugin maturity (complete, partial, experimental).

Released under the MIT License.