我只是不明白这里发生了什么。我对包装纸和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()
答案 0 :(得分:2)
你的逻辑让你连接,然后在请求之间等待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()