Search code examples
websocketalgorithmic-tradingtradingcryptoapibinance

Binance WebSocket Order Book - depths change every time


Below is a python script that subscribes order book information via Biance's Websocket API (Documentation Here).

In both requests(btcusdt@depth and btcusdt@depth@100ms), each json payload is streamed with a varying depth.
Please shed light on what might be the cause of this? Am I doing something wrong? Or might they have certain criteria as to how many depths of an order book to fetch?

import json
import websocket

socket='wss://stream.binance.com:9443/ws'

def on_open(self):
    print("opened")
    subscribe_message = {
        "method": "SUBSCRIBE",
        "params":
        [
         "btcusdt@depth@100ms"
         ],
        "id": 1
        }

    ws.send(json.dumps(subscribe_message))

def on_message(self, message):
    print("received a message")

    ###### depths of bid/ask ######
    d = json.loads(message)
    for k, v in d.items():
        if k == "b":
            print(f"bid depth : {len(v)}")
        if k == "a":
            print(f"ask depth : {len(v)}")

def on_close(self):
    print("closed connection")

ws = websocket.WebSocketApp(socket,
                            on_open=on_open,
                            on_message=on_message,
                            on_close=on_close)

ws.run_forever()

btcusdt@depth@100ms

opened
received a message
received a message
bid depth : 3
ask depth : 12
received a message
bid depth : 14
ask depth : 12
received a message
bid depth : 17
ask depth : 24
received a message
bid depth : 14
ask depth : 16
received a message
bid depth : 3
ask depth : 5
received a message
bid depth : 16
ask depth : 6
.
.
.

btcusdt@depth

opened
received a message
received a message
bid depth : 135
ask depth : 127
received a message
bid depth : 125
ask depth : 135
received a message
bid depth : 95
ask depth : 85
received a message
bid depth : 68
ask depth : 88
received a message
bid depth : 119
ask depth : 145
received a message
bid depth : 127
ask depth : 145
.
.
.

Solution

  • Your code reads the length of the diff for the last 100 ms or 1000 ms (the default value when you don't specify the timeframe). I.e. the remote API sends just the diff, not the full list.

    The varying length of the diff is expected.


    Example:

    An order book has 2 bids and 2 asks:

    • ask price 1.02, amount 10
    • ask price 1.01, amount 10
    • bid price 0.99, amount 10
    • bid price 0.98, amount 10

    During the timeframe, one more bid is added and one ask is updated. So the message returns:

    "b": [
        [ // added new bid
            0.97,
            10
        ]
    ],
    "a": [
        [ // updated existing ask
            1.01,
            20
        ]
    ]
    

    And your code reads this message as

    bid depth: 1
    ask depth: 1
    

    During another timeframe, two bids are updated

    "b": [
        [ // updated existing bid
            0.98,
            20
        ],
        [ // updated existing bid
            0.99,
            20
        ]
    ],
    "a": [] // no changes
    

    So your code reads this as

    bid depth: 2
    ask depth: 0