IbBroker live Trading / IdealPro minimum value / error code : 399 / Odd Lot Orders reported as Rejected
-
Hello,
When my python script place an order, and the order value is below the IdealPro minimum value (placing an Odd Lot Order).
Ideal pro report an error code : 399, with error message :
Warning: Your order size is below the EUR 20000 IdealPro minimum and will be routed as an odd lot order.The order is reported as rejected by the Backtrader platform, but in reality the order seems executed.
See the log below :
2020-08-12 16:44:00,597 [MainThread ] [INFO ] [2020-08-12T03:44:00][10 seconds][Close: 1.1753][Alpha: -0.94][Lot: -75863.0][Position: -70541] 2020-08-12 16:44:00,598 [MainThread ] [INFO ] *** SELL mod: -5322.00 2020-08-12 16:44:01,355 [MainThread ] [INFO ] ********** STORE NOTIF :<error id=2258, errorCode=399, errorMsg=Order Message: SELL 5,322 EUR.USD Forex Warning: Your order size is below the EUR 20000 IdealPro minimum and will be routed as an odd lot order.> 2020-08-12 16:44:10,643 [MainThread ] [INFO ] *** Order Rejected 2020-08-12 16:44:10,643 [MainThread ] [INFO ] *** SELL EXECUTED, Price: 1.1752, Cost: 6254.414400000001, Comm 2.5 2020-08-12 16:44:10,644 [MainThread ] [INFO ] [2020-08-12T03:44:10][10 seconds][Close: 1.1752][Alpha: -0.94][Lot: -75863.0][Position: -75863]
As you can see the new position match the previous target lot value.
-
hmm, at first sight it seems like a bug in IBBroker:
Looking at ibbroker.py:
def push_ordererror(self, msg): with self._lock_orders: try: order = self.orderbyid[msg.id] except (KeyError, AttributeError): return # no order or no id in error if msg.errorCode == 202: if not order.alive(): return order.cancel() elif msg.errorCode == 201: # rejected if order.status == order.Rejected: return order.reject() else: ----> order.reject() # default for all other cases
called from ibstore.py registered
error
notify method:@ibregister def error(self, msg): # 300-399 A mix of things: orders, connectivity, tickers, misc errors ... # < code removed for clarity > if msg.errorCode is None: ... # < code removed for clarity > elif msg.errorCode < 500: # Given the myriad of errorCodes, start by assuming is an order # error and if not, the checks there will let it go if msg.id < self.REQIDBASE: if self.broker is not None: ----> self.broker.push_ordererror(msg) else: # Cancel the queue if a "data" reqId error is given: sanity q = self.qs[msg.id] self.cancelQueue(q, True)
The order is marked rejected for every "unknown" ( to be more exact - unhandled) error/warning.
@backtrader , @ab_trader , @run-out - could you please also take a look ? is it correct ?
-
I, when doing paper trading on EUR.USD-CASH-IDEALPRO with Interactive Brokers, also encounted that submitted orders were first rejected but then executed successfully. In my case, all of these rejected/executed orders also received a error-code-399 warning, saying "Your order size is below the EUR 20000 IdealPro minimum and will be routed as an odd lot order", right before the rejection. Many thanks for @vladisld's explanation, which is quite reasonable.
Is there any order attribute or anything helpful to distinquish a later-executable rejected order from other ordinary rejected orders?
It seems that the order attribute "alive" is not helpful here. As you can see in the log below, a submitted, alive order is reported as "Alive: False" when rejected. The definition of the "alive" attribute decides the order to be no longer alive once rejected:
class OrderBase(with_metaclass(MetaParams, object)): ... # code removed for clarity def alive(self): '''Returns True if the order is in a status in which it can still be executed ''' return self.status in [Order.Created, Order.Submitted, Order.Partial, Order.Accepted]
The below is the log. I hope it is helpful for experts in this community to study the issue and/or find a solution.
2020-09-21 20:24:30, BUY CREATED, size=168, exectype=Market, valid=None ***** STORE NOTIF: Order Message: BUY 168 EUR.USD Forex Warning: Your order size is below the EUR 20000 IdealPro minimum and will be routed as an odd lot order. (errorCode: 399. reqID: 1299) 2020-09-21 20:25:30, Entering: notify_order() Ref: 1 OrdType: 0 OrdType: Buy Status: 1 Status: Submitted Size: 168 Price: None Price Limit: None TrailAmount: None TrailPercent: None ExecType: 0 ExecType: Market CommInfo: <backtrader.brokers.ibbroker.IBCommInfo object at 0x7fc5ebf08a90> End of Session: 737689.9999999999 Info: AutoOrderedDict() Broker: <backtrader.brokers.ibbroker.IBBroker object at 0x7fc5ebf3d1d0> Alive: True {'params': <backtrader.metabase.AutoInfoClass_OrderBase_IBOrder object at 0x7fc5ebf08d50>, 'p': <backtrader.metabase.AutoInfoClass_OrderBase_IBOrder object at 0x7fc5ebf08d50>, '_willexpire': False, 'ordtype': 0, 'ref': 1, 'broker': <backtrader.brokers.ibbroker.IBBroker object at 0x7fc5ebf3d1d0>, 'info': AutoOrderedDict(), 'comminfo': <backtrader.brokers.ibbroker.IBCommInfo object at 0x7fc5ebf08a90>, 'triggered': False, '_active': True, 'status': 1, '_plimit': None, 'created': <backtrader.order.OrderData object at 0x7fc5ebf08cd0>, '_limitoffset': 0.0, 'executed': <backtrader.order.OrderData object at 0x7fc5ebef2b10>, 'position': 0, 'dteos': 737689.9999999999, 'm_lmtPrice': 0.0, 'm_auxPrice': 0.0, 'm_activeStartTime': '', 'm_activeStopTime': '', 'm_outsideRth': False, 'm_openClose': 'O', 'm_origin': 0, 'm_transmit': True, 'm_designatedLocation': '', 'm_exemptCode': -1, 'm_minQty': 9223372036854775807, 'm_percentOffset': 9223372036854775807, 'm_nbboPriceCap': 9223372036854775807, 'm_optOutSmartRouting': False, 'm_startingPrice': 9223372036854775807, 'm_stockRefPrice': 9223372036854775807, 'm_delta': 9223372036854775807, 'm_stockRangeLower': 9223372036854775807, 'm_stockRangeUpper': 9223372036854775807, 'm_volatility': 9223372036854775807, 'm_volatilityType': 9223372036854775807, 'm_deltaNeutralOrderType': '', 'm_deltaNeutralAuxPrice': 9223372036854775807, 'm_deltaNeutralConId': 0, 'm_deltaNeutralSettlingFirm': '', 'm_deltaNeutralClearingAccount': '', 'm_deltaNeutralClearingIntent': '', 'm_deltaNeutralOpenClose': '', 'm_deltaNeutralShortSale': False, 'm_deltaNeutralShortSaleSlot': 0, 'm_deltaNeutralDesignatedLocation': '', 'm_referencePriceType': 9223372036854775807, 'm_trailStopPrice': 9223372036854775807, 'm_trailingPercent': 9223372036854775807, 'm_basisPoints': 9223372036854775807, 'm_basisPointsType': 9223372036854775807, 'm_scaleInitLevelSize': 9223372036854775807, 'm_scaleSubsLevelSize': 9223372036854775807, 'm_scalePriceIncrement': 9223372036854775807, 'm_scalePriceAdjustValue': 9223372036854775807, 'm_scalePriceAdjustInterval': 9223372036854775807, 'm_scaleProfitOffset': 9223372036854775807, 'm_scaleAutoReset': False, 'm_scaleInitPosition': 9223372036854775807, 'm_scaleInitFillQty': 9223372036854775807, 'm_scaleRandomPercent': False, 'm_scaleTable': '', 'm_whatIf': False, 'm_notHeld': False, 'm_orderType': 'MKT', 'm_permid': 0, 'm_action': 'BUY', 'm_totalQuantity': 168, 'm_tif': 'GTC', 'm_ocaType': 1, 'm_clientId': 35, 'm_orderId': 1299, 'plen': 1082} 2020-09-21 20:25:30, Entering: notify_order() Ref: 1 OrdType: 0 OrdType: Buy Status: 8 Status: Rejected Size: 168 Price: None Price Limit: None TrailAmount: None TrailPercent: None ExecType: 0 ExecType: Market CommInfo: <backtrader.brokers.ibbroker.IBCommInfo object at 0x7fc5ebf08a90> End of Session: 737689.9999999999 Info: AutoOrderedDict() Broker: None Alive: False {'params': <backtrader.metabase.AutoInfoClass_OrderBase_IBOrder object at 0x7fc5ebf08d50>, 'p': <backtrader.metabase.AutoInfoClass_OrderBase_IBOrder object at 0x7fc5ebf08d50>, '_willexpire': False, 'ordtype': 0, 'ref': 1, 'broker': None, 'info': AutoOrderedDict(), 'comminfo': <backtrader.brokers.ibbroker.IBCommInfo object at 0x7fc5ebf08a90>, 'triggered': False, '_active': True, 'status': 8, '_plimit': None, 'created': <backtrader.order.OrderData object at 0x7fc5ebf08cd0>, '_limitoffset': 0.0, 'executed': <backtrader.order.OrderData object at 0x7fc5ea6ab110>, 'position': 0, 'dteos': 737689.9999999999, 'm_lmtPrice': 0.0, 'm_auxPrice': 0.0, 'm_activeStartTime': '', 'm_activeStopTime': '', 'm_outsideRth': False, 'm_openClose': 'O', 'm_origin': 0, 'm_transmit': True, 'm_designatedLocation': '', 'm_exemptCode': -1, 'm_minQty': 9223372036854775807, 'm_percentOffset': 9223372036854775807, 'm_nbboPriceCap': 9223372036854775807, 'm_optOutSmartRouting': False, 'm_startingPrice': 9223372036854775807, 'm_stockRefPrice': 9223372036854775807, 'm_delta': 9223372036854775807, 'm_stockRangeLower': 9223372036854775807, 'm_stockRangeUpper': 9223372036854775807, 'm_volatility': 9223372036854775807, 'm_volatilityType': 9223372036854775807, 'm_deltaNeutralOrderType': '', 'm_deltaNeutralAuxPrice': 9223372036854775807, 'm_deltaNeutralConId': 0, 'm_deltaNeutralSettlingFirm': '', 'm_deltaNeutralClearingAccount': '', 'm_deltaNeutralClearingIntent': '', 'm_deltaNeutralOpenClose': '', 'm_deltaNeutralShortSale': False, 'm_deltaNeutralShortSaleSlot': 0, 'm_deltaNeutralDesignatedLocation': '', 'm_referencePriceType': 9223372036854775807, 'm_trailStopPrice': 9223372036854775807, 'm_trailingPercent': 9223372036854775807, 'm_basisPoints': 9223372036854775807, 'm_basisPointsType': 9223372036854775807, 'm_scaleInitLevelSize': 9223372036854775807, 'm_scaleSubsLevelSize': 9223372036854775807, 'm_scalePriceIncrement': 9223372036854775807, 'm_scalePriceAdjustValue': 9223372036854775807, 'm_scalePriceAdjustInterval': 9223372036854775807, 'm_scaleProfitOffset': 9223372036854775807, 'm_scaleAutoReset': False, 'm_scaleInitPosition': 9223372036854775807, 'm_scaleInitFillQty': 9223372036854775807, 'm_scaleRandomPercent': False, 'm_scaleTable': '', 'm_whatIf': False, 'm_notHeld': False, 'm_orderType': 'MKT', 'm_permid': 0, 'm_action': 'BUY', 'm_totalQuantity': 168, 'm_tif': 'GTC', 'm_ocaType': 1, 'm_clientId': 35, 'm_orderId': 1299, 'plen': 1082} 2020-09-21 20:25:30, Leaving notify_order(). 2020-09-21 20:25:30, Entering: notify_order() Ref: 1 OrdType: 0 OrdType: Buy Status: 4 Status: Completed Size: 168 Price: None Price Limit: None TrailAmount: None TrailPercent: None ExecType: 0 ExecType: Market CommInfo: <backtrader.brokers.ibbroker.IBCommInfo object at 0x7fc5ebf08a90> End of Session: 737689.9999999999 Info: AutoOrderedDict() Broker: None Alive: False {'params': <backtrader.metabase.AutoInfoClass_OrderBase_IBOrder object at 0x7fc5ebf08d50>, 'p': <backtrader.metabase.AutoInfoClass_OrderBase_IBOrder object at 0x7fc5ebf08d50>, '_willexpire': False, 'ordtype': 0, 'ref': 1, 'broker': None, 'info': AutoOrderedDict(), 'comminfo': <backtrader.brokers.ibbroker.IBCommInfo object at 0x7fc5ebf08a90>, 'triggered': False, '_active': True, 'status': 4, '_plimit': None, 'created': <backtrader.order.OrderData object at 0x7fc5ebf08cd0>, '_limitoffset': 0.0, 'executed': <backtrader.order.OrderData object at 0x7fc5ea6abb50>, 'position': 0, 'dteos': 737689.9999999999, 'm_lmtPrice': 0.0, 'm_auxPrice': 0.0, 'm_activeStartTime': '', 'm_activeStopTime': '', 'm_outsideRth': False, 'm_openClose': 'O', 'm_origin': 0, 'm_transmit': True, 'm_designatedLocation': '', 'm_exemptCode': -1, 'm_minQty': 9223372036854775807, 'm_percentOffset': 9223372036854775807, 'm_nbboPriceCap': 9223372036854775807, 'm_optOutSmartRouting': False, 'm_startingPrice': 9223372036854775807, 'm_stockRefPrice': 9223372036854775807, 'm_delta': 9223372036854775807, 'm_stockRangeLower': 9223372036854775807, 'm_stockRangeUpper': 9223372036854775807, 'm_volatility': 9223372036854775807, 'm_volatilityType': 9223372036854775807, 'm_deltaNeutralOrderType': '', 'm_deltaNeutralAuxPrice': 9223372036854775807, 'm_deltaNeutralConId': 0, 'm_deltaNeutralSettlingFirm': '', 'm_deltaNeutralClearingAccount': '', 'm_deltaNeutralClearingIntent': '', 'm_deltaNeutralOpenClose': '', 'm_deltaNeutralShortSale': False, 'm_deltaNeutralShortSaleSlot': 0, 'm_deltaNeutralDesignatedLocation': '', 'm_referencePriceType': 9223372036854775807, 'm_trailStopPrice': 9223372036854775807, 'm_trailingPercent': 9223372036854775807, 'm_basisPoints': 9223372036854775807, 'm_basisPointsType': 9223372036854775807, 'm_scaleInitLevelSize': 9223372036854775807, 'm_scaleSubsLevelSize': 9223372036854775807, 'm_scalePriceIncrement': 9223372036854775807, 'm_scalePriceAdjustValue': 9223372036854775807, 'm_scalePriceAdjustInterval': 9223372036854775807, 'm_scaleProfitOffset': 9223372036854775807, 'm_scaleAutoReset': False, 'm_scaleInitPosition': 9223372036854775807, 'm_scaleInitFillQty': 9223372036854775807, 'm_scaleRandomPercent': False, 'm_scaleTable': '', 'm_whatIf': False, 'm_notHeld': False, 'm_orderType': 'MKT', 'm_permid': 0, 'm_action': 'BUY', 'm_totalQuantity': 168, 'm_tif': 'GTC', 'm_ocaType': 1, 'm_clientId': 35, 'm_orderId': 1299, 'plen': 1082} 2020-09-21 20:25:30, Leaving notify_order().
Thanks for reading my post. Any suggestion is welcome.
-
Submitted an issue for further discussion: https://github.com/backtrader2/backtrader/issues/40