Need help with TWS API to download stock fundamental data

Discussion in 'App Development' started by josefer, Nov 16, 2019.

Need help with TWS API to download stock fundamental data

  1. Problem with for cycle?

    0 vote(s)
    0.0%
  2. It stucks with app.run()?

    0 vote(s)
    0.0%
Multiple votes are allowed.
  1. josefer

    josefer

    Hi Guys,

    I wrote the program copied below. When I try to execute with the following data in the input file:
    ADBE,USD,NASDAQ
    CSCO,USD,NASDAQ
    GOOGL,USD,NASDAQ

    it only runs for the first stock, ADBE, and does nothing afterwards. The idea is the program should run for each entry in the input file and downloads the corresponding Analysts forecast from InteractiveBrokers and writes it to a XML file.

    To help you with a better Reading, I also attach a picture of the source code.

    can you please help me to identify the problem why it is running only for the first line in the input file?

    Very much appreciated.

    ****Program****

    from ibapi.client import EClient
    from ibapi.wrapper import EWrapper
    from ibapi.contract import Contract
    import time

    class TestApp(EWrapper, EClient):
    def __init__(self):
    EClient.__init__(self, self)

    def error(self, reqId, errorCode, errorString):
    print("Error: ", reqId, "", errorCode, "", errorString)

    def fundamentalData(self, reqId, fundamental_data):
    Filename = str(Symbol) + '_Anal_Est.xml'
    print("Filename: ", Filename)
    f_out = open(Filename, "w")
    f_out.write(fundamental_data)
    f_out.close()

    def main():
    global Symbol

    # The input file need to contain in each line: company ticker,currency,exchange - no spaces between them
    Company_tickers = open("IB_FD_input.txt", 'r').readlines()
    Number_compnaies = len(Company_tickers)
    for stock in Company_tickers:
    aa = stock.split(",")
    Symbol = aa[0].replace(" ", "") # in case there is a space
    Currency = aa[1].replace(" ", "")
    Exchange = aa[2].replace("\n", "").replace(" ","")
    contract = Contract()
    contract.symbol = Symbol
    contract.secType = "STK"
    contract.exchange = "SMART"
    contract.currency = Currency
    contract.primaryExchange = Exchange

    app = TestApp()
    app.connect("127.0.0.1", 7496, 0)
    time.sleep(10)
    app.reqFundamentalData(8001, contract, "RESC", [])
    time.sleep(10)
    app.run()

    if __name__ == "__main__":
    main()
     
    Last edited: Nov 16, 2019
  2. elt894

    elt894

    app.run starts an infinite loop processing messages from the server and dispatching them to EWrapper. I'd recommend looking at ib_insync if you want to submit requests and get responses in a linear manner.
     
    nooby_mcnoob likes this.
  3. reqFundamentalData() sends a request to IB's servers to provide data on the specified contract. IB sends this requested data back to you, to fundamentalData(), using an xml format. It is up to you to define in fundamentalData() what should be done with the returned data. I do not see fundamentalData() in your source code.
    https://interactivebrokers.github.io/tws-api/fundamentals.html
     
  4. josefer

    josefer

    Thanks for your answer. For the moment I am just writing fundamentalData() to a file as defined in fundamentalData() function. I am making this program as simple as possible to see if I can get it working for many input sumbols, let's say 20. Later I Will add the part to process the xml data to write the final output to a csv file. Now my problem is to get this program writing a xml file for each input symbols. Now it works only for the first symbol, ADBE as in my input exemple. Any idea why this happening? why it stops with first symbol?
     
  5. Your code seems to reuse id 8001 for each of the contracts you request data for. Before you can use the same id for a second contract you have to inform IB that you are ready with the contract you have just requested. So, once you have received the data via fundamentalData() you have to send a message cancelFundamentalData(8001). After you have done this can you reuse the same id for another contract. I don't see this canceling in your code. Alternatively you can give each of your contracts a unique id (e.g. 8001, 8002, 8003). You have to create a map to know which id belongs to which contract.
     
  6. josefer

    josefer

    It seems that you really spot the problem. I add the statement
    app.cancelFundamentalData(8001) right after app.run() but nothing has changed. It seems the program continue to run but I don't know what is doing. I also make it using diferente unique id as you suggested, and it behaves the same way. Any idea on how this can be solved?
     
  7. Use ib_insync dude.
     
  8. josefer

    josefer

    I never used that. Can you please suggest how to insert that in the code? Thanks in advance for your help.
     
  9. josefer

    josefer

    #10     Nov 17, 2019