Skip to main content
Protect a position with a bracket: up to three take profits and up to three stop losses, placed with the entry, on an entry that’s already resting, or on a position you already hold. Use this page when your trading program places entries and has to keep them protected as the market moves. trdrs lays a bracket out as pairs along the position, nearest the entry first. Each pair is a take profit and a stop loss for one stretch of the position, and when one of them fills, the other is cancelled. By the end you have placed an entry with a bracket, protected a position you hold, moved a stop loss, set a stop loss that moves itself, and read back what’s resting.

Before you start

The examples use the variables from the programmatic quickstart and trade ESZ6, the December 2026 E-mini S&P 500 contract, on a Demo in production. A Demo prices futures only from your own futures login, as Place your first order explains, so in the sandbox you run the same calls on HYPERLIQUID:BTC, sized in bitcoin, as Test it end to end does. The TypeScript SDK isn’t published, so call the routes over HTTP, as the curl examples do. The TypeScript examples show the same calls through the SDK’s client, with provider and account set. Check that the account can hold a bracket first. The capabilities of the account snapshot carry exitHolding, which is none where the provider holds no take profits or stop losses, and exitSupport, the parts of a bracket the account can run. A Demo supports all of them.
1

Place an entry with its bracket

Send exits with the order. This one buys 2 contracts and takes profit on them in two steps, one contract at a time, with one stop loss under both.
The two take profits and the stop loss make two pairs: the first contract’s take profit at 6488.50 with its share of the stop loss, and the second contract’s at 6495 with the rest of it. Size each leg by quantity, in the instrument’s own unit, or by share of the order in percent. Place it at a price, or at a distance from the entry in the bracket’s unit: ticks, price, percent, pips where the instrument has a pip, or currency, what the leg makes or loses in the instrument’s settlement currency.The response carries bracket, with its id. Keep it as BRACKET_ID: every change names it. trdrs records the bracket before it sends the entry. While the limit rests, the bracket is pending_entry, and each pair starts protecting the moment the part of the position it covers fills. attached is true where the provider holds the pairs with the entry itself.
2

Protect a position you already hold

Send a bracket to Protect a position. Distances are measured from the position’s average entry, and every price must clear the market on the side it protects, since a stop loss already past the market would close the position at once. This example sets a take profit 58 ticks above the average entry and a stop loss 32 ticks below, each for the whole position.
The response names the bracket, with its id and state, and carries refused, the provider’s reason where it refused a pair, whose stretch the bracket then shows as unprotected. clientOrderId makes a retry of the same request safe.The bracket covers qty of the position when you send one, and otherwise all of the position that no other bracket protects. A position the account’s brackets already protect is refused with 409 position_protected and the bracketId to change instead.On an account that holds each entry as its own ticket, send the ticket’s positionId from the account frame to protect that ticket alone.
3

Move a stop loss

Send the bracket’s ladders as they should be to Change a bracket. A leg that keeps its place in its ladder keeps its id and moves. Here the stop loss moves up to 6478.50 and both take profits stay.
A change is all or nothing. The new layout rests before the old one is cancelled, so the position is never without its stop loss, and if the provider refuses any pair, the bracket stays exactly as it was and refused says why. A take profit or a stop loss of a bracket changes only this way: moving its order with Replace an order is refused with 409 bracket_order.To take the bracket down and keep the position, withdraw it:
Every order the bracket rests is cancelled, the bracket ends as cancelled, and the position stays open.
4

Let a stop loss move itself

A stop loss can move to breakeven once, and trail the price in up to three tiers. trdrs moves it on every provider that holds a bracket, so your program doesn’t have to. Write the rules on the stop loss, with the unit they’re in:
Once the position is 8 ticks in profit, the stop loss moves to 1 tick past the entry. From 16 ticks in profit it follows the best price 8 ticks behind, moving each time the price has gained 2 more ticks. A stop loss that moves itself only ever tightens. The same rules work in an entry’s exits, a protection and a change.
5

Read what's actually resting

List brackets returns the protection around each position: its ladders, the orders resting for them, and how each stop loss that moves itself is running.
If you already hold an account snapshot or an account stream frame, you don’t need this call: the same brackets array is in both, at the same moment as the positions and orders.

Protect a resting order

Put a bracket on an entry you’ve already placed, before it fills, by naming the order in entryOrderId in place of a position. Use this when your program places an entry first and decides its protection afterwards, or when a trader drags a take profit or a stop loss off a resting order on a chart. Here ORDER_ID, and orderId in TypeScript, hold the entry’s providerOrderId, as the order’s response or the account’s working orders give it.
The bracket covers the whole entry and waits on it, pending_entry, as a bracket placed with its entry does: each pair rests once the fill that opens its part of the position arrives. Its prices are measured from the entry’s own price, the limit of a limit order and the trigger of a stop or a stop-limit, and each must lie on its side of that price. None is held to the market, because no position is open. The response is the bracket and entryOrderId, the order the entry rests as afterwards. On the paper book the entry is replaced with itself, at the same price and size, to carry the bracket, so from then on it rests under your clientOrderId. Every other provider keeps the entry’s id. While the entry rests, change the bracket with Change a bracket or withdraw it as you would after the fill. On the paper book each change answers the entry’s new entryOrderId too, and withdrawing the bracket leaves the entry resting with no protection.

Read a bracket

Each entry in brackets is the protection around one position. takeProfits and stopLosses are its ladders, nearest the entry first, and orders are what rests for them, each naming its pairId. runner is how much of the position has a stop loss and no take profit, and unprotected is how much has no stop loss at all. A bracket that ended stays listed for a day, so your interface can show how it ended. A stop loss that moves itself carries automation. Its phase says which stop loss rests now: the one placed (protecting), the breakeven one (breakeven), or a trailing one (trailing). When state is paused, pauseReason says why nothing is moving the stop loss: provider_disconnected, no_price_feed, no_instrument_facts or account_locked. The stop loss resting at the provider still protects the position while it’s paused. Two details catch clients out:
  • The other order of a pair disappears on its own. When one order of a pair fills, the other is cancelled. Don’t cancel it yourself, and don’t treat its disappearance as a fault.
  • An order can rest before it has a provider id. Where the provider holds the pairs with the entry, an order carries holding provider_managed until the provider names it. Match the account’s working orders to a bracket by providerOrderId once it’s there.

When a change is refused

No hold on the account refuses a bracket on a position: it only closes the position it protects, so it can’t add exposure. On the paper book a bracket on a resting entry is carried by replacing the entry, so a hold that refuses new entries refuses that too.

Test it end to end

On your Demo in the sandbox, with HYPERLIQUID:BTC sized in bitcoin:
  1. Buy 0.02 with a limit above the market, so it fills at once, with two take profits of 0.01 each above the limit and one stop loss for 0.02 below the market.
  2. List the brackets and confirm the bracket is active with four working orders, two pairs.
  3. Move the stop loss, then list again: the stop loss’s price changed and the take profits’ didn’t.
  4. Flatten the instrument, and confirm the bracket has ended and nothing of it rests.

Next steps

Manage working orders

Move a resting entry to a new price, and its bracket follows it.

Close a position

Take some off, flatten, or reverse, and see what each cancels first.