Em outras oportunidades aqui no blog e também no meu canal do Youtube eu trouxe tutoriais de como criar robôs de criptomoedas, ou seja, automações via software para comprar e vender criptoativos em corretoras como Binance, Mercado Bitcoin e BityPreço. Em todas essas ocasiões eu trouxe como gatilho de compra e venda o preço do ativo no mercado à vista, afinal nada é mais importante (e óbvio para leigos) do que o preço do ativo, já que a estratégia mais bruta que existe é comprar barato e vender caro, certo?
No entanto estratégias mais elaboradas (e geralmente mais assertivas) não usam unicamente o preço como indicador de melhor momento de compra ou de venda. O mais comum é o uso dos chamados indicadores técnicos: métricas obtidas através de matemática sobre o comportamento passado daquele ativo. Existem centenas de indicadores mas a imensa maioria deles é obtido da seguinte forma:
- pega-se uma amostra de velas (candles) do ativo;
- aplica-se uma fórmula matemática sobre as velas (geralmente o preço de fechamento);
- obtém-se o indicador atualizado para comparação;
E é justamente isso que quero mostrar como você pode fazer hoje.
Vamos lá!
#1 – Setup do Projeto
Dentre os players mundiais de criptomoedas, uma das mais agressivas em termos de taxas e portfólio de moedas é a Binance, considerada a maior exchange de criptomoedas do mundo em volume de negociações. Usaremos ela como fonte de dados aqui pois é um bom termômetro do mercado de criptomoedas, mas o que vou mostrar pode ser usado com qualquer exchange (de cripto ou não) que disponibilize publicamente as suas velas. Nem mesmo você precisa ter conta na Binance para fazer este tutorial, pois ele não efetuará as compras e vendas de fato, ok?
Além disso, existem centenas de indicadores técnicos diferentes, como citei na introdução, então pegarei um como exemplo e depois eu posso trazer outros em oportunidades futuras ou você pega o que aprender aqui e adapta para outros indicadores, ok?
Dito isso, antes de sairmos programando precisamos configurar nosso projeto. Usarei aqui a linguagem JavaScript, então precisamos do Node.js instalado na máquina. Se ainda não tem o ambiente de desenvolvimento para Node.js configurado, você pode ver como fazer no vídeo abaixo.
Agora crie uma pasta no seu computador com o nome de binance-rsi e dentro dela rode o comando abaixo pelo seu terminal de linha de comando para inicializar um projeto Node.js na pasta.
1 2 3 |
npm init -y |
Agora coloque um arquivo index.js vazio dentro da pasta e vamos instalar um pacote via NPM pra deixar nosso projeto preparado. Segue o comando de instalação:
1 2 3 |
npm i dotenv |
O módulo dotenv serve para carregar automaticamente variáveis de ambiente na sua aplicação Node.js. Usaremos estas variáveis de ambiente para colocar as configurações do nosso bot. Agora crie um arquivo “.env” na raiz do seu projeto colocando nele os valores abaixo, conforme instruções:
- SYMBOL: o par de moedas que seu robô vai monitorar e calcular indicadores. Ex: BTCUSDT (sempre em maiúsculas);
- INTERVAL: o tempo gráfico das suas velas. Ex: 1h (para velas de 1h);
- PERIOD: o período (quantidade de velas) que serão usadas no seu cálculo. Ex: 14;
Seu arquivo deve ficar mais ou menos assim (ajuste conforme seu interesse):
1 2 3 4 5 |
SYMBOL=BTCUSDT INTERVAL=1h PERIOD=14 |
Para carregar estas configurações na sua aplicação, modifique o seu package.json para que no script de start ele carregue o .env:
1 2 3 4 5 |
"scripts": { "start": "node -r dotenv/config index" }, |
Note que este robô de monitoramento de indicador irá funcionar com um par de moedas e um indicador, mas pode ser adaptado para vários pares ou pode replicar o projeto várias vezes na sua máquina.
#2 – Obtendo os dados das velas
Para a finalidade de monitoramento das velas/candles a Binance fornece uma API histórica, que é útil para pegar velas em quantidade, e um fluxo de streams que é útil para pegar somente a vela atual. É possível fazer uma abordagem que une o melhor dos dois mundos mas isso complicaria demais esse tutorial, então vou usar uma abordagem mais simplificada, apenas com a API.
Para consumir a API de velas históricas da Binance eu usarei a API nativa Fetch. Ela é um cliente HTTP padrão para JavaScript, usaremos ela em seu arquivo index.js (abaixo), junto das variáveis do .env devidamente carregadas, combinando tudo para chamar a API de velas históricas e imprimir no console o resultado.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
const SYMBOL = process.env.SYMBOL; const INTERVAL = process.env.INTERVAL; const PERIOD = parseInt(process.env.PERIOD); async function getCandles(){ const response = await fetch(`https://api.binance.com/api/v3/klines?symbol=${SYMBOL}&interval=${INTERVAL}&limit=100`); const data = await response.json(); const closes = data.map(k => parseFloat(k[4])); console.log(closes); } getCandles(); |
Nesta amostra de código, após eu ter todas as variáveis necessárias, eu chamo uma função getCandles que faz a request com fetch para a rota klines da REST API da Binance. Essa API espera que a gente passe o symbol (par de moedas), o interval (tempo gráfico) e a quantidade de velas que queremos, sendo que precisamos de no mínimo uma a mais que o período para conseguir calcular o indicador, mas na prática costumamos usar 100 (explicarei o porquê mais adiante). Isso retornará um array de velas que mapeamos para pegar somente o close de cada vela (valor de fechamento que fica na posição 4 da vela), pois é a única informação que precisamos.
Neste primeiro momento, apenas imprimimos os closes no terminal para que você consiga ver se esta primeira etapa funcionou. Experimente rodar o seu projeto com o comando npm start e terá os valores impressos no terminal.
#3 – Entendendo o Cálculo do Indicador
Agora que temos os dados que precisamos para a grande maioria dos indicadores técnicos, é hora de escolher um, estudarmos sua fórmula e implementarmos o seu cálculo em JavaScript. Para este tutorial eu escolhi trabalhar com RSI ou Relative Strength Index (Indicador de Força Relativa), um indicador muito popular entre traders. No entanto, o racional que vamos usar aqui é o mesmo para qualquer outro indicador.
Antes de escrever algoritmos para indicadores técnicos é sempre importante que você entenda a fórmula do mesmo. No caso do RSI, ela é facilmente encontrada na Internet e é expressa como:
Ou seja, primeiro temos de calcular os ganhos médios no período (average gains) e as perdas médias (average losses). Um ganho é quando uma vela fechou com um valor superior no preço em relação ao fechamento da vela anterior. Somam-se as diferenças de ganhos e guarda-se em uma variável, algo como abaixo. Repare que estou considerando o empate como ganho, mas na prática não influencia em nada. Repare também que preciso de um close a mais para ter com quem comparar para o primeiro cálculo de ganho (o laço começa em 1):
1 2 3 4 5 6 7 8 9 |
let gains = 0; for (let i = 1; i < period; i++) { const diff = closes[i] - closes[i - 1]; if (diff >= 0) gains += diff; } |
Depois, fazemos o mesmo para as perdas. Uma perda é quando uma vela fechou com um valor inferior no preço em relação ao fechamento da vela anterior. As perdas são representadas por números negativos, mas como o sinal não nos importa, usei o Math.abs para pegar o valor absoluto (sem sinal), armazenamento o somatório em outra variável.
1 2 3 4 5 6 7 8 9 10 11 |
let gains = 0, losses = 0; for (let i = 1; i < period; i++) { const diff = closes[i] - closes[i - 1]; if (diff >= 0) gains += diff; else losses += Math.abs(diff); } |
Agora que temos o somatório dos ganhos e também das perdas no período, podemos calcular a média deles e aqui vai um truque importantíssimo: você deve usar médias exponenciais e não médias simples se quiser que seu RSI fique igual ao das plataformas (Binance, TradingView, etc). Médias exponenciais dão mais importância aos dados mais recentes do que aos antigos, o que implica em um indicador que reage mais rapidamente aos movimentos do mercado. No entanto, para calcularmos médias exponenciais nós precisamos ter ao menos uma média simples, por isso criaremos a função abaixo usando os códigos anteriores, com algumas adições.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
function averages(closes, period, startIndex) { let gains = 0, losses = 0; for (let i = 0; i < period && (i + startIndex) < closes.length; i++) { const diff = closes[i + startIndex] - closes[i + startIndex - 1]; if (diff >= 0) gains += diff; else losses += Math.abs(diff); } let avgGains = gains / period; let avgLosses = losses / period; return { avgGains, avgLosses }; } |
Para maior precisão nós não calcularemos apenas uma média, mas sim todas as médias possíveis de x períodos dentro da amostra de 100 velas. Ou seja, se estiver trabalhando com 14 períodos, seu algoritmo irá calcular a média da vela 0 a 13, depois 1 a 14, 2 a 15 e assim por adiante, até chegar ao final do array de velas onde está o fechamento atual e consequentemente a média atual.
Para essa finalidade, eu coloquei na assinatura da função para receber os closes (valores de fechamento), o período e índice inicial (startIndex), para que a cada chamada dessa função possamos analisar um segmento diferente dos closes, cuidando apenas para que a soma do iterador do for (i) com o startIndex não estoure o length dos closes. Repare também como retornei um objeto com a média simples dos ganhos e das perdas.
Bora calcular o RSI agora?
#4 – Calculando o RSI em JS
Agora que entendemos como calcular as médias simples de ganhos e perdas em JS, podemos usar essa função para o cálculo do RSI, que usará das médias simples como base para o cálculo das exponenciais e, mais ao final, da força relativa.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function RSI(closes, period) { let { avgGains, avgLosses } = averages(closes, period, 1); for (let i = 2; i < closes.length; i++) { let newAverages = averages(closes, period, i); avgGains = (avgGains * (period - 1) + newAverages.avgGains) / period; avgLosses = (avgLosses * (period - 1) + newAverages.avgLosses) / period; } const rs = avgGains / avgLosses; return 100 - (100 / (1 + rs)); } |
Começamos carregando as médias simples do primeiro período (0-13 em um exemplo de 14 períodos), elas são o nosso “start” no cálculo das médias exponenciais. Depois, fazemos um laço a partir da posição 2 (o que vai excluir a 0 do cálculo pois ela já foi usada na média simples) e pegamos nova média simples de x períodos a partir dessa posição. Com essa nova média, fazemos o cálculo de média exponencial (que dá mais peso para a atual) e repetimos avançando para o próximo segmento e consequentemente próxima média. Por fim, calculamos a força relativa (rs) conforme descrito na fórmula do RSI, transpondo depois para base 100.
Se ficou confuso, o vídeo abaixo explica muito melhor que eu esse aspecto mais metamático do algoritmo.
Isso vai permitir que apenas informando os closes e o período para a função, que teremos o RSI calculado. Agora você pode voltar na função getCandles e adicionar a chamada ao cálculo do RSI, imprimindo o resultado.
1 2 3 4 5 6 7 8 9 10 |
async function getCandles() { const response = await fetch(`https://api.binance.com/api/v3/klines?symbol=${SYMBOL}&interval=${INTERVAL}&limit=100`); const data = await response.json(); const closes = data.map(k => parseFloat(k[4])); const rsi = RSI(closes, PERIOD); console.clear(); console.log(rsi); } |
Por fim, se quiser que esse comportamento se repita de tempos em tempos, basta criar um timer, como abaixo, onde exemplifiquei um intervalo de 3 segundos entre cada cálculo.
1 2 3 |
setInterval(getCandles, 3000); |
O resultado, você vê no seu terminal. Na imagem abaixo, eu tentei colocar lado a lado o meu terminal e o RSI da Binance, mas é muuito difícil conseguir tirar um print no instante que os dois estão iguais pois o gráfico da Binance muda a todo instante e o nosso apenas a cada 3 segundos, mas dá pra ver que ficou bem próximo, alguns décimos de diferença apenas, o que não influencia na análise do indicador, que geralmente é focada no valor inteiro. Ainda assim deu pra ver eles iguais várias vezes durante meus testes.
Quer aprender a calcular outros dois indicadoes? Confira neste post.
Um abraço e até a próxima!

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