Created
August 7, 2020 10:16
-
-
Save snowkidind/5adc755b1630e7dba4ca0cb2c7deaa53 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const chalk = require('chalk'); | |
const player = require('play-sound')(); | |
const eventManager = require('../operations/eventManager'); | |
const diagnostics = require('../utilities/diagnostics.js'); | |
const request = require('request'); | |
let executeTrades = true; | |
let lastBalanceTime = 0; | |
let lastBalance; | |
let lastBalanceToken; | |
let lastTickerTime = 0; | |
let lastTicker; | |
let candles = {}; | |
let markets = {}; | |
let klineEndpoint; | |
let tradesEndpoint; | |
let userDataEndpoint; | |
const logAllApiCalls = false; | |
let apiCallsCount = 1; | |
const binance = require('node-binance-api')().options({ | |
APIKEY: process.env.BINANCE_API_PUB, | |
APISECRET: process.env.BINANCE_API_PRIV, | |
useServerTime: true, // If you get timestamp errors, synchronize to server time at startup | |
verbose: false, | |
test: false // If you want to use sandbox mode where orders are simulated | |
}); | |
// playground for binance api | |
module.exports = { | |
// | |
executePermission(set) { | |
executeTrades = set; | |
}, | |
// | |
ticker: function (pair, cb) { | |
const time = new Date().getTime(); | |
if (time - lastTickerTime > 2000) { | |
// console.log("Get Ticker" + pair); | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " binance.prices: " + pair + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.prices(pair, (error, ticker) => { | |
if (error) { | |
console.log(pair); | |
console.log(chalk.red("binance.ticker error: " + error.body)); | |
cb(false); | |
} else { | |
lastTickerTime = new Date().getTime(); | |
lastTicker = ticker[pair]; | |
cb(ticker[pair]); | |
} | |
}); | |
} else { | |
// console.log("Using cached ticker"); | |
cb(lastTicker); | |
} | |
}, | |
// | |
allBalances: function (cb) { | |
binance.useServerTime(function(){ | |
binance.balance((error, balances) => { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " allBalances.balance: " + Date.now()); | |
apiCallsCount += 1; | |
} | |
if (error) { | |
if (typeof (error.body) !== 'undefined') { // JSON Syntax error - server sent bad data | |
let e = JSON.parse(error.body); | |
switch (e.code) { | |
case -1021: | |
console.log("Binance api had some issue: " + e.msg); | |
console.log("Fix: System Preferences - Date and time:"); | |
console.log("1. uncheck Set date and time automatically"); | |
console.log("2. check Set date and time automatically"); | |
process.exit(); | |
break; | |
default: | |
console.log("Binance api had some issue: " + e.code + ": " + e.msg); | |
} | |
} else { | |
console.log("Binance api sent a syntax error."); | |
console.log(error); | |
} | |
cb(); | |
} else { | |
cb(balances); | |
} | |
}); | |
}) | |
}, | |
// When the stop is reached, a stop order becomes a market order | |
setStopLoss: function (pair, q, limit, stopPrice, cb) { | |
let qty = q.toString(); | |
if (qty.charAt(qty.length - 1) === '.') { | |
qty = qty.slice(0, qty.length - 1); | |
} | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " setStopLoss.sell: " + pair + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
// console.log("Set Stop Loss: p", pair, "q", qty, "p", limit, stopPrice, " binance.js:68"); | |
if (executeTrades) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " setStopLoss.binance.sell - p: ", pair, " q: ", qty, " p: ", limit + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.sell(pair, qty, limit, {stopPrice: stopPrice, type: "STOP_LOSS_LIMIT"}, function (error, response) { | |
if (error) { | |
console.log(chalk.red("binance.setStopLoss: error: " + error.body)); | |
cb(error, false); | |
} else { | |
cb(null, response); | |
} | |
}); | |
} else { | |
console.log("Binance.js is unable to set a stop loss"); | |
} | |
}, | |
// | |
getAllOpenOrders: function (cb) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " getAllOpenOrders.openOrders - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.openOrders(false, (error, openOrders, symbol) => { | |
cb(openOrders); | |
}); | |
}, | |
// | |
cancelOrder: function (pair, orderId, cb) { | |
if (executeTrades) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " cancelOrder.cancel - " + pair + " id: " + orderId + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.cancel(pair, orderId, (error, response, symbol) => { | |
// console.log("Order Canceled"); | |
cb(error, response); | |
}); | |
} else { | |
console.log("Binance.js is unable to cancel orders"); | |
cb("Binance.js is unable to execute trades") | |
} | |
}, | |
marketSell: function (pair, q, callback) { | |
if (executeTrades) { | |
// rounding bug fix where decimal appears and binance doesnt like that | |
let qty = q.toString(); | |
if (qty.charAt(qty.length - 1) === '.') { | |
qty = qty.slice(0, qty.length - 1); | |
} | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " marketSell.marketSell - " + pair + " q: " + qty + " " + Date.now()); | |
apiCallsCount += 1; | |
} | |
// console.log("binance.marketSell: " + pair + " q: " + quantity + " disabled... l124") | |
binance.marketSell(pair, qty, function (error, response) { | |
const time = new Date().getTime(); | |
const date = new Date(time); | |
player.play('./sounds/hurt.mp3', (err) => { | |
if (err) console.log('Could not play sound: ${err}'); | |
}); | |
callback(error, response); | |
}); | |
} else { | |
console.log("Binance.js is unable to market sell: " + pair + " q:" + q); | |
// cb("Binance.js is unable to execute trades") | |
} | |
}, | |
marketBuy: function (pair, q, callback) { | |
if (executeTrades) { | |
let qty = q.toString(); | |
if (qty.charAt(qty.length - 1) === '.') { | |
qty = qty.slice(0, qty.length - 1); | |
} | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " marketBuy.marketBuy - " + pair + " q: " + qty + " " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.marketBuy(pair, qty, function (error, resp) { | |
if (error) { | |
console.log(chalk.red("Unable to place Market Buy: ", error.body.code, error.body.msg)); | |
// console.log("BinanceMarketBuyError: " + JSON.stringify(error)); | |
callback(error, resp); | |
} else { | |
player.play('./sounds/jump.wav', (err) => { | |
if (err) console.log('Could not play sound: ${err}'); | |
}); | |
callback(error, resp); | |
} | |
}); | |
} else { | |
console.log("Binance.js is unable to market buy: " + pair + " q:" + q); | |
callback("Binance.js is unable to execute trades") | |
} | |
}, | |
// | |
cancelAllNow: function (pair, cb) { | |
if (executeTrades) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " cancelAllNow.cancelOrders - " + pair + " " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.cancelOrders(pair, (error, response, symbol) => { | |
// console.log(chalk.green(symbol + " cancel all response:", Object.keys(response))); | |
// console.log(response); | |
cb(true); | |
}); | |
} else { | |
console.log("Binance.js is unable to cancel orders"); | |
cb("Binance.js is unable to execute trades"); | |
} | |
}, | |
// | |
getLastMinuteCandles: function (options, callback) { | |
options = options || {}; | |
pair = options.pair || "BTCUSDT"; | |
interval = options.interval || "1m"; | |
limit = options.lastMinuteCandles || 150; | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " getLastMinuteCandeles.candlesticks: " + options.pair + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.candlesticks(pair, interval, function (error, data) { | |
response = []; | |
for (let i = 0; i < data.length; i++) { | |
map = { | |
"time": isGoodData(data[i][0]), | |
"open": isGoodData(data[i][1]), | |
"high": isGoodData(data[i][2]), | |
"low": isGoodData(data[i][3]), | |
"close": isGoodData(data[i][4]), | |
"volume": isGoodData(data[i][5]), | |
"closeTime": isGoodData(data[i][6]), | |
"assetVolume": isGoodData(data[i][7]), | |
"trades": isGoodData(data[i][8]), | |
"buyBaseVolume": isGoodData(data[i][9]), | |
"buyAssetVolume": isGoodData(data[i][10]), | |
"ignored": isGoodData(data[i][11]), | |
"pair": pair | |
}; | |
response.push(map); | |
} | |
callback(error, response); | |
}, {limit: limit}); | |
}, | |
// | |
getLastCandlesInterval: function (options, callback) { | |
options = options || {}; | |
pair = options.pair || "BTCUSDT"; | |
interval = options.interval || "5m"; | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " getLastCandlesInterval.candlesticks: " + options.pair + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.candlesticks(pair, interval, function (error, data) { | |
// console.log(data) | |
response = []; | |
for (let i = 0; i < data.length; i++) { | |
map = { | |
"time": isGoodData(data[i][0]), | |
"open": isGoodData(data[i][1]), | |
"high": isGoodData(data[i][2]), | |
"low": isGoodData(data[i][3]), | |
"close": isGoodData(data[i][4]), | |
"volume": isGoodData(data[i][5]), | |
"closeTime": isGoodData(data[i][6]), | |
"assetVolume": isGoodData(data[i][7]), | |
"trades": isGoodData(data[i][8]), | |
"buyBaseVolume": isGoodData(data[i][9]), | |
"buyAssetVolume": isGoodData(data[i][10]), | |
"ignored": isGoodData(data[i][11]), | |
"pair": pair | |
}; | |
response.push(map); | |
} | |
callback(error, response); | |
}, {limit: 150}); | |
}, | |
// | |
latestPrice: function (pair, cb) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " latestPrice.prices: " + pair + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
binance.prices(pair, (error, ticker) => { | |
if (error){ | |
console.log("An error occured getting latest price: " + error); | |
diagnostics.connectivity(function(alive){ | |
if (!alive){ | |
console.log("A connectivity issue was discovered."); | |
// fallback on some other api that deals in tether... | |
} | |
}); | |
cb(error, null) | |
} else { | |
cb(null, ticker[pair]); | |
} | |
}); | |
}, | |
// | |
startTradeUpdates: function (pair) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " startTradeUpdates.websockets.trades: " + pair + " - " + Date.now()); | |
apiCallsCount += 1; | |
} | |
if (typeof(tradesEndpoint) === 'undefined') { | |
tradesEndpoint = binance.websockets.trades([pair], (tradesData) => { | |
eventManager.emitMessage('ticker', tradesData.p); | |
}); | |
} | |
}, | |
// | |
terminate: function () { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " terminates.websockets.terminate: " + Date.now()); | |
apiCallsCount += 3; | |
} | |
if (typeof(klineEndpoint) !== 'undefined') binance.websockets.terminate(klineEndpoint); | |
if (typeof(tradesEndpoint) !== 'undefined') binance.websockets.terminate(tradesEndpoint); | |
if (typeof(userDataEndpoint) !== 'undefined') binance.websockets.terminate(userDataEndpoint); | |
}, | |
// | |
// only fires when an action is taken | |
userData: function (cb) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " userData.websockets.userData: " + Date.now()); | |
apiCallsCount += 1; | |
} | |
userDataEndpoint = binance.websockets.userData(function (pkg) { | |
cb(pkg); | |
}) | |
}, | |
// | |
allOrders: function(pair, cb){ | |
binance.allOrders(pair, function(error, data){ | |
if (error){ | |
console.log("Error " + error); | |
} else { | |
data = data.reverse(); // newest orders at zero index | |
cb(error, data); | |
} | |
}, {limit: 15}); | |
}, | |
// | |
allOrdersNoLimit: function (pair, cb) { | |
binance.allOrders(pair, function (error, data) { | |
if (error) { | |
console.log("Error " + error); | |
} else { | |
data = data.reverse(); // newest orders at zero index | |
cb(error, data); | |
} | |
}); | |
}, | |
// | |
exchangeinfo: function (cb) { | |
if (logAllApiCalls) { | |
console.log(apiCallsCount + " exchangeInfo.exchangeInfo: " + Date.now()); | |
apiCallsCount += 1; | |
} | |
let url = 'https://api.binance.com/api/v1/exchangeInfo'; | |
request(url, function (error, response) { | |
cb(error, JSON.parse(response.body)) | |
}); | |
}, | |
// | |
// subscriptions: function (cb) { | |
// console.log("Calling for subs"); | |
// if (logAllApiCalls) { | |
// console.log(apiCallsCount + " subscriptions.websockets.subscriptions: " + Date.now()); | |
// apiCallsCount += 1; | |
// } | |
// binance.websockets.subscriptions(function (subs) { | |
// console.log("returning subs", subs); | |
// cb(subs); | |
// }); | |
// } | |
}; | |
function isGoodData(d) { | |
if (typeof (d) !== 'undefined') { | |
return d; | |
} else { | |
console.log("dataGlitch: " + d); | |
return 0.0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment