Criando o seu primeiro ROBÔ – V1
Introdução
Neste documento vamos ver passo a passo de como criar o seu primeiro robô no Profit Chart DO ZERO…Você verá que com metodologia, organização e boas referências, programar um robô é uma tarefa relativamente fácil! Os verdadeiros desafios estão em outras partes do processo, e que abordaremos em outras oportunidades.
Eu já te prometo, desde já, que eu não vou te passar nenhum setup milagroso para te fazer rico. O objetivo deste documento não é te vender ilusões ou qualquer curso que seja. Eu quero te apresentar como eu vejo o processo de criação de um robô, que metodologia eu utilizo e você terá a real noção das dificuldades que enfrentará para desenvolver o seu próprio setup automatizado e, que se tudo der certo, um setup lucrativo!
Desde que o mundo é mundo, os vendedores sempre utilizaram a técnica de complicar as coisas para te vender facilidades, isso não é diferente nos dias de hoje…Então eu vou começar simplificando…Vou começar pelo começo! Eu criei o fluxograma abaixo para estabelecer uma linha guia de estrutura do nosso raciocínio.
Metodologia de Desenvolvimento de um Robô
A figura abaixo apresenta o fluxograma da metodologia aplicada no desenvolvimento de um robô. Vamos fazer uma passagem geral sobre a metodologia antes de aprofundar em cada etapa.
Tudo começa pela definição de um algoritmo. É daí que vem o termo algotrading….operações baseadas em algoritmos. No jargão popular, a gente chama de robô…e a Nelógica chama de “Estratégia de execução”…É tudo a mesma coisa!
E como é que achamos um algoritmo? Algoritmos, os bons algoritmos, não são achados por aí pela internet em vídeos de Youtube ou páginas sobre análise técnica. O máximo que você vai encontrar na internet são pessoas falando exatamente a mesma coisa, que são setups baseados em indicadores… quais são os sinais de entrada e sáida de cada setup.
Apesar de haver muito chão a percorrer em termos de teste, validação, otimização e backtesting para pegar setups primários baseados em indicadores e transformá-los em algoritmos com alguma chance de sucesso, frequentemente você verá pessoas “vendendo” esses setups, ou até vendendo cursos, dizendo se tratar de estratégias infalíveis ou com alta taxa de acerto! Quem dera fosse fácil assim!
Quando o negócio é muito bom… Desconfie! Principalmente, se não puder ver o código fonte da estratégia que lhe está sendo recomendada! A verdade é que você pode até começar uma ideia por algum setup básico de análise técnica, mas terá que desenvolver por conta própria adaptações para chegar a um algoritmo capaz de rodar em conta real. E minha dica é: COMECE SIMPLES!
Comece um algoritmo o mais simples possível. Rode as três etapas da metodologia e vá melhorando esse algoritmo em iterações sucessivas. Não tente abraçar o mundo logo na primeira implementação.
Uma vez que você tenha um algoritmo inicial, o próximo passo é escrever o código fonte. Esta etapa tem suas dificuldade técnicas de programação, mas você verá com o tempo que não se tratam das maiores dificuldades que encontrará no meio do caminho para desenvolver o seu robô!
Clique aqui para acessar os Modelos de estratégias, ou aqui para acessar a seção de Snippets!
Uma vez escrito o código fonte do algoritmo, sem erros de sintaxe. A gente vai rodar o robô com os dados disponíveis para verificar a aderência da execução do robô ao que havia sido planejado. Nesta terceira etapa, vamos procurar por erros e falhas no código e, se encontradas, vamos voltar à etapa anterior e ajustar a programação.
Agora que já tivemos uma visão geral das etapas, eu devo salientar que a metodologia de desenvolvimento de um robô não é tão linear como na figura apresentada anteriormente. Você verá que teremos muitas iterações entre as etapas, rodando vários ciclos de adaptações e melhorias até chegar a uma versão de robô madura o suficiente para realizarmos a otimização de parâmetros e backtesting, visando verificar a sua viabilidade de execução em conta real. Mas isso é assunto para outra oportunidade. Por ora, vamos aprofundar em cada etapa nas seções abaixo.
Definindo o seu Algoritmo
Nesta primeira etapa precisamos definir com clareza (até onde podemos) como o robô deverá funcionar. Eu recomendo você abrir um bloco de anotações, físico ou virtual, e anotar suas respostas para as seguintes perguntas:
- Qual ativo pretendo operar?
- Meu robô vai operar comprado, vendido ou nos dois lados?
- Em que frequência gráfica ele vai operar? Ou vai operar de acordo com volatilidade em gráficos do tipo Renko?
- Quais indicadores técnicos vou utilizar?
- Quando ele deve abrir uma posição comprada? Em termos mais técnicos…qual é o sinal de compra? Faça a mesma pergunta para posição vendida! Desenvolva a resposta em termos de condições objetivas!
- Ele vai atuar apenas liquidando a posição ou vai permitir reversão de posição? Quais serão os sinais para cada situação?
- Meu robô vai segurar posição para swing trade ou só vai operar daytrade?
- Se não tiver sinal para liquidar ou reverter posição, como será definido o alvo da operação?
- Como será a administração das operações e a gestão de risco delas? Que técnicas de stoploss serão aplicadas? Vou utilizar stop com breakeven? Stop fixo? Stop móvel (Trailing stop)?
Eu sei que são muitas perguntas! Provavelmente você não tem resposta para todas as perguntas e algumas respostas poderão ser obtidas no processo de otimização da estratégia! O objetivo dessas perguntas é que você faça um brainstorming inicial!
Como a evolução natural nos ensina, a gente precisa se desenvolver de forma incremental! Primeiro a gente faz o simples funcionar e depois vamos aperfeiçoando e ajustando aos poucos…Aliás, essa é a filosofia de muitas diferentes metodologias de desenvolvimento de software… Então, não adianta começarmos pensando no mais complexo! Temos que simplificar ao máximo e escrever o código do nosso robô de forma iterativa, começando pela versão mais simples possível!
Escrevendo o Código-fonte
Esta é uma etapa bem “mão na massa”! Como já mencionei anteriormente, você poderá ganhar bastante tempo se aproveitar da experiência e informações compartilhadas pela Comunidade por meio dos Modelos de Estratégias e Snippets (exemplos de código fonte).
Minha recomendação é que comece o seu código fonte com organização desde o começo. Isso vai lhe ajudar a estruturar melhor, entender mais facilmente quando revisitar seu código ou até para que outra pessoa entenda seu código quando você o compartilhar.
Conte com a Comunidade e os fóruns disponíveis no site para te ajudar nessa etapa!
Verificando a aderência do seu robô
Rodar um robô (estratégia de execução) em dados históricos, é bem fácil no Profit. Basta clicar no botão “Executar” e pronto! Mas fácil não quer dizerque seja bom….tem muita coisa pra melhorar no editor de estratégias! Mas é o que temos por hoje temos que extrair o máximo que dá!
A primeira coisa que fazemos depois de rodar a primeira versão do robô (V1) é fazer uma inspeção visual para identificar erros grotescos de implementação! Por exemplo, você pode abrir o gráfico e não ter nenhuma sinalização de ordem. Ou ter apenas uma… Provavelmente, o seu código estaria com algum problema lógico.
Caso encontrasse algum problema, você teria que voltar ao código e tentar corrigir o problema, utilizando até o debug, que apesar de suas limitações é a ferramenta que dispomos para depurar o código fonte das estratégias.
O segundo filtro para identificar possíveis problemas é acessar a aba “Operações” ou “Gráfico de Operações” do modo “Estatísticas”, e inspecionar por problemas óbvios….Operações com lucros ou prejuízos muito grandes, ou operações com duração muito longa, características das operações que você não esperaria encontrar de acordo com os critérios do seu robô.
Caso encontrasse algum problema, você voltaria ao gráfico de simulação e verificaria a operação problemática, analisando o que pode ter ocorrido de diferente do previsto, inclusive depurando por meio de breakpoints.
Um ponto muito importante nessa etapa é tomar o cuidado para utilizar apenas os 70% dos dados históricos disponíveis e mais antigos. E por que disso? Porque os 30% restante dos dados, que são mais recentes serão utilizados para etapa de backtesting.
É muito importante testar, validar e otimizar seu robô em uma janela de dados distinta da janela de dados de backtesting! A razão é meio óbvia, se você otimizar sua estratégia para todos os dados disponíveis, você pode estar ajustando o robô para as situações específicas daqueles dados e terá por consequência (ou ao menos se espera) que você encontre bons resultados!
O que queremos no backtesting é verificar se o robô é capaz de generalizar bem com outros dados. Então não se esqueça de limitar sua análise nesta etapa de teste apenas aos dados que não serão usados no backtesting!
Colocando o Robô para rodar em conta real!
Executei as etapas 1, 2 e 3! Já posso colocar meu robô para rodar em conta real? Muito provavelmente a resposta é NÃO!
Lembra-se que eu disse que o processo de desenvolvimento de um robô é iterativo? Veja a figura abaixo para entender o que eu quis dizer com isso!
Dificilmente você conseguirá em uma única iteração do processo, chegar a um bom robô! Até pode…mas isso é altamente improvável.
Uma vez desenvolvido o código fonte da primeira versão do robô, vamos analisar o desempenho dele por meio de métricas objetivas, tais como taxa de acerto, relação risco ganho, lucro líquido, máximo drawdown.
Em seguida vamos postular ajustes que poderiam ser feitos para melhorar a métrica desejada. Geralmente, você irá buscar identificar aspectos relacionados à: ponto de abertura das operações, administração dos trades e gestão de risco, ponto de encerramento das operações.
Vamos fazer isso de forma iterativa até que cheguemos a uma situação de desempenho aceitável. É importante ter um diário do que está sendo alterado de uma versão para outra, guardar as principais métricas em uma planilha, bem como salvar o código fonte intermediário para não se perder no meio das iterações. Lembre-se, organização é muito importante para não perder o foco e gastar tempo desnecessário tentando entender o que você fez!
Exemplo de desenvolvimento de um robô
Para dar um exemplo prático e tornar mais tangível o processo de criação de um robô, eu utilizei um caso clássico de setup da literatura de indicadores técnicos para seguir tendência, em inglês, trend following system. Apesar de clássico, ou seja, existe há mais de 1 século, muita gente tira da cartola essa ideia todo ano, como se fosse inovadora.
A primeira versão do setup que iremos trabalhar ao longo deste documento e dos próximos, que vou chamar originalmente de Cruzamento triplo de médias móveis terá as seguintes definições:
- Vai operar no mercado de ações permitindo swing trade;
- Só vai operar comprado;
- Vai utilizar 3 três médias móveis exponenciais de 10 (média rápida), 50 (média intermediária) e 200 (média lenta) períodos;
- Vai operar em gráfico candle 15 minutos
- Sinal de compra será o cruzamento da média intermediaria para cima da média lenta, estando a média rápida acima da média intermediária
- Sinal de liquidação será média rápida cruzando para baixo a média intermediária;
- Na primeira versão não será utilizado stoploss.
Pessoal, só para reforçar…este é um exemplo… não estou preocupado se é uma estratégia lucrativa ou não…Se funciona nos dias atuais ou não…Aliás já adianto que a taxa de acerto de setups básicos de cruzamento de médias é baixíssima…Isso é bom para fins didáticos. Vamos ter muito espaço para explorar!
Assista ao vídeo do Youtube que fizemos sobre a metodologia de criação de um robô e execução da primeira iteração do processo resultando na versão 1 (V1), conforme código fonte abaixo.
No próximo documento iremos realizar, na prática, sucessivas iterações a fim de melhorar o desempenho do algoritmo inicialmente proposto.
Nos vemos lá!
Robô de Cruzamento triplo de média móvel (V1)
Segue abaixo o código fonte gerado para primeira versão do robô de Cruzamento triplo de média móvel.
// #######################################################################
// #######################################################################
// #######################################################################
// ###### O #######
// ###### ____|____ #######
// ###### _| |_ #######
// ###### (_| O O |_) #######
// ###### |_________| #######
// ###### #######
// ###### ____ __ ____________ ________ #######
// ###### | | \ | | | |_________| / ____ \ #######
// ###### | |\ \ | | | | / / \ \ #######
// ###### | | \ \ | | | |____ | | | | #######
// ###### | | \ \ | | | |____| | | | | #######
// ###### | | \ \ | | | |____| | | | | #######
// ###### | | \ \ | | | | | | | | #######
// ###### | | \ \ | | | |_________ \ \____/ / #######
// ###### |_| \_\|_| |_|_________| \________/ #######
// ###### #######
// ###### _______ __ __ ____ __ ___ __ _______ #######
// ###### | | \ /\ | \ | | \ | \ / \ | #######
// ###### | |__/ /__\ | ||__ |__/ |___/ | | | #######
// ###### | |\ / \ | || |\ | \ | | | #######
// ###### | | \ / \|__/ |____ | \ |___/ \__/ | #######
// ###### #######
// ###### Comunidade aberta de automatização de estratégias para #######
// ###### negociação de ativos #######
// ###### #######
// ###### www.NeoTraderBot.com #######
// #######################################################################
// #######################################################################
// #######################################################################
//
// -----------------------------------------------------------------------
// ---------------------- DADOS DA ESTRATÉGIA ----------------------------
// -----------------------------------------------------------------------
//
// NOME DA ESTRATÉGIA: _NBT_EXE_3CROSS
// DESENVOLVIDA POR: Johnathas Carvalho
// DATA DE CRIAÇÃO: 02/10/2022
// VERSÃO: 1.0
// ATUALIZADA EM: 02/10/2022
// TIPO DE ESTRATÉGIA: ( ) Indicador ( ) Coloração (X) Execução
// ( ) Screening ( ) Texto ( ) Alarme
//
// DESCRIÇÃO DA ESTRATÉGIA:
// Estratégia baseada em cruzmaento triplo de média móvel
//
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
//
// ######################### FIM DO CABEÇALHO ############################
//
//
// -----------------------------------------------------------------------
// -------------------------- Constantes ---------------------------------
// OBS:
// -----------------------------------------------------------------------
const
cPlotarIndicadores = true;
//
// ---------------------------------------------------------------------
// -------------------------- Parâmetros -------------------------------
// OBS: Segue abaixo a descriação de cada parâmetro
// 1) pLimiteSobreComprado -> Limite no qual considera-se que o cruzamento
// para baixo gere uma operação de venda
// 2) pLimiteSobreVendido -> Limite no qual considera-se que o cruzamento
// para cima gere uma operação de compra
// 3) pTamanhoPosicao -> Tamanho da exposição ao ativo
// ---------------------------------------------------------------------
//input
// pMediaRapida(10);
// pMediaIntermediaria(50);
// pMediaLenta(200);
// pTamanhoPosicao(100);
// ---------------------------------------------------------------------
// ---------------------- Variáveis globais ----------------------------
// OBS:
// ---------------------------------------------------------------------
var
bStarted : boolean;
bSinalCompra,bSinalVenda,bSinalLiquida : boolean;
bComprado,bVendido : boolean;
fMediaRapida,fMediaIntermediaria,fMediaLenta : float;
//Parametros
pMediaRapida: integer;
pMediaIntermediaria: integer;
pMediaLenta: integer;
pTamanhoPosicao: integer;
begin
pMediaRapida := 10;
pMediaIntermediaria := 50;
pMediaLenta := 200;
pTamanhoPosicao := 100;
// ---------------------------------------------------------------------
// ----------------- Inicialização da estratégia -----------------------
// OBS: Inicialização de variáveis a serem utilizadas na estratégia de
// execuçaõ
// ---------------------------------------------------------------------
if Not bStarted then
begin
bStarted := True;
end;
// ---------------------------------------------------------------------
// ------------------ Inicialização de variáveis -----------------------
// OBS: Inicialização de variáveis p/ cada tick/barra
// Nem todas as variáveis são inicializadas aqui porque se não houver
// dados suficientes não faz sentido inicializar algumas variáveis
// ---------------------------------------------------------------------
bSinalCompra := False;
bSinalVenda := False;
bSinalLiquida := False;
bComprado := isBought();
bVendido := isSold();
fMediaRapida := Media(pMediaRapida,Close);
fMediaIntermediaria := Media(pMediaIntermediaria,Close);
fMediaLenta := Media(pMediaLenta,Close);
//BUG: Se não tiver algum plot antes dos comandos de backtesting, não funciona!
if cPlotarIndicadores then
begin
SetPlotColor(1,clRed);
SetPlotWidth(1,2);
SetPlotStyle(1,psDash);
SetPlotColor(2,clOlive);
SetPlotWidth(2,2);
SetPlotColor(3,clWhite);
SetPlotWidth(3,2);
Plot(fMediaRapida);
Plot2(fMediaIntermediaria);
Plot3(fMediaLenta);
end;
// ---------------------------------------------------------------------
// ----------------------- Cálculo dos sinais -------------------------
// OBS: Inserir lógica de cálculo dos sinais de compra/venda
// ---------------------------------------------------------------------
if (fMediaLenta <> 0) then
begin
if (fMediaRapida >= fMediaIntermediaria)
and (fMediaIntermediaria > fMediaLenta)
and (fMediaIntermediaria[1] <= fMediaLenta[1]) then
bSinalCompra := True;
if bComprado
and (fMediaRapida < fMediaIntermediaria)
and (fMediaRapida[1] >= fMediaIntermediaria[1]) then
bSinalLiquida := True;
end;
// ---------------------------------------------------------------------
// ------------------- Envia ordens de compra/venda --------------------
// OBS: Baseando-se nos sinais e na atual posição, cria as ordens de
// compra e venda de acordo com o setup desejado
// ---------------------------------------------------------------------
// Abre posição comprada
if Not (bComprado Or bVendido) and bSinalCompra then BuyAtMarket(pTamanhoPosicao);
// Encerra posição comprada
if (bComprado and bSinalLiquida) then SellToCoverAtMarket(pTamanhoPosicao);
end;
Artigo muito bom. Obrigado