Por que você precisa de Ciência de Dados para fazer Day Trade

Lucas Tavares
12 min readApr 19, 2021

--

Em janeiro de 2020, resolvi usar aprendizado de máquina para construir um sistema de suporte a operações de Day Trade. Apesar do tempo, só consegui algum ganho relevante após quase um ano trabalhando nesse projeto. Sendo assim, o objetivo desse artigo é mostrar a importância da Ciência de Dados no suporte a operações de Day Trade ou de qualquer outra natureza.

Indústria do Day Trade

É da natureza da raça humana o gosto por oportunidades de ganhos fáceis, independente do entendimento sobre os riscos que buscar tais ganhos pode causar. Por isso existe Loteria, Jogos de Azar, Casas de Apostas e também o Day Trade. Entretanto, não há dúvidas de que existe muito mais conteúdo de análises sobre Day Trade do que todos os outros exemplos juntos, mas por que isso acontece? Por uma razão óbvia: faz sentido!

Mas, imagine se tudo que fizesse sentido fosse, de fato, verdade? Tudo que pudéssemos pensar e consolidar em uma hipótese estaria automaticamente certo… Seria maravilhoso, não? Eu acho que não, mas a verdade é que fazer sentido é o primeiro passo de uma longa jornada de investigação para chegar a conceitos considerados “Estados da Arte” ou seja, mais próximos possível da verdade em um momento na história. Por exemplo, o “Estado da Arte” em relação a prevenção de diversas doenças, é o desenvolvimento de vacinas e imunização em massa, já que vários estudos já mostraram que fazendo isso, o número de casos e mortes decorrentes dessas doenças é o menor possível quando comparado a outras alternativas. Sendo assim, fazer sentido muito raramente vai estar relacionado à verdade, mas quase ninguém vai te explicar isso.

Agora, o que acontece quando temos grande interesse em ganhos fáceis e confiamos em qualquer coisa que faça sentido? Exatamente! Ficamos mais pobres. Mais especificamente, além de perder dinheiro nas operações Day Trade, ainda podemos consumir conteúdo de análises que fazem sentido mas não dão indício algum de que podem dar certo. Esse é o tipo de ciclo viciante que move a indústria de análises sobre Day Trade. Um bom exemplo da falta de validação dos métodos é o Monkey Stocks. Eles semanalmente sorteiam 5 papéis e avaliam o desempenho deles, comparando com o desempenho de outras corretoras. Essas ações sorteadas estão frequentemente entre os melhores desempenhos semanais e até anuais! Isso indica que métodos utilizados para recomendação provavelmente não são validados, já que um dos testes mais fundamentais é comparar um determinado método com uma estratégia aleatória (como a do Monkey Stocks).

Mas, o quão relevante seria eu se fizesse essas afirmações sem oferecer nenhuma evidência, certo? Logo, aproveito para citar o trabalho de Fernando Chague e Bruno Giovannetti da FGV de São Paulo. Eles acompanharam todos os traders que iniciaram em 2013 a 2016 e continuaram a operar até 2018. Essa é, talvez, a evidência mais relevante para entendermos o cenário dos Day Traders no Brasil e vamos descrevê-la um pouco melhor na próxima seção.

Tem alguém ganhando dinheiro com Day Trade no Brasil?

Quase ninguém! Mais precisamente, 99.43% de todas as pessoas que tentaram lucrar com Day Trade no período avaliado não continuaram suas operações até 2018. Além disso, entre aqueles que continuaram (0.57%), a média de ganho bruto (sem imposto de renda) foi negativa, ou seja, em média eles perderam dinheiro no período.

É incrível como esses dados já nos fazem entender tanta coisa sem muita discussão. Um exemplo prático é o motivo de existir tanto conteúdo sobre análises para Day Trade sem nenhum indício de que podem dar certo: praticamente todas as pessoas que fazem Day Trade desistem depois de um tempo. Logo, o objetivo aqui passa a ser a venda do sonho de viver com a renda do Day Trade sem considerar os riscos inerentes à atividade. Então, após utilizar técnicas jamais avaliadas, o “aspirante” a Day Trader acaba naturalmente desistindo do sonho após perdas e gastos com conteúdo “analítico” pouco reprodutível…

É importante lembrar que esse tipo de ação é algo natural para quem busca o Day Trade. A parte mais difícil de qualquer estratégia de sucesso, é restringir suas operações ao que foi planejado à priori e mudar, se preciso, no momento certo. Apesar de não ter buscado conteúdos de análises para iniciar, reconheço que, de maneira inversamente proporcional ao tempo que se passa estudando e operando, é bastante difícil manter as operações restritas à uma estratégia traçada à priori. Essa hipótese também pode ser apoiada pelo estudo citado anteriormente. Especificamente, uma tendência natural nos traders era o aumento do prejuízo com o tempo, algo que pode ocorrer com a intenção de correção dos prejuízos, através de novas operações não planejadas previamente.

Mas afinal, será que é tão difícil ganhar dinheiro com Day Trade?

Sem dúvida é a tarefa mais difícil que já me interessei em resolver, mas realmente não sei se só 0.53% das pessoas interessadas em Day Trade conseguiriam resolver. Especificamente, acho que essa dificuldade cai muito se usamos Ciência de Dados. Por isso, nesse artigo, vou explicar alguns métodos para testar estratégias simples da Day Trade. Assim, será possível verificar se determinadas estratégias podem dar retorno ou não no longo prazo. Vamos lá…

Baixando e importando os dados

Os dados diários da B3 podem ser encontrados no site oficial da Bolsa (Link), onde é possível baixar anos inteiros como .txt. A partir daí uso o pacote bovespa2csv para transformar o .txt em um data frame.

from bovespa2csv.BovespaParser import BovespaParser as bp
# Exemplo de importação dos dados de 2019 até 2020
p = bp.BovespaParser()
p.read_txt('../input/b3-daily1920/COTAHIST_A2019.TXT')
p.read_txt('../input/b3-daily1920/COTAHIST_A2020.TXT')
# Data Frame com os dados
df = p.df

Por fim, temos um data frame onde cada linha corresponde aos dados de um papel em um dia. Além disso, 26 colunas compõem a base.

Organizando os dados

A base disponível na B3 contém todos os papéis do mercado à vista, logo, precisamos selecionar somente os dados que vamos usar. Sendo assim, selecionamos todos com o código BDI “02”, que corresponde ao lote padrão. Além disso, também é necessário converter os valores da data do pregão em datetime. Por fim, selecionamos somente as 10 ações com maior liquidez da B3.

# Converter os dados de string para datetime
df['data do pregao'] = [datetime.datetime.strptime(dt, '%Y%m%d') for dt in df['data do pregao']]
# Sortear os dados em função da data do pregão e atualizar o índice
df = df.loc[df['data do pregao'].sort_values(ascending=True).index, :]
df.index = range(0, len(df))
# Retirando espaços excedentes dos nomes dos papéis
df['codigo de negociação do papel'] = [cod.replace(' ', '') for cod in df['codigo de negociação do papel']]
# Selecionar somente papéis com código BDI "02"
df = df.loc[df['codigo bdi'].isin(['02']), :]
# Selecionar os 10 papéis com maior liquidez
df = df.loc[-df['codigo de negociação do papel'].isin(['BOVA11', 'FIBR3', 'KROT3']), :] # Removendo papéis de índices que não foram negociados em 2020
selVar = 'numero de negocios efetuados com o papel mercado no pregao'
papeisSelecionados = list(df.loc[df['data do pregao'] <= np.datetime64('2019-12-31T00:00:00')].groupby('codigo de negociação do papel')[[selVar]].median().sort_values(by=selVar, ascending=False).iloc[:10, :].index)
df = df.loc[df['codigo de negociação do papel'].isin(papeisSelecionados) & (df['data do pregao'] >= np.datetime64('2020-01-01T00:00:00')), :]
print("Selected Stocks:", papeisSelecionados)

Criando algumas features

Nesse artigo vamos tentar propor e testar algumas estratégias básicas de Day Trade. Para isso, precisamos lembrar que na nossa estratégia de Day Trade precisamos comprar ações no valor mais baixo possível e vender no valor mais alto possível. Sendo assim, precisaremos normalizar as features com os valores máximos e mínimos do dia, bem como o valor do final do pregão, em função do valor de abertura. Também vamos deixar uma base com os resultados de uma estratégia de Buy and Hold (comprar e segurar) para compararmos com os resultados da nossa estratégia.

