For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

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.


Log in to reply
 

});