使用 Python API 下载数据时如何消除(或从控制台抑制)Interactive Brokers 错误
How to eliminate (or suppress from console) Interactive Brokers error when downloading data with Python API
我编写了以下代码以从我在盈透证券的账户中读取信息:
# Interactive Brokers functions to import data
def read_positions(): #read all accounts positions and return DataFrame with information
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId
import pandas as pd
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_positions = pd.DataFrame([], columns = ['Account','Symbol', 'Quantity', 'Average Cost'])
def position(self, account, contract, pos, avgCost):
index = str(account)+str(contract.symbol)
self.all_positions.loc[index]=account,contract.symbol,pos,avgCost
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def positionEnd(self):
super().positionEnd()
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 0)
ib_api.reqPositions()
current_positions = ib_api.all_positions
ib_api.run()
return(current_positions)
def read_navs(): #read all accounts NAVs
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId
import pandas as pd
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_accounts = pd.DataFrame([], columns = ['reqId','Account', 'Tag', 'Value' , 'Currency'])
def accountSummary(self, reqId, account, tag, value, currency):
if tag == 'NetLiquidationByCurrency':
index = str(account)
self.all_accounts.loc[index]=reqId, account, tag, value, currency
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def accountSummaryEnd(self, reqId:int):
super().accountSummaryEnd(reqId)
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 0)
ib_api.reqAccountSummary(9001,"All","$LEDGER")
current_nav = ib_api.all_accounts
ib_api.run()
return(current_nav)
如果我调用 read_positions()
或 read_navs()
这两个函数,我会在 DataFrame 变量上得到我想要的结果。但是,我收到一条错误消息(在控制台上),内容为:
"OSError: [WinError 10038] An operation was attempted on something
that is not a socket".
在错误消息本身之前,我收到了很多与错误相关的消息:
unhandled exception in EReader thread Traceback (most recent call
last): File
"C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\reader.py",
line 34, in run
data = self.conn.recvMsg() File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py",
line 99, in recvMsg
buf = self._recvAllMsg() File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py",
line 119, in _recvAllMsg
buf = self.socket.recv(4096)
IB 的服务台拒绝回答我的问题:我该如何避免或抑制此错误消息?我不知道这是我做错了什么,还是他们 API 上的错误。只要我能避免这些垃圾打印在我的控制台上,我就没事了。非常感谢任何指导。
我在 9.76.01 上遇到了类似的问题API,所以我回到了 9.74.01,没有这个问题。
我试图用 try/catch 块来抑制错误,但我从来没有让它起作用。
Matt 上面的回答是正确的:这是一个 API 错误!我添加此答案只是为了提供有关如何降级到旧版本的更清晰的步骤:
1) 从这里下载旧版本:http://interactivebrokers.github.io/downloads/TWS%20API%20Install%20974.01.msi
IB 不显示旧版本的 links,但他们将文件保留在 Github 上(注意 link 地址末尾的版本名称)
2) 卸载当前版本。在 IB 自己的网站上,执行以下操作:
- 从 Windows
中的 "Add/Remove Tool" 卸载 API
像往常一样控制面板
- 删除 C:\TWS API\ 文件夹,如果仍有任何文件以防止版本不匹配。
- 找到文件 "C:\Windows\SysWOW64\TwsSocketClient.dll"。删除这个文件。 [没有找到这个文件]
- 在安装不同的 API 版本之前重新启动计算机。
3) 使用 .msi 文件安装 API
4) 运行 Anaconda 提示符并导航到目录 C:\TWS API\source\pythonclient
5) 运行: "python setup.py install"
6) python setup.py 安装后,重新启动 Spyder(如果它已打开;我在上面的第 5 步之前关闭了我的)
我安装这个旧版本后,错误消失了!
我能够消除错误,但我不确定此修复是否破坏了其他任何东西。也许对API代码有深入了解的人可以告诉我们这样是否可以。
在connection.py
def _recvAllMsg(self):
cont = True
allbuf = b""
while cont and self.socket is not None:
try: #this line added
buf = self.socket.recv(4096)
except OSError: #this line added
buf = b'' #this line added
allbuf += buf
logger.debug("len %d raw:%s|", len(buf), buf)
if len(buf) < 4096:
cont = False
return allbuf
我终于找到了这个问题的答案:你可以看到下面的解决方案:
https://groups.io/g/twsapi/message/43333
它涉及快速更改 connection.py 文件并重新安装 TWS API。我之前在这里留下了答案,以防有人出于某种原因想要安装旧版本。
因此,我没有降级,而是找到了抑制错误消息的快速修复方法。转到它搞砸的脚本,它应该是 connection.py 并且在最底部的第 119 行。这就是我为捕获错误所做的工作并且它起作用了。
while cont and self.socket is not None:
try:
buf = self.socket.recv(4096)
allbuf += buf
logger.debug("len %d raw:%s|", len(buf), buf)
if len(buf) < 4096:
cont = False
except OSError:
pass
我编写了以下代码以从我在盈透证券的账户中读取信息:
# Interactive Brokers functions to import data
def read_positions(): #read all accounts positions and return DataFrame with information
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId
import pandas as pd
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_positions = pd.DataFrame([], columns = ['Account','Symbol', 'Quantity', 'Average Cost'])
def position(self, account, contract, pos, avgCost):
index = str(account)+str(contract.symbol)
self.all_positions.loc[index]=account,contract.symbol,pos,avgCost
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def positionEnd(self):
super().positionEnd()
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 0)
ib_api.reqPositions()
current_positions = ib_api.all_positions
ib_api.run()
return(current_positions)
def read_navs(): #read all accounts NAVs
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import TickerId
import pandas as pd
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_accounts = pd.DataFrame([], columns = ['reqId','Account', 'Tag', 'Value' , 'Currency'])
def accountSummary(self, reqId, account, tag, value, currency):
if tag == 'NetLiquidationByCurrency':
index = str(account)
self.all_accounts.loc[index]=reqId, account, tag, value, currency
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def accountSummaryEnd(self, reqId:int):
super().accountSummaryEnd(reqId)
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 0)
ib_api.reqAccountSummary(9001,"All","$LEDGER")
current_nav = ib_api.all_accounts
ib_api.run()
return(current_nav)
如果我调用 read_positions()
或 read_navs()
这两个函数,我会在 DataFrame 变量上得到我想要的结果。但是,我收到一条错误消息(在控制台上),内容为:
"OSError: [WinError 10038] An operation was attempted on something that is not a socket".
在错误消息本身之前,我收到了很多与错误相关的消息:
unhandled exception in EReader thread Traceback (most recent call last): File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\reader.py", line 34, in run data = self.conn.recvMsg() File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py", line 99, in recvMsg buf = self._recvAllMsg() File "C:\Users\xxxxx\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py", line 119, in _recvAllMsg buf = self.socket.recv(4096)
IB 的服务台拒绝回答我的问题:我该如何避免或抑制此错误消息?我不知道这是我做错了什么,还是他们 API 上的错误。只要我能避免这些垃圾打印在我的控制台上,我就没事了。非常感谢任何指导。
我在 9.76.01 上遇到了类似的问题API,所以我回到了 9.74.01,没有这个问题。
我试图用 try/catch 块来抑制错误,但我从来没有让它起作用。
Matt 上面的回答是正确的:这是一个 API 错误!我添加此答案只是为了提供有关如何降级到旧版本的更清晰的步骤:
1) 从这里下载旧版本:http://interactivebrokers.github.io/downloads/TWS%20API%20Install%20974.01.msi
IB 不显示旧版本的 links,但他们将文件保留在 Github 上(注意 link 地址末尾的版本名称)
2) 卸载当前版本。在 IB 自己的网站上,执行以下操作:
- 从 Windows
中的 "Add/Remove Tool" 卸载 API 像往常一样控制面板 - 删除 C:\TWS API\ 文件夹,如果仍有任何文件以防止版本不匹配。
- 找到文件 "C:\Windows\SysWOW64\TwsSocketClient.dll"。删除这个文件。 [没有找到这个文件]
- 在安装不同的 API 版本之前重新启动计算机。
3) 使用 .msi 文件安装 API
4) 运行 Anaconda 提示符并导航到目录 C:\TWS API\source\pythonclient
5) 运行: "python setup.py install"
6) python setup.py 安装后,重新启动 Spyder(如果它已打开;我在上面的第 5 步之前关闭了我的)
我安装这个旧版本后,错误消失了!
我能够消除错误,但我不确定此修复是否破坏了其他任何东西。也许对API代码有深入了解的人可以告诉我们这样是否可以。
在connection.py
def _recvAllMsg(self):
cont = True
allbuf = b""
while cont and self.socket is not None:
try: #this line added
buf = self.socket.recv(4096)
except OSError: #this line added
buf = b'' #this line added
allbuf += buf
logger.debug("len %d raw:%s|", len(buf), buf)
if len(buf) < 4096:
cont = False
return allbuf
我终于找到了这个问题的答案:你可以看到下面的解决方案:
https://groups.io/g/twsapi/message/43333
它涉及快速更改 connection.py 文件并重新安装 TWS API。我之前在这里留下了答案,以防有人出于某种原因想要安装旧版本。
因此,我没有降级,而是找到了抑制错误消息的快速修复方法。转到它搞砸的脚本,它应该是 connection.py 并且在最底部的第 119 行。这就是我为捕获错误所做的工作并且它起作用了。
while cont and self.socket is not None:
try:
buf = self.socket.recv(4096)
allbuf += buf
logger.debug("len %d raw:%s|", len(buf), buf)
if len(buf) < 4096:
cont = False
except OSError:
pass