Plugins

Amplía el gráfico con indicadores, herramientas de dibujo, tipos de gráfico y capas personalizados, registrados de forma global o por gráfico.

Registro

Hay tres formas de registrar, por orden de prioridad: valores globales por defecto, el constructor y, por último, llamadas imperativas sobre la instancia.

import { Chart, registerPlugin } from '@tradecanvas/chart'

// 1) Global — every Chart created afterward inherits it
registerPlugin({ kind: 'indicator', plugin: new MyIndicator() })

// 2) Per-chart at construction
const chart = new Chart(el, { plugins: [{ kind: 'overlay', plugin: myHeatmap }] })

// 3) Imperative on an instance
chart.plugins.register({ kind: 'chartType', plugin: myCandles })
chart.plugins.unregister('chartType:my-candles')
chart.plugins.list()

Tipos de plugin

TipoContratoDónde se dibuja
indicatorIndicatorPlugin — calculate() + render()superpuesto o en panel
drawingDrawingPlugin — render() + hitTest()capa superpuesta
chartTypeChartTypePlugin — createRenderer() + transform() opcionalserie principal
overlayOverlayPlugin — render(ctx, { viewport, data, theme })main / overlay / ui

Indicador personalizado

Extiende IndicatorBase para usar sus utilidades de dibujo; después regístralo y añádelo como cualquier indicador integrado:

import { IndicatorBase, IndicatorValueMap, registerPlugin } from '@tradecanvas/chart'

class DoubleSMA extends IndicatorBase {
  descriptor = {
    id: 'double-sma', name: 'Double SMA',
    placement: 'overlay', defaultConfig: { fast: 10, slow: 30 },
  }
  calculate(data, config) { /* values = new IndicatorValueMap(); return { values, series } */ }
  render(ctx, output, viewport, style) { /* draw lines */ }
}

registerPlugin({ kind: 'indicator', plugin: new DoubleSMA() })
chart.addIndicator('double-sma', { fast: 10, slow: 30 })

Para values, usa new IndicatorValueMap() en lugar de new Map(): es un Map intercambiable que resulta varias veces más barato de llenar barra a barra en orden temporal, que es justo lo que hace cada cambio de símbolo o de temporalidad sobre todo el historial.

Actualizaciones rápidas en vivo (opcional)

En cada tick en vivo solo cambia la barra en formación. Implementa update() para recalcular solo las barras a partir de from en lugar de todo el historial: el gráfico lo usa con los ticks y las barras nuevas, y recurre a calculate() cuando no existe o devuelve null. Debe producir los mismos valores que produciría calculate().

update(data, config, prev, from) {
  if (!this.canResume(data, prev, from)) return null   // IndicatorBase helper
  for (let i = from; i < data.length; i++) {
    this.writePoint(prev, data, i, { value: /* recompute bar i */ 0 })
  }
  return prev
}

Herramienta de dibujo personalizada

Extiende DrawingBase para usar sus utilidades (de anclas a píxeles, estilos de línea, puntos de control), describe la herramienta y regístrala. La configuración que enumeres en descriptor.options aparece en el diálogo de configuración del widget y se guarda con el dibujo.

import { DrawingBase, registerPlugin } from '@tradecanvas/chart'

class TargetLine extends DrawingBase {
  descriptor = {
    type: 'targetLine', name: 'Target Line', requiredAnchors: 1,
    options: { label: { kind: 'text', label: 'Label', default: 'Target' } },
  }
  render(ctx, state, viewport, selected) { /* en this.anchorToPixel(state.anchors[0], viewport) */ }
  hitTest(point, state, viewport, tolerance) { /* ¿está el puntero sobre él? */ return false }
  // opcional: los precios de sus líneas, para que una alerta pueda seguirlas
  priceAt(state) { return [state.anchors[0].price] }
}

registerPlugin({ kind: 'drawing', plugin: new TargetLine() })
chart.setDrawingTool('targetLine')

El descriptor también puede indicar cómo se dibuja la herramienta (creation: 'clicks', 'freehand' o 'path', con maxAnchors) y si el diálogo ofrece un relleno (fill) o texto (text). Una herramienta puede mover puntos de control que no son anclas con moveHandle() y recibe las barras del gráfico mediante setDataGetter() cuando dibuja a partir de ellas.

Tipo de gráfico personalizado

Un ChartTypePlugin aporta un renderizador y una transformación de datos opcional; cámbiate a él como a uno integrado:

registerPlugin({
  kind: 'chartType',
  plugin: {
    descriptor: { type: 'my-bricks', name: 'My Bricks' },
    createRenderer: () => new MyBrickRenderer(),
    transform: (raw) => toBricks(raw),   // optional
  },
})

chart.setChartType('my-bricks')

Capa personalizada

Un OverlayPlugin dibuja cada fotograma en la capa que elijas y recibe la vista, los datos y el tema actuales:

import { overlayScale, registerPlugin } from '@tradecanvas/chart'

registerPlugin({
  kind: 'overlay',
  plugin: {
    descriptor: { id: 'high-marks', name: 'High marks', layer: 'main' },
    render(ctx, context) {
      const s = overlayScale(context)
      ctx.fillStyle = '#f2a93b'
      for (let i = s.visible.from; i <= s.visible.to; i++) {
        const bar = context.data[i]
        ctx.fillRect(s.indexToX(i) - s.barWidth / 2, s.priceToY(bar.high) - 1, s.barWidth, 2)
      }
    },
  },
})

overlayScale(context) coloca las cosas donde las dibuja el gráfico: timeToX / xToTime por la hora de la vela (entre velas y más allá de la última, en proporción), indexToX / xToIndex, priceToY / yToPrice (también en escala logarítmica o invertida), barWidth y visible, las velas en pantalla. Para filas en la cuadrícula de precios, chart.getPriceStep() es el paso mínimo del símbolo (minTick), la unidad de una fracción o una unidad de los decimales que se muestran. Los renderizadores de indicadores y tipos de gráfico solo reciben el viewport: para ellos se exportan priceToY, barIndexToX, timeToX y sus inversas. Las velas son las que están en pantalla: en un gráfico Renko o Kagi, sus ladrillos (chart.isTimeAligned() indica cuándo son las velas del feed).

Un overlay con ajustes propios (un modo de visualización, un interruptor) puede mostrar un cambio al instante, aunque no llegue ningún tick que redibuje el gráfico: pon enabled: false en el plugin para ocultarlo sin quitar su registro, y llama a chart.requestRender() tras cambiar cualquiera de los dos. Varias peticiones antes del siguiente fotograma dibujan uno solo.

Consulta la referencia de la API para ver las firmas de tipos completas de los plugins.