I'm writing a Node.js application which attempts to re-create the Coinex orderbook for ETH-USDT using their Websocket. My application subscribes to the market depth channel and keeps an ongoing, updated local copy of the orderbook stored in memory.
I have a working implementation, but I'm noticing that my local copy of the orderbook always seems to eventually fall out of sync with the exchange. I've run the application for up to 2 hours without seeing a single issue, but eventually and invariably, I end up with a "stale" price level in my local copy that was removed from the exchange at some point.
I'm fairly certain that the WS message to remove the level was never sent because I've run multiple tests where I log every WS message sent during the test period. I can probably rule out the obvious issue of there being some bug with my system.
Is this just an issue on the Coinex side? Is there some other way I need to be expiring messages? How can I best detect and handle this issue assuming it's a problem with the Coinex Websocket?
Are you making use of the 'complete result' flag in Coinex's depth.update
response (i.e. - params[0]
)? The server occasionally sends a complete copy of the order book (up to the count limit in your request), setting this flag to true
. Completely resetting your local order book state when this flag is set should keep you in sync.
Another thing it could be is how you're handling depth updates with 0 volume for a certain price (i.e. - setting the value at that price to 0 vs removing the key from your map).
Here's a Java example of how I'm handling updates (the maps' sizes stay consistent with the count limit initially sent in the request):
@AllArgsConstructor
@Data
public class LimitOrderBook {
private double last;
private final SortedMap<Double, Double> asks;
private final SortedMap<Double, Double> bids;
private int time;
public void handleUpdate(final LimitOrderBookUpdate update) {
if (update.isFullUpdate()) {
asks.clear();
bids.clear();
}
last = update.getLast();
update.getAskUpdates().forEach(p -> updateMap(asks, p));
update.getBidUpdates().forEach(p -> updateMap(bids, p));
time = update.getTime();
}
private void updateMap(final SortedMap<Double, Double> map, final Pair<Double, Double> pair) {
if (pair.getValue() == 0) {
map.remove(pair.getKey());
} else {
map.put(pair.getKey(), pair.getValue());
}
}
}