nautechsystems/nautilus_trader · error · anyhow::Error

AX does not support reduce-only orders

Error message

AX does not support reduce-only orders

What it means

validate_order_instructions bails immediately when the order carries reduce_only=true: AX's order encoding has no reduce-only flag, so the instruction cannot be represented. It is checked both at submit validation (from the live order) and at order-init validation (OrderInitialized event), so reduce-only orders are denied before submission and never reach the venue. The adapter intentionally fails loudly instead of silently dropping the semantics, which would risk over-closing or flipping positions.

Source

Thrown at crates/adapters/architect_ax/src/execution.rs:1919

    Ok(())
}

fn validate_order_init_instructions(order_init: &OrderInitialized) -> anyhow::Result<()> {
    validate_order_instructions(
        order_init.reduce_only,
        order_init.quote_quantity,
        order_init.display_qty.is_some(),
    )
}

fn validate_order_instructions(
    reduce_only: bool,
    quote_quantity: bool,
    has_display_qty: bool,
) -> anyhow::Result<()> {
    if reduce_only {
        anyhow::bail!("AX does not support reduce-only orders");
    }

    if quote_quantity {
        anyhow::bail!(
            "Architect AX adapter cannot encode quote_quantity; submit a base quantity instead"
        );
    }

    if has_display_qty {
        anyhow::bail!("Architect AX adapter cannot encode display_qty iceberg instructions");
    }

    Ok(())
}

// The AX HTTP API documents only a bare 400 with no error schema, so no venue
// failure can be allowlisted as an unambiguous rejection; those arrive via the
// orders WS `Rejected` and `CancelRejected` events instead. AX therefore never

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Submit the exit order with reduce_only unset (false) and size it exactly to the open position
  2. Track netting positions yourself (AX is Netting/Margin in this adapter) and only send the delta you intend
  3. Add a pre-submit assertion so reduce-only never reaches the AX client

Example fix

// before
let exit = factory.market(id, opposite_side, qty)
    .reduce_only(true); // -> AX does not support reduce-only orders
// after
let exit = factory.market(id, opposite_side, position_qty_open);
// exact size, no flag
Defensive patterns

Strategy: validation

Validate before calling

fn ax_instructions_ok(reduce_only: bool, quote_qty: bool, display_qty: bool) -> bool {
    !reduce_only && !quote_qty && !display_qty
}
debug_assert!(ax_instructions_ok(
    order.is_reduce_only(),
    order.is_quote_quantity(),
    order.display_qty().is_some(),
));

Prevention

When it happens

Trigger: factory.market/limit(...).reduce_only(true); strategies with 'close position' helpers that set reduce_only to avoid over-filling; ported code from futures venues (Binance, Bybit) where reduce-only is native.

Common situations: Position-management code written for CEX futures adapters; risk frameworks that always flag exit orders as reduce-only.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16). Data as JSON: /api/errors/a0a6f776f653ec0c. Report an issue: GitHub.