coinbase / coinbase-pro-node

DEPRECATED — The official Node.js library for Coinbase Pro
Apache License 2.0
844 stars 316 forks source link

Out of sync websocket order books #380

Closed johank16 closed 4 years ago

johank16 commented 5 years ago

I am having trouble keeping a synced order book. I keep getting negative spread, similar to the guy in this thread: https://github.com/coinbase/coinbase-pro-node/issues/183

Can you provide an example of how this should be done? Please let me know if you can help because my whole program is useless without accurate order book info! I've tried these two approaches and get out-of-sync order books within minutes:

Method 1 using the WebsocketClient object:

let openCoinStream = function (coin) {
    coinbaseProCoinStream = new coinbaseProAPI.WebsocketClient([coin]
        , 'wss://ws-feed.pro.coinbase.com'
        , null 
        , {channels:['level2']});
    coinbaseProCoinStream.on('message', data => {
      if(data.type == 'snapshot')
      {
        for(let i in data.asks)
            coinbaseProMarketDepths[data.product_id].asks[data.asks[i][0]] = data.asks[i][1]
        for(let i in data.bids)
            coinbaseProMarketDepths[data.product_id].bids[data.bids[i][0]] = data.bids[i][1]
      }
      else if( data.type == 'l2update')
      {
        let changes = data.changes 
        for(let i in changes)
        {
            if(changes[i][0] == 'buy')
            {
                if(changes[i][2] == 0)
                    delete coinbaseProMarketDepths[data.product_id].bids[changes[i][1]]
                else
                    coinbaseProMarketDepths[data.product_id].bids[changes[i][1]] = changes[i][2]
            }
            else if(changes[i][0] == 'sell')
            {
                if(changes[i][2] == 0)
                    delete coinbaseProMarketDepths[data.product_id].asks[changes[i][1]]
                else
                    coinbaseProMarketDepths[data.product_id].asks[changes[i][1]] = changes[i][2]
            }
        }
      }
      });
    coinbaseProCoinStream.on('error', err => {
      console.log('coinbasepro coin stream error: ' + err.stack)
    });
    coinbaseProCoinStream.on('close', () => {
      console.log('coinbasepro websocket closed, attempting to reopen in 5 seconds...')
      setTimeout(function() { instantiateCoinStream() }, 5000) 
    });
}

if(coinbaseProCoinStream[coinName] == null)
{
    coinbaseProMarketDepths[coinName] = { bids: {}, asks: {} } 
    openCoinStream(coinName)
}

let bids = coinbaseProMarketDepths[coinName].bids
let asks = coinbaseProMarketDepths[coinName].asks

let bidPrices = Object.keys(bids).sort(function(a,b){return(b-a)})
let askPrices = Object.keys(asks).sort()

if(askPrices[0] < bidPrices[0]))
    console.log('coinbasepro order book is out of sync')

Method 2 using the OrderbookSync object:

let openCoinStream = function(coin) {
    console.log('subscribing to coinbase coin ' + coin)
    coinbaseProCoinStream[coin] = new coinbaseProAPI.OrderbookSync(coin)

    coinbaseProCoinStream[coin].on('error', err => {
        console.log('error with ' + coin + ' coinbasepro stream: ' + err.stack)
        console.log('trying to redo connection in 5 seconds')
        setTimeout(function() { openCoinStream(coin) }, 5000)
    })
    coinbaseProCoinStream[coin].on('close', err => {
        console.log('coinbasepro order book websocket closed for ' + coin + ', reconnecting in 5 seconds')
        setTimeout(function() { openCoinStream(coin) }, 5000)
    })
} 

let bids = {} 
let asks = {} 

if(coinbaseProCoinStream[coinName] == null)
    openCoinStream(coinName)
else
{   if(coinbaseProCoinStream[coinName].books[formattedCoin] != null)
    {
        let orderBook = coinbaseProCoinStream[formattedCoin].books[formattedCoin].state()

        for(let i in orderBook.bids)
        {
            if(bids[orderBook.bids[i].price] == null)
                bids[orderBook.bids[i].price] = 0
            bids[orderBook.bids[i].price] += Number(orderBook.bids[i].size)
        }
        for(let i in orderBook.asks)
        {
            if(asks[orderBook.asks[i].price] == null)
                asks[orderBook.asks[i].price] = 0
            asks[orderBook.asks[i].price] += Number(orderBook.asks[i].size)
        }
    }
}

let bidPrices = Object.keys(bids).sort(function(a,b){return(b-a)})
let askPrices = Object.keys(asks).sort()

if(askPrices[0] < bidPrices[0])
    console.log('coinbasepro order book is out of sync')
drewrothstein commented 4 years ago

Hi, we are closing out PRs + Issues as this project is being archived.