当前位置: 首页 > 知识库问答 >
问题:

Python Interactive Brokers IB API非常非常慢

阴鸿才
2023-03-14

我正在尝试新的Python Interactive Broker API,但我在第一步遇到了一些严重的速度问题...

下面的代码(见下文)重复了两次

0:00:08.832813直到数据被接收完毕

0:00:36.000785直到应用程序完全断开连接。。。

为什么这么慢?最好的加速方法是什么?

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.utils import iswrapper #just for decorator
from ibapi.common import *
from ibapi.contract import *
import datetime
from datetime import timedelta


class DataApp(wrapper.EWrapper, EClient):
    def __init__(self):
        wrapper.EWrapper.__init__(self)
        EClient.__init__(self, wrapper=self)

    @iswrapper
    def historicalData(self, reqId: TickerId, date: str, open: float, high: float,
                            low: float, close: float, volume: int, barCount: int,
                            WAP: float, hasGaps: int):
        super().historicalData(reqId, date, open, high, low, close, volume,
                                barCount, WAP, hasGaps)
        print("HistoricalData. ", reqId, " Date:", date, "Open:", open,
               "High:", high, "Low:", low, "Close:", close, "Volume:", volume)

    @iswrapper
    def historicalDataEnd(self, reqId: int, start: str, end: str):
        super().historicalDataEnd(reqId, start, end)
        print("HistoricalDataEnd ", reqId, "from", start, "to", end)
        print(datetime.datetime.now()-startime)
        self.done = True # This ends the messages loop - this was not in the example code...

    def get_data(self):        
        self.connect("127.0.0.1", 4002, clientId=10)
        print("serverVersion:%s connectionTime:%s" % (self.serverVersion(),
                                                self.twsConnectionTime()))

        cont = Contract()
        cont.symbol = "ES"
        cont.secType = "FUT"
        cont.currency = "USD"
        cont.exchange = "GLOBEX"
        cont.lastTradeDateOrContractMonth = "201706"
        self.reqHistoricalData(1, cont, datetime.datetime.now().strftime("%Y%m%d %H:%M:%S"),
                               "1800 S", "30 mins", "TRADES", 0, 1, [])
        self.run()        
        self.disconnect()
        print(datetime.datetime.now()-startime)

global starttime
startime = datetime.datetime.now()
DA = DataApp()
DA.get_data()

我还试图在后台持续运行它,以便只在运行时提交请求

def runMe():
    app.run() # where run() has be removed from the class definition

import threading
thread = threading.Thread(target = runMe)
thread.start()

但速度也非常慢。有什么建议吗

共有3个答案

阎乐池
2023-03-14

app。run()是一个无限循环,而是一个应用程序。done==False,但当应用程序运行时,它不会立即停止。完成设置为真。(我不知道为什么)。

我所做的是编写一个新方法,而不是使用app。运行()

以下是我的解决方案:

import time
from ibapi import (decoder, reader, comm)

并将此函数放入您的客户端类中。

def getMessage(self, wait=3):
    # wait 3 secs for response to come in
    time.sleep(wait)
    # get everything in app.msg_queue
    while not self.msg_queue.empty():
        text = self.msg_queue.get(block=True, timeout=0.2)
        fields = comm.read_fields(text)
        self.decoder.interpret(fields)

用法很简单,只需用app.getMessage()代替app.run()

文国发
2023-03-14

当前的API(2019年5月)通过移除@BenM在其回答中提出的recvMsg中的锁,提高了速度。但是,根据请求的类型,它仍然可能很慢。

删除大部分日志记录会有所帮助,可能是因为某些msg类型相当大。我最初尝试使用日志记录库将其过滤掉,但从速度上看,完全删除代码效果更好,我把这归因于在传递到日志记录之前生成更大字符串所需的额外处理。

用deque替换Queue:在客户机中替换队列可能也值得。py带有一个集合。因为deque是

队列与deque速度比较

范福
2023-03-14

我建议您在ibapi模块的connection类中修改连接套接字锁。该建议来自github上的何世明;如果您有权访问私人互动经纪人回购协议,您可以访问此处的讨论https://github.com/InteractiveBrokers/tws-api/issues/464

我这样做了,它显著提高了性能。

