nautechsystems/nautilus_trader · error
Missing `TrailingOffsetType` for trailing stop calculation
Error message
Missing `TrailingOffsetType` for trailing stop calculation
What it means
`trailing_stop_calculate` requires the order to carry a trailing offset type (`TrailingOffsetType`) to know how to interpret the trailing offset (absolute price, basis points, or ticks). `OrderAny::trailing_offset_type()` returned `None`, meaning the order was built without this field, so the calculator cannot compute the offset and aborts with an anyhow error. It guards against silently computing a trailing price with an undefined offset semantics.
Source
Thrown at crates/execution/src/trailing.rs:75
// Seed from the current trigger only (never the activation price): when the trigger has
// not yet materialized it stays `None` here so the offset candidate below becomes the
// initial trigger on the first update (matches v1 `TrailingStopCalculator`).
let mut trigger_price = trigger_px.or(order.trigger_price());
let mut limit_price = if order_type == OrderType::TrailingStopLimit {
order.price()
} else {
None
};
let trigger_type = order
.trigger_type()
.ok_or_else(|| anyhow::anyhow!("Missing `TriggerType` for trailing stop calculation"))?;
let trailing_offset = order.trailing_offset().ok_or_else(|| {
anyhow::anyhow!("Missing `trailing_offset` for trailing stop calculation")
})?;
let trailing_offset_type = order.trailing_offset_type().ok_or_else(|| {
anyhow::anyhow!("Missing `TrailingOffsetType` for trailing stop calculation")
})?;
let mut new_trigger_price: Option<Price>;
let mut new_limit_price: Option<Price> = None;
let maybe_move = |current: &mut Option<Price>,
candidate: Price,
better: fn(Price, Price) -> bool|
-> Option<Price> {
match current {
Some(p) if better(candidate, *p) => {
*current = Some(candidate);
Some(candidate)
}
None => {
*current = Some(candidate);
Some(candidate)
}
_ => None,View on GitHub (pinned to 18893faf8b)
Solutions
- Set `trailing_offset_type` when constructing the trailing stop order (e.g. `TrailingOffsetType::Price`, `BasisPoints`, or `Ticks`) so it matches the unit of `trailing_offset`.
- Before calling the calculator, check `order.trailing_offset_type().is_some()` and reject/repair the order otherwise.
- If the order came from deserialization or persisted state, migrate/upgrade the stored data to include the offset type.
Example fix
// before
let order = OrderAny::builder()
.order_type(OrderType::TrailingStopMarket)
.trailing_offset(Decimal::from(100))
.build()?;
// after
let order = OrderAny::builder()
.order_type(OrderType::TrailingStopMarket)
.trailing_offset(Decimal::from(100))
.trailing_offset_type(TrailingOffsetType::Price)
.build()?; Defensive patterns
Strategy: validation
Validate before calling
fn ensure_trailing_offset_type(order: &OrderAny) -> Result<(), String> {
if order.trailing_offset_type().is_none() {
return Err(format!(
"order {} of type {} is missing trailing_offset_type",
order.client_order_id(), order.order_type()
));
}
Ok(())
} Type guard
fn has_trailing_offset_type(order: &OrderAny) -> bool {
order.trailing_offset_type().is_some()
} Prevention
- Always set both `trailing_offset` and `trailing_offset_type` together when creating trailing stop orders.
- Use order factory helpers/builder methods that require the offset type rather than hand-building orders.
- Validate order completeness (offset, offset type, trigger price) before submitting to the execution pipeline.
When it happens
Trigger: Calling `trailing_stop_calculate` (directly or via `update_trailing_stop_order`) with an `OrderAny` whose `trailing_offset_type` is `None` — typically a TrailingStopMarket/TrailingStopLimit order constructed without setting `trailing_offset_type`.
Common situations: Hand-building a trailing stop order and forgetting the `trailing_offset_type` field (e.g. copying a factory that only sets `trailing_offset`); deserializing an order from a venue payload or older persisted state that lacked the field; custom order factories that initialize optional fields to `None`.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Missing `limit_offset` for trailing stop limit calculation
- `close_position` cannot be combined with `reduce_only` on Bi
- {FAILED}: {e}
- callbackRate {rate}% out of Binance range [{min_rate}, {max_
- BitMEX only supports PRICE trailing offset type, was {offset
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3cdaa0cbb5292cb7.
Report an issue: GitHub.