Indicators
Indicators are drawing layers hosted inside a Panel. They receive DrawState with priceRange injected by CandlePanel, so they can convert prices to pixel coordinates.
Toggle visibility: indicator.visible = false.
Built-in Indicators
SMAIndicator
Simple Moving Average line.
ts
import { SMAIndicator } from 'chartgpu';
const sma = new SMAIndicator(20, { color: '#f59e0b' });
candlePanel.addIndicator(sma);
// Toggle
sma.visible = false;
chart.redraw();| Argument | Type | Description |
|---|---|---|
period | number | Number of candles to average. |
options.color | string | Line color. Default: #f59e0b |
EMAIndicator
Exponential Moving Average line.
ts
import { EMAIndicator } from 'chartgpu';
const ema = new EMAIndicator(50, { color: '#a78bfa' });
candlePanel.addIndicator(ema);| Argument | Type | Description |
|---|---|---|
period | number | EMA period. |
options.color | string | Line color. Default: #a78bfa |
BollingerBandsIndicator
Upper band, lower band, and middle SMA.
ts
import { BollingerBandsIndicator } from 'chartgpu';
const bb = new BollingerBandsIndicator(20, 2);
bb.visible = false; // off by default
candlePanel.addIndicator(bb);| Argument | Type | Description |
|---|---|---|
period | number | SMA period. Default: 20 |
stdDev | number | Standard deviation multiplier. Default: 2 |
Custom Indicators
Extend Indicator:
ts
import { Indicator, type DrawState } from 'chartgpu';
class VWAPIndicator extends Indicator {
draw(state: DrawState): void {
if (!state.priceRange) return;
const { ctx, candles, viewport, section, chartWidth, paddingX, priceRange } = state;
const { top, height } = section;
const { min, range } = priceRange;
const vp = viewport;
const viewLen = vp.end - vp.start;
// Compute VWAP
let cumPV = 0, cumV = 0;
const values = candles.map(c => {
const typical = (c.high + c.low + c.close) / 3;
cumPV += typical * (c.volume ?? 1);
cumV += (c.volume ?? 1);
return cumPV / cumV;
});
ctx.save();
ctx.strokeStyle = '#f472b6';
ctx.lineWidth = 1.5;
ctx.beginPath();
let started = false;
for (let i = 0; i < values.length; i++) {
const x = paddingX + ((i + 0.5 - vp.start) / viewLen) * chartWidth;
if (x < paddingX - 5 || x > paddingX + chartWidth + 5) { started = false; continue; }
const y = top + height * (1 - (values[i] - min) / range);
if (!started) { ctx.moveTo(x, y); started = true; } else ctx.lineTo(x, y);
}
ctx.stroke();
ctx.restore();
}
}