Pular para o conteúdo
Todos os projetos

Análise de dados financeiros · PWA · Visualização de dados

Cripto Terminal

Um terminal de criptoativos que mostra o risco da carteira inteira e explica cada métrica que calcula

Projeto privado — sem link público

Cliente
Produto pessoal
Cargo
Engenheiro de Software Full-stack — projeto independente
Ano
2026
Tecnologias
  • Next.js 16
  • React 19
  • TypeScript
  • Tailwind CSS 4
  • TanStack Query
  • Zustand
  • Zod
  • lightweight-charts
  • Recharts
  • Radix UI
  • Vitest

Contexto

Aplicação web progressiva (PWA) mobile-first de análise de criptoativos, desenvolvida com Next.js 16, React 19 e TypeScript sobre dados reais de mercado das APIs públicas da CoinGecko e da Binance. Uso pessoal em círculo fechado, com acesso por código. A interface usa linguagem de ferramenta de análise: mede e descreve, sem recomendar compra ou venda.

Desafio

As ferramentas gratuitas em português que avaliei mostram preço e pesos, mas não o risco da carteira consolidada, e raramente informam fórmula, janela ou fonte dos indicadores. As APIs públicas de mercado têm limites de requisição restritos (HTTP 429), o que exige cache, controle de taxa e sinalização de dado defasado para a interface continuar utilizável.

Resultados

testes automatizados (Vitest) cobrindo indicadores, risco, carteira e acesso
237
métricas documentadas com fórmula, janela e armadilha
23
ativos cobertos pelo screener (a tela Mercado exibe o top 100)
250
chamada por minuto por moeda à CoinGecko para os 250 ativos, com cache compartilhado entre telas e usuários
1

