nautechsystems/nautilus_trader · error · anyhow::Error

Unsupported time in force: {:?}, AX supports GTC, IOC, and D

Error message

Unsupported time in force: {:?}, AX supports GTC, IOC, and DAY

What it means

Second check in validate_order_for_ax_submit: AX's REST order API accepts only GTC, IOC and DAY time-in-force. The adapter denies other TIFs (FOK, GTD, AT_THE_OPEN, AT_THE_CLOSE, ...) locally, as the comment states, to avoid an opaque venue error - AX's HTTP API returns a bare 400 with no error schema, so an unsupported TIF would otherwise surface as an unclassifiable failure instead of a clean rejection.

Source

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

        ts_init,
        Some(UUID4::new()),
    ))
}

fn validate_order_for_ax_submit(order: &OrderAny) -> anyhow::Result<()> {
    if !matches!(order.order_type(), OrderType::Market | OrderType::Limit) {
        anyhow::bail!(
            "Unsupported order type: {:?}, the Architect AX adapter accepts Nautilus MARKET and LIMIT orders",
            order.order_type(),
        );
    }

    // AX accepts only GTC, IOC, and DAY; deny others locally to avoid an opaque venue error
    if !matches!(
        order.time_in_force(),
        TimeInForce::Gtc | TimeInForce::Ioc | TimeInForce::Day
    ) {
        anyhow::bail!(
            "Unsupported time in force: {:?}, AX supports GTC, IOC, and DAY",
            order.time_in_force(),
        );
    }

    validate_order_instructions(
        order.is_reduce_only(),
        order.is_quote_quantity(),
        order.display_qty().is_some(),
    )?;

    AxOrderSide::try_from(order.order_side())
        .map_err(|e| anyhow::anyhow!("Invalid order side: {e}"))?;
    quantity_to_contracts(order.quantity())?;

    Ok(())
}

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Set the order's TIF to GTC, IOC or DAY before submitting to AX
  2. Emulate FOK: submit IOC and cancel if the fill is partial (the adapter's market emulation already yields partial-fill handling)
  3. Emulate GTD: submit GTC and schedule a local cancel at the expiry time

Example fix

// before
let order = factory.limit(id, side, qty, px)
    .time_in_force(TimeInForce::Gtd)
    .expire_time(expiry); // -> Unsupported time in force
// after
let order = factory.limit(id, side, qty, px)
    .time_in_force(TimeInForce::Gtc);
// schedule cancel at expiry via a TimeEvent in the strategy
Defensive patterns

Strategy: validation

Validate before calling

fn ax_tif_ok(tif: TimeInForce) -> bool {
    matches!(tif, TimeInForce::Gtc | TimeInForce::Ioc | TimeInForce::Day)
}
debug_assert!(ax_tif_ok(order.time_in_force()));

Type guard

fn is_ax_supported_tif(tif: TimeInForce) -> bool {
    matches!(tif, TimeInForce::Gtc | TimeInForce::Ioc | TimeInForce::Day)
}

Prevention

When it happens

Trigger: Order initialized with TimeInForce::Fok / Gtd / AtTheOpen / AtTheClose submitted to the AX execution client; GTD orders carrying an expiry_time from a strategy template; factory.limit(...).time_in_force(TimeInForce::Fok) for strict all-or-none entries.

Common situations: Reusing order templates from adapters (e.g. dYdX, Binance-futures) that accept FOK/GTD; copying example strategies that set GTD expiries.

Related errors


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