Como criar um clone do TradingView com JS

Node.js

Como criar um clone do TradingView com JS

Luiz Duarte
Escrito por Luiz Duarte em 20/06/2022
Junte-se a mais de 22 mil profissionais de TI

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

Se você investe ou negocia criptomoedas certamente conhece o site Trading View, famoso pelos seus gráficos de velas atualizados em tempo real. No tutorial de hoje vamos aprender justamente a criar gráficos de velas atualizados em real-time, assim como no TV.

Para isso, vamos precisar que você já conheça ao menos o básico de JavaScript pois usaremos muito ele. Se nunca programou JS antes, você pode pegar a base neste ebook gratuito. Também precisamos que você tenha o Node.js instalado na sua máquina, coisa que ensino neste vídeo.

Se preferir, você pode acompanhar este tutorial no vídeo abaixo, que tem o mesmo conteúdo.

#1 – Setup do Projeto

O primeiro passo é fazer a configuração inicial do nosso projeto. Usaremos Node.js para o backend e ReactJS para o frontend, mas manteremos a estrutura muito simples por questões de didática. Sinta-se à vontade para criar algo mais profissional em termos de arquitetura, ok?

Para inicializar o nosso projeto, rode o seguinte comando no terminal (bash, MS-DOS, etc), que vai criar nossa aplicação ReactJS (se algumas coisas sobre React ficarem confusas ou quiser se aprofundar, esta série aqui é ótima).

Esse comando pode demorar um bocado para finalizar pois ele cria toda a estrutura de pastas e baixa uma cacetada de dependências. Quando ele terminar, você deve ainda instalar mais algumas dependências que vamos precisar, com o comando abaixo.

De maneira resumida, essas dependências (que vamos explorar melhor mais à frente) servem para:

  • apexcharts e react-apexcharts: componente para os gráficos de velas (docs);
  • axios: lib para comunicação com o backend (docs);
  • express: lib para construção do backend (docs);
  • cors: lib para permitir a comunicação do frontend com o backend (docs);
  • react-use-websockets: componente para atualização real-time do gráfico (docs);

Apenas para ver se deu tudo certo, você pode entrar na pasta do projeto e rodar o comando abaixo para inicializar ele.

O resultado será o logo do React girando apenas, mostrando que a aplicação está funcionando e pronta para ser customizada.

#2 – Backend e Dados

Nosso gráfico será alimentado por duas fontes de dados diferentes: uma histórica, que servirá para dar sua aparência inicial, com as últimas x velas de um ativo. E a outra para recebermos a vela atual, em tempo real, que faremos mais à frente. Usarei como fontes de dados para ambos cenários a corretora Binance, maior do segmento e que fornece publicamente estes dados tanto via API REST quanto via WebSockets/Streams.

A API da Binance que vamos usar para pegar velas históricas é essa aqui, que recebe o symbol (par de moedas), o intervalo gráfico e a quantidade de velas que deseja, sendo que ele vai trazer as x mais recentes por padrão.

Independente dessa API da Binance, você pode substituir por dados de outra corretora se quiser, apenas adaptando as chamadas. Uma das coisas que será necessário em nosso projeto é um pequeno backend para fazermos estas requests de velas. Isso é devido a uma regra de segurança dos navegadores que não permite que o frontend faça esse tipo de chamada diretamente.

Para criar nosso “backend proxy” crie um arquivo server.js dentro da pasta src do seu projeto com o seguinte conteúdo, que eu explicarei na sequência.

Esta primeira versão não faz nada de útil, é apenas para ver se está tudo funcionando como deveria. Nós carregamos o Express, definimos a porta em que o backend vai rodar como sendo 3001 (nosso front roda na 3000), criamos uma aplicação com o Express (que logo mais vamos implementar as funções) e passamos a escutar na porta mencionada anteriormente.

Se tudo foi implementado corretamente, rode o backend a partir da pasta src do projeto com o comando abaixo, em outra janela do terminal (deixe o frontend rodando sozinho na dele).

Se deu certo, verá a mensagem que o servidor está escutando por requisições.

Agora, vamos implementar a única rota que teremos em nosso backend que serve para conectar na API da Binance e pegar os dados históricos. Coloque o código abaixo onde deixei o comentário anterior.

Começamos este trecho de código configurando o CORS, para que o frontend possa se comunicar livremente com nosso backend.

Depois, configuramos uma rota GET em /klines que toda vez que for chamada irá fazer uma requisição à Binance pedindo os últimos 60 candles (limit=60) do symbol e interval fornecidos na querystring da requisição. Caso não seja passado os parâmetros necessários ou dê erro na requisição, o requisitante receberá um erro como resposta com o motivo do mesmo.

Reinicie seu backend e teste ele via Postman antes de avançar, como mostro na imagem abaixo, onde usei o symbol BTCUSDT como exemplo, no intervalo (tempo gráfico) de 1 minuto. O resultado é um array de arrays com as informações das velas, que vamos tratar no frontend.

Agora que temos o backend funcionando, deixe ele rodando quietinho e vamos trabalhar no frontend.

Livro Node.js

#3 – Frontend e Dados

Vamos começar a construção do nosso frontend. Primeiro precisaremos de um service, ou seja, um módulo para fazer a comunicação do front com o back que construímos, a fim de pegar as velas históricas que vamos precisar. Os dados que vamos precisar para nosso gráfico de velas possui um formato bem específico, então para facilitar sua manipulação vamos criar uma classe Candle para isso, como abaixo.

