Placing orders asyncronously like this without causing issues with the twsapi

31 views Asked by At

I want to check if this is possible. I’m using the python TWSAPI with Asyncio.

I am using the following code which queries a price using certain conditions from an api, the prices are returned to me asynchronously.

I want to place the order as soon as the query has been returned from the api. I put the app.placeorder into the async loop as shown below.

def BracketOrder(self, .....):


    # 1st part: Buy Adaptive Algo order
    opening = Order()
    opening.orderId = parentOrderId
    ./....
    opening.conditions.append(timeCondition)


    # 2nd part take profit or stop loss
    takeProfit = Order()
    takeProfit.orderId = opening.orderId + 2
    ....
    takeProfit.transmit = False

    stopLoss = Order()
    stopLoss.orderId = opening.orderId + 3
    ....
    stopLoss.transmit = False

    # # 3rd part: Sell Adaptive Algo order
    closing = Order()
    closing.orderId = opening.orderId + 4
    ...
    bracketOrder = [opening, takeProfit, stopLoss, closing]
    return bracketOrder


async def get_data(session, ticker):
    while True:
        try:
            async with session.get(url=f'api.exec.com') as response:
                if response.status == 200:
                    data = await response.json()
                    try:
                        df = pd.DataFrame(data)
                    except ValueError:
                        print("Data is not a valid float. Retrying...")
                else:
                    print("Received non-200 status code. Retrying...")
            await asyncio.sleep(1)  
        except Exception as e:
            print("Unable to get url {} due to {}. Retrying...".format(ticker, e.__class__))
            await asyncio.sleep(1)


    bracket = app.BracketOrder(parentOrderId=app.nextOrderId(), .........)

    for o in bracket:
        app.placeOrder(o.orderId, app.EQ_order_MKT(ticker), o)
        app.nextOrderId() 


async def main_loop(ticker_list):
    async with aiohttp.ClientSession() as session:
        ret = await asyncio.gather(*[get_data(session, tick) for tick in ticker_list])
        #return {ticker_list[i]: ret[i] for i in range(len(ticker_list))}
        return ret

def run_loop():
    app.run()

app = ib_class("127.0.0.1", 4002, 999)

#app.nextorderId = None
# Start the socket in a thread
api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()

asyncio.run(main_loop(new_portfolio.keys()))

I will feed a list of tickers, and this function should run for each ticker.

I am worried that I will place multiple orders at the exact same time and the order id's will get messed up. Is there a way around this or does twsapi automatically mitigate this?

0

There are 0 answers