和信明建议您减少套接字锁对象的超时时间,该对象在每次发送或接收消息时都会调用。要修改套接字锁,请转到ibapi的网站包文件夹,并在connection.py内修改连接函数,将“self.socket.settimeout(1)”更改为“self.socket.settimeout(0.01)”。这是我有的版本的connection.py第48行。

如果你看不到何世明的帖子,我会把它放在这篇帖子的底部。

替代选项:另一个有趣的解决方案是利用异步事件循环来实现异步事件循环。我还没有这样做,但看起来很有希望。参见Ewald放在一起的示例https://github.com/erdewit/tws_async

何世明评论:

Connection/ibapi/Connection的实现。py在sendMsg和recvMsg中共享一个锁对象。既然连接,自我。插座settimeout(1)被调用,因此是底层的self。插座recv(4096)每秒仅超时一次。

这种实现会造成性能问题。由于锁是共享的,所以套接字在接收时无法发送数据。在接收的消息长度小于4k字节的情况下,recvMsg函数将在释放锁之前等待1秒,从而使后续的sendMsg等待。在我的实验中,大多数消息似乎都小于4k字节。换句话说,这规定了每秒一个recvMsg的上限。

有一些策略可以缓解这种情况。一个可以将接收缓冲区减少到一个比4k少得多的数字,或者将套接字超时减少到0.001秒左右,以减少阻塞。

或者根据http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid,套接字本身实际上是线程安全的。因此不需要锁。

我尝试了所有三种策略。移除锁效果最好。以类似的方式将超时时间减少到0.001。

我只能担保linux/unix平台,而且我还没有在Windows上尝试过。你会考虑改变实施方式来改进这个吗?

 类似资料:
  • 我搜索了数据库和食谱,但似乎找不到正确的答案。我有一个非常简单的python代码,它总结了一个范围内的自我权力。我需要这个非常非常大的数字的最后十位,我已经尝试了get上下文(). prec,但是我仍然达到了极限。 代码如下: 我怎么能看到这些美丽的数字?它在我的四核上打印速度相对较快。这只是为了给ProjectEuler带来乐趣,问题#48,请不要破坏者。我不想要解决方案,也不想让工作为我完成,

  • 非常道CSS框架是一个国内开源CSS框架,它具有良好的规范性、兼容性、易用性。除了框架有一个良好的展示效果外,还规划了一套比较合理的自定义CSS入库规则,这使得这套框架可以更好的满足一些使用者的CSS定制需求。最后也是最重要的一点,它还处在测试阶段,你的支持和意见将会就是我们坚持的动力,让我们一起使它更加完善,在此感谢! 在线演示:http://www.icsser.com/feichangdao

  • 问题内容: 我很想使用BrowserSync进行开发。但是,页面加载(不仅是更改后重新加载)非常慢。 我使用模式。在没有BrowserSync的情况下浏览网页的速度应该很快。 原因之一可能是我安装BrowserSync时出现以下错误: 我从头开始安装节点(使用和软件包安装程序),但无法摆脱错误。 此外,如果使用Gulp或在命令行上运行BrowserSync,也没有什么不同。 任何想法? 问题答案:

  • 问题内容: 一些背景信息:我想在Red Hat服务器上运行脚本以从/ dev / random中读取一些数据,并使用Perl unpack()命令将其转换为十六进制字符串,以备后用(基准数据库操作)。我在/ dev / random上运行了一些“ head -1”,它看起来工作得很好,但是多次调用后,它还是会挂起。几分钟后,它将最终输出一小段文本,然后结束。 我切换到/ dev / urandom

  • 问题内容: 这是我用来填写QT Designer中绘制的表格的代码。设计为对任何表通用,它可以正常工作,但是…当我尝试显示包含18列和〜12000行的datasat时,它冻结30秒或更长时间。因此,我做错了什么,有没有办法加快速度,保持代码仍然适合任何表? 那是我的代码: 问题答案: 这里是一个测试脚本,它比较了几种填充表格的方法。 自定义模型要快得多,因为它不必先创建所有项- 但请注意,这是一个

  • 我试图使用Java Swing/AWT 2D图形在窗口中显示一些非常基本的信息。在这一点上,我只是画了一些弦,但是尽管这个任务看起来并不困难,但它运行得非常慢。 我是不是根本上错过了什么?