开云体育

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

Not properly parsing modified orders or am I missing the point of `Trade` objects?


 

I'm having some issues getting correct modified order data returned by ib_insync and I'm trying to get to the bottom of it.

As an example workflow, I place a position order and a stop order. Once the position order fills, I modify the stop order and send it.

Placed Order

Order object I transmitted to place the order:

Order(orderId=509133, action='BUY', totalQuantity=200, orderType='LIT', lmtPrice=169.97, auxPrice=169.94, tif='GTD', orderRef='position-2U-2U-1h--eid-1914--ogid-13491', goodTillDate='20240611 18:22:00 UTC', usePriceMgmtAlgo=True), Order(orderId=509134, action='SELL', totalQuantity=200, orderType='STP LMT', lmtPrice=169.83, auxPrice=169.86, orderRef='stop-2U-2U-1h--eid-1914--ogid-13491', parentId=509133, triggerMethod=4, usePriceMgmtAlgo=True)

Trade object received from orderStatusEvent after order placed:

Trade(contract=Stock(conId=76792991, symbol='TSLA', exchange='SMART', primaryExchange='NASDAQ', currency='USD', localSymbol='TSLA', tradingClass='NMS'), order=Order(orderId=509134, clientId=1000, permId=541689050, action='SELL', totalQuantity=200.0, orderType='STP LMT', lmtPrice=169.83, auxPrice=169.86, orderRef='stop-2U-2U-1h--eid-1914--ogid-13491', parentId=509133, triggerMethod=4, usePriceMgmtAlgo=True), orderStatus=OrderStatus(orderId=509134, status='PreSubmitted', filled=0.0, remaining=200.0, avgFillPrice=0.0, permId=541689050, parentId=509133, lastFillPrice=0.0, clientId=1000, whyHeld='child,trigger', mktCapPrice=0.0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 14, 397321, tzinfo=datetime.timezone.utc), status='PendingSubmit', message='', errorCode=0), TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 14, 530493, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='', errorCode=0)], advancedError='')

Here are the TWS API Logs to corroborate what's in the returned Trade object:

14:21:14:340 -> --?5-509134-76792991-TSLA-STK--0-?--SMART-USD-TSLA-NMS-SELL-200-STP LMT-169.83-169.86-DAY-541689049-DU5623872-O-0-stop-2U-2U-1h--eid-1914--ogid-13491-1000-541689050-0-0-0--541689050.0/DU5623872/100----------0---1-0------2147483647-0-0-0--3-0-0--509133-4--0-None--0----?-0-0--0-0------0-0-0-2147483647-2147483647---0--IB-0-0--0-0-PreSubmitted-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308------0-0-0-None-1.7976931348623157E308-169.86-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-0----0-1-0-0-1---0--100-0.02------F3-509134-PreSubmitted-0-200-0-541689050-509133-0-1000-child,trigger-0-

Modified Order

Order object I transmitted to modify the order. I modify lmtPrice and auxPrice:

Order(orderId=509134, clientId=1000, permId=541689050, action='SELL', totalQuantity=200.0, orderType='STP LMT', lmtPrice=169.98, auxPrice=170.02, orderRef='stop-2U-2U-1h--eid-1914--ogid-13491', parentId=509133, triggerMethod=4, usePriceMgmtAlgo=True)]

Trade object received from modifyOrderEvent after modified order placed doesn't reflect the modified price. TradeLogEntry shows message='Modify' so I know I'm receiving the correct event:

Trade(contract=Stock(conId=76792991, symbol='TSLA', exchange='SMART', primaryExchange='NASDAQ', currency='USD', localSymbol='TSLA', tradingClass='NMS'), order=Order(orderId=509134, clientId=1000, permId=541689050, action='SELL', totalQuantity=200.0, orderType='STP LMT', lmtPrice=169.83, auxPrice=169.86, orderRef='stop-2U-2U-1h--eid-1914--ogid-13491', parentId=509133, triggerMethod=4, usePriceMgmtAlgo=True), orderStatus=OrderStatus(orderId=509134, status='PreSubmitted', filled=0.0, remaining=200.0, avgFillPrice=0.0, permId=541689050, parentId=509133, lastFillPrice=0.0, clientId=1000, whyHeld='trigger', mktCapPrice=0.0), fills=[], log=[TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 14, 397321, tzinfo=datetime.timezone.utc), status='PendingSubmit', message='', errorCode=0), TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 14, 530493, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='', errorCode=0), TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 15, 20879, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='', errorCode=0), TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 15, 742958, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='', errorCode=0), TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 15, 748802, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='', errorCode=0), TradeLogEntry(time=datetime.datetime(2024, 6, 11, 18, 21, 36, 525137, tzinfo=datetime.timezone.utc), status='PreSubmitted', message='Modify', errorCode=0)], advancedError='')

However, the TWS API Logs show the modified price in the callback:

14:21:36:376 -> --?5-509134-76792991-TSLA-STK--0-?--SMART-USD-TSLA-NMS-SELL-200-STP LMT-169.98-170.02-DAY-541689049-DU5623872-O-0-stop-2U-2U-1h--eid-1914--ogid-13491-1000-541689050-0-0-0--541689050.1/DU5623872/100----------0---1-0------2147483647-0-0-0--3-0-0--509133-4--0-None--0----?-0-0--0-0------0-0-0-2147483647-2147483647---0--IB-0-0--0-0-PreSubmitted-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308------0-0-0-None-1.7976931348623157E308-170.02-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-1.7976931348623157E308-0----0-1-0-0-1---0---------@3-509134-PreSubmitted-0-200-0-541689050-509133-0-1000-trigger-0-

Since TWS is sending back the price as modified, maybe I'm missing the point of Trade objects in the context of their transmission after things like Order modifications? There's a part of me that could understand if a Trade object was always intended to keep the original Order object intact and the Trade.log entries just log changes in a trade's lifecycle (ie: whyHeld= and status=). If that's the case, then maybe I'm just going about this incorrectly and I should be looking elsewhere to catch updated price data from a modified order?


 


Here is something that may be related. ?Take a look at line 512 of ib_async/wrapper.py, in the openOrder function, where it does

? ? ? ? ? ? trade.order.lmtPrice = order.lmtPrice
In my experience, after I submit a modified orde via ib_async to change the lmtPrice, later, when the modified order is then accepted by the server, IBKR sends back a response that ib_async handles via this openOrder function. ?Among other things, the openOrder function updates the lmtPrice field of the order registered with the trade (at the line noted above). ? This is how I've been tracking when IBKR accepts price modifications (which doesn't always happen right away). ?This has worked pretty reliably for me. ?There was a short email thread about it in the old ib_insync forum, which I don't have a copy of now.

Here is code for the "patched" limit order object that I've used to implement this. ?It adds a new event that fires when the price is accepted in this way:

class PatchedIBOrder(ibs.Order):
? ? def __init__(self, action, totalQuantity, orderType="LMT", **kwargs):
? ? ? ? ibs.Order.__init__(
? ? ? ? ? ? self,
? ? ? ? ? ? orderType=orderType,
? ? ? ? ? ? action=action,
? ? ? ? ? ? totalQuantity=totalQuantity,
? ? ? ? ? ? **kwargs,
? ? ? ? )
? ? ? ? self.priceAcceptedEvent = Event("priceAcceptedEvent")
? ? ? ? self.acceptedPrice = None
? ? ? ? self._lmtPrice = None

? ? @property
? ? def lmtPrice(self):
? ? ? ? return self._lmtPrice

? ? @lmtPrice.setter
? ? def lmtPrice(self, value):
? ? ? ? self._lmtPrice = float(value) if value else None
? ? ? ? if inspect.stack()[1][3] == "openOrder":
? ? ? ? ? ? self.acceptedPrice = value
? ? ? ? ? ? # logging.warning(f"order {self.priceAcceptedEvent}: price accepted")
? ? ? ? ? ? self.priceAcceptedEvent.emit()
? ? ? ? ? ? # logging.warning(f"order {self.orderId}: price accepted event emitted")


 

I notice that in the trade object you received from orderStatusEvent and modifyOrderEvent, the tradingClass is 'NMS' (instead of 'TSLA'). I am not sure this is related to your problem encountered, but in fact I have been stuck with this incorrect tradingClass issue (when defining option contract) for the past weeks and still couldn't? figure out why some tickers could get the correct tradingClass while some tickers got the wrong one. Similarly, sometimes a wrong expiry date for the option contract was used even though I have explicitly put in a correct expiry date. when defining the option contract. Interestingly, the wrong expiry date issue only occurred in Live system (socket 7496), while the same code ran smoothly without error in the Test system (socket 7497). Anyway, not sure my issues are related to yours, but I may create a new topic for my encountered issues later.?