Como criar um bot trader para Binance Futures em Node.js - Parte 2

Cripto

Como criar um bot trader para Binance Futures em Node.js - Parte 2

Luiz Duarte
Escrito por Luiz Duarte em 10/11/2022
Junte-se a mais de 34 mil devs

Entre para minha lista e receba conteúdos exclusivos e com prioridade

Recentemente escrevi um tutorial ensinando o início de um projeto de bot cripto para o mercado futuros da Binance. Você confere este tutorial neste link. A ideia neste post é dar continuidade àquele tutorial mostrando como você pode abrir e fechar posições nos contratos futuros perpétuos do tipo USD-M, ou seja, pareados com stablecoins “dolarizadas”. Talvez o que vou mostrar aqui também sirva para outros tipos de contratos, mas não posso garantir nada pois nunca operei neles.

É importante que você entenda como funciona o mercado Futuro, em específico o da Binance, antes de implementar as operações. Isso porque operar no mercado futuro pode ser muito lucrativo mas é extremamente arriscado e mais complexo do que operar no mercado Spot (à vista). Aqui, ao invés de comprar um ativo e segurar ele até se valorizar, operando sempre comprado, no mercado futuro você pode abrir posições em contratos tanto comprado (long) quanto vendido (short), além de poder operar alavancado (leverage), ou seja, multiplicando “artificialmente” o seu patrimônio investido e consequentemente tendo lucros (ou prejuízos) muito maiores (PnL ou profits and losses).

O que quero alertar, além do risco em si, é que foge do escopo deste tutorial ensinar trading neste mercado, vou me ater única e exclusivamente ao ensino da construção do bot, ok?

É importante frisar também que existem muitas combinações possíveis para a construção das ordens de compra e venda, que são extremamente customizáveis e exigiriam muitos e muitos artigos e/ou vídeos ensinando todas elas, um verdadeiro curso, então vou me ater mais aos fundamentos do envio de ordens e com isso te dar a base para que possa avançar no futuro por conta própria ou buscando conteúdos mais avançados.

E por fim, se preferir, pode assistir a esta parte 2 no vídeo abaixo, ao invés de ler o post.

#1 – Ordens de Futuros

Para abrir ou fechar posições em contratos futuros usando bot é necessário que você aprenda como enviar ordens para o book de Futuros da Binance, o que é feito através da API de New Trade, cuja documentação completa está aqui. Para fazer a comunicação com a API podemos usar qualquer cliente HTTP que você conheça, sendo que na parte 1 deste tutorial nós já deixamos instalado o Axios no projeto, que é um dos mais populares para Node.js.

Por questões de organização vamos criar um novo arquivo api.js para incluir nele as funções de comunicação com a API da Binance, bem como algumas configurações necessárias a essa comunicação, pelas quais começaremos a codificação, como abaixo.

Aqui nós importamos o pacote do Axios, que comentei antes e um pacote nativo do Node.js chamado crypto. Ele servirá para fazermos a criptografia exigida para alguns parâmetros da Binance. Na sequência, apenas carregamos algumas variáveis de ambiente presentes em nosso arquivo .env e que são carregadas para a memória automaticamente quando você executar o projeto com npm start já que deixamos configurado assim em nosso package.json.

O próximo passo é criarmos a função de envio de ordens. Criaremos uma função genérico com o mínimo possível de parâmetros mas que, uma vez entendida, lhe permitirá enviar diversas ordens diferentes e até mesmo personalizar a função mais tarde já que, como disse antes, a API da Binance te dá toneladas de opções de configuração de envio de ordens. Vou separar a construção desta função em 3 etapas, com a primeira estando abaixo.

Nesta primeira etapa vamos definir a assinatura da função newOrder, que vai esperar o symbol (par de moedas), a quantidade a ser negociada, o lado da operação (BUY ou SELL), o tipo de operação (por padrão à mercado) e o preço de negociação (opcional, caso o tipo de ordem seja LIMIT). Caso você venha a querer suportar ordens do tipo “stop”, você pode adicionar mais parâmetros aqui, sem problema algum, apenas seguindo a nomenclatura de parâmetros definida na documentação da API.

