Um bot simples de negociação de criptomoedas

Olá pessoal! Hoje vamos escrever nosso primeiro robô comercial de combate para jogar na bolsa de valores. Troca de criptografia. Por que troca de criptomoeda?


a) tema de hype;
b) são de alguma forma mais simples.


Em primeiro lugar, quero avisar imediatamente os fãs do cassino dos Três Machados: você não ganhará um carro amanhã. O artigo é mais sobre como começar a escrever seus robôs, para que o algoritmo seja primitivo, mas funcione.


Em segundo lugar, você ganhará. Só um pouquinho.


C / f “O jogo da queda” (2015)
- Esse cheiro, o que é? Como cheira?
Colônia?
- Não ...
- Oportunidades?
- não. Dinheiro
- Oh ... está tudo claro
- O cheiro de dinheiro!
Entendo.

Para os mais impacientes, todo o código no github exmo-exchange-trade-bot .


Etapa 1: Troca.


Vamos negociar na bolsa EXMO. Existem várias razões. A troca é popular na CEI, é de língua russa e suporta a entrada de rublos, tem a capacidade de criar pares para o rublo.


Entre as desvantagens estão o inconveniente processo de depositar rublos, uma comissão decente, poucos pares negociados.


Para nós, o principal é que ele possui soluções prontas para trabalhar com sua API. Isso certamente facilitará nosso trabalho.


Então, vamos começar.


Obviamente, você precisa se registrar na bolsa de valores e depositar algum dinheiro. Por exemplo, eu contribuí com US $ 5.


Além disso, em sua conta, você receberá chaves para acessar a API.


Usarei o cliente para o NodeJS (portanto, você precisará instalar o nodejs e o npm).


No seu computador, crie uma nova pasta e um arquivo no qual nosso robô de negociação será (por exemplo, exmo / index.js), abra o console e faça os últimos preparativos padrão.


Nós vamos para a pasta com o nosso projeto e escrevemos - npm init, depois pressione enter para todas as perguntas.


Em seguida, escrevemos


npm install exmo-api 

Enquanto os pacotes estão sendo instalados, crie outro arquivo, chame-o de exmo.js e preencha-o com este conteúdo.


com esses conteúdos
 var CryptoJS = require("crypto-js") http = require('http'), querystring = require('querystring'), request = require('request'), config = { url: 'https://api.exmo.me/v1/' }; function sign(message){ return CryptoJS.HmacSHA512(message, config.secret).toString(CryptoJS.enc.hex); } exports.init_exmo = function (cfg) { config.key = cfg.key; config.secret = cfg.secret; config.nonce = Math.floor(new Date().getTime()*1000); }; exports.api_query = function(method_name, data, callback){ data.nonce = config.nonce++; var post_data = querystring.stringify(data); var options = { url: config.url + method_name, method: 'POST', headers: { 'Key': config.key, 'Sign': sign(post_data) }, form:data }; request(options, function (error, response, body) { if (!error && response.statusCode == 200) { callback(body); }else{ callback(error); } }); }; exports.api_query2 = function(method_name, data, callback){ data.nonce = config.nonce++; var post_data = querystring.stringify(data); var post_options = { host: 'api.exmo.me', port: '80', path: '/v1/' + method_name, method: 'POST', headers: { 'Key': config.key, 'Sign': sign(post_data), 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(post_data) } }; var post_req = http.request(post_options, function(res) { res.setEncoding('utf8'); res.on('data', function (chunk) { callback(chunk); }); }); post_req.write(post_data); post_req.end(); }; exports.test = function(){ return config.key; }; 

Este arquivo contém o endereço da API, a conexão de bibliotecas adicionais necessárias para trabalhar com a API e a principal função para solicitações à API.


É tudo, nós preparamos tudo e agora podemos começar diretamente a criar uma “máquina de fazer dinheiro” pessoal;)


Etapa 2: Código


