Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Changelog

### 3.0.1
* Bugfix: Binance Futures and Binance Delivery L2_BOOK with `depth_interval='250ms'` subscribed to `<symbol>@depth@250ms`, which Binance accepts but never sends data on. The default interval now uses the bare `<symbol>@depth` stream.

### 3.0.0 (2026-09-21)
* Feature: New asyncio core
* Update: REST endpoints removed (trading functionality moves to the cryptotrade project)
Expand Down
5 changes: 4 additions & 1 deletion cryptofeed/exchanges/binance.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class BinanceBase(Feed):
DEFAULT_SNAPSHOT_DEPTH = 1000
SNAPSHOT_RETRIES = 5
SNAPSHOT_RETRY_DELAY = 15
# Depth interval Binance serves on the bare `<symbol>@depth` stream. The
# futures endpoints send nothing on an explicit `@250ms` suffix.
default_depth_interval = None
# m -> minutes; h -> hours; d -> days; w -> weeks; M -> months
valid_candle_intervals = {'1m', '3m', '5m', '15m', '30m', '1h', '2h', '4h', '6h', '8h', '12h', '1d', '3d', '1w', '1M'}
websocket_channels = {
Expand Down Expand Up @@ -152,7 +155,7 @@ def _stream_names(self) -> list:
stream = chan
if normalized_chan == CANDLES:
stream = f"{chan}{self.candle_interval}"
elif normalized_chan == L2_BOOK:
elif normalized_chan == L2_BOOK and self.depth_interval != self.default_depth_interval:
stream = f"{chan}@{self.depth_interval}"

for pair in self.subscription[chan]:
Expand Down
1 change: 1 addition & 0 deletions cryptofeed/exchanges/binance_delivery.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class BinanceDelivery(BinanceBase):

valid_depths = [5, 10, 20, 50, 100, 500, 1000]
valid_depth_intervals = {'100ms', '250ms', '500ms'}
default_depth_interval = '250ms'
websocket_channels = {
**BinanceBase.websocket_channels,
FUNDING: 'markPrice',
Expand Down
1 change: 1 addition & 0 deletions cryptofeed/exchanges/binance_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class BinanceFutures(BinanceBase):

valid_depths = [5, 10, 20, 50, 100, 500, 1000]
valid_depth_intervals = {'100ms', '250ms', '500ms'}
default_depth_interval = '250ms'
websocket_channels = {
**BinanceBase.websocket_channels,
FUNDING: 'markPrice',
Expand Down
24 changes: 24 additions & 0 deletions tests/unit/test_binance_depth_stream.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'''
Copyright (C) 2017-2026 Bryant Moscon - bmoscon@gmail.com

Please see the LICENSE file for the terms and conditions
associated with this software.
'''
import pytest

from cryptofeed.exchanges import Binance, BinanceDelivery, BinanceFutures


@pytest.mark.parametrize('feed_cls, symbol, interval, stream', [
(BinanceFutures, 'BTCUSDT', '250ms', 'btcusdt@depth'),
(BinanceFutures, 'BTCUSDT', '100ms', 'btcusdt@depth@100ms'),
(BinanceFutures, 'BTCUSDT', '500ms', 'btcusdt@depth@500ms'),
(BinanceDelivery, 'BTCUSD_PERP', '250ms', 'btcusd_perp@depth'),
(BinanceDelivery, 'BTCUSD_PERP', '100ms', 'btcusd_perp@depth@100ms'),
(Binance, 'BTCUSDT', '1000ms', 'btcusdt@depth@1000ms'),
(Binance, 'BTCUSDT', '100ms', 'btcusdt@depth@100ms'),
])
def test_depth_stream_name(feed_cls, symbol, interval, stream):
feed = feed_cls(depth_interval=interval)
feed.subscription = {'depth': [symbol]}
assert feed._stream_names() == [stream]