在循环中,对IB的请求响应不同

时间:2018-03-16 20:36:45

标签: python quantitative-finance interactive-brokers

我只是不明白这里发生了什么。我对包装纸和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()

1 个答案:

答案 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()
  • 该程序将首先创建TestApp并阅读csv 文件。
  • 然后你将通过套接字连接到IB网关但不是 阅读到app.run()。
  • 一旦你开始阅读,你就会 rec'v nextValidId和一些关于的信息性错误消息 连接。
  • 一旦nextValidiD被重新开始,你就开始要求提供数据了。
  • 它可以随时出现,但通常是在星期五之前 一切都关闭的夜晚。
  • 如果rec'd,它将打印在您拥有的数据回调中。