Kraken API Trades端点拉取历史数据出现时间戳跳变问题咨询
Kraken API历史成交数据拉取时间戳跳变问题排查
问题复现
编写Python脚本调用Kraken公开Trades接口拉取指定时间区间的历史成交数据,代码如下:
import pandas as pd import json import time import urllib.request def get_data(pair, since, until): global data global query global json_response global api_data data_columns= ["price", "volume", "time", "buy/sell", "market/limit", "miscellaneous"] data = pd.DataFrame(columns= data_columns) api_start = since app_start_time = time.time() counter = 1 while api_start < until: last_time = time.time() api_domain = "https://api.kraken.com/0/public/Trades" + \ "?pair=%(pair)s&since=%(since)s" % {"pair":pair, "since": api_start} api_request = urllib.request.Request(api_domain) try: api_data = urllib.request.urlopen(api_request).read() except Exception: time.sleep(3) api_data = json.loads(api_data) if len(api_data["error"]) != 0: print(api_data["error"]) time.sleep(3) continue query = pd.DataFrame(api_data["result"][pair], columns = data_columns) data = data.append(query, ignore_index= True) api_start = int(api_data["result"]["last"][:10]) counter +=1 time.sleep(1) print("Request number: %s" %counter) print("Time since start: %s minutes" % round((time.time() - app_start_time)/60,2)) print("Time since last request: %s seconds" % round((time.time() - last_time),2)) print("last: %s" %api_start) print("") get_data("XXBTZUSD", 1414761200, 1455761200)
拉取过程中出现异常:成功获取若干次响应后,返回数据中的UNIX时间戳直接从2015年对应的14亿级数值跳变到2022年对应的1654992002.801943,导致最终拉取的历史数据错误,异常响应示例如下:
问题结论
该异常是代码逻辑缺陷+Kraken API本身的设计限制共同导致的,不是单一原因。
代码存在的明确缺陷
- 异常处理逻辑不完整:
try块捕获请求异常(超时、限流、连接失败等)后,仅做了3秒休眠,没有跳过后续的JSON解析流程。如果请求失败,api_data会保留上一次请求成功的返回内容,后续解析直接使用旧数据,极易引发翻页游标错乱。 - 游标处理无校验:Kraken接口返回的
last字段是纳秒级时间戳字符串,代码直接截取前10位转为秒级时间戳作为下一次请求的since参数,既存在精度损失,也没有对返回的游标值做合理性校验,一旦接口返回异常游标,会直接把下一次请求的时间点拉到错误的位置。 - 无入库数据校验:每一批拉取到的成交记录,没有校验时间戳是否落在预设的
[since, until]区间内,异常数据会被直接追加到结果集中。
Kraken API本身的已知限制
Kraken公开Trades接口本身不支持稳定查询过久的历史归档数据,官方文档明确说明:当since参数传入的时间戳距离当前时间过久时,接口不会严格返回指定时间点之后的成交记录,翻页到归档数据边界时,会直接返回近期的成交数据,同时返回的last游标也会跳转到近期时间点,这是接口本身的设计规则,不属于偶发故障。
修复方案
- 补全异常处理逻辑:请求失败后直接进入下一轮重试,不要执行后续解析流程,修复示例:
try: api_data = urllib.request.urlopen(api_request).read() except Exception: time.sleep(3) continue # 请求失败直接重试,跳过后续解析
- 增加游标合理性校验:每次拿到接口返回的
last值后,先判断对应时间戳是否超过设置的until上限,同时和上一次请求的api_start做差值对比,如果单次翻页时间差超过合理阈值(如1小时),判定为返回异常,直接终止或重试,不要使用异常游标请求下一页。 - 增加数据过滤逻辑:每一批成交记录追加到结果集前,先过滤掉时间戳不在目标时间区间内的异常数据。
- 如果需要拉取2015年这类非常早期的历史成交数据,不要使用实时公开接口,Kraken官方提供了专门的历史归档数据导出渠道,公开Trades接口仅适合拉取最近几个月的实时/近线数据,过久的归档数据无法通过翻页稳定拉取。
内容的提问来源于stack exchange,提问作者Dalogh
相关产品推荐
相关产品推荐