# Variação máxima absoluta em relação ao valor de abertura do papel
df['varMax'] = df['preco maximo do papel-mercado no pregao'] - df[
'preco de abertura do papel-mercado no pregao']
# Variação mínima em relação ao valor de abertura do papel
df['varMin'] = df['preco minimo do papel-mercado no pregao'] - df[
'preco de abertura do papel-mercado no pregao']
# Variação entre o preço de abertura e o preço do último negócio do pregão
df['delta'] = df['preco do ultimo negocio do papel-mercado no pregao'] - df['preco de abertura do papel-mercado no pregao']
# Aqui, normalizamos as variações máximas, mínimas e o delta em relação ao valor de abertura do papel
df['varMaxPerc'] = df['varMax'] / df['preco de abertura do papel-mercado no pregao']
df['varMinPerc'] = df['varMin'] / df['preco de abertura do papel-mercado no pregao']
df['deltaPerc'] = (df['delta'])/df['preco de abertura do papel-mercado no pregao']
# Desempenho dos papeis
bnhRes = pd.DataFrame()
for s in papeisSelecionados:
dfStock = df.loc[df['codigo de negociação do papel'] == s,:]
dfStock[s] = (dfStock['preco do ultimo negocio do papel-mercado no pregao'] - dfStock.iloc[0].loc['preco de abertura do papel-mercado no pregao'])/dfStock.iloc[0].loc['preco de abertura do papel-mercado no pregao']
bnhRes = bnhRes.append(dfStock.set_index('data do pregao')[s])
bnhRes = bnhRes.T

Dessa maneira, é possível comparar diversos papéis em relação à variação durante o dia e, consequentemente, em relação aos resultados de uma eventual compra em um valor qualquer.

Identificando estratégias possíveis

Agora, precisamos identificar estratégias interessantes. Particularmente, sempre prefiro iniciar qualquer análise da maneira mais simples possível, então, nesse caso, vamos pensar na variação do valor da ação durante o dia.

Primeiramente, vamos tentar otimizar o valor de compra. Logo, precisamos investigar a variável varMinPerc. Para isso, plotamos um histograma usando o pacote plotly.

import plotly.express as exfig = ex.histogram(df['varMinPerc'], template='simple_white')
fig.update_layout(showlegend=False)
fig.show()

É possível observar que a grande maioria dos valores está bem próxima ao 0 e que valores menores que -5% ocorrem, mas raramente. Sendo assim, como o importante é a variação do dia, será que o valor do último negócio do dia também segue essa distribuição? Plotemos o histograma para verificar…

fig = ex.histogram(df['deltaPerc'], template='simple_white', labels={'value': 'deltaPerc'})
fig.update_layout(showlegend=False)
fig.show()

Opa, claramente a distribuição do deltaPerc se assemelha à uma distribuição normal com média 0 e alguns outliers. Parece que existe uma tendência de que o valor do último negócio do dia seja bem próximo ao valor de abertura (deltaPerc = 0%). Sendo assim, comprando sempre as ações em uma variação mínima específica poderia dar bons resultados. Para investigar essa hipótese, podemos subtrair o valor da variação mínima da variação do dia, assim, teremos a distância (em %) do valor final para a variação mínima do dia.

# Criação da nova feature
varMinDeltaPerc = (df['deltaPerc'] - df['varMinPerc'])
# Plot do histograma
fig = ex.histogram(varMinDeltaPerc, template='simple_white', labels={'value': 'varMinDeltaPerc'})
fig.update_layout(showlegend=False)
fig.show()

Parece que os valores mais comuns nesse caso são maiores que 0. Essa é uma evidência importante à nossa hipótese anterior. Logo, entendemos que o valor de um papel tende a fechar acima do valor mínimo do dia e bem próximo ao de abertura, o que podem ser oportunidades. Sendo assim, prever o valor mínimo do papel no dia deve dar resultados importantes! Entretando, como o objetivo desse artigo é oferecer soluções simples, vamos considerar uma estratégia simples de acompanhar os 10 papéis que selecionamos e comprar sempre que tiverem uma variação mínima específica. Em seguida, vendemos no final do pregão, pelo preço que estiver valendo. Será que existe algum valor ideal de variação mínima para essa estratégia dar certo?

Simulando um cenário de Day Trade

Para testar nossa estratégia, podemos simplesmente simular um cenário de Day Trade na base que temos e variar o parâmetro de valor de compra para buscar algum lucro em alguma condição. Sendo assim, primeiro precisamos criar uma função para avaliar os resultados baseando-se em uma variação de compra ‘x’ % em relação à abertura.

def analisar(df, x):
res = df.loc[df.varMinPerc < x, ['data do pregao', 'codigo de negociação do papel', 'varMinPerc', 'deltaPerc']]
res['result'] = (res['deltaPerc'] - x)
return res[['data do pregao', 'codigo de negociação do papel', 'varMinPerc', 'result']]

Em seguida, precisamos definir uma lista de valores de x para testarmos. Para isso, vamos usar os valores de 0 até -0.049, que corresponderiam a variações do valor de abertura de 0 até -5%. Ao finalizar cada teste, salvamos uma nova linha no dataframe resDict com os resultados de média diária,acumulado total de ganhos e ganho composto.

