Binance期货Websocket获取Tick数据时重复数据问题及解决需求
解决Binance期货Tick数据重复接收的问题
我之前也碰到过Binance WebSocket推送重复Tick的情况,结合你的代码来看,主要有两个可以优化的点来避免重复数据:
1. 修复Socket上下文管理器的错误使用
你的代码在while True循环里每次都调用await socket.__aenter__(),这相当于每次循环都重新初始化Socket连接上下文,很可能导致重复订阅或者接收重复的推送消息。正确的做法是只在循环外进入一次上下文管理器。
2. 添加重复数据过滤逻辑
即使修复了Socket的问题,Binance偶尔还是会推送重复的Tick数据,我们可以通过记录最后处理过的消息标识(比如时间戳Time+价格Price,或者直接用毫秒级的时间戳,因为正常情况下同一毫秒不会有重复的Tick)来过滤掉重复项。
修正后的完整代码
import pandas as pd from binance.client import Client from binance import BinanceSocketManager import asyncio api_key = '***' api_secret = '***' # 初始化客户端和Socket client1 = Client(api_key=api_key, api_secret=api_secret) bsm = BinanceSocketManager(client1) socket = bsm.individual_symbol_ticker_futures_socket(symbol='ETHUSDT') # 转换为DataFrame的函数不变 def createframe(msg): df = pd.DataFrame([msg['data']]) df = df.loc[:, ['s', 'E', 'c']] df.columns = ['symbol', 'Time', 'Price'] df.Price = df.Price.astype(float) df.Time = pd.to_datetime(df.Time, unit='ms') return df async def main(): # 只进入一次Socket上下文,避免重复初始化 async with socket: # 记录最后处理过的时间戳和价格,用于过滤重复 last_time = None last_price = None while True: msg = await socket.recv() frame = createframe(msg) # 获取当前Tick的时间和价格 current_time = frame.iloc[0]['Time'] current_price = frame.iloc[0]['Price'] # 对比是否和上一条重复,不重复才处理 if current_time != last_time or current_price != last_price: print(frame) # 更新最后处理的记录 last_time = current_time last_price = current_price # 这里可以添加写入SQLite的代码,确保只写入非重复数据 if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(main())
额外的数据库层面保障
如果担心还是有漏网的重复数据,你可以在SQLite的表中给symbol、Time和Price(或者单独给Time,因为毫秒级时间戳理论上唯一)添加唯一约束,这样即使有重复数据尝试写入,数据库也会自动拒绝,避免脏数据。
比如创建表的时候可以这样写:
CREATE TABLE IF NOT EXISTS futures_ticks ( symbol TEXT, Time TIMESTAMP UNIQUE, Price REAL, PRIMARY KEY (symbol, Time) );
这样既从代码层面过滤了大部分重复,又从数据库层面做了最后一道防线。
内容的提问来源于stack exchange,提问作者Ksharp
相关产品推荐
相关产品推荐

