Estudo de caso: trading algorítmico com Go
(massive.com)- Caso de um projeto pessoal que construiu em Go um bot de trading de varejo que monitora em tempo real mais de 5.500 ações listadas na NYSE e na NASDAQ e executa negociações automaticamente
- No início, o sistema perdia dinheiro rapidamente, mas, após anos de tentativa e erro, evoluiu para um nível de ponto de equilíbrio, chegando às vezes a gerar lucro
- É composto por três componentes principais: provedor de dados, aplicação em Go e corretora; processa em memória mais de 60 mil eventos por segundo na abertura e no fechamento do mercado
- Lições obtidas na prática são centrais, como testar o sistema com compras aleatórias, geração própria de candles baseada em tick bars e migração para processamento em memória
- Um caso que mostra a complexidade prática e as possibilidades de construir uma plataforma pessoal de trading na interseção entre finanças, programação e análise de dados
Contexto e motivação do projeto
- Partiu de uma ideia de seguir tendências: executar e gerenciar automaticamente cerca de 500 trades de curto prazo em todo o mercado acionário e obter pequenos lucros em cada operação
- A automação começou por causa das limitações do trading manual
- O risco de investir todo o capital em uma única ação era extremamente alto, mas monitorar dezenas de apostas de curto prazo ao mesmo tempo estava além da capacidade humana
- Entradas e saídas rápidas só eram possíveis em ações de alta liquidez, e era necessário comprar pequenas quantidades para obter execução rápida
- O gerenciamento de posições também era um grande desafio: acertar o timing de entrada e saída em mais de 25 apostas simultâneas era muito complexo
- Havia um problema de escalabilidade, pois o número de apostas precisava aumentar conforme o tamanho do capital crescia
- Necessidade de calcular rapidamente custos de transação como spread, comissões, slippage, taxas de API e impostos para avaliar a viabilidade de cada operação
Estrutura da solução
- Ao longo de vários anos, foi desenvolvida uma ferramenta automatizada que monitora em tempo real mais de 5.500 ações da NYSE e da NASDAQ e toma decisões rápidas de trading
- Roda em um sistema gamer de alto desempenho com Linux: 16 núcleos, 128 GB de RAM, 8 TB de armazenamento NVMe, internet de 1 Gbps
-
Três componentes principais
- Data Provider (Massive.com): cobre dados históricos e em tempo real de todo o mercado, com API e documentação intuitivas e amigáveis para desenvolvedores. Modelo de preços simples que permite acesso a todos os dados de mercado sem limitações artificiais
- Aplicação em Go: motor central que coleta e interpreta feeds de dados, toma decisões de trading calculadas e envia ordens de compra e venda para a API da corretora
- Broker (Interactive Brokers): responsável pela execução das ordens, oferecendo uma API simples
-
Por que escolher Go
- Embora o setor de hedge funds dependa de C++ e Python, a escolha recaiu sobre Go, usado pelo autor há anos e que demonstrou excelente adequação para processamento de fluxos de dados e integração com APIs
Principais funcionalidades da aplicação em Go
-
Data Ingestion Loop
- Coleta continuamente dados em tempo real de mais de 5.500 ações por meio da Massive.com
- No início houve uma tentativa de salvar em banco de dados, mas a abordagem não conseguia processar mais de 60 mil eventos por segundo na abertura e no fechamento do mercado, levando à migração completa para processamento em memória
-
Build Our View Of The Stock Market
- Constrói, com os dados coletados, uma visão em tempo real e em memória de todo o mercado, acompanhando preços, spreads, atividade de negociação etc.
- Permite identificar e negociar oportunidades antes das notícias tradicionais
- Dá acesso à atividade de negociação no pré-mercado, mercado regular e after-hours
-
BUY Signal Loop
- Ao identificar uma oportunidade, envia uma solicitação de ordem de compra para a API da corretora
- Não é apenas um gatilho simples: realiza cálculos prévios como estimativa de lucro baseada no spread, determinação da quantidade necessária de ações e inclusão de comissões e impostos
- Inclui lógica para situações como variação de preço, execução parcial e cancelamento de ordens
-
Position Tracking System
- Loop que monitora continuamente as posições em carteira, comparando em tempo real a tabela de posições com os preços atuais para acompanhar ganhos e perdas
- Pela GUI, é possível verificar o motivo do acionamento de uma operação, o estado atual e o momento de venda
- Desempenha papel essencial no refinamento das lógicas de BUY e SELL
-
SELL Signal Loop
- Quando detecta bom lucro ou perda excessiva, executa uma ordem de venda via API da corretora
- Inclui lógica complexa, como atualizações de preço de ações que se movem rapidamente e tratamento de execuções parciais
Interface web e capturas de tela
- Pela interface web integrada, é possível explorar todas as estruturas de dados, visualizar dados e verificar o motivo dos gatilhos de negociação e o estado atual
- Tela de visão geral do mercado inteiro mostrando preços, spreads etc. de mais de 5.500 tickers
- Página de símbolo individual, por exemplo Tesla TSLA, exibindo tick bars e informações relacionadas
- Interface que mostra a proporção de vitórias/derrotas e as posições abertas no momento, com cerca de US$ 900 de prejuízo em uma sessão de exemplo
- Tela que mostra metadados e gráficos de negociações em tempo real, com o ponto de compra marcado por uma linha laranja
- Tela de logs do console que registra eventos em tempo real, como ordens de compra e venda
Desenvolvimento de estratégia e backtesting
- A aplicação em Go, a estratégia e o backtesting são tratados como três elementos principais separados
- A maior parte das discussões se concentra em estratégias, como reversão à média, seguimento de tendência e regressão linear, e em backtesting, mas a prática e a logística de implementar estratégias em trading intradiário em tempo real tendem a ser negligenciadas
- Usa a ampla base de dados históricos de negociações e cotações da Massive.com para explorar estratégias e fazer backtesting em Python, motivo para usar 8 TB de armazenamento NVMe
- O backtesting é comparado a “dirigir para frente olhando pelo retrovisor”, mas é um meio valioso de validação como base para decisões sobre spreads, impostos, comissões e pontos de entrada e saída
- Insights obtidos no desenvolvimento de estratégias e no backtesting são convertidos na lógica do BUY Signal Loop
Exemplo de código
- Inclui pseudocódigo de alto nível e amostras reais de código Go; a aplicação real tem cerca de 7.000 linhas
- Principais estruturas de dados: TrackedSymbols (mapa completo de símbolos, flag de ativação de trading, lock global), Symbol (dados brutos de negociações e cotações, Aggregate, Position etc.), TradeEvent, QuoteEvent, Aggregate, Position
- Estrutura do loop principal
- Coleta dados de negociações e cotações por conexão WebSocket e faz o parsing dos eventos
- Salva no mapa de símbolos e combina dados de negociações e cotações em Aggregates
- Envia sinais para a lógica de compra e venda por canais Go
- Fornece, via servidor HTTP, funções para consultar todos os símbolos, posições e watchlists personalizadas
Principais lições (Lessons Learned)
-
Entender abstrações
- A NYSE e a NASDAQ não são um sistema único, mas um grande sistema distribuído composto por mais de 19 bolsas
- Dados de candlestick são uma enorme abstração criada a partir dos dados brutos de negociações (ticks), e entendê-la em profundidade é essencial
- Regras diferentes se aplicam a cada janela de negociação do mercado, como pré-mercado, mercado regular e after-hours
-
Gerenciamento de ordens
- Não se trata apenas de enviar ordens simples de compra e venda: dimensionamento prévio de posição, capacidade de negociar rapidamente, gerenciamento simultâneo de mais de 25 posições, cálculo de impostos e comissões, gerenciamento de slippage e monitoramento do status das ordens contribuem para um trading bem-sucedido
-
Casos de borda
- Há inúmeros casos de borda, como execução, rastreamento, modificação, cancelamento e execução parcial de ordens, além de interrupções de negociação no mercado; se forem ignorados, podem causar prejuízo financeiro
- É indispensável testar com paper trading (simulação) em vez de dinheiro real
- Experiência de comprar no topo uma ação que havia subido 40% no pré-mercado e depois despencou, resultando em perda de 40% em poucos minutos por falha ao ajustar a ordem de venda. No pré-mercado e no after-hours, as regras diferem das do mercado regular, e oscilações extremas podem ocorrer rapidamente
-
Uso de compras aleatórias
- Mais importante do que descobrir uma estratégia secreta é testar as funcionalidades centrais do sistema
- Executar 1.000 compras aleatórias de ações por dia durante uma semana permite validar de forma eficaz a lógica de compra e venda, o gerenciamento de execuções parciais, a lógica de cancelamento e o sistema de acompanhamento de posições
- Integrar compras aleatórias ao processo de teste em uma conta de paper trading é uma forma eficiente de verificar vários aspectos do sistema ao mesmo tempo
-
Tick bars vs time bars
- Barras de candlestick fornecidas por corretoras cobrem intervalos de tempo fixos, por exemplo 30 segundos, mas em movimentos bruscos do mercado há o problema de que 100 negociações e milhares de negociações podem se misturar no mesmo intervalo
- Com dados brutos de ticks e cotações, é possível construir barras próprias baseadas no número de negociações, oferecendo resolução muito maior em períodos de alta atividade, como abertura e fechamento do mercado, e permitindo adicionar métricas personalizadas como spread
-
Migração para processamento em memória
- A abordagem inicial com banco de dados não suportava os grandes picos de atividade na abertura e no fechamento do mercado
- Migração completa para uma abordagem em memória usando um mapa grande com mutex locks, resolvendo problemas de escalabilidade
- A estrutura que contém todos os dados é salva como arquivo gob compactado para armazenamento e pode ser recarregada na reinicialização. Ao longo de um dia, cresce para mais de 40 GB, e foi necessário aplicar um patch no build do Go para dar suporte a dumps gob desse tamanho
- Após a experiência de perder todos os dados de estado em produção por causa de uma queda de energia, a adoção de uma fonte de alimentação ininterrupta (UPS) tornou-se essencial
-
Complexidade e solidão
- Um projeto muito mais desafiador e demorado do que o esperado, que evoluiu de um pequeno hobby para uma obsessão séria
- Pode ser solitário, pois tudo se resume a aumentar o saldo da conta, e envolve uma montanha-russa emocional extrema
-
Uso combinado de Go e Python
- Abordagem híbrida: o sistema de trading é escrito em Go, enquanto a exploração de dados usa o amplo ecossistema de bibliotecas de ciência de dados do Python
-
Uso de um PC pessoal
- PCs desktop modernos, com otimização suficiente, são poderosos o bastante para lidar com o monitoramento em tempo real de todo o mercado acionário
-
Uso do ChatGPT
- Em vez do método anterior de depender de buscas e leituras quando não se sabia como resolver um problema, passou-se a descrever o problema ao ChatGPT, perguntar como resolvê-lo e até pedir geração de código, resultando na percepção de aumento de produtividade de 3x
Experiência com eventos de mercado
- Diversas anomalias de mercado, como o episódio das meme stocks, grandes eventos de IPO, altas e quedas fortes do mercado, notícias do Fed e aumentos de juros, puderam ser detectadas pelo próprio sistema e verificadas antes das notícias
- Uma experiência como estar em um assento na primeira fila vendo eventos de mercado se desenrolarem diante dos olhos
1 comentários
Comentários do Hacker News
Trabalhei por um tempo com HFT, e todo esse campo era realmente fascinante; fiquei contente em ver que o autor do post original sentiu uma diversão parecida
O motivo de a plataforma em si muitas vezes ficar de fora das discussões é que trading é uma área onde alta tecnologia, complexidade, regulação pesada e concorrência extrema se concentram ao mesmo tempo
Construir um sistema de entrada de ordens, um sistema de gestão de risco e um sistema de rastreamento de posições já é, por si só, uma grande conquista, mas do ponto de vista de uma firma de trading isso já fica perto do custo de entrada
Por isso as pessoas falam de estratégia. A plataforma básica todo mundo já tem; agora a questão é encontrar um jeito de ganhar dinheiro com ela
Além disso, os participantes do mercado nem estão jogando o mesmo jogo. Em HFT, competíamos por alfas de poucos segundos, tirando nanossegundos em FPGA e microssegundos em redes sem fio de Nova Jersey, enquanto bancos se preocupam mais com eleições e geopolítica do que com o clima em Carteret. Se chove, naquele dia a rede de micro-ondas não funciona
No meio disso há inúmeras estratégias buscando alfa que dura de algumas horas a algumas semanas, então fica difícil até falar a mesma língua em um fórum público. Ainda assim, é um mundo interessante e às vezes sinto falta dele
Já a estratégia é a parte que exige descoberta. Há algumas estratégias bem conhecidas que ainda são lucrativas, mas em geral as maiores empresas já ficaram com elas, e o resto é exploração. Algumas estratégias só dão lucro em regimes de mercado muito curtos
Eu também às vezes sinto falta, mas ficou tão consolidado que agora é, em grande parte, o mundo das grandes firmas
Parece que a maior parte disso fica em silos dentro de cada empresa e não é discutida fora
HFT está jogando um jogo completamente diferente. Li sobre a arquitetura das bolsas e a fiação real, e eu recebo dados via SIP, enquanto HFT se conecta direto à bolsa [1]
Eu opero em segundos, e HFT, como foi dito, opera em microssegundos, então não dá para comparar. Em certo sentido, até gosto de não competir diretamente com eles. Ou talvez eu esteja competindo, mas ainda assim dê para ganhar um pouco de dinheiro
[1] https://www.researchgate.net/figure/Latencies-in-the-Electro...
Minha dúvida é se, basicamente, é fazer o medium-frequency trading mais rápido, ou se há vantagens específicas, como ganhar prioridade na fila de ordens
Se alguém tiver perguntas sobre este projeto, posso responder. Começou como um projeto paralelo e acabou virando uma obsessão completa
O sistema em si não tem tantos segredos, e o ponto principal é ter uma plataforma sólida na qual se possa encaixar estratégias
Talvez eu até possa abrir o código como open source, mas antes teria que limpar todos os hacks que enfiei nele
O Tech Trader se apresenta como um sistema de trading totalmente autônomo que opera com dinheiro real há mais de 10 anos sem intervenção humana nem atualizações
A explicação é que ele difere dos sistemas algorítmicos tradicionais porque não usa abordagem quantitativa, arbitragem estatística nem alta frequência, e sim observa ações de forma parecida com a de um humano, mas com a disciplina fria e o foco infinito de uma máquina
Desde o lançamento em dezembro de 2012, ele teria feito trading totalmente automatizado com capital real, e a pessoa que o criou seria um único desenvolvedor autodidata que usa o nick de jogo pftq
Queria saber se você poderia compartilhar a abordagem para encaixar várias estratégias. Um sistema de estratégias em estilo plugin pode atravessar várias camadas e ficar complicado rapidamente
Também queria saber se, no backtest, você armazena todos os dados de ofertas/ticks para reproduzi-los depois, ou se usa apenas dados históricos agregados
Depois de ler o texto, pensei em talvez montar algo com WebSocket da Polygon, mas vi que o primeiro pacote com funcionalidade de WebSocket custa 29 dólares, e o pacote Advanced com dados em tempo real custa 200 dólares por mês
Dados em tempo real com chamadas ilimitadas de API parecem bem interessantes, mas minhas estratégias, com um tamanho de capital típico, têm no máximo uns 78% de taxa de acerto, então seria difícil justificar 200 dólares por mês
Gostaria de saber qual pacote você usa e quais são os prós e contras dele. Se preferir responder por e-mail, está no meu perfil
Não sei se a IB envia o feed de preços em tempo real. A tela da TWS fica se atualizando o tempo todo, então parece que os dados são enviados em tempo real, mas queria saber se o book de ofertas também é disponibilizado pela API
Sei que este texto foi publicado no blog da polygon.io, mas fiquei curioso se a estrutura poderia funcionar só com a API da IB/TWS mesmo
Um dos conceitos mais mal compreendidos em trading algorítmico é que, na maioria dos sistemas, velocidade não é o fator decisivo
Modelos como o meu sistema, https://grizzlybulls.com/models/vix-ta-macro-mp-extreme, superaram o mercado com folga em operações reais por mais de 3 anos, mas em média operam só uma vez a cada 18 pregões e geram sinais apenas perto de viradas em janelas horárias
Os últimos 18 meses foram mais fracos do que o início por causa de uma grande mudança estrutural, com inflação alta e rápida alta dos juros, mas desde o lançamento do site em janeiro de 2022 rendeu +14,11%, enquanto o SPX ficou em -7,83%
Isso foi feito sem alavancagem, e no mesmo período o drawdown máximo também foi menor, em -16,48%, contra -27,57% do SPX
É uma apresentação montada para fazer parecer que o modelo realmente superou muito o mercado. Se você realmente tem uma mina de ouro inexplorada, isso é impressionante, mas pessoalmente acho difícil acreditar por causa de alguns sinais de alerta
Se você tem interesse em trading algorítmico, vale a pena olhar o Collective2. É um lugar onde engenheiros oferecem sinais de compra e venda mediante assinatura
Parece uma espécie de liga menor do trading algorítmico e é bem interessante
Como o sistema acompanha lucro e prejuízo, é difícil fraudar o relatório de desempenho, e se você autorizar o Collective2 a acessar sua conta da Interactive Brokers, ele pode executar os sinais de trade por você
O serviço existe há pelo menos 10 anos, então dá para ver desempenho de longo prazo, mas a maioria dos sistemas não dura tudo isso
https://collective2.com/leader-board
Mesmo os líderes atuais quase nunca permanecem no topo por muito tempo, em geral só 1 a 2 anos. Isso mostra que o alfa da maioria dos sistemas desaparece bem rápido
As curvas de retorno também são irregulares, e a estrutura é de que algumas poucas operações respondem pela maior parte do lucro
Ao desenvolver um sistema de trading automatizado, os eixos importantes são feed e coleta de dados, geração de features, geração de sinais, execução real das operações e gestão de ordens, além da orquestração de tudo isso
Dados brutos raramente são usados diretamente na tomada de decisão, e uma boa geração de features costuma ser o principal fator de sucesso. Média móvel é um exemplo, mas hoje em dia isso por si só quase não funciona mais
Este texto mostra o lado técnico de processar dados e gerenciar ordens, além do pipeline como um todo, mas eu gostaria que houvesse mais detalhes sobre escalar a solução e a implementação assíncrona
Principalmente por usar Go, fiquei ainda mais curioso por causa da estrutura de canais adequada a esse objetivo
Entendo que esse não é o foco do texto, mas também teria sido útil alguma informação geral sobre a lógica de trading, como plugar novas estratégias e como parametrizar estratégias existentes
Os links do final foram interessantes, e eu estou desenvolvendo um bot de trading inteligente baseado em machine learning e engenharia de features (https://github.com/asavinov/intelligent-trading-bot), então textos assim podem ser importantes
A estrutura é simples: componentes se comunicam com goroutines e channels, e tudo é protegido com um grande mutex
Quando entram novos dados, ele gera os agregados necessários, isto é, candlesticks baseados em ticks, e esses dados disparam o loop da lógica de BUY. Se algo for detectado, isso gera uma ordem pela API da IB
É tudo muito simples, nada muito complexo. Já acompanhei mais de 100 posições ao mesmo tempo e simplesmente funcionou, então não mexi muito com lógica assíncrona mais complexa
Os parâmetros na prática estão hardcoded dentro do loop de BUY. Pode soar estranho, mas em uma configuração pequena isso não muda com tanta frequência
A ideia é rodar alguns trades, ajustar os valores, reiniciar e testar de novo. Em um ambiente enterprise talvez houvesse uma linguagem formal ou hot loading, mas no meu caso hardcode já funciona bem o suficiente
Nem o Go em si nem qualquer outra linguagem traz uma grande vantagem. O que traz vantagem é o algoritmo de trading, e isso é sempre difícil de encontrar
Passei meses procurando os parâmetros ideais, mas no fim eles só funcionavam em dados históricos, e na prática era tudo completamente diferente
Se o algoritmo e a estratégia forem perfeitos, até Visual Basic pode ser melhor do que Go, Rust ou qualquer outra linguagem. A linguagem é só uma ferramenta
Foi bom usar Go, mas o título pode ser um pouco enganoso. As pessoas podem entender isso como algum tipo de vantagem, mas não é o caso
E, para HFT, não acho que uma linguagem com coletor de lixo seja uma boa escolha
Como desenvolver essa lógica, ou seja, a estratégia, manualmente é obviamente difícil, eu criei um bot de trading inteligente que deriva estratégias de trading a partir de dados históricos
https://github.com/asavinov/intelligent-trading-bot
Atualmente ele funciona com cripto, mas pode ser aplicado a outros mercados
https://t.me/intelligent_trading_signals
Funcionar bem só em dados históricos e divergir da realidade é uma situação típica. O ponto principal é criar uma estratégia que funcione também em dados futuros ainda não vistos
O algoritmo de backtest também deve ser projetado para que dados futuros não vazem para o passado
No setor, C++ e Python são muito usados, então usar Go pode até ser uma desvantagem, mas era a linguagem que eu sabia usar
Não foi minha intenção causar mal-entendido. Go se encaixa muito bem em receber e processar dados e chamar APIs remotas, então na prática funcionou bem
Porém, se você estiver tentando conseguir emprego com base nisso, provavelmente não vai ajudar muito
Há lugares que usam Java e pré-alocam toda a memória necessária logo no início. A Jane Street também é famosa por usar OCaml
Assim, o desempenho fica bem bom e você não precisa se preocupar com bugs de memória
Depois de experimentar por algum tempo com dados históricos, a utilidade desses dados diminui
Estou fazendo bots em TypeScript porque é a linguagem que conheço, e em Python porque há muitas ferramentas
É um trabalho muito esmagador e solitário. Em outros projetos eu sempre trabalhei em equipe e, mesmo quando o time era bem pequeno e o trabalho autônomo, pelo menos havia reuniões e standups de vez em quando
Já faz 6 meses que estou fazendo isso sozinho, então pensei em chamar um amigo para participar só para não ficar sozinho
Como é um projeto paralelo, talvez eu não consiga avançar muito, mas topo conversar a qualquer momento
A única forma que consigo imaginar é obter dados que eles não têm
Acho este artigo totalmente sem sentido e caça-cliques. Em resumo, seria algo como: “você pode usar o polygon.io para dados de mercado, mas trading algorítmico continua difícil de qualquer forma, então ainda não há muito para compartilhar”
Pessoalmente, eu queria compartilhar a estrutura de alto nível de montar o próprio sistema. Quando caí nessa toca do coelho, pensei que teria sido bom existir um artigo assim
Se você me disser o que poderia ter sido incluído para melhorar, terei prazer em incorporar
Vale a pena encontrar pessoas que curtam o loop de feedback puro entre código, estratégia e dinheiro que o trading oferece
Tenho estudado timing e correlações entre ações e índices como fonte de alfa, e tenho tido algum sucesso
Agora estou tentando automatizar esse processo, e realmente gosto muito do trabalho em si
Não estou tentando atuar como formador de mercado nem ficar pulando de ativo em ativo. Estou focado em refinar um modelo preciso para rentabilizar muito bem alguns poucos ativos
Ferramentas úteis incluem TradingView e indicadores/estratégias em Pinescript, modelos em Excel com dados exportados para backtesting, Python e Go para machine learning no backend e ChatGPT para iterar código novo rapidamente
Se tiver interesse, gostaria de conversar em trading @ dianazink.com
Bom artigo, gostei da explicação concreta e principalmente das capturas de tela
Entendo não entrar em detalhes sobre a estratégia, mas queria saber se as operações são inteiramente baseadas em análise técnica ou se você usa dados externos ou feeds de dados alternativos
Em outras palavras, queria saber se é um sistema quase fechado, com entrada do Polygon e saída pela API da IB, ou uma configuração mais ampla que inclui feeds de dados personalizados como sites de notícias, Twitter e Reddit
Se for o segundo caso, também tenho curiosidade sobre como você equilibra isso com o backtesting histórico quando a cobertura histórica de algumas fontes de dados é parcial
Recentemente, venho olhando uma forma de usar tabelas de consulta com valores históricos pré-calculados para detecção de anomalias, por exemplo, para julgar coisas como “essa atividade é normal neste ativo?”
O BXRX de hoje é um bom exemplo [1]
Também estou analisando atividade de opções para tentar usá-la como sinal
[1] https://www.google.com/search?q=BXRX