{"record":{"id":"7b65b42d0f312db9","repo":"nautechsystems/nautilus_trader","slug":"trailingstopmarket-requires-trailing-offset","errorCode":null,"errorMessage":"TrailingStopMarket requires trailing_offset","messagePattern":"TrailingStopMarket requires trailing_offset","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/okx/src/execution.rs","lineNumber":891,"sourceCode":"        let trigger_type = context.trigger_type;\n        let trigger_price = context.trigger_price;\n        let price = context.price;\n        let is_reduce_only = context.is_reduce_only;\n\n        let trailing_offset = order.trailing_offset();\n        let trailing_offset_type = order.trailing_offset_type();\n        let activation_price = order.activation_price();\n\n        let close_fraction = get_param_as_string(&cmd.params, \"close_fraction\");\n        let reduce_only = if close_fraction.is_some() {\n            Some(true)\n        } else {\n            Some(is_reduce_only)\n        };\n\n        let (callback_ratio, callback_spread) = if order_type == OrderType::TrailingStopMarket {\n            let offset = trailing_offset\n                .ok_or_else(|| anyhow::anyhow!(\"TrailingStopMarket requires trailing_offset\"))?;\n            let offset_type = trailing_offset_type.ok_or_else(|| {\n                anyhow::anyhow!(\"TrailingStopMarket requires trailing_offset_type\")\n            })?;\n\n            match offset_type {\n                TrailingOffsetType::BasisPoints => {\n                    // Convert basis points to ratio (e.g., 100 bps = 0.01)\n                    let ratio = offset / Decimal::from(10000);\n                    (Some(ratio.to_string()), None)\n                }\n                TrailingOffsetType::Price => (None, Some(offset.to_string())),\n                _ => {\n                    anyhow::bail!(\"Unsupported trailing_offset_type for OKX: {offset_type:?}\");\n                }\n            }\n        } else {\n            (None, None)\n        };","sourceCodeStart":873,"sourceCodeEnd":909,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/okx/src/execution.rs#L873-L909","documentation":"submit_conditional_order for an OKX TrailingStopMarket order requires a trailing_offset (the activation callback distance). When the command arrives without it, the adapter cannot compute OKX's callback_ratio or callback_spread and rejects the submission immediately. This mirrors the fact that OKX trailing orders must carry an activation offset.","triggerScenarios":"Calling submit_order with order_type == TrailingStopMarket on the OKX execution client while leaving the order command's trailing_offset unset (None).","commonSituations":"Strategy code building SubmitOrder without setting trailing_offset; orders translated from another adapter where offset was optional; UI/backtest configs omitting the trailing parameters; migrating strategy code between order types without updating parameters.","solutions":["Set trailing_offset on the order command before submitting a TrailingStopMarket order.","Also set trailing_offset_type (see error 3457) — both are required for this order type.","Validate at strategy level: raise a user error early if order type is trailing but offset is missing.","Switch to a non-trailing order type if you did not intend a trailing stop."],"exampleFix":"// before\nlet order = order_factory.market(\n    instrument_id, OrderSide::Sell, quantity,\n); // submitted as TrailingStopMarket\n// after\nlet order = order_factory.trailing_stop_market(\n    instrument_id, OrderSide::Sell, quantity,\n    Decimal::from(1),           // trailing_offset\n    TrailingOffsetType::BasisPoints,\n);","handlingStrategy":"validation","validationCode":"if order_type == OrderType::TrailingStopMarket\n    && (trailing_offset.is_none() || trailing_offset_type.is_none()) {\n    return Err(anyhow::anyhow!(\n        \"TrailingStopMarket requires trailing_offset and trailing_offset_type\"\n    ));\n}","typeGuard":"fn trailing_params_valid(\n    trailing_offset: Option<Decimal>,\n    trailing_offset_type: Option<TrailingOffsetType>,\n) -> bool {\n    trailing_offset.is_some() && trailing_offset_type.is_some()\n}","tryCatchPattern":null,"preventionTips":["Always create trailing orders via order_factory.trailing_stop_market, which takes both offset parameters.","Centralize order construction so required trailing params cannot be omitted.","Add unit tests asserting trailing commands carry both fields."],"tags":["okx","order-submission","trailing-stop","missing-parameter"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}