Principais entregas

  1. 01Implementei em TypeScript puro, com testes Vitest, o painel de risco de 90 dias da carteira (volatilidade anualizada, Sharpe, Sortino, drawdown máximo, VaR 95%, beta em relação ao BTC, HHI e matriz de correlação), que reúne o risco da carteira consolidada em uma única tela.
  2. 02Desenvolvi gráficos de candles com lightweight-charts, de 15 minutos a 1 semana, com indicadores calculados em TypeScript (SMA 20, EMA 50, Bandas de Bollinger, RSI e MACD em painéis) e fallback sinalizado para candles diários da CoinGecko quando o ativo não tem par na Binance.
  3. 03Criei um screener sobre o top 250 por market cap, com filtros de market cap, variação de 24h, RSI horário e tendência, que calcula os indicadores a partir da sparkline horária da CoinGecko: uma única chamada por minuto por moeda cobre os 250 ativos.
  4. 04Projetei a biblioteca de componentes e o design system com tokens no @theme do Tailwind CSS 4, contraste WCAG AA e estados documentados (foco, erro, vazio, dado defasado, HTTP 429), reutilizados em todas as telas junto com popovers Radix UI e gráficos em Recharts e SVG.
  5. 05Arquitetei a camada de dados com Route Handlers do Next.js, validação com Zod, cache LRU com dedupe e stale-on-error, rate limit por IP e tratamento de HTTP 429 sem retentativas em cascata, exibindo a idade do dado na interface.
  6. 06Protegi o app com CSP com nonce por requisição e acesso por código com cookie HMAC-SHA256, limitado a 5 tentativas por IP a cada 15 minutos, e centralizei a metodologia das 23 métricas em uma fonte única que gera os popovers e a página de ajuda, com teste que falha após 12 meses sem revisão.
  1. Mercado

    A tela de mercado lista o top 100 por market cap e mostra no cabeçalho há quanto tempo o dado foi atualizado.

    Tela de mercado no tema escuro: cartões de market cap global, volume de 24h, dominância do BTC e moedas ativas; listas das maiores altas e baixas de 24h; busca por nome ou símbolo; e a tabela do top 100 com preço, variação de 1h, 24h e 7 dias, market cap, volume e sparkline de 7 dias.
    Tela de mercado no tema escuro: cartões de market cap global, volume de 24h, dominância do BTC e moedas ativas; listas das maiores altas e baixas de 24h; busca por nome ou símbolo; e a tabela do top 100 com preço, variação de 1h, 24h e 7 dias, market cap, volume e sparkline de 7 dias.
  2. Gráfico com indicadores

    O gráfico usa candles da Binance e sobrepõe SMA, EMA, Bollinger e MACD, calculados em TypeScript no próprio app.

    Tela do Bitcoin no intervalo de 4 horas: gráfico de candles da Binance com SMA 20, EMA 50, Bandas de Bollinger e volume, painel de MACD com histograma, e abaixo a leitura técnica com RSI, histograma do MACD e distância para as médias.
    Tela do Bitcoin no intervalo de 4 horas: gráfico de candles da Binance com SMA 20, EMA 50, Bandas de Bollinger e volume, painel de MACD com histograma, e abaixo a leitura técnica com RSI, histograma do MACD e distância para as médias.
  3. Carteira e métricas no celular

    A carteira mostra P&L, custo e alocação por ativo. No celular, o gráfico de candles mantém os indicadores técnicos, e cada métrica abre fórmula, janela e armadilha com um toque.

    • Carteira fictícia no celular: patrimônio, P&L total, variação de hoje e custo em cartões, rosca de alocação entre BTC, ETH, SOL, LINK e HYPE, e o início da tabela de posições.
      Carteira fictícia no celular: patrimônio, P&L total, variação de hoje e custo em cartões, rosca de alocação entre BTC, ETH, SOL, LINK e HYPE, e o início da tabela de posições.
    • Bitcoin no celular: preço em destaque, atalhos de watchlist, alerta e carteira, seletor de intervalo e gráfico de candles de 1 hora com médias móveis, volume e RSI.
      Bitcoin no celular: preço em destaque, atalhos de watchlist, alerta e carteira, seletor de intervalo e gráfico de candles de 1 hora com médias móveis, volume e RSI.
    • Tela de moeda no celular com o popover do RSI (14) aberto sobre o gráfico: fórmula, janela de 14 candles do intervalo de 1 hora, como ler, armadilha, fonte Binance e data de revisão; abaixo, a leitura técnica com RSI, histograma do MACD e distância para as médias.
      Tela de moeda no celular com o popover do RSI (14) aberto sobre o gráfico: fórmula, janela de 14 candles do intervalo de 1 hora, como ler, armadilha, fonte Binance e data de revisão; abaixo, a leitura técnica com RSI, histograma do MACD e distância para as médias.
  4. Risco da carteira

    O painel mede o risco da carteira inteira, expõe a amostra em chips e avisa que a ferramenta não recomenda operações.

    Painel de risco de 90 dias de uma carteira fictícia, abaixo do fim da tabela de posições: chips com janela, número de retornos, pesos e benchmark; cartões de volatilidade anualizada, Sharpe, Sortino, drawdown máximo, VaR 95%, beta em relação ao BTC e concentração HHI; a matriz de correlação completa entre BTC, ETH, SOL, LINK e HYPE; e o aviso de que a ferramenta não constitui recomendação de investimento.
    Painel de risco de 90 dias de uma carteira fictícia, abaixo do fim da tabela de posições: chips com janela, número de retornos, pesos e benchmark; cartões de volatilidade anualizada, Sharpe, Sortino, drawdown máximo, VaR 95%, beta em relação ao BTC e concentração HHI; a matriz de correlação completa entre BTC, ETH, SOL, LINK e HYPE; e o aviso de que a ferramenta não constitui recomendação de investimento.
  5. Métricas explicadas

    A página de ajuda é gerada do mesmo objeto que alimenta os ícones ⓘ das telas.

    Página de ajuda com a seção de metodologia: a entrada do RSI (14) aberta mostra fórmula, janelas, como ler, armadilha, referência e origem do dado, seguida das demais métricas recolhidas.
    Página de ajuda com a seção de metodologia: a entrada do RSI (14) aberta mostra fórmula, janelas, como ler, armadilha, referência e origem do dado, seguida das demais métricas recolhidas.
  6. Watchlist e screener

    A watchlist acompanha os ativos com sparklines e cria alertas de preço, e o screener filtra 250 ativos e informa qual série alimenta o RSI.

    • Watchlist no celular com cinco ativos seguidos, cada um com sparkline de 7 dias, preço e variação de 24h, e o formulário de novo alerta de preço com ativo, condição e preço alvo.
      Watchlist no celular com cinco ativos seguidos, cada um com sparkline de 7 dias, preço e variação de 24h, e o formulário de novo alerta de preço com ativo, condição e preço alvo.
    • Screener no celular: filtros de market cap, variação de 24h, RSI 14 horário, tendência e ordenação, o aviso de que RSI e tendência vêm da série horária de 7 dias da CoinGecko, e o início da tabela com o universo de 250 ativos.
      Screener no celular: filtros de market cap, variação de 24h, RSI 14 horário, tendência e ordenação, o aviso de que RSI e tendência vêm da série horária de 7 dias da CoinGecko, e o início da tabela com o universo de 250 ativos.
  7. Fundamentos

    A prancha de fundamentos reúne os tokens do @theme do Tailwind CSS 4: cor, contraste, tipografia, raios e paleta de gráficos.

    Prancha 01 do design system do Cripto Terminal, fundamentos: rampa de superfícies e bordas do fundo ao border-strong com hexadecimais, cores de texto com contraste WCAG calculado sobre o fundo, cores semânticas de alta, baixa, destaque, ciano e violeta com a variação suave de 14% de alfa, raios de 14, 12, 8 e 6 px e pill, escala tipográfica com Inter e JetBrains Mono tabular, e a paleta dos indicadores e da rosca de alocação.
    Prancha 01 do design system do Cripto Terminal, fundamentos: rampa de superfícies e bordas do fundo ao border-strong com hexadecimais, cores de texto com contraste WCAG calculado sobre o fundo, cores semânticas de alta, baixa, destaque, ciano e violeta com a variação suave de 14% de alfa, raios de 14, 12, 8 e 6 px e pill, escala tipográfica com Inter e JetBrains Mono tabular, e a paleta dos indicadores e da rosca de alocação.
  8. Biblioteca de componentes

    A biblioteca de componentes documenta variantes e estados, inclusive dado defasado e limite de API (HTTP 429).

    Prancha 02 da biblioteca de componentes: botões primário, secundário, fantasma e perigo nos estados padrão, hover, foco e desabilitado; controle segmentado de intervalo, alternância USD/BRL e chips de indicador; campos de formulário padrão, com foco e com a mensagem de erro do Zod; estados de dados com o aviso de dado defasado, a caixa de erro do limite de requisições (HTTP 429) com botão de tentar de novo, o estado vazio e o toast de confirmação; e sinais de variação, tendência, RSI por faixa e chips de ressalva.
    Prancha 02 da biblioteca de componentes: botões primário, secundário, fantasma e perigo nos estados padrão, hover, foco e desabilitado; controle segmentado de intervalo, alternância USD/BRL e chips de indicador; campos de formulário padrão, com foco e com a mensagem de erro do Zod; estados de dados com o aviso de dado defasado, a caixa de erro do limite de requisições (HTTP 429) com botão de tentar de novo, o estado vazio e o toast de confirmação; e sinais de variação, tendência, RSI por faixa e chips de ressalva.
  9. Visualização de dados

    Os componentes de visualização de dados são reutilizados nas telas de moeda, carteira e screener.

    Prancha 04 de visualização de dados com valores fictícios: cartão do gráfico de candles com SMA 20, EMA 50, Bollinger, volume e MACD; rosca de alocação com legenda em porcentagem; linhas do screener com variação, RSI colorido por faixa, tendência e sparkline de 7 dias; e matriz de correlação com escala de −1 a +1.
    Prancha 04 de visualização de dados com valores fictícios: cartão do gráfico de candles com SMA 20, EMA 50, Bollinger, volume e MACD; rosca de alocação com legenda em porcentagem; linhas do screener com variação, RSI colorido por faixa, tendência e sparkline de 7 dias; e matriz de correlação com escala de −1 a +1.
  10. Anatomia do StatTile

    A anatomia do StatTile e do MetricInfo mostra medidas, estados e a fonte única da metodologia.

    Prancha 03 de anatomia: stat tile do Sharpe ampliado duas vezes com pinos numerados para superfície, raio e respiro, rótulo, gatilho de informação, valor e dica; os estados do gatilho fechado, hover, foco e aberto; o popover de metodologia com fórmula, janela, como ler, armadilha e fonte marcados de A a D; e o fluxo da fonte única, do arquivo de métricas ao popover, à página de ajuda e ao teste de revisão.
    Prancha 03 de anatomia: stat tile do Sharpe ampliado duas vezes com pinos numerados para superfície, raio e respiro, rótulo, gatilho de informação, valor e dica; os estados do gatilho fechado, hover, foco e aberto; o popover de metodologia com fórmula, janela, como ler, armadilha e fonte marcados de A a D; e o fluxo da fonte única, do arquivo de métricas ao popover, à página de ajuda e ao teste de revisão.
  11. Arquitetura

    O quadro segue uma atualização da tela Mercado de 1 a 12: o navegador nunca chama a CoinGecko nem a Binance, toda cotação passa pelas funções na região gru1, com limite por IP, cache com dedupe e o dado anterior na falha, e a tela mostra a idade do dado.

    Quadro de arquitetura do Cripto Terminal no estilo de um board do Miro, do toque ao provedor, com os números 237 testes automatizados em Vitest, 23 métricas com fórmula, janela e armadilha, 250 ativos cobertos pelo screener, 1 chamada por minuto por moeda para os 250, no máximo 2 chamadas ao provedor com a API no limite e 5 tentativas de código por IP a cada 15 min. Seis zonas: Cliente, a PWA instalável com as telas em Next.js 16 App Router, TanStack Query, o núcleo de análise em TypeScript puro que roda no navegador, o Zustand persistido com reidratação validada, o AlertWatcher e o service worker; Vercel, com o proxy que confere o cookie de acesso e emite a CSP com nonce, a CDN, as páginas SSR, as variáveis de ambiente validadas e as funções na região gru1 (São Paulo): handleRoute com token bucket por IP, cache em memória com dedupe e o dado anterior por até 15 min na falha, clientes da CoinGecko e da Binance validados com Zod, fetchJson com timeout e retentativa controlada, login, candles com fallback, Route Handlers e logs JSON; Provedores de dados, a CoinGecko API v3 e a Binance API spot, que responde HTTP 451 para IPs dos EUA, por isso as funções rodam em gru1; CI/CD com o ci.yml e o deploy por push na main; Segurança, fechada por padrão; e Decisões e trade-offs em notas adesivas. A jornada de uma atualização da tela Mercado é numerada de 1 a 12, e os fluxos A, B e C mostram o acesso por código, os candles com fallback e a entrega.
    Quadro de arquitetura do Cripto Terminal no estilo de um board do Miro, do toque ao provedor, com os números 237 testes automatizados em Vitest, 23 métricas com fórmula, janela e armadilha, 250 ativos cobertos pelo screener, 1 chamada por minuto por moeda para os 250, no máximo 2 chamadas ao provedor com a API no limite e 5 tentativas de código por IP a cada 15 min. Seis zonas: Cliente, a PWA instalável com as telas em Next.js 16 App Router, TanStack Query, o núcleo de análise em TypeScript puro que roda no navegador, o Zustand persistido com reidratação validada, o AlertWatcher e o service worker; Vercel, com o proxy que confere o cookie de acesso e emite a CSP com nonce, a CDN, as páginas SSR, as variáveis de ambiente validadas e as funções na região gru1 (São Paulo): handleRoute com token bucket por IP, cache em memória com dedupe e o dado anterior por até 15 min na falha, clientes da CoinGecko e da Binance validados com Zod, fetchJson com timeout e retentativa controlada, login, candles com fallback, Route Handlers e logs JSON; Provedores de dados, a CoinGecko API v3 e a Binance API spot, que responde HTTP 451 para IPs dos EUA, por isso as funções rodam em gru1; CI/CD com o ci.yml e o deploy por push na main; Segurança, fechada por padrão; e Decisões e trade-offs em notas adesivas. A jornada de uma atualização da tela Mercado é numerada de 1 a 12, e os fluxos A, B e C mostram o acesso por código, os candles com fallback e a entrega.

