交易工具

幣安 API 拉歷史 K 線 怎麼避免漏資料

2026-04-23 · 6 分鐘閱讀

用 API 拉歷史 K 線做回測要分頁要去重本文給出標準正規化。

回測策略需要歷史 K 線。先在 幣安官網 建立只讀 API Key,APP 用 幣安官方APP(iOS 見 iOS安裝教程)。

介面

GET /api/v3/klines
引數: symbol, interval, startTime, endTime, limit

limit 最大 1000 條。

一次性拉全部歷史

不可能。limit 限制 1000 條。需要分頁。

分頁正規化

import time
all_klines = []
end = int(time.time() * 1000)
start = end - 365 * 24 * 3600 * 1000  # 1 年

while start < end:
    klines = client.get_klines(
        symbol='BTCUSDT',
        interval='1h',
        startTime=start,
        limit=1000
    )
    if not klines:
        break
    all_klines.extend(klines)
    start = klines[-1][0] + 1  # 下一批從最後一根 + 1ms 開始
    time.sleep(0.5)  # 限速保護

去重

邊界 K 線可能重複。每批末尾 + 1ms 避免。

或者:

import pandas as pd
df = pd.DataFrame(all_klines)
df = df.drop_duplicates(subset=[0])  # 時間戳去重

K 線格式

每條 K 線是陣列:

[
  open_time,    # 開盤時間戳 ms
  open,         # 開盤價
  high,         # 最高
  low,          # 最低
  close,        # 收盤
  volume,       # 成交量
  close_time,   # 收盤時間戳
  quote_volume, # 報價幣種成交額
  trades,       # 成交筆數
  taker_buy_base,
  taker_buy_quote,
  ignore
]

轉 DataFrame

df = pd.DataFrame(all_klines, columns=[
    'open_time','open','high','low','close','volume',
    'close_time','quote_volume','trades',
    'taker_buy_base','taker_buy_quote','ignore'
])
df['open_time'] = pd.to_datetime(df['open_time'], unit='ms')
df.set_index('open_time', inplace=True)
df = df.astype({'open': float, 'high': float, 'low': float, 'close': float, 'volume': float})

之後能用 pandas / numpy / 各種回測庫。

週期與資料量

週期 1 年 K 線數
1m 525600
5m 105120
15m 35040
1h 8760
4h 2190
1d 365

按 1000 條/批拉:

  • 1m 1 年 = 526 次請求 = 4-5 分鐘
  • 1h 1 年 = 9 次請求 = 幾秒

多幣種併發

import concurrent.futures
symbols = ['BTCUSDT', 'ETHUSDT', 'SOLUSDT']

def fetch(s):
    return get_history(s, '1h', 365)

with concurrent.futures.ThreadPoolExecutor(max_workers=3) as ex:
    results = list(ex.map(fetch, symbols))

併發但不要超過 weight 上限。

公開 vs 鑑權

歷史 K 線是公開資料,不需要 API Key 也能拉:

import requests
url = 'https://api.binance.com/api/v3/klines'
params = {'symbol': 'BTCUSDT', 'interval': '1h', 'limit': 1000}
r = requests.get(url, params=params)

但鑑權(帶 Key)能享受更高 weight 上限。

完整年度資料

幣安提供歷史資料下載(zip CSV 包),可以一次性下載好幾年的資料:

  • data.binance.vision/

按月、按 K 線型別。比 API 拉快很多。

持續更新

回測後實盤需要持續更新最新 K 線。兩種方式:

1. 定時拉

每分鐘拉最近 5 根 K 線,更新本地。

2. WebSocket

訂閱 K 線 WS:

wss://stream.binance.com:9443/ws/btcusdt@kline_1h

每根 K 線更新即時推送。

WS 適合實時;REST 適合歷史補充。

資料質量

注意:

  • 網路抖動可能漏一批
  • 時間戳要校對(毫秒不是秒)
  • 未收盤 K 線(最近一根)會變化

回測時排除最近一根未收盤 K 線。

持久化

拉到的資料存:

  • CSV:簡單
  • Parquet:高效壓縮
  • SQLite:查詢方便
  • DuckDB:分析快
  • 時序資料庫:海量資料

中等量用 Parquet。

衍生品歷史

合約 K 線介面:

  • U 本位:/fapi/v1/klines
  • 幣本位:/dapi/v1/klines

引數和返回格式與現貨 v3 一致。

資金費率歷史

GET /fapi/v1/fundingRate?symbol=BTCUSDT&limit=1000

每 8 小時一條。最多 1000 條 = 333 天。

常見問題

問:拉歷史會被限速嗎? 答:會。注意 sleep。

問:能拉所有幣種嗎? 答:能。但有些已下架的幣歷史保留有限。

問:1m K 線佔記憶體多大? 答:1 年 ≈ 50MB(CSV)。多幣累計很大。

問:回測能模擬滑點嗎? 答:需要自己加滑點模型。幣安資料不帶。

問:歷史資料可以商用嗎? 答:用於自己策略 OK。重新公開發布需看條款。

延伸閱讀

歷史 K 線是回測的燃料。學會拉資料 + 去重 + 持久化,量化策略已經成功一半。