Gráficos de acciones

Velas OHLCV (apertura, máximo, mínimo, cierre, volumen), rangos temporales de mercado, indicadores, perfiles, niveles de precio y marcadores.

Inicio rápido por framework

Renderiza el mismo gráfico bursátil de seis formas

Elige la API imperativa de TypeScript o un adaptador ligero. Todas las pestañas usan los mismos datos tipados y opciones.
chart.ts@sixtyfold/stock
import { StockChart, type TimeRange } from "@sixtyfold/stock";

const data = {
  timestamp: new Float64Array([0, 60_000, 120_000, 180_000]),
  open: new Float64Array([100, 102, 101, 104]),
  high: new Float64Array([103, 104, 105, 107]),
  low: new Float64Array([99, 100, 100, 103]),
  close: new Float64Array([102, 101, 104, 106]),
  volume: new Float64Array([420, 510, 470, 630]),
  length: 4,
};

const canvas = document.querySelector<HTMLCanvasElement>("#chart")!;
const chart = new StockChart(canvas, {
  renderMode: "auto",
  timeScale: "market",
  showVolume: true,
  priceUnit: { prefix: "$", decimals: 2 },
});

await chart.initialize();
chart.setData(data);

// The application owns the controls: choose any labels and ranges, or none.
const controls = document.querySelector("#stock-ranges")!;
for (const range of ["1D", "1M", "ALL"] as const satisfies readonly TimeRange[]) {
  const button = document.createElement("button");
  button.type = "button";
  button.textContent = range;
  button.addEventListener("click", () => chart.setTimeRange(range));
  controls.append(button);
}


window.addEventListener("pagehide", () => chart.destroy(), { once: true });

@sixtyfold/stock representa columnas ordenadas de apertura, máximo, mínimo, cierre y volumen (OHLCV) con capas analíticas específicas del mercado. Su proceso de nivel de detalle (LOD) combina automáticamente muchas velas visibles en periodos OHLCV válidos y luego vuelve a velas más finas al hacer zoom.

La configuración exacta y las firmas de métodos están en el generado Stock options, en los métodos StockChart methods y en los tipos de datos OHLCV data types como referencia.

StockChart expone métodos de ciclo de vida, viewport, apariencia, superposición, renderizador y agrupamiento (batching) de forma directa. En el modo de tiempo de mercado, sus métodos de viewport preservan coordenadas comprimidas de sesión observada mientras que los valores públicos permanecen como marcas temporales reales.

Velas y volumen

Elija filled, hollow o ohlc para la geometría de las velas. candleColors controla los cuerpos y mechas alcistas y bajistas. El volumen tiene colores, opacidad y proporción de altura de panel independientes.

El renderizador limita la precisión mostrada para tooltips OHLCV y callbacks del crosshair. Suministre priceUnit y volumeUnit cuando la aplicación requiera formateo explícito de moneda, unidad, decimales o compacto.

Intervalos de tiempo gestionados por el host

StockChart no crea ni estiliza botones de intervalo de tiempo. La aplicación host es la propietaria de las etiquetas, el número, el orden, la disposición y la accesibilidad de sus controles —o puede no renderizar ningún control.

Llame a setTimeRange() cuando un botón corresponda a uno de los presets de conveniencia exportados: 1D, 5D, 1M, 3M, 6M, YTD, 1Y, 5Y o ALL. Un preset que se extienda más allá del historial cargado se ajusta (clamp) a los datos disponibles.

const controls = document.querySelector<HTMLElement>("[data-stock-ranges]")!;
const ranges = [
  ["Day", "1D"],
  ["Six months", "6M"],
  ["Everything", "ALL"],
] as const;

for (const [label, range] of ranges) {
  const button = document.createElement("button");
  button.type = "button";
  button.textContent = label;
  button.dataset.range = range;
  button.addEventListener("click", () => chart.setTimeRange(range));
  controls.append(button);
}

canvas.addEventListener("sixtyfold:time-range-change", (event) => {
  const detail = (event as CustomEvent).detail;
  for (const button of controls.querySelectorAll("button")) {
    button.setAttribute(
      "aria-pressed",
      String(button.dataset.range === detail.range),
    );
  }
});

Para un intervalo que no sea un preset nombrado, envíe marcas de tiempo reales mediante la API ordinaria de viewport:

const twoWeeks = 14 * 24 * 60 * 60_000;
let latestDataTimestamp = 0;

const chart = new StockChart(canvas, {
  onVisibleRangeChange({ dataBounds }) {
    latestDataTimestamp = dataBounds.xMax;
  },
});

customButton.addEventListener("click", () => {
  chart.setViewport({
    xMin: latestDataTimestamp - twoWeeks,
    xMax: latestDataTimestamp,
  });
});

En el modo de escala temporal market, los valores públicos del viewport siguen siendo marcas de tiempo reales; el gráfico los convierte internamente a coordenadas comprimidas de sesión observada. Los callbacks del constructor proporcionan onTimeRangeChange, onCrosshairMove y onVisibleRangeChange. Se exportan constantes de eventos DOM con espacio de nombres para los mismos cambios de estado.

Indicadores

Los indicadores integrados se calculan a partir de velas crudas y se muestrean en la agregación activa para el renderizado y los valores del crosshair.

chart.setIndicators([
  { type: "sma", id: "sma-20", period: 20, color: "#ffd166" },
  { type: "ema", id: "ema-50", period: 50, color: "#64d8ff" },
  { type: "bollinger", id: "bb-20", period: 20, deviation: 2 },
  { type: "vwap", id: "vwap-day", reset: "day" },
]);

Funciones puras están disponibles en @sixtyfold/stock/analytics: calculateSMA, calculateEMA, calculateBollingerBands, calculateVWAP y computeStockIndicator. Los valores fuente no finitos rompen una ventana deslizante en lugar de interpolarse silenciosamente.

Capas de mercado

chart.setVolumeProfile({ rows: 48, placement: "right", valueAreaPercent: 70 });
chart.setPriceLines([
  { id: "entry", price: 182.4, label: "Entry", showAxisLabel: true },
]);
chart.setMarkers([
  { id: "earnings", timestamp, position: "above", shape: "diamond", label: "E" },
]);

El perfil de volumen es un histograma estimado de volumen por precio, no una reconstrucción trade-a-trade del flujo de órdenes. Divide la escala de precios visible en filas y distribuye el volumen de cada vela OHLCV de forma uniforme a lo largo del rango reportado de mínimo a máximo de esa vela. Las barras horizontales más anchas representan más volumen estimado alrededor de un precio. Las porciones alcistas y bajistas se determinan por la dirección de la vela, el punto de control marca la fila con el mayor volumen estimado y el área de valor se expande a través de filas adyacentes hasta contener el porcentaje configurado del volumen visible.

El perfil sigue el rango de tiempo y precio visible. Rangos largos usan la agregación de velas completadas más fina que mantenga el cálculo en o por debajo de 4.096 velas fuente; rangos con zoom usan velas sin procesar. Esto mantiene la interacción acotada, pero ambas vías siguen siendo aproximaciones derivadas de velas porque los datos OHLCV no informan dónde, dentro del rango de cada vela, ocurrieron las operaciones individuales. No describa esta capa como datos exactos de operaciones-por-precio, footprint o flujo de órdenes.

Las líneas de precio son niveles horizontales anclados a datos. Los marcadores están ordenados por marca temporal y se recortan al rango visible; use eventos escasos en vez de un marcador por vela.

Transmisión

Después de initialize(), cree un stream con una capacidad entera positiva:

chart.initStreaming(250_000);
chart.addCandle(timestamp, open, high, low, close, volume);

Las marcas temporales de la transmisión deben ser finitas y estrictamente crecientes, incluso entre llamadas, velas escalares en cola y fronteras de fragmentos. Un append con la misma marca temporal no actualiza una vela existente; desduplique la fuente primero.

Para feeds columnarios, use addCandles o addCandleBatches con seis columnas OHLCV de tamaño igual. addCandleBatches valida la lista completa de fragmentos antes de cualquier transferencia. El orden inválido de marcas temporales, marcas no finitas o longitudes desiguales se rechazan sin vaciar velas en cola ni desacoplar los buffers del llamante. Las llamadas escalares y por lotes válidas conservan su orden. En modo worker se transfieren buffers válidos, por lo que capture los valores que la aplicación necesite antes de hacer append.

initialTimeRange puede aplicarse en la misma pasada del renderizador que un lote inicial transferido, evitando un fotograma de rango completo antes de que aparezca el área de visualización prevista. Las ventanas de visualización en tiempo de mercado conservan sus anclajes temporales cuando nuevas velas cambian la cadencia inferida.

La setData estática tiene un contrato de orden distinto: se acepta un historial monótonamente ascendente o descendente, incluidos sellos de tiempo iguales, y se normaliza a orden ascendente. Reemplazar datos o restablecer la transmisión descarta muestras pendientes y cancela la animación de área de visualización del conjunto de datos antiguo.

Las jerarquías de agregación de transmisión se reconstruyen a partir de instantáneas fuera de pantalla y reemplazan la jerarquía activa de forma atómica. Los niveles completados siguen siendo utilizables mientras continúan los anexos; el gráfico no publica reemplazos parcialmente construidos.

Cargando CSV

loadOHLCVFromCSV se proporciona para conjuntos de datos sencillos en el navegador, con una devolución de llamada de progreso opcional. Para feeds Parquet muy grandes o propietarios, decodifique fuera del hilo principal y transfiera seis columnas tipadas validadas directamente.