nautechsystems/nautilus_trader · error
callbackRate {rate}% out of Binance range [{min_rate}, {max_
Error message
callbackRate {rate}% out of Binance range [{min_rate}, {max_rate}] What it means
For Binance trailing-stop orders the Nautilus trailing offset (basis points) is converted to Binance's callbackRate percent, which the exchange limits to [0.1%, 10.0%]. trailing_offset_to_callback_rate divides the offset by 100 and rejects anything outside that band; submit_order validates it before the order is sent so the order is denied locally rather than rejected by the API.
Source
Thrown at crates/adapters/binance/src/futures/conversions.rs:102
Some(true)
} else {
None
}
}
/// Converts a Nautilus trailing offset (percent) into a Binance `callbackRate` decimal.
///
/// # Errors
///
/// Returns an error if the computed rate is outside the Binance accepted range
/// `[0.1%, 10.0%]`.
pub(crate) fn trailing_offset_to_callback_rate(offset: Decimal) -> anyhow::Result<Decimal> {
let rate = offset / rust_decimal::Decimal::ONE_HUNDRED;
let min_rate = rust_decimal::Decimal::new(1, 1);
let max_rate = rust_decimal::Decimal::new(100, 1);
if rate < min_rate || rate > max_rate {
anyhow::bail!("callbackRate {rate}% out of Binance range [{min_rate}, {max_rate}]");
}
Ok(rate)
}
/// Converts a Nautilus trailing offset (percent) into a Binance `callbackRate` string.
///
/// # Errors
///
/// Returns an error if the computed rate is outside the Binance accepted range.
pub(crate) fn trailing_offset_to_callback_rate_string(offset: Decimal) -> anyhow::Result<String> {
let rate = trailing_offset_to_callback_rate(offset)?;
Ok(format_callback_rate(rate))
}
/// Formats a `callbackRate` decimal for Binance request params.
///
/// Whole percents are rendered with a trailing `.0` to match Binance examples.View on GitHub (pinned to a4b06ed870)
Solutions
- Set trailing_offset between 10 and 1000 basis points (0.1% to 10%): e.g. 250 bps for a 2.5% callback.
- Double-check the unit conversion: percent * 100 = bps; 0.5% is 50 bps, not 5.
- Validate the offset before submission and clamp or reject in strategy code so the order never reaches the denial path.
Example fix
# before
order = OrderFactory.trailing_stop_market(
trailing_offset=5, # intended 0.5% but is 0.05%
trailing_offset_type=TrailingOffsetType.BASIS_POINTS,
)
# after
order = OrderFactory.trailing_stop_market(
trailing_offset=50, # 0.5% = 50 bps (within 10..=1000)
trailing_offset_type=TrailingOffsetType.BASIS_POINTS,
) Defensive patterns
Strategy: try-catch
Validate before calling
MIN_BPS, MAX_BPS = 10, 1000 # Binance callbackRate 0.1%..10.0%
def callback_rate_bps_ok(offset) -> bool:
return MIN_BPS <= offset <= MAX_BPS
assert callback_rate_bps_ok(order.trailing_offset) Type guard
def is_valid_binance_callback_bps(offset) -> bool:
return isinstance(offset, (int, float)) and 10 <= offset <= 1000 Try / catch
try:
client.submit_order(order)
except Exception as e:
if 'callbackRate' in str(e) and 'out of Binance range' in str(e):
# clamp into [0.1%, 10.0%] or surface to risk checks; do NOT blind-retry
log.warning('trailing offset out of Binance callback range: %s', e)
else:
raise Prevention
- Convert percent to bps with percent * 100 before setting trailing_offset.
- Enforce the 10..=1000 bps band in strategy risk checks before order creation.
- Test trailing-stop submission against testnet once when changing offset units.
When it happens
Trigger: Submitting a TRAILING_STOP_MARKET order on a Binance futures client with trailing_offset outside 10..=1000 bps — e.g. trailing_offset=5 (0.05%, below minimum), or trailing_offset=5000 (50%, above maximum), with trailing_offset_type=BASIS_POINTS.
Common situations: Porting stop distances from price units or percent into bps incorrectly (e.g. intending 0.5% and writing 5 bps); very tight trailing stops copied from spot scalping configs; not realizing Binance caps the callback rate at 10%.
Related errors
- Unsupported `OrderSide` for Binance: {value:?}
- Unsupported `TimeInForce` for Binance: {value:?}
- custom data request requires `instrument_id` metadata
- Binance only supports TrailingOffsetType::BasisPoints, recei
- instrument_id is required for historical orders
AI-assisted analysis of nautechsystems/nautilus_trader@a4b06ed870 (2026-08-16).
Data as JSON: /api/errors/28ea63e395dcca6a.
Report an issue: GitHub.