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 ?


Log in to reply
 

});