Indicadores

El catálogo de aproximadamente 160 indicadores técnicos vive en un paquete aparte, @stocksharp/indicators. Llega junto con el gráfico como dependencia, pero las definiciones hay que importarlas precisamente de él. Cualquier definición la calcula el IndicatorRuntime público sobre sus velas, y el resultado lo dibuja usted mismo con series ordinarias: como superposición en el panel de precios o como oscilador en un subpanel propio.

Demostración en vivo

Bandas de Bollinger sobre las velas, con RSI y MACD en paneles separados debajo.

Configuración

Importe el runtime y las definiciones que necesite, ejecute cada una sobre las velas y trace las salidas. Al runtime se le alimenta con pares { time, value }, donde value es la vela:

import { createChart, CandlestickSeries, LineSeries, HistogramSeries, BandSeries } from '@stocksharp/chart';
import {
  IndicatorRuntime,
  BollingerBandsIndicator,
  RelativeStrengthIndexIndicator,
  MacdHistogramIndicator,
} from '@stocksharp/indicators';

// Calcula un indicador sobre las velas; devuelve sus puntos agrupados por id de salida.
function compute(definition, parameters, candles) {
  const runtime = new IndicatorRuntime({ definition, parameters });
  runtime.resetStreaming(candles.map(c => ({ time: c.time, value: c })));
  const out = {};
  for (const p of runtime.points()) {
    if (p.time == null || p.value == null) continue;   // las barras de calentamiento no emiten nada
    (out[p.outputId] ||= []).push({ time: p.time, value: p.value });
  }
  return out;
}

const chart = createChart(document.getElementById('chart'), {});
const price = chart.addSeries(CandlestickSeries, { upColor: '#26a69a', downColor: '#ef5350' });
price.setData(candles);

// Bandas de Bollinger (20, 2) como envolvente superpuesta en el panel de precios.
const bb = compute(BollingerBandsIndicator, { length: 20, width: 2 }, candles);   // salidas: upper, middle, lower
chart.addSeries(BandSeries, { upperColor: '#42a5f5', lowerColor: '#42a5f5' })
  .setData(bb.upper.map((u, i) => ({ time: u.time, value: bb.middle[i].value, upper: u.value, lower: bb.lower[i].value })));

// RSI (14) en su propio subpanel.
const rsiPane = chart.addPane();
const rsi = compute(RelativeStrengthIndexIndicator, { length: 14 }, candles);     // salida: oscillator
chart.addSeries(LineSeries, { color: '#4a9eff', lineWidth: 2 }, rsiPane).setData(rsi.oscillator);

// MACD (12, 26, 9) en un segundo subpanel.
const macdPane = chart.addPane();
const macd = compute(
  MacdHistogramIndicator,
  { shortMaLength: 12, longMaLength: 26, signalMaLength: 9 },                    // salidas: macd, signal, histogram
  candles);
chart.addSeries(HistogramSeries, {}, macdPane).setData(macd.histogram);
chart.addSeries(LineSeries, { color: '#4a9eff' }, macdPane).setData(macd.macd);
chart.addSeries(LineSeries, { color: '#f5c542' }, macdPane).setData(macd.signal);

chart.timeScale().fitContent();

Parámetros y salidas

Cada definición declara sus propios parámetros e identificadores de salida, y hay que acceder a ellos por esos identificadores y no por nombres descriptivos:

Definición Parámetros Salidas Panel
BollingerBandsIndicator length (20), width (2), upBandWidth, lowBandWidth upper, middle, lower superposición
RelativeStrengthIndexIndicator length (15) oscillator propio
MacdHistogramIndicator shortMaLength (12), longMaLength (26), signalMaLength (9) macd, signal, histogram propio

Caution

Un identificador de parámetro desconocido se descarta en silencio y el indicador se calcula con el valor predeterminado. No habrá error: habrá una línea incorrecta. Por ese mismo motivo, en las bandas de Bollinger la desviación se indica con la clave width y no con stdDev, y en el RSI la longitud predeterminada es 15 y no 14: si necesita el período habitual, hay que pasarlo explícitamente, como en el ejemplo anterior.

La lista completa de definiciones con sus parámetros la entrega el catálogo:

import { getClientCatalog } from '@stocksharp/indicators';

for (const item of getClientCatalog()) {
  console.log(item.id, item.name, item.parameters.map(p => p.id));
}

Datos en tiempo real

No hace falta un recálculo completo en cada barra. Conserve el IndicatorRuntime y llame a update, que devuelve un parche con lo que ha cambiado:

const runtime = new IndicatorRuntime({ definition: RelativeStrengthIndexIndicator, parameters: { length: 14 } });
runtime.resetStreaming(history.map(c => ({ time: c.time, value: c })));

// Barra sin cerrar: false significa un valor preliminar que se sustituirá en la siguiente llamada.
runtime.update({ time: bar.time, value: bar }, false);

// La barra se ha cerrado: el valor pasa a ser definitivo.
const patch = runtime.update({ time: bar.time, value: bar }, true);

Mientras la barra no se cierra, el runtime mantiene un punto preliminar y lo sustituye en cada llamada, por lo que el historial no crece con las actualizaciones dentro de una misma barra. discardPreview() retira el punto preliminar y correct(index, input) recalcula una barra histórica que ha llegado con una corrección.

Véase también