Logo abaixo da declaração da função nós montamos um objeto data com os parâmetros obrigatórios: symbol, side, type e quantity. Se veio preço, então adicionamos esta informação no objeto data, para que seja enviada junto da ordem. Além disso, se o tipo de ordem for LIMIT, devemos informar mais um parâmetro que é o timeInForce, que estou definindo como GTC (Good ‘Till Cancelled) mas que você pode usar outro conforme seu conhecimento como FOK, IOC, etc (mais aqui).

Na sequência eu coloquei uma validação, para o bot somente avançar na submissão da ordem se a apiKey e o apiSecret estão devidamente carregados. Caso contrário, o bot vai jogar um erro avisando.

E por fim, o timestamp da ordem eu defino como sendo agora (now) e o recvWindow, que é a janela de tolerância de atraso entre o timestamp de envio e o de processamento. Estas informações todas serão usadas a seguir na criptografia e envio da nossa ordem, mas antes eu gostaria de frisar que problemas com timestamp são os mais comuns em ordens enviadas via bot. Isso porque é extremamente comum em máquinas Windows os relógios estarem atrasados ou adiantados alguns segundos. Caso você tenha problemas relacionados a tempo, consulte a lista de erros comuns da Binance e as possíveis soluções, que agrupei neste post.

Agora vamos avançar para a parte de criptografia  e mais parâmetros da ordem. Isso porque existem dois tipos de comunicação com a Binance: a pública e a privada. A comunicação privada (informações confidenciais, ordens, etc) deve ser assinada digitalmente pelo usuário usando um algoritmo de criptografia chamado HMAC-SHA256. Basicamente o que este algoritmo faz é gerar uma assinatura digital usando os parâmetros da requisição + uma senha sua, sendo que a nossa senha é a nossa secret key da API. Abaixo uma implementação desta criptografia usando o objeto crypto, que importamos mais cedo.

O processo de criptografia tem três etapas: primeiro configuramos o HMAC com a opção sha256 (algoritmo de hashing exigido pela Binance) e com nosso secret. Depois, criptografamos uma string contendo todos nossos parâmetros no formato querystring, ou seja, chave1=valor&chave2=valor2, etc. O resultado dessa criptografia é um array de bytes que a gente converte na terceira etapa para uma string hexadecimal que é a representação da nossa assinatura digital que irá junto em nossa requisição através de um campo signature exigido pela Binance para chamadas privadas/autenticadas.

Após este processo de criptografia, é hora de montar os parâmetros da ordem no formato esperado pela Binance, o que fazemos juntando tudo o que temos no data com o timestamp, o recvWindow e o signature e convertendo para uma string no formato de querystring, com um sinal de  interrogação na frente.

Agora estamos preparados para enviar a ordem em si, que faremos usando o Axios.

Aqui fazemos um HTTP POST para a URL formada pela apiUrl mais o endpoint de envio de ordens e a querystring com todos os parâmetros (incluindo assinatura). Além disso, definimos um cabeçalho HTTP exigido pela Binance, onde devemos informar a nossa api key. Assim, quando a ordem chegar no servidor da Binance, ela vai ver neste cabeçalho quem enviou e conferir a assinatura pra ver se bate com a sua, repetindo a criptografia com o seu secret que eles possuem armazenado. Se tiver alguma divergência, eles rejeitam o envio.

Tudo dando certo, retornaremos os dados da resposta como resultado desta função, como mostrado na última linha. Não esqueça de exportar esta função ao final do seu api.js para que possamos usá-la em outros pontos do sistema.

Curso Node.js e MongoDB

#2 – Enviando as Ordens

Agora que fizemos a parte mais complicada, usar esta função para enviar ordens para Binance fica extremamente simples. Você deve voltar ao index.js, importar o api.js no topo e nas lógicas onde deseja abrir e fechar suas posições basta incluir as chamadas com os parâmetros que mais fizerem sentido para a sua estratégia.

Abaixo, um exemplo didático de uma posição abrindo comprado em 19.000 em fechando com a venda em 21000.

Neste exemplo, dentre vários possíveis, eu abro a posição de BTCUSDT comprando (BUY) quantidade de 0.001 (BTC). Importante que as informações de symbol, side e type estejam sempre em maiúsculas e que a quantidade que você for negociar esteja aderente às regras de trade da corretora. Todas corretoras possuem regras de quantidade mínima, valor nominal mínimo, etc para cada symbol, regras estas que eu discuti outro dia em um vídeo no canal, o qual incluo abaixo, caso queira assistir e aprender como verificar.

