Bracket Order - Closing Positions

Will canceling a bracket order open position liquidate and close my bracket order position or will it just cancel the open position without liquidation?

For example, I have an open bracket order (buy) and it hasn’t hit the limit or stop price yet and I’d like to liquidate and sell the position. Will the ‘cancel_order’ function cancel the open order and/or liquidate and sell the long position? If it just cancels does this mean I’ll have to manually sell out of that position?

@suraj Canceling one leg of a bracket order will cancel the other leg too. It won’t liquidate anything. It simply deletes the order(s).

The best way to ‘sell out’ or close a position which has an outstanding bracket order is to replace the take profit limit price with a ‘marketable’ price. The take profit limit leg will then execute immediately and close the position. This is nice because it keeps all 3 orders intact.

Thank you Dan. Am I allowed to replace both the limit price and stop price in the same replace function? I tried replacing the limit price along with the stop price for my bracket order however it only allowed me to change limit price.

@suraj The replace_order endpoint requires an order number and only updates a single order at a time. The stop loss and take profit orders are two separate orders. Therefore you would need to update the stop price (for the stop loss order) and the limit price (for the take profit order) separately.

Thank you. I am using the order number (id number) when I query for the 2 open positions (limit price and stop price) and only ‘order type’ for ‘limit price’ is appearing. I am able to replace that leg however I am unable to find the open position for ‘stop price’. How do I query for open order type for ‘stop price’?

Trying to use the limit price id to replace stop price does not work and returns the error:
APIError: limit orders must not have stop_price

@suraj How are you getting the ‘order number’? Which order is it? Is it the parent order ID or one of the legs?

The best way to work with bracket orders is to keep track of the parent order ID. When you have that you can easily get the order IDs of the two leg orders. The leg order info is stored with the parent order in the attribute called legs.

The first leg (ie legs[0]) is always the take profit limit order. The second leg (ie legs[1]) is always the stop limit order. Below is an example of a parent bracket order with the two leg order details in the legs attribute.

{ ‘asset_class’: <AssetClass.US_EQUITY: ‘us_equity’>,
‘asset_id’: UUID(‘b0b6dd9d-8b9b-48a9-ba46-b9d54906e415’),
‘canceled_at’: None,
‘client_order_id’: ‘73773fa3-551f-4c54-adbe-fd9ae0f51334’,
‘created_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 224183, tzinfo=datetime.timezone.utc),
‘expired_at’: None,
‘extended_hours’: False,
‘failed_at’: None,
‘filled_at’: None,
‘filled_avg_price’: None,
‘filled_qty’: ‘0’,
‘hwm’: None,
‘id’: UUID(‘374e5da7-71fe-4b1d-8296-6d89285e4a67’),
‘legs’: [ { ‘asset_class’: <AssetClass.US_EQUITY: ‘us_equity’>,
‘asset_id’: UUID(‘b0b6dd9d-8b9b-48a9-ba46-b9d54906e415’),
‘canceled_at’: None,
‘client_order_id’: ‘e7199a8d-d82a-491d-bdb3-af576e0f706d’,
‘created_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 224215, tzinfo=datetime.timezone.utc),
‘expired_at’: None,
‘extended_hours’: False,
‘failed_at’: None,
‘filled_at’: None,
‘filled_avg_price’: None,
‘filled_qty’: ‘0’,
‘hwm’: None,
‘id’: UUID(‘300a3588-b274-4521-85d6-e851a7114dd9’),
‘legs’: None,
‘limit_price’: ‘150’,
‘notional’: None,
‘order_class’: <OrderClass.BRACKET: ‘bracket’>,
‘order_type’: <OrderType.LIMIT: ‘limit’>,
‘qty’: ‘1’,
‘replaced_at’: None,
‘replaced_by’: None,
‘replaces’: None,
‘side’: <OrderSide.SELL: ‘sell’>,
‘status’: <OrderStatus.HELD: ‘held’>,
‘stop_price’: None,
‘submitted_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 222565, tzinfo=datetime.timezone.utc),
‘symbol’: ‘AAPL’,
‘time_in_force’: <TimeInForce.DAY: ‘day’>,
‘trail_percent’: None,
‘trail_price’: None,
‘type’: <OrderType.LIMIT: ‘limit’>,
‘updated_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 224215, tzinfo=datetime.timezone.utc)},
{ ‘asset_class’: <AssetClass.US_EQUITY: ‘us_equity’>,
‘asset_id’: UUID(‘b0b6dd9d-8b9b-48a9-ba46-b9d54906e415’),
‘canceled_at’: None,
‘client_order_id’: ‘fb472043-1f4e-4445-b5f2-174d1535a118’,
‘created_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 224232, tzinfo=datetime.timezone.utc),
‘expired_at’: None,
‘extended_hours’: False,
‘failed_at’: None,
‘filled_at’: None,
‘filled_avg_price’: None,
‘filled_qty’: ‘0’,
‘hwm’: None,
‘id’: UUID(‘58a81cd9-f5ab-43a7-8835-5c543b022925’),
‘legs’: None,
‘limit_price’: None,
‘notional’: None,
‘order_class’: <OrderClass.BRACKET: ‘bracket’>,
‘order_type’: <OrderType.STOP: ‘stop’>,
‘qty’: ‘1’,
‘replaced_at’: None,
‘replaced_by’: None,
‘replaces’: None,
‘side’: <OrderSide.SELL: ‘sell’>,
‘status’: <OrderStatus.HELD: ‘held’>,
‘stop_price’: ‘100’,
‘submitted_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 222565, tzinfo=datetime.timezone.utc),
‘symbol’: ‘AAPL’,
‘time_in_force’: <TimeInForce.DAY: ‘day’>,
‘trail_percent’: None,
‘trail_price’: None,
‘type’: <OrderType.STOP: ‘stop’>,
‘updated_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 224232, tzinfo=datetime.timezone.utc)}],
‘limit_price’: ‘125’,
‘notional’: None,
‘order_class’: <OrderClass.BRACKET: ‘bracket’>,
‘order_type’: <OrderType.LIMIT: ‘limit’>,
‘qty’: ‘1’,
‘replaced_at’: None,
‘replaced_by’: None,
‘replaces’: None,
‘side’: <OrderSide.BUY: ‘buy’>,
‘status’: <OrderStatus.ACCEPTED: ‘accepted’>,
‘stop_price’: None,
‘submitted_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 222565, tzinfo=datetime.timezone.utc),
‘symbol’: ‘AAPL’,
‘time_in_force’: <TimeInForce.DAY: ‘day’>,
‘trail_percent’: None,
‘trail_price’: None,
‘type’: <OrderType.LIMIT: ‘limit’>,
‘updated_at’: datetime.datetime(2023, 1, 24, 21, 31, 22, 224183, tzinfo=datetime.timezone.utc)}

The leg info can fetched something like this

take_profit_leg = my_parent_order.legs[0]
stop_loss_leg = my_parent_order.legs[1]

Each of the legs can then be replaced using their respective order IDs

take_profit_order_id = take_profit_leg.id
stop_loss_leg_id = stop_loss_leg.id

Does that help?

Thank you. I realized I needed to use the ‘nested = true’ as an argument when getting all orders.

Can you please show python code that does this on an existing bracket order that uses a user specified client_order_id when the bracket order is originally submitted. thank you.

Also is a marketable price just a ‘market sell’ or do I have to determine the marketable price before replacing the take profit limit price?

thank you for help. seeing the python code do this would be so helpful.

@Dan_Whitnable_Alpaca If you use a bracket order to open a position, and then you submit a request to DELETE the position or to DELETE all positions, would either of those calls succeed?