BloxwapChart SDK
Guides

Indicators

Add built-in studies or register a calculation of your own.

Built-in studies

NameStudyDefault placementDefault params
smaSimple moving averageMain paneperiod: 20
emaExponential moving averageMain paneperiod: 20
bollBollinger BandsMain paneperiod: 20, mult: 2
vwapVolume weighted average price, with optional bandsMain paneanchor: 0, bands: 0
ma-ribbonMoving average ribbon, up to eight averagesMain panetype: 1, len1: 20, len2: 50, len3: 100, len4: 200
supertrendSupertrendMain paneperiod: 10, multiplier: 3
ichimokuIchimoku CloudMain paneconversion: 9, base: 26, span: 52, displacement: 26
donchianDonchian ChannelsMain paneperiod: 20
psarParabolic SARMain panestart: 0.02, increment: 0.02, max: 0.2
macdMoving average convergence/divergenceSub-panefast: 12, slow: 26, signal: 9
rsiRelative strength indexSub-paneperiod: 14
kdjKDJ oscillatorSub-paneperiod: 9
volVolumeSub-paneNone
adxAverage directional index with +DI and -DISub-paneadxSmoothing: 14, diLength: 14
cciCommodity channel index, with ±100 bandsSub-paneperiod: 20
mfiMoney flow index, with 80/20 bandsSub-paneperiod: 14
obvOn balance volumeSub-paneNone
atrAverage true rangeSub-paneperiod: 14
stochStochastic, with 80/20 bandsSub-paneperiod: 14, smoothK: 1, smoothD: 3
stochrsiStochastic RSI, with 80/20 bandsSub-panersi: 14, stoch: 14, k: 3, d: 3

The newer studies follow TradingView's definitions. Choice inputs are numbers: VWAP's anchor is 0 (session), 1 (week), or 2 (month), and a positive bands multiplier adds bands with a fill. The MA ribbon's type is 0 (SMA) or 1 (EMA), and a length of 0 turns that average off. Ichimoku's spans are displaced into the whitespace after the last bar.

const smaId = chart.addIndicator({ name: 'sma', params: { period: 20 } });
const rsiId = chart.addIndicator({ name: 'rsi', params: { period: 14 } });
chart.addIndicator({ name: 'vol' });

// Remove a specific instance, rather than all instances with the same name.
chart.removeIndicator(smaId);

addIndicator merges parameter overrides with the registered defaults; colors replaces the default color list. It returns an instance ID. Supply your own stable id when an application needs to refer to a study later.

Configure existing indicators

chart.updateIndicator(rsiId, { params: { period: 21 } }); // params merge per key
chart.updateIndicator(rsiId, { visible: false });          // hide, keeping the config
chart.getIndicator(rsiId);                                 // the config, or undefined

updateIndicator(id, patch) returns whether the instance exists. params merge over the current values; colors, lineWidths, and hiddenLines replace. Only parameter and color changes recompute; widths, hidden plots, pane, and visibility just repaint. Replacing the whole indicators array through updateConfig still works.

Style an instance

Each instance can restyle its plots without a new definition:

chart.addIndicator({
  name: 'macd',
  colors: ['#00ff3f', '#ff479c', 'up', 'down'], // MACD, signal, histogram positive and negative
  lineWidths: [2, 1],                  // per line plot
  hiddenLines: ['hist'],               // keys of lines, bars, fills, or levels to hide
});
  • Colors replace the definition's defaultColors and are indexed the same way, so pass one per entry. The 'up' and 'down' tokens follow the series colors, so direction-colored bars always match the candles.
  • Widths are indexed by the definition's line plots, in the order of indicatorLineKeys(def), so a width stays with its plot when a study omits some lines. Missing or non-positive entries keep 1px.
  • Hidden plots hide lines, histogram bars, fills, or levels by key. A band fill stays when you hide one of its boundary lines, as in TradingView; hide the fill by its own key.

The keys and color slots of each built-in are in its styles metadata (below). For example, CCI and MFI have upperBand and lowerBand levels (colors 1 and 2), and VWAP's band fill is bandsFill (color 3, default rgba(76, 175, 80, 0.1)).

Indicators dialog

createIndicatorsDialog from @bloxwap/chart/ui adds TradingView's indicator picker and per-study settings:

import { createIndicatorsDialog } from '@bloxwap/chart/ui';

const indicators = createIndicatorsDialog({
  chart,
  document,                 // injected, never a global
  theme: 'dark',            // change later with setTheme()
  settingsOnAdd: true,      // open a study's settings right after adding it (default false)
  onOpen: () => settings.close(),
  onChange: () => save(chart.getConfig().indicators),
});