Mas voltando ao assunto principal, você pode abrir sua posição vendido (SELL) também, tudo vai depender da sua estratégia. O importante é que, para fechar a sua posição mais tarde, você deve enviar uma ordem no lado contrário, ou seja, se abriu com BUY, deve fechar com SELL e vice-versa, na mesma quantidade, a fim de fechar ela completamente.

Para trabalhar o retorno da função newOrder, que é assíncrono, eu usei promises, você pode aprender mais sobre programação assíncrona neste material.

Mas Luiz, e as liquidações? Vou falar delas a seguir.

Curso Web3 para Iniciantes

#3 – Monitorando Posições e Carteira

Se você opera em futuros sabe que as liquidações são um perigo constante, certo?

Isso porque se você operar alavancado (multiplicando seu patrimônio artificialmente) você tende a diminuir a sua margem e com isso se o mercado seguir uma tendência contrária à da sua posição (você abriu comprado e o mercado caiu, por exemplo), mesmo que poucos %, a Binance pode liquidar a sua posição em virtude da falta de fundos para manter o seu investimento no contrato futuro. Enfim, é um pouco complexo e eu não sou o especialista mais indicado para explicar, mas o fato é que sim, é importante você saber que monitorar a sua posição em cada um dos contratos abertos é algo importante no seu bot, tanto para você ver a sua lucratividade até o momento (quando a posição está aberta) quanto para você saber se está prestes a ser liquidado e aí tomar uma decisão de aumentar sua posição (nova ordem no mesmo side) ou aceitar o prejuízo.

Para obter os dados não apenas das posições abertas mas da carteira de futuros também, podemos usar a API Account Information V2, cuja documentação completa está aqui. O código é relativamente parecido com o da ordem, mas menor, já que existem menos parâmetros a serem passados.

Aqui temos a mesma lógica de verificação das chaves, de carregamento do timestamp, recvWindow e geração da assinatura com estes poucos parâmetros. Depois montamos a requisição que é um HTTP GET para o endpoint de account. A grande diferença aqui é a forma como trabalhamos o retorno da função, já que esse endpoint retorna MUITAS informações.

Basicamente o que foi foi pegar apenas o que mais importa da minha carteira, que são as moedas com balance superior a zero (apenas symbol e balance) e o que mais importa das minhas posições, que são apenas as abertas, com posição diferente de zero (não use maior que zero, já que ao operar vendido sua posição é negativa). Isso garante que tenhamos informações importantíssimas para deixar nosso bot mais inteligente.

O que você deve fazer agora é alguma lógica para pegar estas informações de tempos em tempos, a fim de usá-la para tomar alguma decisão. Embora seja possível receber notificações de mudanças de saldos e posições via websockets/streams, achei mais interessante fazer desta forma já que vem de uma maneira muito completa e interessante.

O exemplo de código acima obtém os dados a cada 10.000ms (10s) e apenas imprime o resultado no console, mas você poderia colocar condições ou mesmo atribuir alguns dados à variáveis de controle que o bot leia cruzando com a informação de preço. O céu é o limite do que você pode inventar com estes dados e tantos outros existentes na Binance. Abaixo, um exemplo de retorno da função acima, para ter uma ideia das informações.

E por fim, talvez você esteja se perguntando como se altera a alavancagem e o tipo de margem de um contrato. Essas operações podem ser feitas via API também, mas devem ser feitas ANTES de abrir uma posição, usando a API de leverage e de margin. Como não é algo que se mude com muita frequência (na minha experiência), eu acho mais interessante você fazer esta alteração manualmente no painel da Binance autenticado na sua conta, desta forma afetando a alavancagem e tipo de margem que o bot estará operando.

E com isso cobrimos as principais atividades que um bot de futuros vai desempenhar. Claro que podem ser feitas muito mais coisas e recomendo que dê uma olhada tanto na documentação oficial das APIs e Streams da Binance quanto em meus outros tutoriais de bot aqui no blog e no canal (por exemplo esse aqui de RSI). Lhe convido também a assistir ao vídeo abaixo, onde falo sobre decisões de arquitetura e funcionalidades possíveis em bots de futuros na Binance.

TAGS:

Olá, tudo bem?

O que você achou deste conteúdo? Conte nos comentários.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *