Automated closing using take_profit and stop_loss

Hello!

I have a problem concerning automated closing of an instance.
My goal is to close the position if a certain market value is crossed (limit in both directions!).

I copied the following function from the alpaca documentation.
As for now, it just opens a position but doesnt close it.
Is there any conceptual/code-related issue in the code?
And can anyone explain me, what the limit_price in stop_loss is used for exactly?

I appreciate any kind of help.
Thank you in advance.
Sincerely Mühle

def buy(recent_data):
    response = api.submit_order(
        symbol='BTCUSD',
        qty=0.1,
        side='buy',
        type='market',
        time_in_force='gtc',
        order_class= 'simple',
        take_profit= {
            'limit_price': recent_data['high'] * 1.01 # position should close if market value crosses takeprofit limit (bullish)
        },
        stop_loss= {
            'stop_price': recent_data['low'] * 0.99, # position should close if market value falls below stoploss limit (bearish)
            'limit_price':  recent_data['low'] * 0.98 
        }
    )
    return response

Assuming that Crypto is like Equity, issue here is in

order class that should be

"order_class": "bracket"

as per documentation here

donot waste your time.
bracket ordering does not work on alpaca.
most of the time the position is closed out of bracket you set.

@TEKNECI Could you give an example, ideally an order number, of a bracket order not functioning as you expected. I personally, and many others, use bracket orders and they work exactly as expected. There are currently no known issues and no reason to not use bracket orders.

exp-1:
Order ID c69d0e62-9ab7-49d0-bcf0-7a02a19676b7
ICLK
DATE 1/17/2023
bracket: [5.15 - 4.66]
set TP%=-5%
set SL%=-5%
closed at: 4.46, out of bracket at -9%.

|DATE|OPEN|TP|SL|TP%|SL%|CLOSE|P/L %|P/L $|
|1/17/2023|4.90|5.15|4.66|5.1%|-4.9%|4.46|-9.0%|(88.00)|

Type Qty
ICLK Average Cost
USD Amount
USD Status Time
Stop SELL @ $0 200 4.46 892.00 Filled 4 days ago
Limit SELL @ $5.15 - - - Replaced 4 days ago
Market BUY 200 4.90 980.80 Filled 4 days ago
Stop SELL @ $0 200

ICLK
Stop Sell 200 shares
Order ID c69d0e62-9ab7-49d0-bcf0-7a02a19676b7
Status filled
Symbol ICLK
Side sell
Order Type stop
Quantity 200
Time In Force gtc
Extended Hours No
Limit Price -
Stop Price 4.66
Created At 2023-01-17T14:33:00.880896Z
Submitted At 2023-01-17T14:33:15.028101Z

exp-2:
Order ID ba7285a8-1178-4147-b11b-76f1dfc72e1a
TEDU
DATE 1/13/2023
bracket: [5.48 4.96]
set TP%=-5%
set SL%=-5%
closed at: 4.70, out of bracket at -10%.

|DATE|SYM|open_at|limit_price|stop_price|OPEN|TP|SL|TP%|SL%|CLOSE|P/L %|P/L $|
| — | — | — | — | — | — | — | — | — | — | — | — | — |
|1/13/2023|TEDU|0933|5.00%|-5.00%|5.22|5.48|4.96|5.0%|-5.0%|4.70|-10.0%|(104.00)|

Type Qty
TEDU Average Cost
USD Amount
USD Status Time
Stop SELL @ $0 200 4.70 940.00 Filled 8 days ago
Limit SELL @ $5.48 - - - Replaced 8 days ago
Market BUY 200 5.22 1,044.00 Filled 8 days ago

TEDU
Stop Sell 200 shares
Order ID ba7285a8-1178-4147-b11b-76f1dfc72e1a
Status filled
Symbol TEDU
Side sell
Order Type stop
Quantity 200
Time In Force gtc
Extended Hours No
Limit Price -
Stop Price 4.96
Created At 2023-01-13T14:33:04.409831Z
Submitted At 2023-01-13T15:40:59.027586Z

and many others
these are only for January 2023:

@TEKNECI I looked at the first two orders and both executed properly. The ‘last’ price dropped below the stop price which triggered the market sell order. I am guessing your issue is the fill price of the market sell is lower than expected? Typically the fill price will be close to the stop price, however since it is a market order, it will fill at whatever the market is at the time the stop is triggered.

The underlying issue is you are trading very small cap stocks with very low volume and very large bid/ask spreads. For example, the first order for ICLK (iClick Interactive Asia Group Limited) only had 16 trades during the minute it was executed (ie 2023-01-17 9:33 EST). Two of those trades were actually yours (your initial buy and then the stop market sell). Here are the 20 seconds of trades after your initial market buy at $4.90 (the first trade is your buy) along with the quotes during that time.

The very first trade is your buy. It filled at $4.904 which was better than the current ask at that time of $5.00. Then your stop loss order was submitted with a stop price of $4.66. The next trade occurred 15 seconds after yours (the 2nd trade in the list) and executed at $4.55. Notice that it executed as expected at the bid price at that time (it must have been a sell order). That is the trade which triggered your stop order. The price of $4.55 was below your stop price of $4.66 and therefore triggered your market order to sell 200 shares. Your market order filled almost immediately at 09:33:15.04. The most recent bid when it filled was from 09:33:15.02 (the 4th bid in the list). As expected, your market order filled at that bid price of $4.46.

The other orders you mentioned follow the same general pattern and all fill as expected. Perhaps the misunderstanding is that your order should fill at your stop price? The stop price is simply the price which ‘triggers’ your stop order. Since your stop order was a ‘market’ order it will fill at the ‘market’ price which, for a sell, would typically be the bid at that time.

To guarantee the price, you should be submitting a ‘stop limit’ order and not a ‘stop market’ order. You could set the limit price to be the same as the stop price, but often traders set the limit just a bit lower than the stop price. Note that limit orders will fill at or better than the limit price, but there is no guarantee they will fill. Use market orders when you want to ensure the order fills but don’t care about the price. Use limit orders when you want to ensure the price but don’t care if it fills.

As mentioned, trading in low volume stocks with large bid ask spreads will often result in big price swings (and surprises) if using market orders. Use limit orders to eliminate surprises. Note the huge bid/ask spread in the quotes above. The very first quote is $4.46 bid and $4.99 ask. That’s a 10% spread! Considering that buys typically fill at the ask and sells fill at the bid, if one were to buy then immediately sell, one would loose 10%.

Use limit orders and you will see your orders fill at the expected prices. This is not only true for your stop loss orders but it’s also probably good practice to use limit orders for your initial entry order too. This will ensure no surprises.