nautechsystems/nautilus_trader · error
Missing `trailing_offset` for trailing stop calculation
Error message
Missing `trailing_offset` for trailing stop calculation
What it means
trailing_stop_calculate requires a numeric trailing_offset, but `order.trailing_offset()` returned None. Without the offset there is no distance definition for recalculating the trailing stop's trigger price.
Source
Thrown at crates/execution/src/trailing.rs:72
anyhow::bail!("Invalid `OrderType` {order_type} for trailing stop calculation");
}
// 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);View on GitHub (pinned to 18893faf8b)
Solutions
- Specify trailing_offset (price or percentage per trailing_offset_type) when creating the trailing stop order
- Fix the order factory/config so trailing_offset is always set for TrailingStop* orders
- Migrate deserialized order payloads to include trailing_offset
- In tests, build orders with a valid trailing_offset fixture value
Example fix
// before
order = order_factory.trailing_stop_limit(
side=OrderSide.BUY, trigger_type=TriggerType.LAST_PRICE,
)
// after
order = order_factory.trailing_stop_limit(
side=OrderSide.BUY, trigger_type=TriggerType.LAST_PRICE,
trailing_offset=Decimal("0.005"),
trailing_offset_type=TrailingOffsetType.BASIS_POINTS,
) Defensive patterns
Strategy: validation
Validate before calling
if order.trailing_offset() is None:
raise ValueError("Trailing stop order requires trailing_offset") Type guard
fn has_trailing_offset(order: &OrderAny) -> bool {
order.trailing_offset().is_some() && order.trailing_offset_type().is_some()
} Try / catch
match trailing_stop_calculate(order_type, trigger_px, &order, bid, ask, last) {
Ok(prices) => apply(prices),
Err(e) => { log::error!("trailing calc failed: {e}"); leave_trigger_unchanged() }
} Prevention
- Always provide trailing_offset (and trailing_offset_type) for trailing stop orders
- Centralize order construction in a factory that validates trailing-stop fields
- Validate order fixtures in tests before invoking the calculator
When it happens
Trigger: Calling trailing_stop_calculate (or update_trailing_stop_order) with an order whose trailing_offset() is None — the order was created without trailing_offset or constructed/deserialized incompletely.
Common situations: Omitting trailing_offset in order templates or strategy config; older serialized orders lacking the field; test fixtures building invalid trailing stop orders.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Missing `TriggerType` for trailing stop calculation
- Limit orders require a price
- Stop market orders require a trigger price
- Stop limit orders require a trigger price
- Trailing stop orders are not yet supported on the Kraken WS
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8dced1978007903e.
Report an issue: GitHub.