erdewit / ib_insync

Python sync/async framework for Interactive Brokers API
BSD 2-Clause "Simplified" License
2.84k stars 769 forks source link

Wrong Results #367

Closed dangalea closed 3 years ago

dangalea commented 3 years ago

Hi,

I am trying to get yesterday's % change for all the symbols traded. To do this, I am ingesting two .txt files containing all the symbols and then using a multiprocessing pool to call ib.reqHistoricalData() for each symbol, after which I calculate the % change. However, when I do this, I'm getting inconsistent results between runs: some symbols return a different value between runs and some return no value between runs. Could anyone help?

from ib_insync import *
import subprocess as sp
import pandas as pd
import copy
import multiprocessing as mp

def get_all_symbols():

    sp.run(["wget", "ftp://ftp.nasdaqtrader.com/symboldirectory/nasdaqlisted.txt"]) 
    sp.run(["wget", "ftp://ftp.nasdaqtrader.com/symboldirectory/nasdaqtraded.txt"]) 

    listed = pd.read_csv("nasdaqlisted.txt", delimiter="|")
    listed = listed[listed['ETF'] == 'N']
    listed = listed[listed['Test Issue'] == 'N']
    listed = listed["Symbol"].values

    traded = pd.read_csv("nasdaqtraded.txt", delimiter="|")
    traded = traded[traded['ETF'] == 'N']
    traded = traded[traded['Test Issue'] == 'N']
    traded = traded["Symbol"].values

    full = copy.deepcopy(traded)

    for symb in listed:
        if symb not in full:
            full.append(copy.deepcopy(symb))

    sp.run(["rm", "/home/daniel/Documents/IBApi/nasdaqtraded.txt"])
    sp.run(["rm", "/home/daniel/Documents/IBApi/nasdaqlisted.txt"])

    return full

def get_perc_change(contract):

    try:
        symbol = contract.symbol
        bars = ib.reqHistoricalData(contract, endDateTime='', durationStr='2 D', barSizeSetting='1 min', whatToShow='MIDPOINT', useRTH=True)

        # convert to pandas dataframe:
        df = util.df(bars)
        open_price = df[df["date"] == "2021-05-06 14:30:00"].open.values[0]
        close_price = df[df["date"] == "2021-05-06 20:30:00"].open.values[0]

        return symbol, (open_price - close_price)/open_price*100

    except:
        return symbol, None

if __name__ == "__main__":

    ib = IB()
    ib.RequestTimeout = 3
    ib.connect('127.0.0.1', 7497, clientId=1)

    symbols = get_all_symbols()

    inputs = []
    for symbol in symbols:
        inputs.append(Stock(symbol, "SMART", "USD"))

    pool = mp.Pool(20)
    res = list(pool.map(get_perc_change, inputs))

    for r in res:
        print(r)    
erdewit commented 3 years ago

using a multiprocessing pool to call ib.reqHistoricalData()

The API connection is not safe to use in multiple threads or processes.