Last active
February 6, 2019 08:59
-
-
Save welblaud/00175194481668e04f2be130d8017d18 to your computer and use it in GitHub Desktop.
App for trading on gate.io forex market
This file contains 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
// newBot.js | |
/* ##################### MODULES ####################### */ | |
let fetch = require( 'node-fetch' ); | |
let fs = require( 'fs' ); | |
let crypto = require( 'crypto' ); | |
let querystring = require( 'querystring' ); | |
/* ##################### CONSTANTS ####################### */ | |
const KEY = ''; | |
const SECRET = ''; | |
const pairs = [ ['btc_usdt', 0.0018], ['eth_usdt', 0.028], ['etc_usdt', 1] ]; | |
const logPath = '/home/bob/git/Gate.io/app/log/log.txt'; | |
const MARKETINFO_URL = 'api2/1/marketinfo'; | |
const MARKETLIST_URL = 'api2/1/marketlist'; | |
const API_QUERY_URL = 'https://data.gate.io/'; | |
const API_TRADE_URL = 'https://api.gate.io/'; | |
const BUY_URL = 'api2/1/private/buy'; | |
const SELL_URL = 'api2/1/private/sell'; | |
const GETORDER_URL = 'api2/1/private/getOrder'; | |
const OPENORDERS_URL = 'api2/1/private/openOrders'; | |
const CANCELORDER_URL = 'api2/1/private/cancelOrder'; | |
const CANCELALLORDERS_URL = 'api2/1/private/cancelAllOrders'; | |
const TICKER_URL = 'api2/1/ticker'; | |
const USER_AGENT = ''; | |
/* ##################### ORDER LISTS ####################### */ | |
let ordersBuy = []; | |
let ordersSell = []; | |
/* ################### MAKING BUSINESS ##################### */ | |
// businessmanBot( 'eth_usdt', 0.028 ) | |
for (pair of pairs) { | |
let code = pair[0]; | |
let amount = pair[1]; | |
businessmanBot( code, amount ) | |
} | |
/* ################################################################################################# * | |
* +++++++++++++++++++++++++++++++++++++++++ THE BOT +++++++++++++++++++++++++++++++++++++++++++++++ * | |
* ################################################################################################# */ | |
async function businessmanBot( currencyPair, amount ) { | |
// Čistíme log před každým cyklem. | |
await cleanLog(); | |
// Nastavujeme interval na 10 vteřin | |
// a spouštíme bota. | |
setInterval( function() { doBusiness( currencyPair, amount ) }, 10000 ); | |
} | |
// Hlavní funkce bota | |
async function doBusiness( currencyPair, amount ) { | |
// Získáváme info o tickeru a nastavujeme hodnoty. | |
let tickerInfo = await fetch( API_QUERY_URL + TICKER_URL + '/' + currencyPair, { method: 'GET', headers: { 'User-Agent': USER_AGENT } }).catch(err => console.log(err)); | |
let tickerJSON = await tickerInfo.json(); | |
let lowestAsk = await tickerJSON.lowestAsk; | |
let highestBid = await tickerJSON.highestBid; | |
let rate = await highestBid + 0.01; | |
let percentDiff = await ( lowestAsk - highestBid ) / lowestAsk * 100; | |
let datum = new Date(); | |
datum = 'Čas: ' | |
+ datum.getFullYear().toString() | |
+ '-' + (datum.getMonth() + 1).toString() | |
+ '-' + datum.getDate().toString() | |
+ ' ' + (datum.getHours().toString().length === 1 ? '0' + datum.getHours().toString() : datum.getHours().toString()) | |
+ ':' + (datum.getMinutes().toString().length === 1 ? '0' + datum.getMinutes().toString() : datum.getMinutes().toString()) | |
+ ':' + (datum.getSeconds().toString().length === 1 ? '0' + datum.getSeconds().toString() : datum.getSeconds().toString()); | |
// Jestliže je rozdíl mezi lowestAsk a highestBid větší než 0.4, kupujeme. | |
if (( percentDiff !== undefined ) && ( percentDiff > 0.5 )) { | |
log( | |
'\n###########################\n' | |
+ '| ' + datum + ' |\n' | |
+ '---------------------------\n' | |
+ '| currencyPair: ' + currencyPair + '\n' | |
+ '| lowestAsk: ' + lowestAsk + '\n' | |
+ '| highestBid: ' + highestBid + '\n' | |
+ '| rate: ' + rate.toFixed(2) + '\n' | |
+ '| percentDiff: ' + percentDiff.toFixed(4) + '\n' | |
+ '---------------------------' | |
); | |
// Provádíme nákup, informace o orderu ukládáme do proměnné (buyOrder). | |
let buyOrder = await placeOrder ( currencyPair, rate, amount ); | |
// Pokud je něco špatně (např. došly peníze na účtu), logujeme a zastavujeme bota. | |
if ( buyOrder.status !== true || buyOrder.orderNumber === undefined ) { | |
log( 'Něco je špatně, order nebyl umístěn: ' + buyOrder.status); | |
//stopTimer(intID); | |
} else if ( buyOrder.status === true && buyOrder.orderNumber !== undefined ) { | |
// Ověřujeme stav orderu. | |
let verifyOrder = await orderInfo( buyOrder.orderNumber, currencyPair ); | |
// Jestliže je rozdíl mezi aktuálně zjištěnou rate (verifyOrder) a původní highestBid roven 0.01 (cent)... | |
if (( verifyOrder.rate !== undefined ) && (( verifyOrder.rate - highestBid ) === 0.01 )) { | |
// ... vše je v pořádku a informace o orderu (buyOrder) umisťujeme do seznamu pro BUY ordery. | |
ordersBuy.push( await buyOrder ); | |
// Logujeme. | |
await log( | |
'\n----------------------------\n' | |
+ 'Order BUY umístěn: ' + buyOrder.oderNumber + '\n' | |
); | |
// Jinak... | |
} else { | |
// ... rušíme order. | |
await cancelOrder( buyOrder.orderNumber, currencyPair ); | |
// Logujeme. | |
await log( 'Order BUY zrušen: ' + buyOrder.oderNumber + '\n' ); | |
} // end ELSE | |
} else { | |
console.log('Došlo k jinému problému. Log ř. 124.'); | |
} | |
} else if ( percentDiff === undefined ) { | |
log('Problém se získáním percentDiff!\n'); | |
} // end IF/ELSE | |
// V tuto chvíli by měl být order v seznamu (BUY) a čekat na další akce. Pokud jsme ho rušili, | |
// do seznamu (BUY) zařazen nebyl. | |
/* ####################### BUY LOOP ###################### */ | |
// Pro každý order zařazený do seznamu pro BUY ordery (v minulém cyklu i teď). | |
ordersBuy.forEach(async (buy, index) => { | |
// Zjišťumjeme aktuální stav orderu. | |
let orderState = await orderInfo( buy.orderNumber, currencyPair ); | |
orderState = await orderState; | |
// Jestliže je order closed a amount byla rovna initial_amount... | |
if (( orderState.status === 'closed' ) | |
&& ( orderState.amount === orderState.initial_amount )) { | |
// ... zjišťujeme aktuální rozdíl mezi původní zadávanou rate (pro BUY) a současnou rate. | |
let sellRate = lowestAsk - 0.01; | |
let sellPerc = ( buy.rate- sellRate ) / buy.rate * 100; | |
// Jestliže je rozdíl mezi oběma rate větší než 0.25 %... | |
if ( sellPerc > 0.25 ) { | |
// Prodáváme (SELL), čáska je rovna částce z informace v orderState, měla by být | |
// navíc rovna rate BUY orderu (jak je uvedeno v podmínce). | |
let sellOrder = await orderSell( currencyPair, sellRate, orderState.amount ); | |
sellOrder = await sellOrder; | |
// Order hned ověřujeme. | |
let verifyOrder = await orderInfo( sellOrder.orderNumber, currencyPair ); | |
verifyOrder = await verifyOrder; | |
// Jestliže je rozdíl mezi aktuálně zjištěnou rate (verifyOrder) a původní highestBid roven 0.01 (cent)... | |
if (( verifyOrder.rate - highestBid ) === 0.01 ) { | |
// ... zařazujeme order do seznamu (SELL) pro SELL ordery a současně mažeme | |
// order (BUY) ze seznamu pro BUY ordery. | |
ordersSell.push( await sellOrder ); | |
ordersBuy.splice( index, 1 ); | |
// Logujeme. | |
await log( 'Order SELL umístěn: ' + sellOrder.oderNumber + '\n' ); | |
// Jinak... | |
} else { | |
// ... rušíme order (SELL). | |
// #### Tady je otázka, co se má stát dál [prodali jsme, ale nejso podmínky pro orderSELL] | |
await cancelOrder( sellOrder.orderNumber, currencyPair ); | |
// Logujeme. | |
await log( 'Order SELL zrušen: ' + sellOrder.oderNumber + '\n' ); | |
} // end ELSE | |
} // end IF | |
// Jestliže je order open (visí) a odkoupená částka je nižší než částka zamýšlená (initial_amount), | |
// navíc pokud z daného orderu (BUY) ještě nebyl proveden order (SELL)... | |
} else if (( orderState.status === 'open' ) | |
&& ( orderState.amount < orderState.initial_amount ) | |
&& ( buy.remainder === undefined )) { | |
// ... zjišťujeme aktuální rozdíl mezi původní zadávanou rate (pro BUY) a současnou rate. | |
let sellRate = lowestAsk - 0.01; | |
let sellPerc = ( buy.rate- sellRate ) / buy.rate * 100; | |
// Jestliže je rozdíl mezi oběma rate větší než 0.25 %... | |
if ( sellPerc > 0.25 ) { | |
// Prodáváme (SELL), čáska je rovna částce z informace v orderState, | |
// protože je to částka, která už byla využita (nakoupeno) [ošetření zbytku níže]. | |
let sellOrder = await orderSell( currencyPair, rate, orderState.amount ); | |
sellOrder = await sellOrder; | |
let verifyOrder = await orderInfo( sellOrder.orderNumber, currencyPair ); | |
verifyOrder = await verifyOrder; | |
// Jestliže je rozdíl mezi aktuální rate a highestBid zjištěnou na začátku cyklu 0.01 (cent)... | |
if (( verifyOrder.rate - highestBid ) === 0.01 ) { | |
// ... do informace pro daný order (BUY) přidáváme informaci o převisu, | |
// současně zařazujeme nový order (SELL) do seznamu pro SELL ordery. | |
buy.remainder = orderState.initial_amount - orderState.amount; | |
ordersSell.push( await sellOrder ); | |
// Logujeme. | |
await log( 'Order SELL umístěn: ' + sellOrder.oderNumber + '\n' ); | |
// Jinak... | |
} else { | |
// ... rušíme order (SELL). | |
await cancelOrder( sellOrder.orderNumber, currencyPair ); | |
// Logujeme. | |
await log( 'Order SELL zrušen: ' + sellOrder.oderNumber + '\n' ); | |
} // end ELSE | |
} // end IF | |
// Jestliže je order open (visí) a odkopená částka je nižší než částka zamýšlená (initial_amount), | |
// navíc pokud už byl z daného orderu (BUY) proveden v předchozím kole order (SELL), | |
// k tomu ještě pokud je zbytek (převis) nevyužitý pro order (SELL) z minulého kola větší | |
// než zbytek (převis) současný (což znamená, že došlo k dalšímu nákupu [využití initial_amount] | |
// bez toho, aby se vyčerpal celý zbytek a order byl closed)... | |
} else if (( orderState.status === 'open' ) | |
&& ( orderState.amount < orderState.initial_amount ) | |
&& ( buy.remainder !== undefined ) | |
&& ( buy.remainder > ( orderState.initial_amount - orderState.amount ))) { | |
// ... zjišťujeme aktuální rozdíl mezi původní zadávanou rate (pro BUY) a současnou rate. | |
let sellRate = lowestAsk - 0.01; | |
let sellPerc = ( buy.rate - sellRate ) / buy.rate * 100; | |
// Jestliže je rozdíl mezi oběma rate větší než 0.25 %... | |
if ( sellPerc > 0.25 ) { | |
// Prodáváme (SELL), čáska by měla odpodívat rozdílu mezi nově zjištěným | |
// rozdílem v částkách (amountDiff = amount vs initial_amount) a původním | |
// zbytkem (převisem [remainder]) pro daný order (BUY). | |
let sellOrder = await orderSell( currencyPair, rate, newRemainder ); | |
sellOrder = await sellOrder; | |
let verifyOrder = await orderInfo( sellOrder.orderNumber, currencyPair ); | |
verifyOrder = await verifyOrder; | |
let amountDiff = await orderState.initial_amount - orderState.amount; | |
let newRemainder = await buy.remainder - amountDiff; | |
buy.remainder = await newRemainder; | |
ordersSell.push( await sellOrder ); | |
// Jestliže je rozdíl mezi aktuální rate a highestBid zjištěnou na začátku cyklu 0.01 (cent)... | |
if (( verifyOrder.rate - highestBid ) === 0.01 ) { | |
// ... v informacích pro daný order (BUY) aktualizujeme částku převisu, | |
// současně zařazujeme nový order (SELL) do seznamu pro SELL ordery. | |
buy.remainder = newRemainder; | |
ordersSell.push( await sellOrder ); | |
// Logujeme. | |
await log( 'Order SELL umístěn: ' + sellOrder.oderNumber + '\n' ); | |
// Jinak... | |
} else { | |
// ... rušíme order (SELL). | |
await cancelOrder( sellOrder.orderNumber, currencyPair ); | |
// Logujeme. | |
await log( 'Order SELL zrušen: ' + sellOrder.oderNumber + '\n' ); | |
} // end ELSE | |
} // end IF | |
} // end ELSE IF | |
}) // end forEach() for BUY array | |
/* ####################### SELL LOOP ###################### */ | |
// Pro každý order zařazený do seznamu pro SELL ordery (v minulém cyklu i teď). | |
ordersSell.forEach(async (sell, index) => { | |
// Zjišťumjeme aktuální stav orderu. | |
let orderState = await orderInfo( sell.orderNumber, currencyPair ); | |
orderState = await orderState; | |
if (( orderState.status === 'closed' )) { | |
// Je-li order SELL v pořádku celý uzavřen, mažeme ho ze seznamu. | |
ordersSell.splice( index, 1 ); | |
// Logujeme. | |
await log( 'Order SELL closed v pořádku: ' + sellOrder.oderNumber + '\n' ); | |
// Jestliže není rozdíl mezi aktuální rate a highestBid zjištěnou na začátku cyklu 0.01 (cent)... | |
} else if (( orderState.status === 'open' ) | |
&& (( orderState.rate - highestBid ) !== 0.01 )) { | |
// ... rušíme order (SELL). | |
await cancelOrder( sell.orderNumber, currencyPair ); | |
// Současně odstraňujeme order (SELL) ze seznamu pro SELL ordery. | |
ordersSell.splice( index, 1 ); | |
// Logujeme. | |
await log( 'Order SELL zrušen kvůli rate: ' + sellOrder.oderNumber + '\n' + (orderState.rate - highestBid) ); | |
} // end ELSE IF | |
// Další akce už by neměly být třeba, protože buď se order (SELL) uzavřel | |
// a vše proběhlo úspěšně, nebo visí. Pokud je rozdíl mezi aktuální rate | |
// a highestBid zjištěnou na začátku 0.01, je vše v pořáku a order doběhne, | |
// v opačném případě je stornován. | |
}) // end forEach() for SELL array | |
} // end doBusiness() | |
/* ################################################################################################# * | |
* +++++++++++++++++++++++++++++++++++++++++ HELPERS +++++++++++++++++++++++++++++++++++++++++++++++ * | |
* ################################################################################################# */ | |
// STOP TIMER | |
function stopTimer(timerID) { | |
clearInterval(timerID); | |
} | |
// CLEAN LOG | |
function cleanLog() { | |
// Clean the file only if the overall size exceedes cca 0.5MB. | |
fs.stat( logPath, function (err, stats) { | |
if (stats.size > 500000) { | |
fs.writeFile( logPath, '', | |
function errLog( err ) { | |
if ( err ) { | |
console.log( err ); | |
log( err ); | |
} // end IF | |
} // end FUNCT | |
) // end writeFile | |
} // end IF | |
}) // end FS.STAT | |
} // end cleanLog | |
// LOG | |
function log( message ) { | |
console.log( message ); | |
fs.appendFile( logPath, | |
message, function errLog( err ) { | |
if ( err ) { | |
console.log( err ); | |
log( err ); | |
} // end IF | |
} // end FUNCT | |
) // end appendFile | |
} | |
// GET SIGN | |
async function getSign( form ) { | |
return await crypto.createHmac( 'sha512', SECRET ).update( form ).digest( 'hex' ).toString(); | |
} | |
// PLACE ORDER | |
async function placeOrder ( currencyPair, rate, amount ) { | |
let form = { 'currencyPair': currencyPair, 'rate': rate, 'amount': amount }; | |
let header = {}; | |
header.KEY = KEY; | |
header.SIGN = await getSign(querystring.stringify(form)); | |
let orderRes = await fetch(API_TRADE_URL + BUY_URL, { method: 'POST', headers: header, form: form } ); | |
orderRes = orderRes.json(); | |
return orderRes; | |
} | |
// ODER INFO | |
async function orderInfo ( orderNumber, currencyPair ) { | |
if (orderNumber !== undefined) { | |
let form = { 'currencyPair': currencyPair, 'orderNumber': orderNumber }; | |
let header = { 'Content-Type': 'application/x-www-form-urlencoded' }; | |
header.KEY = KEY; | |
header.SIGN = await getSign(querystring.stringify(form)); | |
let orderRes = await fetch(API_TRADE_URL + GETORDER_URL, { headers: { 'User-Agent' : USER_AGENT } } ); | |
orderRes = orderRes.json(); | |
return orderRes; | |
} else { | |
console.log('Nemáme číslo orderu!'); | |
} | |
} | |
// CANCEL ORDER | |
async function cancelOrder ( orderNumber, currencyPair ) { | |
let form = { 'currencyPair': currencyPair, 'orderNumber': orderNumber }; | |
let header = { 'Content-Type': 'application/x-www-form-urlencoded' }; | |
header.KEY = KEY; | |
header.SIGN = await getSign(querystring.stringify(form)); | |
let orderRes = await fetch(API_TRADE_URL + CANCELORDER_URL, { method: 'POST', headers: header, form: form } ); | |
orderRes = orderRes.json(); | |
return orderRes; | |
} | |
// ORDER SELL | |
async function orderSell ( currencyPair, rate, amount ) { | |
let form = { 'currencyPair': currencyPair, 'rate': rate, 'amount': amount }; | |
let header = {}; | |
header.KEY = KEY; | |
header.SIGN = await getSign(querystring.stringify(form)); | |
let orderRes = await fetch(API_TRADE_URL + SELL_URL, { method: 'POST', headers: header, form: form } ); | |
orderRes = orderRes.json(); | |
return orderRes; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment