币安 API 拉历史 K 线 怎么避免漏数据
用 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 线是回测的燃料。学会拉数据 + 去重 + 持久化,量化策略已经成功一半。