resDict = pd.DataFrame()
for v in range(50):
x = -(v / 10 ** 3)
res = analisar(df, x)
res = res.loc[(res.varMinPerc < x), :]
mediaDia = (res.groupby('data do pregao')['result'].sum()/10).mean()
total = (res.groupby('data do pregao')['result'].sum() / 10).sum()
totalAc = ((res.groupby('data do pregao')['result'].sum() / 10)+1).cumprod().iloc[-1]
resDict = resDict.append({'x': x, 'mediaDia': mediaDia, 'totalAcumulado': total, 'totalComposto': totalAc}, ignore_index=True)
# Por fim plotamos os gráficos com os resultados de resDict
ex.line(resDict, x='x', y='mediaDia', template='simple_white').show()
ex.line(resDict, x='x', y='totalAcumulado', template='simple_white').show()
ex.line(resDict, x='x', y='totalComposto', template='simple_white').show()

Fica claro no gráfico que valores de x menores que -2.5% apresentam ganhos nas simulações. Além disso, vemos que quanto menor é o valor de x, maior é o ganho diário. Entretanto, pensando no gráfico que vimos anteriormente da distribuição da variação mínima diária, valores de -5% não são muito frequentes e podem não dar o mesmo retorno a logo prazo pois as ações seriam compradas mais raramente do que com valores menores. Mas, graças à Ciência de Dados, também podemos testar essa hipótese plotando o resultado total composto.

Agora conseguimos observar que, apesar de oferecer um ganho interessante para valores muito baixos de x, o os maiores ganhos estão em -4%. Além disso, valores menores que -2.5% oferecem pouco retorno ou prejuízos importantes.

Plotando os Resultados

Agora já temos uma estratégia interessante para considerar. Entretanto, ainda existe uma característica desses resultados que não testamos: a variabilidade dos resultados durante o período de tempo proposto. Especificamente, precisamos saber se essa é uma boa estratégia na maior parte do tempo, ou se os resultados são muito extremos, o que poderia causar grandes ganhos, mas também grandes perdas. Para isso plotamos os resultados por dia ao longo de 2020.

x = -0.04
serieRes = analisar(df, x)
dfPlot = serieRes.groupby(‘data do pregao’)[[‘result’]].sum()/10
dfPlot[‘Resultado Acumulado’] = dfPlot[‘result’].cumsum() + 1
dfPlot[‘Resultado Acumulado Composto’] = (dfPlot[‘result’] + 1).cumprod()
dfPlot[“Buy n’ Hold”] = bnhRes.mean(axis=1) + 1
fig = ex.line(dfPlot, y=[‘Resultado Acumulado’, ‘Resultado Acumulado Composto’, “Buy n’ Hold”], template=’simple_white’)
fig.update_layout(legend=dict(
yanchor=”bottom”,
y=0.01,
xanchor=”right”,
x=1
))
fig.show()

Se comprássemos todas as ações selecionadas em todos os pregões em que o valor dessas ações caísse 4% ou menos em relação ao valor de abertura desde 2017 até hoje, teríamos algo entre 11 e 12% de retorno positivo no ano, o que é bem melhor do que perder 1.5% comprando todas as ações e vendendo no último dia no ano (Buy n’ Hold). Não é algo que nos deixará rico, mas sem dúvida tem uma chance muito boa de dar resultados positivos, já que em diversas simulações tivemos bons retornos. Além disso, por se tratar de uma estratégia extremamente simples, muita coisa pode ser melhorada como testar outros critérios de seleção de papéis (desvio padrão do valor, volume), outras frequências em que as ações mais líquidas são selecionadas (mensalmente, diariamente), números diferentes de papéis e por aí vai. Utilizar aprendizado de máquina e técnicas estatísticas como Autorregressão ainda são opções que podem ajudar muito. No meu caso, desenvolvi um sistema baseado em Random Forests e já testei outros regressores como SVM e Regressão Linear para prever o valor mínimo do dia seguinte e recomendar quais ações comprar, mas, como pretendo escrever um artigo científico explicando esses métodos, publicá-los aqui inviabilizaria qualquer publicação em periódicos.

Conclusão

Até o momento nada pode validar melhor uma técnica de day trade do que uma análise extensa de seus resultados. Sendo assim, quando usamos dados para validar técnicas, podemos perceber que bons resultados no day trade podem não ser tão difíceis de serem atingidos. Lembre-se sempre que, tratando-se de day trade, somente fazer sentido não significa absolutamente nada.

O Jupyter Notebook com os experimentos está disponível no Kaggle por este link.

--

--

Lucas Tavares
Lucas Tavares

Written by Lucas Tavares

Passionate by Data Science since my first performance analysis job in 2016. MSc in Exercise and Sports Sciences at UERJ and in Data Science at CEFET.

No responses yet