Datafeed
The Datafeed is the contract between your data source and the chart. Three
methods are required — getHistoryKLineData, subscribe, unsubscribe —
plus the optional searchSymbols (only used by useSymbolSearch); the
library calls them as the user searches symbols, scrolls history, and watches
live updates.
interface Datafeed { /** * Search symbols by a query string. Optional — when omitted, * useSymbolSearch simply returns no results. * signal — AbortSignal to cancel the request when a newer query is typed. */ searchSymbols?( search: string, signal?: AbortSignal, ): Promise<PartialSymbolInfo[]>;
/** * Load historical bars. * from/to — timestamps in milliseconds; `to` is EXCLUSIVE (forward * pagination asks for oldestLoadedBar.timestamp - 1). Bars must be sorted * ascending by timestamp — klinecharts never sorts or dedupes them. * When from=0, load the most recent available data. */ getHistoryKLineData( symbol: SymbolInfo, period: TerminalPeriod, from: number, to: number, ): Promise<KLineData[]>;
/** * Subscribe to real-time updates. * callback is called for every new bar. */ subscribe( symbol: SymbolInfo, period: TerminalPeriod, callback: (data: KLineData) => void, ): void;
/** Unsubscribe from real-time updates. */ unsubscribe(symbol: SymbolInfo, period: TerminalPeriod): void;}PartialSymbolInfo
Section titled “PartialSymbolInfo”Minimal description of a trading instrument:
interface PartialSymbolInfo { ticker: string; // e.g. "BTCUSDT", "AAPL", "EUR/USD" pricePrecision?: number; // decimal places for price display volumePrecision?: number; // decimal places for volume display [key: string]: unknown; // any additional fields}KLineData
Section titled “KLineData”Each bar returned from getHistoryKLineData / pushed to subscribe is a
klinecharts KLineData:
interface KLineData { timestamp: number; // ms open: number; high: number; low: number; close: number; volume?: number; turnover?: number;}Example: Binance public API
Section titled “Example: Binance public API”A complete, self-contained datafeed (the same one powering the live demos on this site):
import type { Datafeed, TerminalPeriod } from "react-klinecharts-ui";import type { KLineData, SymbolInfo } from "klinecharts";
function periodToInterval(p: TerminalPeriod): string { const map: Record<string, string> = { minute: "m", hour: "h", day: "d", week: "w", month: "M", }; return `${p.span}${map[p.type] ?? "d"}`;}
export const binanceDatafeed: Datafeed = { async searchSymbols(q) { const list = ["BTCUSDT", "ETHUSDT", "SOLUSDT"]; return list .filter((t) => t.includes(q.toUpperCase())) .map((ticker) => ({ ticker, pricePrecision: 2 })); },
async getHistoryKLineData(symbol, period, _from, to) { const url = new URL("https://api.binance.com/api/v3/klines"); url.searchParams.set("symbol", symbol.ticker); url.searchParams.set("interval", periodToInterval(period)); url.searchParams.set("endTime", String(to)); url.searchParams.set("limit", "1000"); const res = await fetch(url); if (!res.ok) return []; const rows: unknown[][] = await res.json(); return rows.map((k) => ({ timestamp: k[0] as number, open: +(k[1] as string), high: +(k[2] as string), low: +(k[3] as string), close: +(k[4] as string), volume: +(k[5] as string), })); },
subscribe(symbol, period, callback) { const stream = `${symbol.ticker.toLowerCase()}@kline_${periodToInterval(period)}`; const ws = new WebSocket(`wss://stream.binance.com:9443/ws/${stream}`); ws.onmessage = (ev) => { const k = JSON.parse(ev.data).k; callback({ timestamp: k.t, open: +k.o, high: +k.h, low: +k.l, close: +k.c, volume: +k.v, }); }; },
unsubscribe() { /* close the socket you opened in subscribe */ },};The chart consumes this datafeed through
createDataLoader.