DeviaVir / zenbot

Zenbot is a command-line cryptocurrency trading bot using Node.js and MongoDB.
MIT License
8.23k stars 2.04k forks source link

ggetBalance error (4.04) #193

Closed vincentbollaert closed 7 years ago

vincentbollaert commented 7 years ago
ggetBalance error:
{ error: 'Nonce must be greater than 149582751298100. You provided 149582751297600.' }

Poloniex API is down! unable to call getBalance, retrying in 10s

While making its 1st purchase on poloniex.BCN-BTC

crack00r commented 7 years ago

someone fix it here https://github.com/rferro/plnx/issues/2 but i cant implement it

nao0811ta commented 7 years ago

sorry too late it's mine it works

var Poloniex = require('poloniex.js')
  , path = require('path')
  , moment = require('moment')
  , n = require('numbro')
  , colors = require('colors')

module.exports = function container (get, set, clear) {
  var c = get('conf')

  var public_client, public_client2, authed_client

  function publicClient (product_id) {
    if (!public_client) public_client = new Poloniex(c.poloniex.key, c.poloniex.secret)
    return public_client
  }

  function authedClient () {
    if (!authed_client) {
      if (!c.poloniex || !c.poloniex.key || c.poloniex.key === 'YOUR-API-KEY') {
        throw new Error('please configure your Poloniex credentials in conf.js')
      }
      authed_client = new Poloniex(c.poloniex.key, c.poloniex.secret)
    }
    return authed_client
  }

  function joinProduct (product_id) {
    return product_id.split('-')[1] + '_' + product_id.split('-')[0]
  }

  function retry (method, args) {
    if (method !== 'getTrades') {
      console.error(('\nPoloniex API is down! unable to call ' + method + ', retrying in 10s').red)
    }
    setTimeout(function () {
      exchange[method].apply(exchange, args)
    }, 10000)
  }

  var orders = {}
  var lock = false
  var exchange = {
    name: 'poloniex',
    historyScan: 'backward',
    makerFee: 0.15,
    takerFee: 0.25,

    getProducts: function () {
      return require('./products.json')
    },

    getTrades: function (opts, cb) {
//console.error('getTrades')
      var func_args = [].slice.call(arguments)
if (lock) {
//  console.log('locked from getTrades')
  return retry('getTrades', func_args)
}
//console.log('getTrades')
lock = true
      var client = publicClient()
      var args = {
        currencyPair: joinProduct(opts.product_id)
      }
      if (opts.from) {
        args.start = opts.from
      }
      if (opts.to) {
        args.end = opts.to
      }
      if (args.start && !args.end) {
        // add 2 hours
        args.end = args.start + 7200
      }
      else if (args.end && !args.start) {
        // subtract 2 hours
        args.start = args.end - 7200
      }

      client._public('returnTradeHistory', args, function (err, body) {
lock = false
//console.log('finish getTrades')
        if (err) return cb(err)
//console.error('getTrades returnTradeHistory')
        if (typeof body === 'string') {
          return retry('getTrades', func_args)
        }
        if (!body.map) {
          console.error('\getTrades odd result:')
          console.error(body)
          return retry('getTrades', func_args)
        }
        var trades = body.map(function (trade) {
          return {
            trade_id: trade.tradeID,
            time: moment.utc(trade.date).valueOf(),
            size: Number(trade.amount),
            price: Number(trade.rate),
            side: trade.type
          }
        })
        cb(null, trades)
      })
    },

    getBalance: function (opts, cb) {
      var args = [].slice.call(arguments)
      var client = authedClient()
if(lock){
// console.error('locked from getBalance')
 return retry('getBalance', args)
}
lock = true
//console.log('getBalance')
      client.returnCompleteBalances(function (err, body) {
lock = false
//console.log('finish getBalance')
        if (err) return cb(err)
//console.error('getBalance returnCompleteBalances')
        var balance = {asset: 0, currency: 0}
        if (typeof body === 'string') {
          return retry('getBalance', args)
        }
        if (body.error) {
          console.error('\ggetBalance error:')
          console.error(body)
          return retry('getBalance', args)
        }
        if (body[opts.currency]) {
          balance.currency = n(body[opts.currency].available).add(body[opts.currency].onOrders).format('0.00000000')
          balance.currency_hold = body[opts.currency].onOrders
        }
        if (body[opts.asset]) {
          balance.asset = n(body[opts.asset].available).add(body[opts.asset].onOrders).format('0.00000000')
          balance.asset_hold = body[opts.asset].onOrders
        }
        cb(null, balance)
      })
    },

    getQuote: function (opts, cb) {
//console.error('getQuote')
      var args = [].slice.call(arguments)
      var client = publicClient()
      var product_id = joinProduct(opts.product_id)
      client.getTicker(function (err, body) {
        if (err) return cb(err)
//console.error('getQuote getTicker')
        if (typeof body === 'string') {
          return retry('getQuote', args)
        }
        if (body.error) {
          console.error('\ggetQuote error:')
          console.error(body)
          return retry('getQuote', args)
        }
        var quote = body[product_id]
        if (!quote) return cb(new Error('no quote for ' + product_id))
        if (quote.isFrozen == '1') console.error('\nwarning: product ' + product_id + ' is frozen')
        cb(null, {
          bid: quote.highestBid,
          ask: quote.lowestAsk,
        })
      })
    },

    cancelOrder: function (opts, cb) {
//console.error('cancelOrder')
      var args = [].slice.call(arguments)
      var client = authedClient()
      client._private('cancelOrder', {orderNumber: opts.order_id}, function (err, result) {
//console.error('cancelOrder2')
        if (typeof result === 'string') {
          return retry('cancelOrder', args)
        }
        if (!err && !result.success) {
          // sometimes the order gets cancelled on the server side for some reason and we get this. ignore that case...
          if (result.error !== 'Invalid order number, or you are not the person who placed the order.') {
            err = new Error('unable to cancel order')
            err.body = result
          }
        }
        cb(err)
      })
    },

    trade: function (type, opts, cb) {
//console.error('trade')
      var args = [].slice.call(arguments)
if(lock)
{
 return retry('trade', args)
}
lock = true
      var client = authedClient()
      var params = {
        currencyPair: joinProduct(opts.product_id),
        rate: opts.price,
        amount: opts.size,
        postOnly: opts.post_only === false ? '0' : '1'
      }
      client._private(type, params, function (err, result) {
//console.error('trade2')
lock = false
        if (typeof result === 'string') {
          return retry('trade', args)
        }
        var order = {
          id: result ? result.orderNumber : null,
          status: 'open',
          price: opts.price,
          size: opts.size,
          post_only: !!opts.post_only,
          created_at: new Date().getTime(),
          filled_size: '0'
        }
        if (result && result.error === 'Unable to place post-only order at this price.') {
          order.status = 'rejected'
          order.reject_reason = 'post only'
          return cb(null, order)
        }
        else if (result && result.error && result.error.match(/^Not enough/)) {
          order.status = 'rejected'
          order.reject_reason = 'balance'
          return cb(null, order)
        }
        if (!err && result.error) {
          err = new Error('unable to ' + type)
          err.body = result
        }
        if (err) return cb(err)
        orders['~' + result.orderNumber] = order
        cb(null, order)
      })
    },

    buy: function (opts, cb) {
      exchange.trade('buy', opts, cb)
    },

    sell: function (opts, cb) {
      exchange.trade('sell', opts, cb)
    },

    getOrder: function (opts, cb) {
//console.error('getOrder')
      var args = [].slice.call(arguments)
      var order = orders['~' + opts.order_id]
      if (!order) return cb(new Error('order not found in cache'))
      var client = authedClient()
      var params = {
        currencyPair: joinProduct(opts.product_id)
      }
      client._private('returnOpenOrders', params, function (err, body) {
        if (err) return cb(err)
//console.error('returnOpenOrders')
        if (typeof body === 'string' || !body) {
          return retry('getOrder', args)
        }
        var active = false
        if (!body.forEach) {
          console.error('\nreturnOpenOrders odd result:')
          console.error(body)
        }
        else {
          body.forEach(function (api_order) {
            if (api_order.orderNumber == opts.order_id) active = true
          })
        }
        if (!active) {
          order.status = 'done'
          order.done_at = new Date().getTime()
          return cb(null, order)
        }
        client.returnOrderTrades(opts.order_id, function (err, body) {
//console.error('returnOrderTrades')
          if (typeof body === 'string' || !body) {
            return retry('getOrder', args)
          }
          if (err || body.error || !body.forEach) return cb(null, order)
          order.filled_size = '0'
          body.forEach(function (trade) {
            order.filled_size = n(order.filled_size).add(trade.amount).format('0.00000000')
          })
          if (n(order.filled_size).value() == n(order.size).value()) {
            order.status = 'done'
            order.done_at = new Date().getTime()
          }
          cb(null, order)
        })
      })
    },

    // return the property used for range querying.
    getCursor: function (trade) {
      return Math.floor((trade.time || trade) / 1000)
    }
  }
  return exchange
}
crack00r commented 7 years ago

