循环调用Bybit API获取K线时遭遇429错误(Http状态码非200)
解决Bybit API批量获取K线时的429限流问题
我用以下代码从Bybit批量导出K线数据:
for i in range(len(pairName)): coinKline = session.query_kline(symbol=pairName[i], interval=str(sinceTime), from_time=since)['result'] time.sleep(0.05)
原本运行正常,但批量获取多个交易对时频繁抛出429错误,错误触发的循环位置不固定,调整time.sleep时长(甚至到1秒)也无法解决。错误信息如下:
Traceback (most recent call last): File "c:\Users\XXXXXXXX\OneDrive\algoTrading\coinbaseData\bybit\multiple_coin_check.py", line 95, in <module> coinKline = session.query_kline(symbol=pairName[i], interval=str(sinceTime), from_time=since)['result'] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\XXXXXXXX\AppData\Local\Programs\Python\Python311\Lib\pybit\usdt_perpetual.py", line 30, in query_kline return self._submit_request( ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\XXXXXXXX\AppData\Local\Programs\Python\Python311\Lib\pybit\_http_manager.py", line 307, in _submit_request raise FailedRequestError( pybit.exceptions.FailedRequestError: Http status code is not 200. (ErrCode: 429) (ErrTime: 14:10:00). Request → GET https://api.bybit.com/public/linear/kline: {'symbol': 'BAKEUSDT', 'interval': '1', 'from': 1705402146}.
可行的解决方法
1. 实现指数退避重试机制
固定sleep时长应对限流不够灵活,指数退避能在触发限流后逐步延长等待时间,避免持续触发限流。手动实现示例:
import time from pybit.exceptions import FailedRequestError for i in range(len(pairName)): retries = 3 delay = 0.5 # 初始延迟 success = False while retries > 0 and not success: try: coinKline = session.query_kline(symbol=pairName[i], interval=str(sinceTime), from_time=since)['result'] success = True except FailedRequestError as e: if "ErrCode: 429" in str(e): retries -= 1 time.sleep(delay) delay *= 2 # 每次重试延迟翻倍 else: raise e if not success: raise Exception(f"获取{pairName[i]}数据重试耗尽") time.sleep(0.1) # 基础请求间隔
2. 严格遵守Bybit API限流规则
Bybit公开API的线性合约K线接口(public/linear/kline)限流为:每秒最多10次请求,每分钟最多600次请求。可以用计数器控制请求频率:
import time from collections import deque from pybit.exceptions import FailedRequestError # 存储最近请求的时间戳,控制频率 request_timestamps = deque(maxlen=600) for i in range(len(pairName)): now = time.time() # 控制每分钟请求数不超过600 while request_timestamps and now - request_timestamps[0] < 60: time.sleep(0.1) now = time.time() # 控制每秒请求数不超过10 if len(request_timestamps) >= 10 and now - request_timestamps[-10] < 1: time.sleep(0.1) try: coinKline = session.query_kline(symbol=pairName[i], interval=str(sinceTime), from_time=since)['result'] request_timestamps.append(time.time()) except FailedRequestError as e: if "ErrCode: 429" in str(e): time.sleep(1) # 重试一次 coinKline = session.query_kline(symbol=pairName[i], interval=str(sinceTime), from_time=since)['result'] request_timestamps.append(time.time()) else: raise e
3. 配置pybit自动重试
pybit库支持针对特定错误码的自动重试,初始化session时可以配置:
from pybit.usdt_perpetual import HTTP session = HTTP( endpoint="https://api.bybit.com", retry_codes=[429], # 针对429错误重试 retry_times=3, # 重试次数 retry_delay=0.5 # 初始重试延迟 )
4. 避免重复请求相同数据
如果脚本重复请求同一时间段的K线数据,可能会被判定为恶意请求,加剧限流。确保from_time参数每次请求都是正确的,不要重复获取已拉取过的数据。
内容的提问来源于stack exchange,提问作者mmm bbb
相关产品推荐
相关产品推荐

