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 programaçã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, preferenciamento na documentação oficial.
Vamos lá!
#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 Order, 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.
|
1 2 3 4 5 6 7 8 9 10 11 |
import axios from "axios"; import crypto from "crypto"; const apiKey = process.env.API_KEY; const apiSecret = process.env.SECRET_KEY; const apiUrl = process.env.API_URL; if (!apiKey || !apiSecret || !apiUrl) throw new Error('Preencha corretamente seu .env'); |
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.
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.
O próximo passo é criarmos a função de envio de ordens. Criaremos uma função genérica 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.
|
1 2 3 4 5 6 7 8 9 10 11 |
async function newOrder(symbol, quantity, side = 'BUY', type = 'MARKET', price = 0) { const data = { symbol, side, type, quantity }; if (price) data.price = parseInt(price); if (type === 'LIMIT') data.timeInForce = 'GTC'; const timestamp = Date.now(); const recvWindow = 60000; } |
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).
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.
|
1 2 3 4 5 6 7 8 9 |
const signature = crypto .createHmac('sha256', apiSecret) .update(`${new URLSearchParams({ ...data, timestamp, recvWindow }).toString()}`) .digest('hex'); const newData = { ...data, timestamp, recvWindow, signature }; const qs = `?${new URLSearchParams(newData).toString()}`; |
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.
|
1 2 3 4 5 6 7 8 |
const result = await axios({ method: 'POST', url: `${apiUrl}/v1/order${qs}`, headers: { 'X-MBX-APIKEY': apiKey } }); return result.data; |
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.
|
1 2 3 4 5 |
export default { newOrder } |
#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 100.000 e fechando com a venda em 110000 (esta não é uma recomendação, é apenas um exemplo).
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import api from "./api.js"; ws.onmessage = async (event) => { console.clear(); const obj = JSON.parse(event.data); console.log(`Symbol: ${obj.s}`); console.log(`Price: ${obj.c}`); const price = parseFloat(obj.c); try { if (price < 100000 && !isOpened) { console.log('Abrir posição!'); const result = await api.newOrder("BTCUSDT", "0.01", "BUY") console.log(result); isOpened = true; } else if (price > 110000 && isOpened) { console.log('Fechar posição!'); const result = await api.newOrder("BTCUSDT", "0.01", "SELL") console.log(result); isOpened = false; } } catch (err) { console.error(err); process.exit(0); } } |
Neste exemplo, dentre vários possíveis, eu abro a posição de BTCUSDT comprando (BUY) quantidade de 0.01 (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.
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 naquele contrato.
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 e esse de Médias Móveis). 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.
Até a próxima!

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


