如何使用Python API在盈透证券上获得我的账户头寸?
我找到了关于错误消息的解决方案-这是IB API上的错误.我在下面作为答案给出的代码对于那些希望使用干净的解决方案以从其在IB账户中读取头寸以及资产净值的人来说应该有用.
EDITED: I found a solution regarding the error messages - it was a bug on IB's API. The code I show as an answer below should be useful for those looking for a clean solution to read positions, and also NAVs, from their accounts at IB.
原始问题[请参见下面的解决方案;请参见下文.在此离开原始问题]:我正在尝试使用该公司的API来获取我在盈透证券[IB]的所有账户头寸.他们的文档尽管内容广泛,却极为混乱.示例代码中充满了不必要的命令-我想要简化一些内容.
The original question [SEE SOLUTION BELOW; LEAVING ORIGINAL QUESTION HERE FOR CONTEXT]: I'm trying to get all my accounts positions at Interactive Brokers [IB] using the firm's API. Their documentation, although extensive, is extremely confusing. Sample codes are full of unnecessary commands - I want something very streamlined.
我需要帮助:
- 如何按帐户"获取信息[已解决]
- 如何将变量带到DataFrame [已解决]
- 如何避免IB的API打印一系列错误消息[已解决]
到目前为止的代码:
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.common import * #for TickerId type
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):
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()
当我运行上面的代码时,我得到了一系列(i)帐号,(ii)合约符号,(iii)头寸和(iv)平均成本.因此,这回答了问题1.您可能需要打印"这些值,以查看IB的API如何向您发送信息.
When I run the code above I get a series of (i) account numbers, (ii) the contract symbol, (iii) position and (iv) average cost. This, therefore, answers question #1. You might want to "print" these values to see how IB's API send you the information.
我还能够定义一个DataFrame变量all_positions
来接收我正在寻找的信息.请参阅下面的结果.请注意,我必须创建一个索引"变量,该变量是DataFrame每行的唯一标识符(作为帐号和符号的组合).没有这种索引",我找不到将信息附加"到DataFrame的方法(欢迎任何有关此操作的想法):
I was also able to define a DataFrame variable all_positions
that receives the information I was looking for. See the result below. Note that I had to create an "index" variable that is a unique identifier for each row of the DataFrame (as a combination of the account number and symbol). I didn't find a way to 'append' information to the DataFrame without this 'index' (any idea on how to do it would be welcome):
关于最后一个问题(错误消息):
As for the last issue (the error messages):
Brian关于错误"功能的建议(见下文)摆脱了"-1"错误.但是我仍然得到以下信息:
Brian's suggestion of the "error" function (see below) got rid of the "-1" errors. But I still get the following:
EReader线程Traceback中的未处理的异常(最新调用) 最后):文件 "C:\ Users \ danil \ Anaconda3 \ lib \ site-packages \ ibapi-9.76.1-py3.7.egg \ ibapi \ reader.py", 运行中的第34行 数据= self.conn.recvMsg()文件"C:\ Users \ danil \ Anaconda3 \ lib \ site-packages \ ibapi-9.76.1-py3.7.egg \ ibapi \ connection.py", recvMsg中的第99行 buf = self._recvAllMsg()文件"C:\ Users \ danil \ Anaconda3 \ lib \ site-packages \ ibapi-9.76.1-py3.7.egg \ ibapi \ connection.py", _recvAllMsg中的第119行 buf = self.socket.recv(4096)OSError:[WinError 10038]尝试对非套接字的东西进行操作
unhandled exception in EReader thread Traceback (most recent call last): File "C:\Users\danil\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\danil\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py", line 99, in recvMsg buf = self._recvAllMsg() File "C:\Users\danil\Anaconda3\lib\site-packages\ibapi-9.76.1-py3.7.egg\ibapi\connection.py", line 119, in _recvAllMsg buf = self.socket.recv(4096) OSError: [WinError 10038] An operation was attempted on something that is not a socket
经过大量的实验,这是我编写的最终代码,它位于名为AB_API的".py"文件中:
After a lot of experimentation, here is the final code I wrote, which is on a ".py" file named AB_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
import time
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_positions = pd.DataFrame([], columns = ['Account','Symbol', 'Quantity', 'Average Cost', 'Sec Type'])
def error(self, reqId:TickerId, errorCode:int, errorString:str):
if reqId > -1:
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
def position(self, account, contract, pos, avgCost):
index = str(account)+str(contract.symbol)
self.all_positions.loc[index]=account,contract.symbol,pos,avgCost,contract.secType
def positionEnd(self):
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 10)
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
import time
class ib_class(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.all_accounts = pd.DataFrame([], columns = ['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 accountSummary(self, reqId, account, tag, value, currency):
if tag == 'NetLiquidationByCurrency':
index = str(account)
self.all_accounts.loc[index]=reqId, account, tag, value, currency
def accountSummaryEnd(self, reqId:int):
self.disconnect()
ib_api = ib_class()
ib_api.connect("127.0.0.1", 7496, 10)
ib_api.reqAccountSummary(9001,"All","$LEDGER")
current_nav = ib_api.all_accounts
ib_api.run()
return(current_nav)
我现在可以使用两个单行功能读取所有帐户头寸和资产净值:
I can now read all accounts positions and NAVs with two single-line functions:
import IB_API
print("Testing IB's API as an imported library:")
all_positions = IB_API.read_positions()
all_navs = IB_API.read_navs()
我希望盈透证券为客户提供一些简单的示例,以使某人更容易测试一些想法并确定他们是否要使用其API.
I wish Interactive Brokers had some simple examples available for clients that would make it easier for someone to test a few ideas and decide if they want to use their API or not.