Skip to content
All library documents

Limit-If-Touched Orders: Triggered Limit Execution and Non-Fill Risk

Article NautilusTrader

Summary

A Limit-If-Touched order waits for a specified trigger price, then releases a limit order at a separate specified price. This lets a trader delay placing a price-protected order until the market reaches a chosen level. The example uses a buy order on a perpetual futures contract, with the trigger above the limit price, and shows optional settings for trigger source, time in force, expiry, post-only behavior, reduce-only status, and order tags.

The document notes a central limitation: after triggering, the limit order may remain unfilled if the market moves past its limit. It also says FIX has no dedicated order-type value for this instruction and mentions a commonly used stop-limit representation. The examples illustrate order construction in two programming languages, but provide no evidence about fill rates, venue support, or execution outcomes.

Key ideas

  • A Limit-If-Touched order releases a limit order after its trigger price is reached.
  • The trigger and limit prices determine when the order activates and the price constraint it accepts.
  • A triggered order can fail to fill if the market moves beyond its limit price.
  • Trigger source, expiration, time in force, and other execution settings can be specified.

Tags

Full text
# Limit-If-Touched


# Limit-If-Touched

`FIX OrdType <40>` no dedicated value (commonly `4` Stop Limit with a favorable trigger)

A *Limit-If-Touched* order releases a *Limit* order at the specified price when its trigger price is
reached.

## Use cases

Use a *Limit-If-Touched* order to activate a price-protected order only after a trigger is touched,
for example to place a take-profit *Limit* order as price approaches a target instead of resting it
early. As with a *Stop-Limit*, the order may not fill if the market moves through the limit after the
trigger.

## Example

The following example creates a *Limit-If-Touched* order to BUY 5 BTCUSDT-PERP perpetual futures
contracts on Binance Futures at a limit price of 30,100 USDT once the market reaches 30,150 USDT.
The order expires one hour after creation:

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

let expire_time = self.clock().timestamp_ns() + DurationNanos::from_mins(60);
let order = self.order().limit_if_touched(
    InstrumentId::from("BTCUSDT-PERP.BINANCE"),
    OrderSide::Buy,
    Quantity::from(5),
    Price::from("30100"),
    Price::from("30150"),
    Some(TriggerType::LastPrice), // optional (default DEFAULT)
    Some(TimeInForce::Gtd),       // optional (default GTC)
    Some(expire_time),            // one hour from now
    Some(true),                   // post_only (default false)
    Some(false),                  // 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("TAKE_PROFIT")]), // tags
    None,                         // client_order_id
);
```

```python tab="Python"
from nautilus_trader.model import InstrumentId
from nautilus_trader.model import LimitIfTouchedOrder
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 TriggerType

order: LimitIfTouchedOrder = self.order_factory.limit_if_touched(
    instrument_id=InstrumentId.from_str("BTCUSDT-PERP.BINANCE"),
    order_side=OrderSide.BUY,
    quantity=Quantity.from_int(5),
    price=Price.from_str("30_100"),
    trigger_price=Price.from_str("30_150"),
    trigger_type=TriggerType.LAST_PRICE,  # <-- optional (default DEFAULT)
    time_in_force=TimeInForce.GTD,  # <-- optional (default GTC)
    expire_time=self.clock.timestamp_ns() + 3_600_000_000_000,
    post_only=True,  # <-- optional (default False)
    reduce_only=False,  # <-- optional (default False)
    tags=["TAKE_PROFIT"],  # <-- optional (default None)
)
```

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

## Related guides

- [Orders](index.md#trigger-type) - Trigger types and other execution instructions.
- [Emulated orders](emulated.md) - Emulating conditional orders 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.