跳到主要内容

K 线(蜡烛图)

通道名

spot:kline:{symbol}:{interval}

鉴权:不需要(公开通道)。

支持的周期:1m5m15m1h4h1d。参见 Enums — K 线周期

描述

订阅时推送最新 K 线作为快照,此后每次落在当前 K 线时间窗口内的成交均推送实时 OHLCV 更新。时间窗口结束时,下一次推送的 is_closedtrue。对同一交易对订阅多个周期,每次成交将分别对每个周期产生一条推送。

订阅

发送:

{ "type": "subscribe", "channel": "spot:kline:DFUSDT:1m" }

响应:

{ "type": "subscribed", "channel": "spot:kline:DFUSDT:1m" }

确认后立即推送一条 spot_kline_snapshot

推送格式

spot_kline_snapshot

订阅时发送一次。包含数据库中最新的已完成或进行中的 K 线。

{
"type": "spot_kline_snapshot",
"channel": "spot:kline:DFUSDT:1m",
"data": {
"symbol": "DFUSDT",
"interval": "1m",
"open_time": 1778399940,
"close_time": 1778399999,
"open": "0.4800",
"high": "0.5100",
"low": "0.4700",
"close": "0.5000",
"volume": "10000",
"quote_volume": "4900",
"trade_count": 234,
"is_closed": false
}
}

spot_kline_update

每次落在当前 K 线时间窗口内的成交后推送。数据格式与 spot_kline_snapshot 完全一致。

{
"type": "spot_kline_update",
"channel": "spot:kline:DFUSDT:1m",
"data": {
"symbol": "DFUSDT",
"interval": "1m",
"open_time": 1778399940,
"close_time": 1778399999,
"open": "0.4800",
"high": "0.5100",
"low": "0.4700",
"close": "0.5010",
"volume": "10030",
"quote_volume": "4915",
"trade_count": 235,
"is_closed": false
}
}

is_closed 变为 true 时,该 K 线已完成。下一次推送将携带新 K 线的 open_time

字段类型描述
symbolstring交易对标识符。
intervalstringK 线周期,如 1m
open_timeintegerK 线开盘时间 — Unix
close_timeintegerK 线收盘时间 — Unix 。等于 open_time + interval_seconds − 1
openstring (decimal)本 K 线开盘价。
highstring (decimal)本 K 线内迄今最高成交价。
lowstring (decimal)本 K 线内迄今最低成交价。
closestring (decimal)本 K 线内最近一笔成交价。
volumestring (decimal)本 K 线内基础资产总成交量。
quote_volumestring (decimal)本 K 线内计价资产总成交量。
trade_countinteger本 K 线内成交笔数。
is_closedbooleanK 线时间窗口结束后为 true

所有时间戳均为 Unix

推送频率

  • 每次落在该周期时间窗口内的成交后推送一条 spot_kline_update
  • 对同一交易对同时订阅 1m + 5m + 1h,每次成交将产生三条推送(每个周期各一条,分别更新对应 K 线)。
  • 无固定轮询定时器 — 更新纯粹由事件驱动。

由于每次推送均完整替换当前 K 线,漏掉的推送会被下一次推送覆盖,无需重新同步。参见快照与实时同步顺序

代码示例

const ws = new WebSocket('wss://api-sepolia.p99.world/ws');

// Local candle state keyed by interval
const candles = {};

ws.onopen = () => {
ws.send(JSON.stringify({ type: 'subscribe', channel: 'spot:kline:DFUSDT:1m' }));
ws.send(JSON.stringify({ type: 'subscribe', channel: 'spot:kline:DFUSDT:1h' }));
setInterval(() => ws.send(JSON.stringify({ type: 'ping' })), 30000);
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);

if (msg.type === 'spot_kline_snapshot' || msg.type === 'spot_kline_update') {
const d = msg.data;
candles[d.interval] = d;

if (d.is_closed) {
console.log(`[${d.interval}] Candle closed: O=${d.open} H=${d.high} L=${d.low} C=${d.close} V=${d.volume}`);
// Advance your chart to the next candle
} else {
console.log(`[${d.interval}] Live candle: C=${d.close} V=${d.volume}`);
// Repaint the live (rightmost) bar on your chart
}
}
};