nautechsystems/nautilus_trader · error

Binance Futures supports L1_MBP and L2_MBP order book subscr

Error message

Binance Futures supports L1_MBP and L2_MBP order book subscriptions

What it means

Binance futures only publishes top-of-book and partial-depth order book streams, so the adapter accepts exactly `BookType::L1_MBP` and `BookType::L2_MBP` for book-deltas subscriptions. Any other BookType — most commonly `L3_MBO` — is rejected immediately with this bail, before depth or subscription state are even considered.

Source

Thrown at crates/adapters/binance/src/futures/data.rs:1931

    fn subscribe_book_deltas(&mut self, cmd: SubscribeBookDeltas) -> anyhow::Result<()> {
        if cmd.book_type == BookType::L1_MBP {
            anyhow::ensure!(
                cmd.depth.is_none_or(|depth| depth.get() == 1),
                "Binance Futures L1_MBP supports depth 1 only"
            );
            anyhow::ensure!(
                !self.book_subscriptions.contains_key(&cmd.instrument_id),
                "cannot subscribe L1_MBP and L2_MBP for the same Binance Futures instrument"
            );
            self.l1_book_subscriptions.rcu(|subscriptions| {
                *subscriptions.entry(cmd.instrument_id).or_insert(0) += 1;
            });
            self.subscribe_top_of_book(cmd.instrument_id);
            return Ok(());
        }

        if cmd.book_type != BookType::L2_MBP {
            anyhow::bail!("Binance Futures supports L1_MBP and L2_MBP order book subscriptions");
        }
        anyhow::ensure!(
            !self.l1_book_subscriptions.contains_key(&cmd.instrument_id),
            "cannot subscribe L1_MBP and L2_MBP for the same Binance Futures instrument"
        );

        let instrument_id = cmd.instrument_id;
        let depth = cmd.depth.map_or(1000, |d| d.get() as u32);

        if !BINANCE_BOOK_DEPTHS.contains(&depth) {
            anyhow::bail!(
                "Invalid depth {depth} for Binance Futures order book. \
                Valid values: {BINANCE_BOOK_DEPTHS:?}"
            );
        }

        // Track subscription for reconnect handling
        self.book_subscriptions.insert(instrument_id, depth);

View on GitHub (pinned to a4b06ed870)

Solutions

  1. Use BookType.L2_MBP (partial depth, valid depths 5/10/20/50/100/500/1000) for order book data on Binance Futures
  2. Use BookType.L1_MBP for top-of-book only
  3. If the strategy needs order-by-order updates, rework it against L2 deltas — Binance futures has no MBO stream to map to

Example fix

# before
actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L3_MBO)

# after
actor.subscribe_order_book_deltas(instrument_id, book_type=BookType.L2_MBP, depth=100)
Defensive patterns

Strategy: type-guard

Validate before calling

if book_type not in (BookType.L1_MBP, BookType.L2_MBP):
    raise ValueError(f'Binance Futures order books support L1_MBP/L2_MBP only, got {book_type}')

Type guard

from nautilus_trader.model.enums import BookType

def is_supported_binance_book_type(book_type) -> bool:
    return book_type in (BookType.L1_MBP, BookType.L2_MBP)

Try / catch

try:
    actor.subscribe_order_book_deltas(instrument_id, book_type=book_type)
except Exception as e:
    if 'supports L1_MBP and L2_MBP' in str(e):
        raise ValueError('Binance has no market-by-order feed; rework the strategy against L2 deltas') from e
    raise

Prevention

When it happens

Trigger: `subscribe_book_deltas` with `book_type=BookType.L3_MBO` (or any variant other than L1_MBP/L2_MBP). The L1 branch runs first, so this error specifically means the type was neither.

Common situations: Strategies ported from venues that offer market-by-order feeds; config defaults assuming MBO is universal; copying a Coinbase/L3-style book config into a Binance futures run.

Related errors


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