{"record":{"id":"496b4939de29a44b","repo":"nautechsystems/nautilus_trader","slug":"conditional-orders-require-a-trigger-price","errorCode":null,"errorMessage":"Conditional orders require a trigger price","messagePattern":"Conditional orders require a trigger price","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/execution.rs","lineNumber":2280,"sourceCode":"    order: &impl Order,\n    client_order_id: ClientOrderId,\n    is_post_only: bool,\n    is_quote_quantity: bool,\n    use_gtd: bool,\n) -> anyhow::Result<NewOrderParams> {\n    let binance_side = BinanceSide::try_from(order.order_side())?;\n    let binance_order_type = order_type_to_binance_spot(order.order_type(), is_post_only)?;\n\n    let requires_trigger = matches!(\n        order.order_type(),\n        OrderType::StopMarket\n            | OrderType::StopLimit\n            | OrderType::MarketIfTouched\n            | OrderType::LimitIfTouched\n    );\n\n    if requires_trigger && order.trigger_price().is_none() {\n        anyhow::bail!(\"Conditional orders require a trigger price\");\n    }\n\n    let supports_tif = matches!(\n        binance_order_type,\n        BinanceSpotOrderType::Limit\n            | BinanceSpotOrderType::StopLossLimit\n            | BinanceSpotOrderType::TakeProfitLimit\n    );\n    let binance_tif = time_in_force_to_binance_spot(order.time_in_force(), use_gtd)?;\n    let binance_tif = if supports_tif {\n        Some(binance_tif)\n    } else {\n        None\n    };\n\n    let qty_str = order.quantity().to_string();\n    let (base_qty, quote_qty) = if is_quote_quantity {\n        (None, Some(qty_str))","sourceCodeStart":2262,"sourceCodeEnd":2298,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/a4b06ed870971b5671d12754ea138a3ab99b1dec/crates/adapters/binance/src/spot/execution.rs#L2262-L2298","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass `trigger_price=...` when submitting conditional orders (and for stop/limit variants also the limit `price`)","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","Validate order type vs. trigger price in strategy code before submitting (see defense)"],"exampleFix":"# before\norder = self.order_factory.submit(\n    strategy_id=self.id,\n    instrument_id=instrument_id,\n    order_side=OrderSide.SELL,\n    order_type=OrderType.STOP_LIMIT,\n    quantity=qty,\n    price=limit_price,          # only limit price set\n    time_in_force=TimeInForce.GTC,\n)\n\n# after\norder = self.order_factory.submit(\n    strategy_id=self.id,\n    instrument_id=instrument_id,\n    order_side=OrderSide.SELL,\n    order_type=OrderType.STOP_LIMIT,\n    quantity=qty,\n    price=limit_price,\n    trigger_price=stop_price,   # Binance requires the stop price\n    time_in_force=TimeInForce.GTC,\n)","handlingStrategy":"validation","validationCode":"# Python: validate before submitting\ndef assert_conditional_order_valid(order_type: OrderType, trigger_price) -> None:\n    conditional = order_type in (\n        OrderType.STOP_MARKET,\n        OrderType.STOP_LIMIT,\n        OrderType.MARKET_IF_TOUCHED,\n        OrderType.LIMIT_IF_TOUCHED,\n    )\n    if conditional and trigger_price is None:\n        raise ValueError(f\"{order_type} requires a trigger_price for Binance Spot\")","typeGuard":"# Python\ndef is_submittable_on_binance_spot(order) -> bool:\n    \"\"\"True when conditional orders carry the trigger price Binance requires.\"\"\"\n    conditional = order.order_type in {\n        OrderType.STOP_MARKET, OrderType.STOP_LIMIT,\n        OrderType.MARKET_IF_TOUCHED, OrderType.LIMIT_IF_TOUCHED,\n    }\n    return (not conditional) or (order.trigger_price is not None)","tryCatchPattern":null,"preventionTips":["Always pass trigger_price (and for stop-limits, also price) when submitting conditional orders","Centralize order construction in one helper that enforces trigger price by order type","Add a unit test per order type your strategy submits, asserting the built order has a trigger price for conditional types","Remember the mapping: trigger_price becomes Binance's stopPrice — a limit price alone is never the trigger"],"tags":["binance-spot","order-submission","conditional-order","trigger-price","validation","nautilustrader"],"backgroundTag":"stop-order-missing-trigger-price","analyzedSha":"a4b06ed870971b5671d12754ea138a3ab99b1dec","analyzedAt":"2026-08-16T22:54:50.089Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}