Tiempo real y repetición
Transmite datos en vivo, agrega ticks en barras y repite datos históricos a una velocidad controlada.
● DemosMapa de calor de liquidezDatos de mercado simulados, generados en tu navegadorAdaptadores integrados
Todos gratuitos y sin clave de API; se conectan todos de la misma forma:
import { BinanceAdapter, CoinbaseAdapter, BybitAdapter, KrakenAdapter } from '@tradecanvas/chart'
chart.connect({ adapter: new BinanceAdapter(), symbol: 'BTCUSDT', timeframe: '1m' })
chart.connect({ adapter: new BybitAdapter(), symbol: 'BTCUSDT', timeframe: '1m' })
chart.connect({ adapter: new KrakenAdapter(), symbol: 'BTC/USD', timeframe: '5m' })
chart.connect({ adapter: new CoinbaseAdapter(), symbol: 'BTC-USD', timeframe: '15m' }) Interfaz DataAdapter
interface DataAdapter {
name: string
connect(config): void
disconnect(): void
getConnectionState(): ConnectionState
fetchHistory(symbol, timeframe, limit?): Promise<OHLCBar[]>
on(event, listener): void // 'bar' | 'tick' | 'snapshot' | 'connectionChange' | 'error' | 'symbolInfo'
off(event, listener): void
dispose(): void
// Optional
fetchHistoryBefore?(symbol, timeframe, before, limit): Promise<OHLCBar[]>
searchSymbols?(query, options?): Promise<SymbolInfo[]>
resolveSymbol?(symbol): Promise<SymbolInfo | null>
subscribeQuotes?(symbols, onQuotes): () => void // a watchlist's rows
fetchNews?(symbol, limit?): Promise<NewsItem[]> // the symbol info panel
fetchTrades?(symbol, limit?): Promise<Trade[]> // tick charts, with
subscribeTrades?(symbol, onTrades): () => void // subscribeTrades
} Datos del símbolo que el feed conoce más tarde
Un gráfico conectado llama a resolveSymbol una vez. Un feed que conoce los datos del símbolo solo más tarde (en su primer mensaje, por ejemplo) los envía con un evento symbolInfo, y el gráfico los aplica: la escala de precios, la leyenda y las etiquetas con los decimales del símbolo (pricePrecision), las marcas de la escala en su paso de precio (minTick) y el horario de la bolsa.
emit('symbolInfo', { symbol: 'VNM', pricePrecision: 0, minTick: 10, currency: 'VND' }) // como tu adaptador envía sus otros eventos Cualquier fuente de datos en ~20 líneas
Extiende WebSocketAdapter (en vivo + historial por REST) o PollingAdapter (fuentes solo REST). La clase base se encarga del
ciclo de vida de la conexión, la reconexión, la decodificación y la emisión de
eventos; tú solo aportas una URL y una función de análisis.
import { WebSocketAdapter } from '@tradecanvas/chart'
const myAdapter = new WebSocketAdapter({
name: 'myexchange',
wsUrl: (c) => 'wss://api.myexchange.com/ws/' + c.symbol + '@kline_' + c.timeframe,
fetchHistory: (symbol, tf, limit) => fetch('/candles?...').then((r) => r.json()),
parseMessage: (raw) => ({ bar: toBar(raw), closed: raw.k.x }),
}) Agregación de ticks
Agrupa los ticks sin procesar en barras OHLC para cada temporalidad:
import { TickAggregator } from '@tradecanvas/chart'
const agg = new TickAggregator('1m')
agg.processTick({ time, price, volume })
const current = agg.getCurrentBar() // forming bar
const closed = agg.flushClosedBars() // bars that have rolled over Cotizaciones de muchos símbolos
Una fuente con subscribeQuotes envía cotizaciones (último precio, variación del día, máximo, mínimo,
volumen, compra y venta) de muchos símbolos a la vez hasta que la detienes. BinanceAdapter envía
una instantánea de 24 h y luego su flujo mini-ticker; MockAdapter se inventa las cotizaciones. La
lista de seguimiento de un widget llena sus filas con ellas.
const stop = new BinanceAdapter().subscribeQuotes(['BTCUSDT', 'ETHUSDT'], (quotes) => {
for (const q of quotes) console.log(q.symbol, q.last, q.changePercent)
})
stop()
readQuote({ symbol: 'AAPL', last: 190, prevClose: 188 }) // → change 2, changePercent 1.06 Gráficos de ticks
Una temporalidad de ticks — '100T' — dibuja una barra cada 100 operaciones. Se construye con las
operaciones de la fuente: las recientes para el historial (fetchTrades) y después las que llegan en vivo
(subscribeTrades). BinanceAdapter transmite operaciones agregadas. Un gráfico de ticks no
tiene cuenta atrás ni carga historial más antiguo; una fuente sin operaciones rechaza las temporalidades de ticks.
Las barras de ticks no están espaciadas por igual en el tiempo, así que el eje de tiempo y la cruz solo dan hora
a las barras, no al espacio vacío a su lado.
chart.connect({ adapter: new BinanceAdapter(), symbol: 'BTCUSDT', timeframe: '100T' })
await chart.setTimeframe('500T')
// Your own trades into tick bars
const builder = new TickBarBuilder(100)
builder.push([{ time, price, volume }]) // → [{ bar, closed }] Estado del mercado y noticias
marketStatus(info, now) indica si el mercado de un símbolo está abierto en un momento dado, a partir de su
horario en la zona de su bolsa (con los cambios de hora incluidos), y cuándo cambia eso. Las sesiones pueden indicar los
días de la semana en que abren. El fetchNews de una fuente da titulares para el panel de información del
símbolo del widget; readNews solo conserva los elementos con título y hora, y solo los enlaces a páginas web.
const info = {
symbol: 'AAPL',
timezone: 'America/New_York',
sessions: [{ start: '09:30', end: '16:00', days: [1, 2, 3, 4, 5] }],
}
marketStatus(info, Date.now()) // { state: 'closed', next: <next open, ms> } · 'open' · 'always' (24/7) Reconexión
ReconnectManager gestiona un retroceso exponencial con un límite y una renuncia final.
import { ReconnectManager } from '@tradecanvas/chart'
const rm = new ReconnectManager({ maxRetries: 6, baseDelay: 500, maxDelay: 30_000 })
rm.start()
rm.schedule(() => connectWebsocket()) // call on disconnect; backs off automatically
rm.onConnected() // call on a successful connect to reset Modo de repetición
Hace avanzar una DataSeries histórica a una velocidad controlada.
Está desacoplado de Chart, así que sirve tanto para la repetición
en la interfaz como para backtests sin interfaz.
import { ReplayController } from '@tradecanvas/chart'
const replay = new ReplayController({
data: historicalBars,
speed: 10, // bars per second
startIndex: 0,
})
// Seed the chart with everything before startIndex
chart.setData(replay.getPrefix())
// Wire each emitted bar into the chart
replay.on('bar', ({ bar }) => chart.appendBar(bar))
replay.on('finished', () => console.log('done'))
replay.start()
// replay.pause(); replay.resume(); replay.step(5); replay.seek(200); replay.setSpeed(20) En el modo de repetición del widget, haz clic en cualquier barra ya
mostrada para llevar ahí el cursor de la repetición. De forma más
general, el gráfico emite ahora los eventos click y barClick con los clics izquierdos simples (pulsar y soltar sin
arrastrar):
chart.on('barClick', (e) => {
const { bar, barIndex, point } = e.payload
}) Repetición en el gráfico, en pasos más finos
chart.replayStart() repite la propia serie del gráfico. Pásale barras más
finas como steps (barras de 5 minutos bajo un gráfico horario) y cada paso
hace crecer con ellas la barra en formación, tal como creció en el mercado; las barras
cerradas se muestran tal como están en la serie. startIndex y replaySeekToBar cuentan las barras del gráfico. En ChartWidget, el menú Paso de la barra de repetición ofrece los intervalos más finos que tiene
la fuente (o que se pueden construir con las barras que cargaste).
const steps = await adapter.fetchHistory('BTCUSDT', '5m', 2000)
chart.replayStart({ steps, startIndex: 120, paused: true, speed: 5 })
chart.replayResume()
chart.getReplayBarIndex() // the chart bar forming now
chart.replaySeekToBar(150) // to the end of bar 150
chart.replaySeekToTime(t) // to the bars that opened before t
chart.on('replayStep', (e) => e.payload) // { barIndex, time, until, total }
chart.on('replayComplete', (e) => e.payload) // { barIndex, time }
chart.on('replayState', (e) => e.payload) // { state: 'playing' | 'paused' | 'stopped' }
chart.replayStop() // back to the live series Una repetición en tu propia app
Las marcas de compra y venta y las zonas de operación aparecen cuando la repetición llega a ellas: una marca cuando se muestra su vela, una operación cuando se entra, dibujada abierta hasta que se llega a su salida (revealMarks: false, ChartWidget: replayRevealMarks: false las muestra todas). startTime empieza en un momento en lugar de en una vela; hideHistory deja fuera las velas anteriores al inicio hasta que la repetición se detiene; duration llega al final en más o menos ese tiempo, haya las velas que haya, varias por fotograma, y un fotograma tardío la frena en lugar de saltar.
chart.setSignalMarkers(signals) // todo el backtest, se conserva
chart.setTradeZones(trades)
chart.replayStart({
startTime: Date.now() - 30 * 86_400_000, // los últimos 30 días
hideHistory: true, // solo ellos en el gráfico
duration: 3500, // en unos 3,5 s
})
chart.on('replayComplete', () => chart.replayStop()) // y luego la serie completa
chart.replayStart({ startIndex: 100, revealMarks: false }) // todas las marcas desde el inicio Trading simulado en una repetición
Un adaptador de ejecución con setMarkPrice(price, time) (como PaperExecutionAdapter) opera sobre la repetición: durante una repetición, el
gráfico le pasa cada precio y hora repetidos, así que las órdenes y los stops se ejecutan
cuando la repetición pasa por ellos y las ejecuciones quedan sobre las barras repetidas.
Cuentan el mínimo y el máximo de cada paso, y un salto hacia delante pasa por todos los
pasos intermedios. Solo avanza: tras un salto hacia atrás, espera a que la repetición
supere el punto más lejano que ha visto. Mientras tanto, el precio en vivo no lo mueve;
cuando termina la repetición vuelve al precio en vivo, y las ejecuciones, a la hora real.
Las alertas de precio siguen vigilando el mercado en vivo todo el tiempo; las alertas
sobre líneas de indicador esperan a que termine la repetición.
chart.connectExecution(new PaperExecutionAdapter())
chart.replayStart({ startIndex: 300, paused: true })
// place orders from the chart or the order ticket, then play API
| Método | Función |
|---|---|
start() | Empieza a emitir desde el índice actual. |
pause() / resume() | Pausa/reanuda el temporizador. |
step(n) | Emite N barras de forma síncrona, sin el temporizador. |
seek(index) | Salta sin emitir las barras intermedias. |
setSpeed(bps) | Barras por segundo (con un mínimo de 0.01). |
destroy() | Elimina el temporizador y los listeners. |
Consulta Análisis para usar la repetición junto con el backtester.