{"record":{"id":"5110c01e19fbdb7d","repo":"nautechsystems/nautilus_trader","slug":"missing-triggertype-for-trailing-stop-calculatio","errorCode":null,"errorMessage":"Missing `TriggerType` for trailing stop calculation","messagePattern":"Missing `TriggerType` for trailing stop calculation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/trailing.rs","lineNumber":70,"sourceCode":"        OrderType::TrailingStopMarket | OrderType::TrailingStopLimit\n    ) {\n        anyhow::bail!(\"Invalid `OrderType` {order_type} for trailing stop calculation\");\n    }\n\n    // Seed from the current trigger only (never the activation price): when the trigger has\n    // not yet materialized it stays `None` here so the offset candidate below becomes the\n    // initial trigger on the first update (matches v1 `TrailingStopCalculator`).\n    let mut trigger_price = trigger_px.or(order.trigger_price());\n\n    let mut limit_price = if order_type == OrderType::TrailingStopLimit {\n        order.price()\n    } else {\n        None\n    };\n\n    let trigger_type = order\n        .trigger_type()\n        .ok_or_else(|| anyhow::anyhow!(\"Missing `TriggerType` for trailing stop calculation\"))?;\n    let trailing_offset = order.trailing_offset().ok_or_else(|| {\n        anyhow::anyhow!(\"Missing `trailing_offset` for trailing stop calculation\")\n    })?;\n    let trailing_offset_type = order.trailing_offset_type().ok_or_else(|| {\n        anyhow::anyhow!(\"Missing `TrailingOffsetType` for trailing stop calculation\")\n    })?;\n    let mut new_trigger_price: Option<Price>;\n    let mut new_limit_price: Option<Price> = None;\n\n    let maybe_move = |current: &mut Option<Price>,\n                      candidate: Price,\n                      better: fn(Price, Price) -> bool|\n     -> Option<Price> {\n        match current {\n            Some(p) if better(candidate, *p) => {\n                *current = Some(candidate);\n                Some(candidate)\n            }","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/trailing.rs#L52-L88","documentation":"trailing_stop_calculate requires the order to expose a TriggerType, but `order.trigger_type()` returned None. A trailing stop (TrailingStopMarket or TrailingStopLimit) must carry a trigger type (e.g. LastPrice, BidAsk) to determine which market price drives the trailing offset calculation.","triggerScenarios":"Calling trailing_stop_calculate (directly or via update_trailing_stop_order) with an OrderAny whose trigger_type() is None — typically a trailing stop order built without specifying trigger_type, or a custom/order-generic order wrapper that omits it.","commonSituations":"Constructing trailing stop orders from templates/config where trigger_type was omitted; deserializing orders from an older schema without trigger_type; passing a non-trailing order cast generically into the calculator in tests.","solutions":["Set trigger_type (e.g. TriggerType.LastPrice or BidAsk) when creating the TrailingStopMarket/TrailingStopLimit order","Check the order factory/config used to build the order and ensure trigger_type is populated","If deserializing, migrate the order payload to include trigger_type","If testing, use a valid trailing stop order fixture with trigger_type set"],"exampleFix":"// before\norder = order_factory.trailing_stop_market(\n    side=OrderSide.SELL, trailing_offset=Decimal(\"0.01\"),\n)\n// after\norder = order_factory.trailing_stop_market(\n    side=OrderSide.SELL, trailing_offset=Decimal(\"0.01\"),\n    trigger_type=TriggerType.LAST_PRICE,\n)","handlingStrategy":"validation","validationCode":"if order.trigger_type() is None:\n    raise ValueError(\"Trailing stop order requires trigger_type\")","typeGuard":"fn has_trigger_type(order: &OrderAny) -> bool {\n    order.trigger_type().is_some()\n}","tryCatchPattern":"match trailing_stop_calculate(order_type, trigger_px, &order, bid, ask, last) {\n    Ok(prices) => apply(prices),\n    Err(e) => { log::error!(\"trailing calc failed: {e}\"); leave_trigger_unchanged() }\n}","preventionTips":["Always set trigger_type when creating TrailingStopMarket/TrailingStopLimit orders","Validate order completeness in the strategy before submitting updates","Check deserialized orders for required trailing-stop fields"],"tags":["trailing-stop","missing-field","orders"],"backgroundTag":"missing-required-config-field","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}