nautechsystems/nautilus_trader · error

`close_position` requires `reduce_only=true` on the Nautilus

Error message

`close_position` requires `reduce_only=true` on the Nautilus order

What it means

Binance's `closePosition=true` parameter closes an entire position with a market-style algo order and inherently reduces exposure, so the adapter requires the Nautilus order to be flagged `reduce_only`. If the `close_position` param is set in `SubmitOrder` params but the order itself is not reduce-only, validation fails to prevent a contradictory or rejected-by-venue request.

Source

Thrown at crates/adapters/binance/src/futures/execution.rs:3658

        anyhow::ensure!(
            offset_type == TrailingOffsetType::BasisPoints,
            "Binance only supports TrailingOffsetType::BasisPoints, received {offset_type:?}"
        );

        if let Some(offset) = order.trailing_offset() {
            trailing_offset_to_callback_rate(offset)?;
        }
    }

    let close_position = cmd
        .params
        .as_ref()
        .and_then(|params| params.get_bool(PARAMS_CLOSE_POSITION))
        .unwrap_or(false);

    if close_position {
        let order_type = order.order_type();
        anyhow::ensure!(
            order.is_reduce_only(),
            "`close_position` requires `reduce_only=true` on the Nautilus order"
        );
        anyhow::ensure!(
            matches!(
                order_type,
                OrderType::StopMarket | OrderType::MarketIfTouched
            ),
            "`close_position` is not supported for order type {order_type:?} on Binance"
        );
    }

    if let Some(price_match) = cmd
        .params
        .as_ref()
        .and_then(|params| params.get_str("price_match"))
    {
        BinancePriceMatch::from_param(price_match)?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Rebuild the order with `reduce_only=true` (e.g. pass `reduce_only=true` to the OrderFactory method).
  2. Alternatively remove the `close_position` param if full-position close is not intended.
  3. Check that the account is not in hedge mode in a way that conflicts with reduce-only semantics, and that the position side matches.

Example fix

// before
let order = factory.market(if_long(BUY, SELL), quantity);
submit_order(order, Some(params_with_close_position()));
// after
let order = factory.market(if_long(BUY, SELL), quantity, None, TimeInForce::Gtc, None,
    /*reduce_only=*/ true);
submit_order(order, Some(params_with_close_position()));
Defensive patterns

Strategy: validation

Validate before calling

fn check_close_position(order: &OrderAny, params: &Option<NautilusParams>) -> Result<(), String> {
    let close = params.as_ref()
        .and_then(|p| p.get_bool("close_position"))
        .unwrap_or(false);
    if close && !order.is_reduce_only() {
        return Err("close_position=true requires reduce_only order".into());
    }
    Ok(())
}

Type guard

fn is_valid_close_position(order: &OrderAny, params: &Option<NautilusParams>) -> bool {
    params.as_ref().and_then(|p| p.get_bool("close_position")).unwrap_or(false)
        .implies(|| order.is_reduce_only())
}

Try / catch

match client.submit_order(cmd).await {
    Err(e) if e.to_string().contains("close_position`) requires") => {
        // rebuild order with reduce_only=true or drop the param
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `submit_order` on a BinanceFuturesExecutionClient with `params.close_position = true` while the order was constructed without `reduce_only=true` (e.g. `OrderFactory::market(..., reduce_only=false)` or default factory settings).

Common situations: Adding the `close_position` param as an afterthought to an existing order builder call; copying an order template where reduce_only was not set; confusion between Binance-side closePosition and the Nautilus reduce_only flag.

Related errors


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