Abra nosso index.js e conecte o arquivo exmo.js:


 const exmo = require("./exmo"); 

Em seguida, vá para a troca em sua conta pessoal para o local em que criamos nossas chaves para acessar a API. Nós os copiamos e salvamos em variáveis:


 const apiKey = ' '; const apiSecret = ' '; 

Agora crie duas variáveis:
currency1 é o que compramos;
currency2 - moeda pela qual estamos comprando.


Quero comprar bitcoins por dólares:


 const currency1 = 'BTC'; const currency2 = 'USD'; 

A seguir, um ponto importante - criamos uma variável com um valor mínimo de aposta. A troca não permite comprar menos que esse valor.


Vamos para o endereço https://api.exmo.com/v1/pair_settings/, procuramos seu par (para mim é BTC_USD) e olhamos para o primeiro parâmetro - min_quantity - 0,001


 const currency1MinQuantity = 0.001; 

E mais algumas variáveis:


o número de minutos após os quais um pedido não atendido será cancelado na moeda1


 const orderLifeTime = 3; 

comissão de câmbio (0,002 = 0,2%)


 const stockFee = 0.002; 

período de tempo (em minutos) para calcular o preço médio (isso será necessário para o nosso algoritmo)


 const avgPricePeriod = 1; 

a quantidade de moeda2 para comprar a moeda1 em uma transação única (joguei US $ 5 - operarei com eles)


 const canSpend = 5; 

o valor desejado de lucro de cada transação (0,001 = 0,1%)


 const profit = 0.001; 

Se o tempo de troca diverge do atual


 const stockTimeOffset = 0; 

Por conveniência, combinamos nosso par através de _


 let currentPair = currency1+'_'+currency2; 

Inicialize a conexão.


 exmo.init_exmo({key:apiKey, secret:apiSecret}); 

Para o teste, você pode solicitar informações sobre si mesmo:


 exmo.api_query("user_info", { }, result => console.log(result);); 

Vá para o console e execute


 node index.js 

Se tudo for feito corretamente, você verá informações sobre você!


Tudo funciona e você pode passar para a parte mais interessante - a função que as avós irão gerar para nós.


Então, eu já disse acima que nosso algoritmo será estúpido, agora você entenderá quanto)


O truque é levar o histórico de transações concluídas para qualquer período - nós temos a variável avgPricePeriod responsável por isso - e calcular o preço médio pela qual a moeda1 foi vendida. Por esse preço médio, faremos nosso pedido.


Então, vamos começar. Escrevemos nossa função trade ()


 function trade(){} 

Primeiro, obtemos uma lista de nossos pedidos em aberto:


1) verificamos se temos pedidos abertos para o nosso par usando o método da API user_open_orders. Se houver também à venda,