indicatorsButton.onclick = () => indicators.openPicker();
legendGear.onclick = () => indicators.openSettings(studyId); // false if there is no such study
  • Picker: search every registered indicator by name, short name, or group. Overlays go on the price pane; oscillators get their own pane. Click a result, or type and press Enter, to add it. The On chart list shows each study's short name and inputs (for example MACD 12 26 9) with settings, show/hide, and remove buttons.
  • Settings: Inputs are number fields that honor each input's min, max, step, and whole-number rules, or selects for choice inputs. Style has one row per plot with a visibility checkbox, a color per series (the MACD histogram and Supertrend have two), and a 1 to 4px width for lines and dots. Translucent colors keep their opacity when you pick a new color; their swatches show the color at full opacity, and the tooltip gives the stored value. Visibility chooses the pane and shows or hides the study.
  • Buttons: changes apply live. OK keeps them. Cancel, Escape, or the close button restores the study as it was when its settings opened. Defaults restores the definition's inputs, colors, widths, visible plots, and pane.
  • Accessibility: it is a labelled, modal role="dialog". Focus moves in on open and returns on close, Tab stays inside, arrow keys move through the list, and Escape clears the search, then closes. After a finger press, focus goes to the dialog itself rather than the search or the first input, so the on-screen keyboard doesn't cover it; tap a field to type.
  • Outside changes: the dialog follows studies added, changed, hidden, or removed anywhere (the context menu, the toolbar, your own code) as soon as they render, through subscribeConfigChange. The open picker relists On chart (keeping the search and the focused row button), open settings resync their controls and candle-following colors when their study or the candle colors change (a value you are typing survives changes to other studies), and settings whose study is removed go back to the picker they were opened from, or close. indicators.refresh() is only needed inside a chart.batch or after editing indicator configs in place. setTheme(theme) refreshes too.

Custom indicators registered without metadata work as well: each defaultParams key becomes a number field (smoothK is labelled "Smooth K"), and each default color becomes a "Plot n" row. indicatorInputs(def) and indicatorStyleGroups(def) return the same input and style-row model for your own UI. INDICATORS_DIALOG_CSS is exported for shadow-DOM or server-rendered hosts.

The chart's context menu adds Settings…, Hide, and Remove for the indicator under the pointer, found with chart.indicatorAt(x, y), and for the study owning a sub-pane when you right-click its empty space, found with chart.paneAt(y).

Register a custom indicator

import type { IndicatorDef } from '@bloxwap/chart';

const reference: IndicatorDef = {
  name: 'close-offset',
  defaultParams: { offset: 5 },
  defaultColors: ['#bcf582'],
  defaultPane: 'main',
  compute(candles, params, colors) {
    return {
      pane: 'main',
      lines: [{
        key: 'reference',
        color: colors[0],
        values: candles.map((candle) => candle.close + params.offset),
      }],
    };
  },
};

chart.indicators.register(reference);
chart.addIndicator({ name: 'close-offset', params: { offset: 10 } });

Calculations must be pure. Return values aligned to the input candles, using null for unavailable values such as a moving average's warmup period. Results are cached; do not mutate them after returning them.

Output shapes

compute returns an IndicatorOutput:

FieldDraws
linesLines with key, values, and color; optional lineWidth, style ('line', 'step', or 'dots'), dash, offset (bars to shift the plot, e.g. Ichimoku), and per-bar colors (Supertrend)
barsDirection-colored histogram bars (VOL, the MACD histogram) with an optional key
fillsBands filled between two lines by upperKey and lowerKey, with color and an optional colorBelow
fillLinesBoundary lines used only by fills, never stroked
levelsHorizontal reference lines with value, color, and an optional dash (default [4, 4])

Metadata

Definitions can describe themselves for settings UIs. The built-ins all do.

FieldPurpose
labelDisplay name, such as 'Ichimoku Cloud'
shortNameLegend name, such as 'Ichimoku'; the status line uses it for single-line studies
inputsEditable params in display order: key, label, and optional min, max, step, integer, and options (a choice list of { value, label })
stylesStyleable plots in display order: key, label, colorIndex, and kind ('line', 'dots', 'histogram', 'fill', or 'level'). A plot with several colors has one row per color sharing its key

The status line labels each line with the study's short name, or with the line's style label for multi-line studies. Without metadata it falls back to the key in capitals.

To keep an outlying overlay from expanding the price range, set priceAxis.scaleSeriesOnly: true.

Edit on GitHub

On this page