Skip to content
All library documents

Trailing Stop-Limit Orders: Dynamic Triggers and Fill Risk

Article NautilusTrader

Summary

A trailing stop-limit order moves its stop trigger with favorable price changes, maintaining a set offset from a chosen market reference. Once triggered, it releases a limit order; the limit price can also adjust with the market before activation. The document describes configuration choices such as the activation price, trailing and limit offsets, trigger type, and time in force.

The example configures a buy order for AUD/USD, activated at a specified price and using a price-based trailing offset. The document also explains that leaving both activation and trigger prices unset causes immediate activation, with the trigger formed on the first market update. Its main caveat is execution risk: after a rapid reversal, the released limit order may not fill, leaving the position open. The guide explains order behavior and setup, but provides no performance evidence or guidance for selecting offsets.

Key ideas

  • A trailing stop-limit order follows favorable price movement by keeping its trigger a specified offset from a market reference.
  • When triggered, it submits a limit order, which may remain unfilled during a fast reversal.
  • An activation price can delay when trailing begins, while omitted activation and trigger prices result in immediate activation.
  • The order can be configured with different trigger references, offset types, and time-in-force settings.

Tags

Full text
# Trailing-Stop-Limit


# Trailing-Stop-Limit

`FIX OrdType <40>=4` (Stop Limit) + trailing peg

A *Trailing-Stop-Limit* order keeps its stop trigger a fixed offset from the specified market price
as the market moves favorably. It releases a *Limit* order when triggered, and the limit price also
updates with the market until then.

## Use cases

Use a *Trailing-Stop-Limit* order for dynamic trailing protection with a worst acceptable fill
price. As with a *Stop-Limit*, the released *Limit* order may not fill during a fast reversal and can
leave the position open.

## Example

In the following example we create a *Trailing-Stop-Limit* order on the Currenex FX ECN to BUY 1,250,000 AUD using USD
at a limit price of 0.71000 USD, activating at 0.72000 USD then trailing at a stop offset of 0.00100 USD
away from the current ask price, active until further notice:

```rust tab="Rust"
use nautilus_model::{
    enums::{OrderSide, TimeInForce, TrailingOffsetType, TriggerType},
    identifiers::InstrumentId,
    types::{Price, Quantity},
};
use rust_decimal_macros::dec;
use ustr::Ustr;

let order = self.order().trailing_stop_limit(
    InstrumentId::from("AUD/USD.CURRENEX"),
    OrderSide::Buy,
    Quantity::from(1_250_000),
    Price::from("0.71000"),          // limit price
    dec!(0.00050),                   // limit_offset
    dec!(0.00100),                   // trailing_offset
    Some(TrailingOffsetType::Price), // optional (default PRICE)
    Some(Price::from("0.72000")),    // activation_price
    None,                            // trigger_price (materializes from the offset on the first trail)
    Some(TriggerType::BidAsk),       // optional (default DEFAULT)
    Some(TimeInForce::Gtc),          // optional (default GTC)
    None,                            // expire_time
    Some(false),                     // post_only (default false)
    Some(true),                      // reduce_only (default false)
    None,                            // quote_quantity (default false)
    None,                            // display_qty
    None,                            // emulation_trigger
    None,                            // trigger_instrument_id
    None,                            // exec_algorithm_id
    None,                            // exec_algorithm_params
    Some(vec![Ustr::from("TRAILING_STOP")]), // tags
    None,                            // client_order_id
);
```

```python tab="Python"
from decimal import Decimal

from nautilus_trader.model import InstrumentId
from nautilus_trader.model import OrderSide
from nautilus_trader.model import Price
from nautilus_trader.model import Quantity
from nautilus_trader.model import TimeInForce
from nautilus_trader.model import TrailingOffsetType
from nautilus_trader.model import TrailingStopLimitOrder
from nautilus_trader.model import TriggerType

order: TrailingStopLimitOrder = self.order_factory.trailing_stop_limit(
    instrument_id=InstrumentId.from_str("AUD/USD.CURRENEX"),
    order_side=OrderSide.BUY,
    quantity=Quantity.from_int(1_250_000),
    price=Price.from_str("0.71000"),
    activation_price=Price.from_str("0.72000"),
    trigger_type=TriggerType.BID_ASK,  # <-- optional (default DEFAULT)
    limit_offset=Decimal("0.00050"),
    trailing_offset=Decimal("0.00100"),
    trailing_offset_type=TrailingOffsetType.PRICE,
    time_in_force=TimeInForce.GTC,  # <-- optional (default GTC)
    expire_time=None,  # <-- optional (default None)
    reduce_only=True,  # <-- optional (default False)
    tags=["TRAILING_STOP"],  # <-- optional (default None)
)
```

:::info
If both `activation_price` and `trigger_price` are omitted, the order activates immediately at the
current market and its trigger price materializes from `trailing_offset` on the first update.
:::

See the
[`TrailingStopLimitOrder` API reference](/docs/python-api-latest/model/orders.html#nautilus_trader.model.TrailingStopLimitOrder)
for further details.

## Related guides

- [Orders](index.md#trailing-offset-type) - Trigger and trailing offset types.
- [Emulated orders](emulated.md) - Emulating trailing stops on venues without native support.
- [Execution](../execution/) - How orders reach the venue and fills are handled.

Shown in full with attribution under the source's licence. Licence: LGPL-3.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.