altangent / ccxws

WebSocket client for 38 cryptocurrency exchanges
MIT License
617 stars 186 forks source link

Liquid order book goes out of sync #182

Closed nudabagana closed 4 years ago

nudabagana commented 4 years ago

Exchange Happens with Liquid exchange.

Subscription type Order book (l2update).

Describe the bug Liquid order book goes out of sync (old orders not being deleted).

To Reproduce code sandbox here: https://codesandbox.io/s/node-js-04ccj?file=/src/index.js

bmancini55 commented 4 years ago

Liquid order books are best described as a hybrid snapshot-update stream. Each update is a one sided snapshot (bid or ask) that contains the top 40 values on that side. So instead of doing insert/update/delete for each item based on price points, you need to do a complete replacement of one side of the book with the data in the update message.

bmancini55 commented 4 years ago

If I get some time today I'll port over a order book implementation for it.

bmancini55 commented 4 years ago

I pushed a prototype to master: https://github.com/altangent/ccxws/blob/master/src/orderbooks/LiquidOrderBook.js

Some sample code to use this orderbook:

const ccxws = require("ccxws");
const LiquidOrderBook = require("ccxws/src/orderbooks/LiquidOrderBook");

const client = new ccxws.liquid();
const market = { id: "btceur", base: "BTC", quote: "EUR" };
const ob = new LiquidOrderBook();

client.subscribeLevel2Updates(market);
client.on("l2update", update => {
  ob.update(update);
  printSnap(ob.snapshot(10));
});

function printSnap(snap) {
  const now = Date.now();
  const printNow = (side, point) => printPoint(now, side, point);

  try {
    console.clear();
    for (const ask of snap.asks.reverse()) {
      printNow("A", ask);
    }
    console.log("~");
    for (const bid of snap.bids) {
      printNow("B", bid);
    }
  } catch (ex) {
    console.error(ex);
  }
}

function printPoint(now, side, point) {
  const price = point.price;
  const size = point.size;
  const secs = secsAgo(now, point.timestamp).toFixed(2);
  console.log(`${side} ${price} ${size} ${secs}s ago`);
}

function secsAgo(now, start) {
  return (now - start) / 1000;
}