então apenas esperamos que eles sejam cumpridos (às vezes até o fim dos tempos). Se houver pedidos, lembre-se deles.


 exmo.api_query("user_open_orders", { }, result => { let res = JSON.parse(result); if(res[currentPair] == undefined) console.log('  '); let buyOrders = []; for(let i in res[currentPair]){ console.log(res[currentPair][i]); if(res[currentPair][i].type == 'sell'){ console.log(',    /    '); }else{ buyOrders.push(res[currentPair][i]); } } 

2) Verificamos se temos pedidos de compra abertos.


Classificamos todos os pedidos e obtemos um histórico deles usando o método order_trades , passando o ID do pedido para lá.


Pode haver três opções:


 if(buyOrders.length > 0){ for(let key in buyOrders){ console.log(',     ', buyOrders[key]['order_id']); exmo.api_query('order_trades', {"order_id": buyOrders[key]['order_id']}, result => { let res = JSON.parse(result); 

1) podemos comprar a moeda necessária não no todo, mas em partes de pedidos de vendedores.
Portanto, se já compramos pelo preço desejado, aguardamos a compra de todo o valor.


 if(res.result !== false){ console.log(',       ,     '); } 

2) com a segunda opção, precisamos verificar se nosso pedido está atrasado demais. Os preços mudam rapidamente e talvez o preço médio não seja mais relevante. Para isso, criamos a variável orderLifeTime, na qual indicamos quanto o nosso pedido deve demorar em minutos.


Se o tempo acabar, cancele o pedido usando o método order_cancel , passando o ID do pedido.


 let timePassed = (new Date().getTime() / 1000) + stockTimeOffset * 60 * 60 - (buyOrders[key]['created']); if(timePassed > orderLifeTime * 60){ exmo.api_query('order_cancel',{"order_id":buyOrders[key]['order_id']}, res => { let result = JSON.parse(res); if(result.error) console.log(result.error); console.log(`   ${orderLifeTime}     ${currency1}`); }); }else{ 

3) se o tempo ainda não chegou, esperamos que possamos comprar pelo nosso preço.


 console.log(`,        ,      ${timePassed} `); } } }); } }else{ 

Tudo, descobrimos pedidos em aberto, agora o nosso robô sabe o que fazer com os pedidos quando os cria. Metade do trabalho feito.


Então, um bloco se não tivermos pedidos.


Obtemos informações sobre nossa conta usando o método user_info :


 exmo.api_query('user_info',{},(result)=>{ let res = JSON.parse(result); 

Por conveniência, anotamos saldos para nossos pares:


 let balance = res.balances[currency1]; let balance2 = res.balances[currency2]; 

Verifique se existe uma moeda1 que possa ser vendida?


 if(balance >= currency1MinQuantity){} 

Nesse caso, precisamos calcular a taxa de venda.


Você precisa vender toda a moeda que comprou, o valor que comprou mais lucro menos a comissão de câmbio.


Um ponto importante! Temos menos moedas do que compramos - a bolsa levou uma comissão.


 let wannaGet = canSpend + canSpend * (stockFee+profit); console.log('sell', balance, wannaGet, (wannaGet/balance)); 

Ao criar pedidos, o método order_create precisa receber os parâmetros:


  • par é o nosso par atual para negociação;
  • quantidade - quantidade;
  • preço - preço;
  • tipo - tipo do pedido criado (compra / venda);

Queremos vender - do tipo que especificamos vender .


 let options = { "pair": currentPair, "quantity": balance, "price": wannaGet / balance, "type": 'sell' }; 

e enviar uma solicitação, se tudo estiver correto, você verá a entrada "Uma ordem de venda foi criada"


 exmo.api_query("order_create", options,(result)=>{ if(result.error) console.log(result.error); console.log("   ", currency1, result.order_id); }); 

Só isso. Se tivéssemos uma moeda, simplesmente criamos um pedido para vendê-la.


Agora, passamos ao bloco mais interessante: o caso, se não tivermos a moeda1 (btc) e quisermos comprá-lo para a nossa moeda2 (usd).


Primeiro, verifique se há dinheiro suficiente no balanço na moeda2.


 if(balance2 >= canSpend){} 

Se houver, precisamos obter o preço médio pelo qual a moeda1 (btc) é vendida pelo período especificado em avgPricePeriod .


Um pouco de letra:
Exmo tem um método de ticker com estatísticas e volumes de negociação para pares de moedas. As estatísticas mostram o preço médio nas últimas 24 horas. No entanto, a diferença entre o preço médio e o preço em que o leilão está sendo realizado pode ser muito diferente.


Por esse motivo, podemos esperar muito tempo pela execução de uma ordem de venda.


Nós vamos fazer a nossa bicicleta.


Exmo tem um método de negociação , retorna uma lista de transações para um par de moedas.


Tomaremos a oferta perfeita para o avgPricePeriod do qual estamos interessados ​​e, a partir deles, calcularemos o preço médio.


Esta não é uma opção ideal, mas mostrará os preços reais pelos quais eles vendem e compram.


Por exemplo, no momento da redação deste artigo, o preço médio do BTC_USD é 8314, enquanto a compra na bolsa é realizada ao preço de 7970.


Se fizermos um pedido a um preço médio, ele será imediatamente executado pelo preço mínimo indicado nas ordens de venda.


Mas, adicionando lucro e comissão de câmbio, é provável que esperemos muito tempo pela venda.


Então, vejamos o método de negociação e solicitamos estatísticas sobre nosso par atual de pares:


 exmo.api_query("trades",{"pair":currentPair}, result => { let res = JSON.parse(result); let prices = []; let summ = 0; 

Examinaremos todos os resultados e deixaremos apenas aqueles adequados ao nosso período de tempo.


 for(deal in res[currentPair]){ let timePassed = (new Date().getTime() / 1000) + stockTimeOffset * 60 * 60 - res[currentPair][deal].date; if(timePassed < avgPricePeriod * 60){ summ += parseInt(res[currentPair][deal].price); prices.push(parseInt(res[currentPair][deal].price)); } } 

E calcule o preço médio.


 let avgPrice = summ2 / prices.length; 

Temos um preço médio, mas precisamos corrigi-lo um pouco - subtraia a comissão de câmbio da stockFee e adicione o lucro desejado. Assim, tendo recebido um preço abaixo do preço médio de mercado, compraremos um pouco mais de moeda, uma vez que a bolsa posteriormente faz parte dela;


 let needPrice = avgPrice - avgPrice * (stockFee + profit); 

Recebemos o valor final que precisamos comprar.


 let ammount = canSpend / needPrice; console.log('Buy', ammount, needPrice); 

Verificamos se é possível comprar uma quantia dessa moeda (o valor mínimo de compra não é violado).


 if(ammount >= currency1MinQuantity){} 

Se nossa quantidade for maior, formaremos os parâmetros para o método order_create , somente desta vez com o tipo de compra .


  let options = { "pair": currentPair, "quantity": ammount, "price": needPrice, **"type": 'buy'** }; exmo.api_query('order_create', options, res => { let result = JSON.parse(res); if(result.error) console.log(result.error); console.log('   ', result.order_id); }); }else{ console.log(',      '); } }); }else{ console.log(',   '); } 

Agora precisamos colocar nossa função no cronômetro (o intervalo é uma vez a cada 5 segundos, por exemplo) e podemos executá-lo.


 var timerId = setTimeout(function tick() { trade(); timerId = setTimeout(tick, 5000); }, 5000); 

 node index.js 

Parabéns, você escreveu seu primeiro robô de negociação: você pode terminar o algoritmo e ganhar muito dinheiro) brincando .


Eu acho que você tem uma pergunta razoável: "Quanto dinheiro você pode ganhar dessa maneira?"


Para uma operação com US $ 5, ganho cerca de 2-3 centavos. Isso se deve à primitividade do algoritmo, que funciona se o preço flutuar em um determinado intervalo (e isso quase sempre não é o caso nas trocas de criptomoedas). Cerca de 10 a 20 operações ocorrem por dia (com boas mãos). Você pode contar a si mesmo;)


Mas não estamos dominando o código por uma questão de dinheiro)


Mais uma vez, um link para o github com a versão completa do bot e comentários.
https://github.com/v-florinskiy/exmo-exchange-trade-bot


Este é o meu primeiro artigo - não julgue estritamente)


Todo o lucro.


PS: Para aqueles que não trabalharam com o nó, seu script funcionará naturalmente enquanto o console estiver aberto.


Para o seu robô funcionar 24/7, você precisa de algum tipo de vps: lá você coloca nodejs, npm e, por exemplo, pm2. Usando esse utilitário, o script continuará funcionando, mesmo se o console estiver fechado.

Source: https://habr.com/ru/post/pt416073/


All Articles