no rly bug, only api down

Poloniex API is down! unable to call getBalance, retrying in 10s

Poloniex API is down! unable to call getBalance, retrying in 10s

crack00r commented 7 years ago

and again returnOpenOrders odd result: { error: 'Nonce must be greater than 149756185095800. You provided 149756185068600.' }

nao0811ta commented 7 years ago

Api down is not bug. Maybe the reason is your request is frequent. My code is for avoiding noce error from requesting multiple api at the same time.

nao0811ta commented 7 years ago

My code is not occured since few days before.

crack00r commented 7 years ago

http://prntscr.com/fk9qzp

crack00r commented 7 years ago

http://prntscr.com/fk9s4o

crack00r commented 7 years ago

and it didnt cancel the orders http://prntscr.com/fk9slg

so right now, but is useless

jjngpuri commented 7 years ago

Are you play with the date of you pc? I do a few days ago and make the bot crazy with nonce error! The solution was make a new poloniex key.

crack00r commented 7 years ago

works, i set my server time 2min. above the real time... no Nonce must be greater than anymore but still Poloniex API is down! unable to call getBalance, retrying in 10s is there any way to add 2 ore more apikeys?

http://prntscr.com/fke1ch

tuxitor commented 7 years ago

@crack00r It is really no help in advancing your computers time. the only factor the exchange care about is that the nonce has a higher value than the previous one. The most important factor is to have a stable clock. You can achieve that by using NTP, but that might not help if you have an unstable computer.

