开云体育

ctrl + shift + ? for shortcuts
© 2025 开云体育

async orders getting stuck in "preSumbitted" status


 
Edited

I have some code below that functions as intended like 80% of the time but for some reason, random orders are not being placed in IBKR. When I debug the issue, it seems that certain orders never make it past this "preSumbitted" status, despite being completely valid orders that I'm trying to send to IBKR. I tried using "sleeps" (IB, Time, and asyncio), but I can't seem to get this to work 100% of the time. Is there something wrong with my async logic here? It's a pretty simple script that uses a polygon.io WebSocket.
from polygon import WebSocketClient
from polygon.websocket.models import WebSocketMessage
import pandas as pd
import numpy as np
import datetime
import time
from ib_insync import IB, Stock, LimitOrder, Order
import asyncio
import nest_asyncio nest_asyncio.apply()
t = 'AAPL' client = WebSocketClient("xxx") # hardcoded api_key is used client.subscribe("AM." + t) # all aggregates #Connect IBKR ib = IB() ib.connect('127.0.0.1', 7496, clientId=0) #Change for paper async def handle_msg(msgs: List[WebSocketMessage]): for m in msgs: data = {'ticker': [m.symbol], 'close': [m.close], 'vwap': [m.vwap], 'start_timestamp': [m.start_timestamp], 'end_timestamp': [m.end_timestamp]} data['start_timestamp'] = pd.to_datetime(data['start_timestamp'], unit='ms') data['end_timestamp'] = pd.to_datetime(data['end_timestamp'], unit='ms') data['gtd_buy'] = data['end_timestamp'] + pd.Timedelta(seconds=58) data['gtd_buy'] = data['gtd_buy'].astype(str).str.replace('-', '') gtd = data['gtd_buy'][0] df = pd.DataFrame(data) buy = np.where(df.close < df.vwap, 1, 0) print(df.head(1), buy[0]) pos = pd.DataFrame(ib.positions()) #Buy if buy[0] == 1: if pos.shape[0] == 0: contract = Stock(t, 'SMART', 'USD') ib.qualifyContracts(contract) curr_dt = datetime.datetime.now() order = LimitOrder('BUY', totalQuantity = 1, lmtPrice = m.close, tif = 'GTD', goodTillDate = gtd, hidden=True) order.orderId = int(curr_dt.timestamp()) print('Buy Triggered', order.orderId) trade = ib.placeOrder(contract, order) await asyncio.sleep(30) async def main(): await asyncio.gather(client.connect(handle_msg))


 

On Sun, Nov 10, 2024 at 05:04 AM, <briankubs557@...> wrote:
order.orderId = int(curr_dt.timestamp())
1. I haven't seen order ids created like this before. Maybe it's fine, but it's more standard to just use
orderId=self.ib.client.getReqId()
?
2. The sleep after you place the order might be fine, but also recommend using ib.sleep instead
?
3. Your order may be presubmitted because it's not marketable and ibkr sometimes keeps an order as presubmitted until it's marketable, then submits it to the exchange once the price reaches your limit. Not sure if that's happening here but it's happened to me before, especially in the paper acct.


 

Appreciate the feedback. I'll give #1 a shot to see if it clears up the issue.
?
Regarding #2, I've tried that as well but it doesn't seem to matter (orders still get stuck for me).
?
For #3, I've manually tracked when the order should become marketable (as in the buy/sell order should be sent to TWS) but it's just totally missing submitting orders regardless (which causes obvious drift from backtesting results). I also don't even bother testing in the paper account because it's so wonky (I just run live tests with 1 share to ensure repeatability).
?
?


 

Hm yea I'm not sure. I'd say remove the sleeps entirely and setup listeners on all the ib-async events in case there's some useful info coming through there.?
?
Do you get the same issue when using market orders instead of limit?


 

I haven't tried using market orders as they're generally just not profitable with my trading strategies over the years but I'll test some out tomorrow when the market opens up. Appreciate the tips!


 

Was able to figure it out. It was related to the limit order. Specifically, I was not rounding my limit price to 2 decimals, so IBKR just ignores any orders with >2 decimals (which is very bad behavior, no errors are given). When it was filling before it was just getting lucky the price happened to have 2 decimals. I just added some code to round off to 2 decimals and no issues.
?
Thanks for your help!