A trailing stop follows the best price since it started tracking and fires when the price reverses
by a set distance. Unlike a fixed stop, its trigger level moves with the market in your favor and
never moves back. Other venues call the distance a callback rate. Create one with CreateTrigger (POST /v1/triggers) and a trailingStop strategy.
How it tracks the price
SELL· Tracks the highest price, its peak
Trigger level: peak minus the distance. Fires when the price falls to or below the level.BUY· Tracks the lowest price, its trough
Trigger level: trough plus the distance. Fires when the price rises to or above the level.
The price is the one named by trigger_price_source: the last traded price by default, or the index price. Activation, the peak or trough, and the fire all follow that price.
A distance in basis points is applied to the current peak or trough, so the level keeps the same percentage as the price moves. A distance in ticks is a fixed price amount.
trailing.peak_price_ticks or trailing.trough_price_ticks shows the tracked extreme, and trailing.trigger_price_ticks the current level. The level is absent until the trailing stop starts
tracking.
Activation
Without activation_price_ticks, the trailing stop starts tracking as soon as it is installed.
With an activation price, it waits in CREATED until the price reaches it: at or above it for a
sell, at or below it for a buy. Polyester then records EVENT_ACTIVATED, the status becomes ARMED, and tracking starts from that price. Use activation to start trailing only once a position
is in profit.
The activation price must be one the watched price has not reached yet when the trailing stop is
installed. A create whose activation price an earlier price already reached ends FAILED with TRIGGER_WOULD_TRIGGER_IMMEDIATELY: it never activates, places no order, and releases its reserved
funds. To start trailing from the market at once, leave the activation price unset.
Child order
| Side | Without a slippage cap | With a slippage cap |
|---|---|---|
SELL | A market order | An IOC limit order at the fire price minus the cap, rounded up to the tick size |
BUY | An IOC limit order at limit_price_ticks | An IOC limit order at the fire price plus the cap, or limit_price_ticks if lower, rounded down |
The fire price is the trigger level when the trailing stop fired. A buy trailing stop never pays
more than limit_price_ticks, its maximum price. A rise that fires it above that maximum still fires
it, and the child then fills only at or below the maximum, or not at all.
A sell's market child is still price-protected without a cap: it uses the Pair's default market slippage for a sell, or 200 basis points when the Pair has no positive default, measured from the fire price. On a gap past that limit it can fill partly or not at all. See Market order price protection.
Fields and validation
| Field | Rule |
|---|---|
side | Required: BUY or SELL |
trailing_distance_ticks or trailing_distance_bps | Required, exactly one. Ticks positive; basis points 1 to 10000 |
activation_price_ticks | Optional. Positive and on the Pair's tick size |
max_slippage_ticks or max_slippage_bps | Optional, at most one. Ticks positive; basis points 1 to 9999 on either side |
limit_price_ticks | Required for a buy, on the tick size, and at least activation_price_ticks. Must be unset for a sell |
trigger_price_source | Optional: LAST_PRICE (default) or INDEX_PRICE |
A buy placed without an activation price must have limit_price_ticks at or above the price it
watches when it is installed. Otherwise it fails with LIMIT_PRICE_INVALID and places nothing.
A positive distance in price is accepted whether or not it is a multiple of the Pair's tick size.
In REST, the distance in price is trailingDistance and the prices are activationPrice and limitPrice, all decimal strings. Basis-point and tick slippage fields keep their integer form.
Funds reserved at creation
A sell trailing stop reserves its quantity in the base Asset. A buy trailing stop reserves limit_price_ticks times the quantity, plus the fee, in the quote Asset. When it fires, the
reserve moves to the child order, and any part the child does not need is released.
A create whose child could never pass the Pair's order limits is rejected with that check's code,
such as MIN_NOTIONAL: a buy is valued at its maximum price, and a sell, whose fire price has no
upper bound, is checked on its quantity only (MIN_QUANTITY, STEP_SIZE).
Examples
A sell trailing stop on 0.5 BTC that starts tracking once BTC-USDT reaches 70,000 and fires after a 2% fall from the highest price since then. Its market child is capped at 1% below the fire price.
POST /v1/triggers
{
"trigger": {
"symbol": "BTC-USDT",
"qty": "0.5",
"clientTriggerId": "ts-btc-1",
"trailingStop": {
"side": "SELL",
"trailingDistanceBps": 200,
"activationPrice": "70000",
"maxSlippageBps": 100
}
}
}/triggers.v1.TriggersService/CreateTrigger, assuming Pair ID 1 and a base_quantity_scale of 8.
{
"trigger": {
"symbolId": 1,
"qtyScaled": "50000000",
"clientTriggerId": "ts-btc-1",
"trailingStop": {
"side": "SELL",
"trailingDistanceBps": 200,
"activationPriceTicks": "70000000000000",
"maxSlippageBps": 100
}
}
}With the example above:
- BTC-USDT trades at 68,000. The trailing stop is
CREATEDand waits for 70,000. - A trade at 70,000 activates it. The peak is 70,000 and the level is 68,600.
- The price rises to 75,000. The peak follows, and the level moves up to 73,500.
- The price falls to 73,500 and the trailing stop fires at that level. Its child sells 0.5 BTC with an IOC limit at 72,765, 1% below the fire price.
Buys 0.5 BTC after the price rises 150 USDT from its lowest point, paying at most 66,000.
{
"trigger": {
"symbol": "BTC-USDT",
"qty": "0.5",
"clientTriggerId": "ts-btc-buy-1",
"trailingStop": {
"side": "BUY",
"trailingDistance": "150",
"limitPrice": "66000"
}
}
}Without a cap, the child is an IOC limit order at 66,000. With maxSlippageBps, it would be placed
at the fire price plus the cap, if that is below 66,000.
Modify, pause, and resume
ModifyTrigger changes the distance, the activation price, and the slippage
cap. Set activation_price_ticks or the cap to 0 to clear it. The side, quantity, price source, and limit_price_ticks cannot change; setting limit_price_ticks is refused with TRIGGER_CHILD_PRICE_NOT_MODIFIABLE.
A change that would make the trailing stop act at once is refused with TRIGGER_WOULD_TRIGGER_IMMEDIATELY, and nothing changes:
- a new activation price, on a trailing stop not yet activated, that the watched price has already reached;
- a new distance, on an activated trailing stop, that puts its trigger price at or past the latest price.
Clearing the activation price (0) is accepted and starts trailing from the market at once. An
activation price off the Pair's tick size is refused with PRICE_TICK_SIZE and a tick_size violation on activation_price_ticks (REST activationPrice), with or without the optional symbol_id. A change is also refused with MIN_QTY, QTY_STEP_SIZE, or MIN_NOTIONAL when the
child order would fall below the Pair's current minimums, which can happen only if they rose after
the create. A resumed trailing stop is checked against the latest price at once, so it can activate
or fire straight away.
Attached trailing stops
A trailing stop can be attached to an order as its stop leg. It starts tracking once the order fills, or once its activation price is reached, and exits on the opposite side of the order:
- On a buy order, the trailing stop sells. Leave
limit_price_ticksunset; an order that sets it is rejected withBAD_PRICE. - On a sell order, the trailing stop buys back and requires
limit_price_ticks, its maximum price, at or above any activation price. An order without it is rejected withTRIGGER_BUY_REQUIRES_LIMIT.
The violation names the attached field, order.attached_risk.trailing_stop.limit_price_ticks (REST order.attachedRisk.trailingStop.limitPrice). Order reads return that maximum in the order's attached_risk.trailing_stop.policy.limit_price_ticks (REST attachedRisk.trailingStop.policy.limitPrice).
On an order with a fill, the activation and distance rules above apply to the attached trailing
stop too when you change it with ModifyTrigger. ModifyOrder replaces the leg instead, so these
rules judge only the new leg's activation price. A new distance on a leg without an activation price
is accepted, and the new leg starts trailing from the latest price.
See Attached take-profit and stop-loss.
Errors
TRIGGER_BUY_REQUIRES_LIMIT
A buy trailing stop has nolimit_price_ticks.BAD_PRICE
A sell setlimit_price_ticks, or a buy's maximum is below its activation price.VALIDATION_ERROR
The distance is missing, not positive, or outside1to10000bps.MAX_SLIPPAGE_INVALID
The slippage cap is10000bps.PRICE_TICK_SIZE
The activation or maximum price is not on the Pair's tick size.TRIGGER_WOULD_TRIGGER_IMMEDIATELY
A modify would move the activation price or the trigger price onto a price already reached. A create with such an activation price endsFAILEDwith this reason instead.TRIGGER_PRICE_SOURCE_UNSUPPORTED
The source isMARK_PRICEor not a defined source.INSUFFICIENT_FUNDS
The available balance cannot cover the reserve.MIN_QUANTITY,STEP_SIZE,MIN_NOTIONAL
The child order could never pass the Pair's order limits.MIN_QTY,QTY_STEP_SIZE,MIN_NOTIONALon a modify
The change would leave the child order below the Pair's minimums. The trailing stop is unchanged.
See Error codes for HTTP and ConnectRPC statuses.