IBKR/Alpaca Order Clarification

I have the same intraday strategy on 2 different moonshot files; one for ibkr and one for alpaca orders. It's always a 3 piece order with initial MKT, child STP, and child MOC for the same Sid. TotalQuantity is just different dollar amounts in paper accounts. I'm not glued to either approach if there is a better way.

Ultimate Goal

Only submit MOC order at both brokers if STP did not trigger intraday.

IBKR Orders

Alpaca Orders

Background reading I've done:
I read the ibkr parent-child order docs here. My question in this case is about the second child order for MOC and if this order is only executed if the first child order has not triggered, or if a more advanced order is needed for this if/else condition. I don't believe a bracket order can capture the MOC element.

For the alpaca orders I've simply changed OrderType and Tif to MKT and CLS as defined in the docs but believe alpaca does not recognize the ParentId Column and currently will submit the CLS order regardless.

With IBKR, you are close but need to also include an OCA group (one-cancels-all) on the two child orders. To do this, you need to add two fields for the child orders:

  • OcaGroup: a unique identifier that ties the orders together. You can use the ParentId for this or any unique identifier. This tells IBKR to cancel one of the orders if the other order fills.
  • OcaType: how exactly to handle the remaining order when an execution occurs on the other order. See the choices here.

An alternate approach with IBKR is to only attach the STP order, then schedule two additional jobs on your crontab. The first would be a job to cancel all open orders for the strategy, which would run shortly before the cutoff for placing MOC orders and would cancel any STP orders that hadn't filled. Then, a few minutes later, schedule a command that closes any open positions with MOC orders, as described in the docs.

For Alpaca, bracket orders aren't supported, so it's less convenient. You can use the alternate approach I just described for canceling STP orders and placing MOC orders, but in addition you will need a job that places STP orders in the first place after the MKT orders fill. That could be accomplished with a custom script that queries positions and places stop orders accordingly.

I was planning on moving to Alpaca but some of the daily ETB's are too erratic or non-availabe so I'm back to IBKR.

IBKR Issues

Added OcaGroup & OcaType. Simply copied ParentId to OcaGroup then added OcaType=1 for non-null rows. Then I ran into a circular issue:

OcaType=str(1), pandas casts column to 'object' and I get this error.

WARNING ibg1 client 6001 got IBKR message code 320: Error reading request. Unable to parse data. java.lang.NumberFormatException: For input string: "1.0"

OcaType=int(1), I force an int cast with .fillna(0)

Order rejected - reason:Invalid OCA handling method.

OcaType=float(1.0), I force a float cast which can accept NaN but looks like IBKR's java re-casts the float to an object and won't accept it.

WARNING ibg1 client 6001 got IBKR message code 320: Error reading request. Unable to parse data. java.lang.NumberFormatException: For input string: "1.0"

The second one is correct, where you set OcaType to 0 for the parent order. The reason for "Invalid OCA handling method" on that one is because you have a MOC order and a STP order and have specified an OCA type that blocks duplicate fills. That's not possible with MOC since the STP order could get filled after the deadline for canceling the MOC order. To include an MOC order you should specify OCA type 3 (non-blocking). You can prevent duplicate fills in a different way, by adding a GoodTillDate to the STP order that ends before the cutoff time for the MOC order to be cancelled.

Hi Brian thanks for insight. Orders seem to be taking properly over a few trial days. Only small extra piece was adding GTD to Tif and formatting the GoodTillDate properly.