对 IB 的请求在循环中以不同的方式响应



我只是不明白这里发生了什么。我对包装器和IB有点陌生。这是我覆盖和解析 XML 的函数。应该主要解析 XML 吗?我只想获取 CSV 文件中所有交易品种的基本数据。当我注释掉循环并运行单个请求时,它有时会起作用。这是怎么回事?

class TestApp(EWrapper, EClient):
def __init__(self):
EWrapper.__init__(self)
EClient.__init__(self, wrapper=self)
self.csv = pd.read_csv('getfund.csv');
self.symbols = self.csv['Symbol']
self.exchanges = self.csv['Exchange']
def nextValidId(self, reqId: int):
reqs_do()
def reqs_do():
for i in range(len(symbols)):
contract = Contract()
contract.symbol = self.symbols[i]
contract.secType = "STK"
contract.exchange = self.exchanges[i]
contract.currency = "USD"
contract.primaryExchange = "NASDAQ"
print(contract)
print(symbols[i])
print(exchanges[i])
print(i)
app.reqFundamentalData(8001 , contract, "ReportsFinSummary", [])
def error(self, reqID:TickerId, errorCode:int, errorString:str):
print("Error: ", reqID, " " , errorCode, " ", errorString)
def fundamentalData(self, reqId: TickerId, data: str):
super().fundamentalData(reqId, data)
print("FundamentalData. ", reqId, data)
e = ET.fromstring(data)
e.tag
e.attrib
##code to parse the XML file returned from the ib reqfundamentaldata function.
##there are multiple report types and I am uncertain what they mean, worth
##looking into later.
row_list = []
for atype in e.iter('TotalRevenue'):
if atype.attrib['reportType']=="A"  and atype.attrib['period']=="3M":
dict1 = {"Date": atype.attrib['asofDate'], 
'Revenue':atype.text}
row_list.append(dict1)
columns = ['Date', 'Revenue']
tr = pd.DataFrame(row_list, columns=columns)

row_list = []
for atype in e.iter('DividendPerShare'):
if atype.attrib['reportType']=="A" and atype.attrib['period']=="3M":
dict1 = {"Date": atype.attrib['asofDate'],
'Dividend':atype.text}
row_list.append(dict1)
columns = ['Date', 'Dividend']
dps = pd.DataFrame(row_list, columns=columns)

row_list = []
for atype in e.iter('EPS'):
if atype.attrib['reportType']=="A" and atype.attrib['period']=="3M":
dict1 = {"Date": atype.attrib['asofDate'],
'EPS':atype.text}
row_list.append(dict1)
columns = ['Date', 'EPS']
eps = pd.DataFrame(row_list, columns=columns)
temp = tr.merge(dps, left_on='Date', right_on='Date', how='left')
fin = temp.merge(eps, left_on='Date', right_on='Date', how='left')
print(fin)
#fin.to_csv("fin.csv", sep=',')
if done: app.disconnect()

def main():
app = TestApp()
app.connect("127.0.0.1", 4001, clientId=123)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),
app.twsConnectionTime()))
app.run()

if __name__ == "__main__":
main()

您的逻辑让您连接然后请求所有数据,同时在请求之间等待 60 秒......然后侦听响应 (app.run)。

app.run() 从套接字开始循环读取响应。 如果没有一些线程,则在此调用后无法执行任何操作。 您可以编写程序以异步方式执行操作。

一旦你有一个运行读取循环的连接,你就可以开始请求数据了。 nextValidId 用于此目的,因为它是 TWS(IBG) 发送的第一个响应。 所以在nextValidId中,你真正启动了你的程序。

您的代码永远不会断开连接,因为 app.run() 正在阻塞线程。 您需要使用异步逻辑来决定何时断开连接。 在这个简单的情况下,只需计算请求数。

不是真正的程序,只是为了说明逻辑流程。

class TestApp(EWrapper, EClient):
def __init__(self):
#other stuff
#make the following members instead of global
self.csv = pd.read_csv('getfund.csv');
self.symbols = csv['Symbol']
self.exchanges = csv['Exchange']
def nextValidId(self, reqId: int):
reqs_do()
def reqs_do():
for i in range(len(symbols)):
# same, just use self.symbols etc..
def fundamentalData(self, reqId: TickerId, data: str):
# similar but disconnect after everything has been rec'd 
if done: app.disconnect()
def main():
app = TestApp()
app.connect("127.0.0.1", 4001, clientId=123)
app.run()
if __name__ == "__main__": main()
  • 该程序将通过首先创建测试应用程序并读取csv来工作 文件。
  • 然后,您将通过套接字连接到IB网关,但不是 读取直到 app.run()。
  • 一旦你开始阅读,你就会 rec'v nextValidId 和一些关于 连接。
  • 一旦下一个ValidiD被记录下来,你就会开始要求数据。
  • 它可以随时出现,但通常马上出现,但周五除外 一切都关闭的夜晚。
  • 如果已记录,它将打印在您拥有的数据回调中。

最新更新