如何在Python中迭代获取Interactive Brokers历史数据?数据重复问题排查
解决IBAPI历史数据累加问题
问题根源:你创建的app是全局单一实例,self.data仅在类初始化时被清空一次,每次调用reqHistoricalData时,historicalData回调都会往同一个列表里追加数据,导致每次请求后数据持续累加。
解决方案1:每次请求前手动清空数据
在发起历史数据请求前,直接重置app.data为空列表,确保每次请求都基于全新的数据集:
# ... 原有代码不变 ... while (time.time() <= timeout ): if (datetime.datetime.now().minute % 1==0 )and (datetime.datetime.now().second<10): # 关键:请求前清空数据列表 app.data = [] app.reqHistoricalData(1, contract, '', '3600 S', '1 min', 'TRADES', 0, 1, False, []) time.sleep(2) df = pandas.DataFrame(app.data) df.columns=['DateTime','Open','High','Close','Low','Volume'] print(len(df)) print(df)
解决方案2:利用historicalDataEnd回调(更可靠)
time.sleep(2)的方式存在网络延迟风险,可能导致数据未完全接收就开始处理。IBAPI提供了historicalDataEnd回调,当所有历史数据接收完成时会触发该方法,我们可以在这里处理数据并重置状态:
修改IBapi类,添加回调方法和数据接收标记:
class IBapi(EWrapper, EClient): def __init__(self): EClient.__init__(self, self) self.data =[] self.data_received = False # 标记数据是否接收完成 def historicalData(self, reqId, bar): print(f'DateTime: {bar.date} Open: {bar.open} High: {bar.high} Close: {bar.close} Low: {bar.low} Volume: {bar.volume}') self.data.append([bar.date, bar.open,bar.high,bar.close,bar.low,bar.volume]) def historicalDataEnd(self, reqId, start, end): print("历史数据接收完成") self.data_received = True # 触发回调时标记完成
修改主循环,等待数据完全接收后再处理:
# ... 原有代码不变 ... while (time.time() <= timeout ): if (datetime.datetime.now().minute % 1==0 )and (datetime.datetime.now().second<10): # 重置数据和标记位 app.data = [] app.data_received = False app.reqHistoricalData(1, contract, '', '3600 S', '1 min', 'TRADES', 0, 1, False, []) # 等待数据接收完成,替代固定时长sleep while not app.data_received: time.sleep(0.1) df = pandas.DataFrame(app.data) df.columns=['DateTime','Open','High','Close','Low','Volume'] print(len(df)) print(df)
该方案既解决了数据累加问题,又能确保数据完全接收后再处理,避免因网络波动导致的数据不全。
内容的提问来源于stack exchange,提问作者Hai Li
相关产品推荐
相关产品推荐

