K 线(蜡烛图)
通道名
spot:kline:{symbol}:{interval}
鉴权:不需要(公开通道)。
支持的周期:1m、5m、15m、1h、4h、1d。参见 Enums — K 线周期。
描述
订阅时推送最新 K 线作为快照,此后每次落在当前 K 线时间窗口内的成交均推送实时 OHLCV 更新。时间窗口结束时,下一次推送的 is_closed 为 true。对同一交易对订阅多个周期,每次成交将分别对每个周期产生一条推送。
订阅
发送:
{ "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。
| 字段 | 类型 | 描述 |
|---|---|---|
symbol | string | 交易对标识符。 |
interval | string | K 线周期,如 1m。 |
open_time | integer | K 线开盘时间 — Unix 秒。 |
close_time | integer | K 线收盘时间 — Unix 秒。等于 open_time + interval_seconds − 1。 |
open | string (decimal) | 本 K 线开盘价。 |
high | string (decimal) | 本 K 线内迄今最高成交价。 |
low | string (decimal) | 本 K 线内迄今最低成交价。 |
close | string (decimal) | 本 K 线内最近一笔成交价。 |
volume | string (decimal) | 本 K 线内基础资产总成交量。 |
quote_volume | string (decimal) | 本 K 线内计价资产总成交量。 |
trade_count | integer | 本 K 线内成交笔数。 |
is_closed | boolean | K 线时间窗口结束后为 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
}
}
};