O construtor do Candle espera o tempo de abertura da vela e as informações do OHLC (abertura, máxima, mínima e fechamento), que ele guarda em propriedade x e y. Essas propriedades não são sugestões, é exatamente o formato que nosso gráfico de velas espera onde x é o eixo horizontal do tempo e y o eixo vertical do preço do ativo.

Agora, crie um arquivo DataService.js dentro da src do projeto para criarmos a função de comunicação front > back com Axios, como abaixo.

A função getCandles espera as informações de symbol e interval vindo do frontend e com elas faz a chamada com Axios para nosso backend. O resultado é convertido para um array de candles, usando a classe que definimos há pouco, o que vai facilitar bastante a construção do gráfico, você vai ver.

Para testar esse código é bem simples, você pode ir no App.js, carregar a função e chamá-la em um useEffect, imprimindo o resultado na tela ou no console de qualquer jeito só para ver se está funcionando.

Verá que ele traz o array de Candles corretamente através do caminho frontend > backend > Binance. Agora é a hora de começarmos a falar do gráfico em si.

Curso Node.js e MongoDB

#4 – Gráfico de Velas

Para criação do gráfico de velas vamos usar uma biblioteca de componentes gráficos chamada ApexCharts que é gratuita e que possui uma versão para React chamada React ApexCharts, que nós já instalamos na etapa 1 deste tutorial.

Para encapsular a complexidade de montar o gráfico de velas, vamos criar um componente React chamado Chart.js com ele dentro.

Aqui definimos que vamos receber via props um data, que nada mais é do que um array de Candles. Esse data é usado para montar o array series, que terá apenas um objeto com o data dentro. Além disso, neste componente definimos as options do gráfico, dizendo que no eixo x temos datas e que no y queremos tooltips (aqueles balões descritivos).

Esses dois objetos, options e series, usamos nas propriedades do componente ApexChart, junto do type candlestick (para definir como o gráfico deve se comportar na renderização) e as dimensões do gráfico.

Agora para usar este gráfico é bem simples, você posiciona o componente no seu App.js e eu fiz questão de incluir dois selects também, para que o usuário possa trocar o symbol e interval exibidos no gráfico.

Os states que criei são autoexplicativos e servem para guardar os dados e forçar a renderização do gráfico atualizado quando necessário. Os selects também não têm nada de especial: apenas coloquei algumas informações úteis e no evento onChange estou alterando os respectivos states.

Repare também que atualizei o useEffect para que ele use os states, o que vai fazer com que qualquer alteração ele recarregue os dados. Com isso, o carregamento inicial dos dados está pronto e o resultado esperado pode ser visto abaixo.

O que precisamos agora, é de um mecanismo para manter este gráfico sempre atualizado.

Curso FullStack

#5 – Atualizando o Gráfico

Nossa última etapa é garantir que nosso gráfico se mantenha atualizado conforme o preço do ativo subir ou descer e sem a necessidade de ficar fazendo refresh na tela. Isso é possível graças à tecnologia WebSocket que permite que seja criado um canal de comunicação entre o browser e a corretora, por onde ela envia atualizações sempre que houverem.

Na Binance são fornecidas publicamente diversas streams (fluxos) de dados que você pode se conectar para receber updates e a que vamos usar é a de velas, documentada aqui. Se estiver usando outra exchange, consulte a documentação da mesma para ver a existência desse recurso.

Uma coisa bacana do protocolo websocket é que você pode conectar seu frontend diretamente à stream, o que faremos no ReactJS usando um componente chamado React useWebSocket, que já instalamos na etapa 1 do tutorial. Esse componente faz a ligação conforme nossas configurações e define uma função que vai ser chamada a cada atualização recebida, que vamos usar para atualizar o gráfico, como abaixo.

Eu omiti com reticências as partes que não nos interessam no momento e foquei aqui na configuração do hook useWebSocket. Primeiro, montamos a URL com as informações do symbol e interval armazenados no state. Depois, configuramos para que uma mensagem seja impressa no console logo que a conexão for estabelecida, para sabermos que funcionou.

O evento onMessage é o coração do componente e nele nós testamos se chegou um JSON como atualização, transformamos este JSON em um novo candle e fazemos uma cópia dos dados atuais do gráfico, para manipulá-los conforme a última vela que chegou: se a última vela estiver completa, removemos a primeira e colocamos ela na última posição, para que o gráfico sempre tenha 60 velas. Se a última vela estiver incompleta (os updates chegam a cada 2 segundos com valores parciais/incompletos), apenas substituímos a última exibida por ela, o que vai garantir que o gráfico esteja atualizado.

Ao término dos ajustes no array de dados, mandamos o state ser atualizado o que vai forçar a renderização do gráfico que inteligentemente não pisca, apenas ajusta a vela que atualizou.

Com isso conseguimos completar o funcionamento do principal recurso do TradingView que é o gráfico de velas atualizado em tempo real. Esta biblioteca ApexCharts, permite que você combine gráficos, então dá pra plotar os gráficos de indicadores, junto colocar as linhas de preços das suas ordens e muito mais.

Estas e outras funcionalidades do Trading View quem sabe eu não mostro em outro tutorial futuro? Se gostou da ideia, deixe nos comentários!

Olá, tudo bem?

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