Other reasons:

jjngpuri commented 7 years ago

due to the asyncronous nature of a node program, an old nonce can slip through

I made some test... that is the problem... the program make 2 even 3 calls to poloniex whitout wait for the first to be resolved.

ghost commented 7 years ago

Fixed by adding --lock and installing NTP on centos and set to sync every minute with --period=1m But this does not fix my nonce issue!!!!!

THE EDIT in exchange.js:


  var orders = {}
  var lock = false
  var exchange = {
    name: 'poloniex',
    historyScan: 'backward',
    makerFee: 0.15,
    takerFee: 0.25,

    getProducts: function () {
      return require('./products.json')
    },

    getTrades: function (opts, cb) {
//console.error('getTrades')
      var func_args = [].slice.call(arguments)
if (lock) {
//  console.log('locked from getTrades')
  return retry('getTrades', func_args)
}
//console.log('getTrades')
lock = true
      var client = publicClient()
      var args = {
        currencyPair: joinProduct(opts.product_id)
      }
      if (opts.from) {
        args.start = opts.from
      }
      if (opts.to) {
        args.end = opts.to
      }
      if (args.start && !args.end) {
        // add 2 hours
        args.end = args.start + 7200
      }
      else if (args.end && !args.start) {
        // subtract 2 hours
        args.start = args.end - 7200
      }

      client._public('returnTradeHistory', args, function (err, body) {
lock = false
ghost commented 7 years ago

You also need to do this instead of running docker, use separate configs for each instance for different coins and API keys. I run 5.


 ./zenbot.sh trade --conf=/zenbot0/conf0.js --period=1m --buy_pct=100 --sell_pct=100 --lock
 ./zenbot.sh trade --conf=/zenbot0/conf1.js --period=1m --buy_pct=100 --sell_pct=100 --lock
 ./zenbot.sh trade --conf=/zenbot0/conf2.js --period=1m --buy_pct=100 --sell_pct=100 --lock
 ./zenbot.sh trade --conf=/zenbot0/conf3.js --period=1m --buy_pct=100 --sell_pct=100 --lock
 ./zenbot.sh trade --conf=/zenbot0/conf4.js --period=1m --buy_pct=100 --sell_pct=100 --lock

But this is still giving the getbalance nonce error? Adjusting the time correctly using ntp seems to help.
Also setting period to 3m seems to help even more.

I guess poloniex has some type of IP-based flood protection.

I have no idea.. Still getting the nonce issue. But atleast now it's only the nonce issue.

UPDATE: 
I read somewhere that nonce is a generated with time, and for some reason poloniex takes 30 seconds to s send market data so I set my clock 30 seconds ahead about and did get some better results. 
zalaudekr commented 7 years ago

Had following problem with kraken:

Kraken API warning - unable to call trade (Error: Kraken API returned error: API:Invalid nonce), retrying in 0.15s

Increased the nonce window at Kraken API key settings to 360. No problems right now. I think the request takes to long to process and run into this timeout.

With Kraken - check status page https://status.kraken.com/ 👎

Update: It's no as often as before but still there. Very often if connection to Kraken had a problem Kraken API warning - unable to call getTrades (Connection between Cloudflare CDN and api.kraken.com failed), retrying in 0.15s Kraken API warning - unable to call trade (Error: Kraken API returned error: API:Invalid nonce), retrying in 0.15s

DeviaVir commented 7 years ago

Looks like a Kraken issue, closing this side of the equation.