nautechsystems/nautilus_trader · error · anyhow::Error

FOK time in force is not supported on Kraken WS v2; use REST

Error message

FOK time in force is not supported on Kraken WS v2; use REST

What it means

compute_ws_time_in_force translates Nautilus TimeInForce to Kraken WS time-in-force values. Kraken's WS v2 addOrder API does not support fill-or-kill, so Fok is explicitly rejected and the caller is directed to the REST API.

Source

Thrown at crates/adapters/kraken/src/common/order_params.rs:226

            cl_ord_id: Some(vec![truncate_cl_ord_id(&cmd.client_order_id)]),
        }
    }
}

pub(crate) fn compute_ws_time_in_force(
    is_limit_order: bool,
    time_in_force: TimeInForce,
    expire_time: Option<UnixNanos>,
) -> anyhow::Result<Option<KrakenTimeInForce>> {
    if !is_limit_order {
        return Ok(None);
    }

    match time_in_force {
        TimeInForce::Gtc => Ok(None),
        TimeInForce::Ioc => Ok(Some(KrakenTimeInForce::ImmediateOrCancel)),
        TimeInForce::Fok => {
            anyhow::bail!("FOK time in force is not supported on Kraken WS v2; use REST")
        }
        TimeInForce::Gtd => {
            expire_time.ok_or_else(|| {
                anyhow::anyhow!("GTD time in force requires expire_time parameter")
            })?;
            Ok(Some(KrakenTimeInForce::GoodTilDate))
        }
        _ => anyhow::bail!("Unsupported time in force: {time_in_force:?}"),
    }
}

#[cfg(test)]
mod tests {
    use nautilus_core::{UUID4, UnixNanos};
    use nautilus_model::identifiers::{
        ClientOrderId, InstrumentId, StrategyId, TraderId, VenueOrderId,
    };
    use rstest::rstest;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Use time-in-force IoC (immediate-or-cancel) instead of Fok if partial fills are acceptable, via the WS path.
  2. Route FOK orders through the Kraken REST execution client.
  3. Configure the strategy's order templates to use Gtc/Ioc for Kraken WS execution.

Example fix

// before
order_factory.limit(instrument_id, side, qty, price, TimeInForce::Fok, None)
// after
order_factory.limit(instrument_id, side, qty, price, TimeInForce::Ioc, None) // FOK unsupported on WS v2
Defensive patterns

Strategy: validation

Validate before calling

if order.time_in_force() == TimeInForce::Fok {
    // use REST execution client or switch to TimeInForce::Ioc
}

Try / catch

if let Err(e) = ws_client.submit(order).await {
    if e.to_string().contains("FOK time in force") {
        rest_client.submit(order).await?;
    } else { return Err(e); }
}

Prevention

When it happens

Trigger: Submitting any order with time_in_force = Fok through the Kraken WS path, either via build_add_order_params or build_batch_order.

Common situations: Strategy uses FOK for aggressive all-or-nothing entries (common pattern ported from crypto derivatives venues); Kraken Spot WS has no equivalent TIF so it must go through REST or be replaced.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/aac913bd7e6e57ed. Report an issue: GitHub.