Stop loss vs stop limit: certainty of an exit, or certainty of a price
A stop makes sure you get out. A stop limit makes sure of the price. Neither can promise both, on CodeBull or anywhere else.
You set a stop at 95. Bad news overnight, and the next price is 90. You
sell at about 90, and the stop did exactly what it was built to do. Whether
that is acceptable decides which of the ticket's three stop tabs you want,
Stop, Stop Limit or Trailing, and why the if price <= stop_price: in your
strategy is none of them.
A stop is an order that waits on the far side of the price. It does nothing until the market reaches a level you chose, and then it acts. What it does next is where the three differ.
The trade-off, one step later
When the price reaches your stop, a stop becomes a market order and a stop limit becomes a limit order. So it is the same trade-off as market against limit, deferred until the stop is hit. A stop guarantees you get out, but not the price you get out at. A stop limit guarantees the price, but not that you get out.
Nothing guarantees both. That is not a CodeBull limitation. It is what an order can and cannot promise when the market moves faster than you do.
Stop
A sell stop, the classic stop loss, sits below the current price and protects a position you own. A buy stop sits above it and protects a short, or buys a breakout. On the ticket you enter one number, the Stop.
Say you own a share bought at 100 and place a sell stop at 95. Nothing happens while the price stays above 95. When the price reaches 95, the stop becomes a market sell and fills at the bid: 94.9525, half the spread below 95, exactly as a market order would.
Now the case from the top of this post, the one the stop is really for: the next price after 100 is 90, with nothing in between. The stop triggers at 90, because that is the first price at or below 95, and it sells at the bid of 90, which is 89.955. You set 95 and got about 90. That is not a malfunction. A stop is a trigger, not a price. It promises to get you out once the market has reached your level. It cannot make the market trade there.
The ticket refuses a stop on the wrong side of the market: a sell stop above the last price, or a buy stop below it. That order would trigger the moment it was placed. If you want out now, that is a market order.
Stop Limit
A stop limit takes two prices: the Stop, which triggers it, and the Price, which is the limit it then becomes.
Take a sell stop limit with a stop of 95 and a limit of 94. When the price reaches 95, it becomes a sell limit at 94. If the price is 94.50 when that happens, it fills at 94, your limit. As with any limit on CodeBull, it fills at the limit, never better.
Now the gap again: 100, then 90. The stop triggers, but the market is below your limit, so nothing fills. You still own the share, and it is now worth 90. The order did exactly what you told it to, which was to sell at 94 or not at all. That is the price of guaranteeing the price.
The order does not go away. Once triggered it is a sell limit at 94, and it stays in the book as one. If the price recovers to 96, it fills at 94.
The distance between the stop and the limit is how much slippage you will accept. Set them too close and a fast move can skip straight past both. Set them too far apart and you have a stop with extra steps.
Trailing
A trailing stop has no fixed level. You enter a Trail, a distance in price, not a percentage: a trail of 5 means 5.00. The stop follows the market at that distance. It moves only in your favour.
A sell trailing stop with a trail of 5, placed at 100, starts with its stop at 95. The price rises to 110, so the stop rises to 105. The price slips to 107 and the stop stays at 105, because it never moves back. At 104 the price has crossed the stop, and it fills as a market sell at the bid of 104, 103.948.
It protects a gain without making you choose an exit price in advance. Once triggered, it behaves exactly like a stop, so it can fill well past its level in a gap, just as a stop can.
Place one
A Stop needs Starter. A Stop Limit or a Trailing stop needs Pro. If you followed the walkthrough in limit vs market order, you already own a share. If you don't own one, buy a share first.
- Open Instruments and find the stock you own. Its card shows Add, Reduce and Close instead of Buy and Sell. Click Details and note the last price.
- Click Reduce. It opens the ticket on the Sell side. Switch to
Stop, enter a quantity of
1and a stop a little below the last price, then place it. The confirmation says Order accepted: pending, resting in the book. - Go to Portfolio, then Open Orders. Your stop is there with its price. It fills only if the market comes down to it.
Where CodeBull differs from a real exchange
The rules above hold in any market. The fill prices are CodeBull's. This section covers orders placed from the ticket, which is paper trading. Backtests come after it.
A triggered stop limit fills at its limit, even when the market is better. In the example above, the bid was 94.45 when the stop triggered, and the order filled at 94. On an exchange it would have filled at about 94.45, because a limit only sets the worst price you will accept. This one works against you, as it does for any limit here; limit vs market order covers it.
Stops are checked when quotes refresh. A dip to your stop and back up between two refreshes never triggers it. On an exchange, a single trade at your level is enough. This one cuts both ways: you get stopped out less often by a brief wick, but a stop that a fast move goes through triggers at the refresh that sees it, and fills at that refresh's price.
The spread on a stop's fill is always 0.10%. A triggered stop pays half of it, like any market order here. On an exchange the spread widens exactly when stops fire: at the open, around news, in a fall. This one flatters stops.
A trailing stop follows the prices CodeBull sees, not every trade. It moves up to the highest refreshed price, not to the true high of the day, so on a fast spike your stop can sit lower than a broker's would.
In a backtest
A strategy places a stop with ctx.place_order, and a backtest fills it
from the bars, not from refreshes. The rules:
- A stop never fills when it is placed. It is first tested against the next bar.
- It triggers when the bar's range reaches it: the low for a sell stop, the high for a buy stop. A bar that dips through 95 and closes back at 96 still triggers a sell stop at 95.
- It fills at the stop, adjusted by half the market maker's spread, wherever the bar closes. With the default spread of 20 basis points (0.20%), a sell stop at 95 fills at 94.905.
- A bar that opens past the stop fills at the open, adjusted the same way. A sell stop at 95 on a bar that opens at 90 fills at 89.91.
- With the market maker switched off (Advanced, Enable Market Maker on the simulation form), it fills at the stop itself.
- A stop limit fills on its trigger bar if that price is within its limit. If not, it rests as a limit order and fills on a later bar that reaches it, as on an exchange.
- Trailing stops are refused in backtests and arenas for now. They work in paper trading only.
Two of these deserve a warning. A fill at the stop on a bar that fell straight through it is generous: it assumes the market traded at your level on the way down. In a fast real market your stop fills wherever the next trade happens to be. And the default backtest spread, 0.20%, is twice the ticket's 0.10%. The same stop pays more in a default backtest than on the ticket.
A stop in your code is not a stop order
Some strategy templates manage their exit in code instead. The Momentum
Breakout template checks if price <= stop_price: on every tick and, when
it is true, sells with a market order:
ctx.place_order(symbol, "sell", 10, "market").
That check only sees price, the price the strategy is called with, which
in a backtest is the bar's close. A stop order sees the whole bar. The two
part ways on the bars that matter most:
- A bar that opens at 96, falls to 90 and closes at 91. A stop order at 95 fills at 94.905 on the way down. The coded check sees 91, sells at market, and fills at the bid of 91, 90.909: about 4 a share worse.
- A bar that dips to 94 and closes at 96. A stop order at 95 fills at 94.905. The coded check sees 96 and does nothing.
Neither one is wrong. They are different rules, and a backtest of one tells you nothing about the other. Pick the one you mean, and know which one your strategy actually uses.
To use a real stop instead, place it once, when you enter:
ctx.place_order(symbol, "sell", 10, "stop_loss", stop_price=stop_price).
One catch: a strategy cannot cancel an order yet. A stop placed this way
stays in the book after the strategy exits some other way, such as
Momentum Breakout's profit target. If it triggers later, it sells shares
you no longer hold and leaves you short. For now, a real stop suits a
strategy whose stop is its only way out.
Which one
A Stop when getting out matters more than the exact price, which is what most protective exits are for. A Stop Limit when you would rather keep the position than sell below a certain price, and you accept that a gap can leave you holding it. A Trailing stop when you want to protect a gain without choosing the exit in advance.
None of them is a guarantee against loss. Each one is a rule written down ahead of time, so that you don't have to make the decision under pressure. This article describes how three order types behave. It is not a recommendation to buy or sell anything.
Educational content, not financial advice. Every order on CodeBull is placed with simulated money against prices from a third-party feed, and nothing is sent to a real exchange.