Funcionalidades e as dores que resolvem

Cada funcionalidade nasceu de um problema real da operação.

  1. 01

    Risco da carteira

    Dor
    Quem investe em cripto acompanha a carteira entre o app da corretora e uma planilha, e as ferramentas gratuitas em português que avaliei mostram preço e peso de cada ativo, mas não o risco da carteira como um todo.
    Solução
    O painel busca a série diária de 90 dias de cada posição na CoinGecko (até 14 ativos, mais o BTC de referência) e calcula, em TypeScript puro e testado, volatilidade anualizada, Sharpe, Sortino, drawdown máximo, VaR 95%, beta em relação ao BTC, concentração HHI e a matriz de correlação. Chips expõem as premissas, e o chip da amostra fica amarelo abaixo de 60 retornos.

    Impacto: 7 medidas sobre 90 dias de retornos diários, mais a concentração (HHI)

  2. 02

    Posições e P&L

    Dor
    Sem preço médio e cotação no mesmo lugar, P&L, custo e alocação dependem de atualização manual, e numa versão anterior do app um ativo fora do top 250 valia 0 sem aviso.
    Solução
    Cada posição guarda quantidade, preço médio e a moeda em que foi digitada; a tela calcula patrimônio, P&L, variação de hoje e alocação em rosca. Ativos fora do top 250 são cotados à parte, e a posição sem cotação é marcada e sai do cálculo de risco.

    Impacto: Sem cadastro: quantidades e preços médios ficam só no aparelho

  3. 03

    Métricas explicadas (ⓘ e Ajuda)

    Dor
    As ferramentas de mercado raramente dizem com que janela e sobre quantos dados um número foi calculado, e a documentação, quando existe, fica fora do gráfico e em inglês.
    Solução
    Um único arquivo tipado descreve cada métrica (fórmula, janela real, como ler, armadilha, fonte, data de revisão) importando as constantes do próprio código, e gera os popovers Radix das telas e a página /ajuda. Testes falham com texto sem revisão há mais de 12 meses ou com verbos de recomendação.

    Impacto: 23 métricas com fórmula, janela e armadilha

  4. 04

    Gráfico de candles com indicadores

    Dor
    Os indicadores técnicos costumam aparecer sem a janela em que foram calculados, e hospedado na região padrão (EUA) o app nem receberia candles: a Binance responde HTTP 451 a servidores americanos.
    Solução
    Candles da Binance em lightweight-charts com SMA 20, EMA 50, Bollinger, RSI e MACD calculados em TypeScript, e a leitura técnica logo abaixo; as funções rodam na região de São Paulo (gru1). Ativo sem par na Binance recebe candles diários sintetizados da CoinGecko, marcados na tela.

    Impacto: 5 intervalos, de 15 minutos a 1 semana

  5. 05

    Screener

    Dor
    Filtrar por RSI e tendência no mesmo universo da carteira exigiria candles de centenas de ativos, o que estouraria o limite da API pública.
    Solução
    Filtros de market cap, variação de 24h, RSI 14 horário e tendência contra a SMA de 24h, com ordenação, calculados sobre a sparkline horária de 7 dias que já vem na listagem da CoinGecko. Uma nota informa de qual série o RSI sai.

    Impacto: Top 250 filtrado sem nenhuma chamada extra

  6. 06

    Mercado

    Dor
    O panorama do mercado fica no CoinGecko, e a carteira e os gráficos, em outras ferramentas.
    Solução
    A tela inicial reúne market cap global, volume de 24h, dominância do BTC, maiores altas e baixas de 24h, busca e a tabela do top 100 com variação de 1h, 24h e 7 dias e sparkline de 7 dias.

    Impacto: Top 100 fatiado da mesma chamada do top 250

  7. 07

    Alertas de preço

    Dor
    Acompanhar um preço-alvo exige olhar a cotação o tempo todo, e um alvo definido em dólar não pode mudar de valor quando a tela passa a mostrar reais.
    Solução
    O alerta (acima ou abaixo) guarda a moeda em que foi criado e é avaliado nela a cada atualização de 60 s enquanto a tela Mercado ou Watchlist está aberta e visível, convertendo pelo câmbio; sem câmbio, não avalia. Dispara uma vez com toast e notificação do navegador, se autorizada, e rearmar não apaga o histórico.

    Impacto: Guarda os últimos 20 disparos por alerta; a tela mostra os 3 mais recentes

  8. 08

    USD e BRL

    Dor
    Cotações de cripto vêm em USD e a carteira pode ter sido registrada em BRL; sem guardar a moeda de origem, trocar a moeda de exibição distorce custo e P&L.
    Solução
    Uma alternância USD/BRL, salva no aparelho, pede as cotações da CoinGecko já na moeda escolhida (os candles da Binance seguem em USDT) e converte preços médios pelo câmbio implícito (market cap global em BRL ÷ em USD), que a página de Ajuda documenta com fórmula e armadilha.
  9. 09

    Idade do dado e limite de API

    Dor
    Sem chave, a API da CoinGecko responde HTTP 429 depois de poucas requisições; o app mostrava o erro cru, e uma única atualização, com a API já no limite, podia virar até 9 chamadas ao provedor.
    Solução
    Toda chamada passa pelo servidor, com cache LRU compartilhado (pedidos iguais em andamento viram um só, e o dado anterior é servido em caso de erro), limite por IP (120 de pico, 2 por segundo) e no máximo uma nova tentativa no 429. A tela Mercado mostra "atualizado há X min" e, se for o caso, o aviso de dado defasado.

    Impacto: Com a API no limite, no máximo 2 chamadas ao provedor por requisição

  10. 10

    Acesso e segurança

    Dor
    A ferramenta é de uso pessoal, sem contas e com orçamento zero: aberta na internet, qualquer script consumiria a cota de API, e um script injetado leria as posições salvas no navegador.
    Solução
    Um proxy exige o código antes de qualquer tela ou API (Ajuda e Privacidade seguem públicas), validado com Zod, comparado em tempo constante e trocado por um cookie HttpOnly assinado com HMAC-SHA256, válido por 30 dias. O mesmo proxy emite CSP com nonce por requisição e strict-dynamic, além de nosniff, X-Frame-Options e Referrer-Policy.

    Impacto: 5 tentativas por IP a cada 15 min (limite por instância)