nautechsystems/nautilus_trader · error

Conditional orders require a trigger price

Error message

Conditional orders require a trigger price

What it means

`build_new_order_params` validates the order before translating it to a Binance Spot new-order request: for StopMarket, StopLimit, MarketIfTouched and LimitIfTouched (conditional) order types, Binance requires a stop price, which maps from the Nautilus order's `trigger_price`. If the order has no trigger price the submission is rejected locally with this error — no request reaches Binance.

Source

Thrown at crates/adapters/binance/src/spot/execution.rs:2280

    order: &impl Order,
    client_order_id: ClientOrderId,
    is_post_only: bool,
    is_quote_quantity: bool,
    use_gtd: bool,
) -> anyhow::Result<NewOrderParams> {
    let binance_side = BinanceSide::try_from(order.order_side())?;
    let binance_order_type = order_type_to_binance_spot(order.order_type(), is_post_only)?;

    let requires_trigger = matches!(
        order.order_type(),
        OrderType::StopMarket
            | OrderType::StopLimit
            | OrderType::MarketIfTouched
            | OrderType::LimitIfTouched
    );

    if requires_trigger && order.trigger_price().is_none() {
        anyhow::bail!("Conditional orders require a trigger price");
    }

    let supports_tif = matches!(
        binance_order_type,
        BinanceSpotOrderType::Limit
            | BinanceSpotOrderType::StopLossLimit
            | BinanceSpotOrderType::TakeProfitLimit
    );
    let binance_tif = time_in_force_to_binance_spot(order.time_in_force(), use_gtd)?;
    let binance_tif = if supports_tif {
        Some(binance_tif)
    } else {
        None
    };

    let qty_str = order.quantity().to_string();
    let (base_qty, quote_qty) = if is_quote_quantity {
        (None, Some(qty_str))

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Pass `trigger_price=...` when submitting conditional orders (and for stop/limit variants also the limit `price`)
  2. If the trigger is genuinely unknown at submission time, submit a plain order and manage the trigger client-side instead of using a conditional order type
  3. Validate order type vs. trigger price in strategy code before submitting (see defense)

Example fix

# before
order = self.order_factory.submit(
    strategy_id=self.id,
    instrument_id=instrument_id,
    order_side=OrderSide.SELL,
    order_type=OrderType.STOP_LIMIT,
    quantity=qty,
    price=limit_price,          # only limit price set
    time_in_force=TimeInForce.GTC,
)

# after
order = self.order_factory.submit(
    strategy_id=self.id,
    instrument_id=instrument_id,
    order_side=OrderSide.SELL,
    order_type=OrderType.STOP_LIMIT,
    quantity=qty,
    price=limit_price,
    trigger_price=stop_price,   # Binance requires the stop price
    time_in_force=TimeInForce.GTC,
)
Defensive patterns

Strategy: validation

Validate before calling

# Python: validate before submitting
def assert_conditional_order_valid(order_type: OrderType, trigger_price) -> None:
    conditional = order_type in (
        OrderType.STOP_MARKET,
        OrderType.STOP_LIMIT,
        OrderType.MARKET_IF_TOUCHED,
        OrderType.LIMIT_IF_TOUCHED,
    )
    if conditional and trigger_price is None:
        raise ValueError(f"{order_type} requires a trigger_price for Binance Spot")

Type guard

# Python
def is_submittable_on_binance_spot(order) -> bool:
    """True when conditional orders carry the trigger price Binance requires."""
    conditional = order.order_type in {
        OrderType.STOP_MARKET, OrderType.STOP_LIMIT,
        OrderType.MARKET_IF_TOUCHED, OrderType.LIMIT_IF_TOUCHED,
    }
    return (not conditional) or (order.trigger_price is not None)

Prevention

When it happens

Trigger: Submitting via the order factory any of STOP_MARKET, STOP_LIMIT, MARKET_IF_TOUCHED or LIMIT_IF_TOUCHED without passing `trigger_price` — e.g. `self.order_factory.submit(...)` with only `price`/`quantity` set, or a generic order-building helper that never sets trigger prices.

Common situations: Forgetting the `trigger_price` argument; setting only the limit `price` on a StopLimit and assuming it doubles as the stop; porting strategies from venues where the trigger is optional or named differently; dynamically choosing order types where one branch omits the trigger.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/496b4939de29a44b. Report an issue: GitHub.