beatzxbt / bybit-smm

bybit simple market maker
MIT License
398 stars 125 forks source link

Orderbooks resetting book on every update regardless if its a snapshot or delta message #20

Closed OfferLifted closed 3 weeks ago

OfferLifted commented 1 month ago

Below is from the bybit orderbook handler but saw the same thing in the binance one. on snapshot or update_id representing a snapshot message ob is reset using snapshot data

                self.update_id = new_update_id
                self.bids = np.array(data["b"], dtype=np.float64)
                self.asks = np.array(data["a"], dtype=np.float64)
                self.orderbook.refresh(self.asks, self.bids)

Makes sense, note self.update_id is set (probably to 1 because of snapshot).

Then if message is not snapshot and not update_id 1 (so perhaps "delta" and 1234). We then check if 1234 > self.update_id which is probably still 1 from the last snapshot reset. So any delta msg will then reset bids or asks if it has any data for them. self.bids = np.array(data["b"], dtype=np.float64) for example

Is this intented? Surely you would want to update your book on delta messages rather than overwriting one or both sides entirely? Afaik current implementation only works if you get a full book update on delta messages but then whats the snapshot for? I thought usually delta message only contains data for bids/asks that actually had a change in p or q in any way. Anyways love to hear your thoughts I might just be missing something simple!

    def process(self, recv: Dict) -> None:
        try:
            data = recv["data"]
            new_update_id = int(data["u"])
            update_type = recv["type"]

            if new_update_id == 1 or update_type == "snapshot":
                self.update_id = new_update_id
                self.bids = np.array(data["b"], dtype=np.float64)
                self.asks = np.array(data["a"], dtype=np.float64)
                self.orderbook.refresh(self.asks, self.bids)

            elif new_update_id > self.update_id:
                self.update_id = new_update_id

                if len(data.get("b", [])) > 0:
                    self.bids = np.array(data["b"], dtype=np.float64)
                    self.orderbook.update_bids(self.bids)

                if len(data.get("a", [])) > 0:
                    self.asks = np.array(data["a"], dtype=np.float64)
                    self.orderbook.update_asks(self.asks)

        except Exception as e:
            raise Exception(f"Orderbook Process :: {e}")
beatzxbt commented 1 month ago

hey, thanks for the comment. its so easy for me to miss bugs developing this all alone, so i really do appreciate you looking through the code :D

but, this isnt a bug. from what i understand, you understand that the self.bids/self.asks represent the arrays within the orderbook (in the sharedstate), but they just ref the placeholder arrays in the base class for ease of use. infact, i may just remove it to avoid this very confusion (makes no difference whatsoever storing it as a self.bids or just bid_update within the same fn and then passing that to the self.orderbook.update() func.

the orderbook maintains its own set of self.bids/self.asks, seperate from the handler, as i dont like mixing numba with external numpy/py types. causes a lot of printing issues for debugging...