Estudos BOVESPA
Carregando, aguarde alguns segundos.

2 - Análise Técnica Básica (ATB)

Parte 1

A Análise Técnica Básica (ATB) da B3/BOVESPA compreende as etapas de:

  • Aquisição do arquivo zipado (extensão ".zip")", baixado do site da B3.
  • Carregamento dos dados do arquivo baixado.
  • Ajuste dos dados para otimização da consulta.
  • Consulta do conjunto e subconjuntos de dados, dos códigos de negociações, por faixas de datas.
  • Transformação dos dados em informações.
  • Plotagem e apresentação dos gráficos de dados e informações.

2.1 - Importe os pacotes Python

Importe os pacotes Python utilizados na ATB.

import os
from io import BytesIO
from zipfile import ZipFile
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns

2.2 - Prepare os dados

Os dados utilizados estão disponíveis no site da B3 e devem ser baixados, e depois copiados, da pasta onde foram baixados em arquivos (no Windows é a pasta Downloads), para pasta de trabalho BOVESPA.

Os arquivos baixados estão em formato compactado (com extensão .zip), geralmente referido como formato zipado, e são baixados por períodos (diário, mensal ou anual).

Confirme que é humano na opção de confirmação da janela do captcha anti-robô.

Após baixados, os arquivos de cotação devem ser transferidos para o diretório de trabalho BOVESPA, onde poderão ser localizados, carregados e utilizados.

Pasta BOVESPA

Crie uma pasta nomeada "BOVESPA" na raiz do seu disco "C:" (ou no disco em que desejar, usaremos C como referência).

Baixe os arquivos da BOVESPA do site da B3

Com o navegador da Internet carregue a página de séries históricas da B3/BOVESPA.

O site de séries históricas pode ser acessado aqui.

Clique em "Qual o formato do arquivo?" e depois clique em "Arquivo de demonstração".

Observe no canto inferior esquerdo o arquivo baixado.

Copie o arquivo de demonstração "SeriesHistoricas_ DemoCotacoesHistoricas12022003.zip" da pasta onde foi baixado (geralmente a pasta Downloads do Windows) para a pasta "BOVESPA".

Clique nesse arquivo e com o botão direito do mouse selecione a opção "extrair aqui" (ou "extract here"), para extrair o arquivo-texto de dentro do arquivo-zip.

O arquivo-texto "DemoCotacoesHistoricas12022003.txt" de demostração contem as linhas dos dados do pregão do dia 12/02/2003.

2.3 - Posicionamento de diretório

Com os pacotes do Python importados, iniciamos a usar o Python com as instruções para a realização da ATB (Análise Técnica Básica).

Primeiro, selecionamos a pasta BOVESPA como pasta de trabalho, onde os arquivos utilizados serão localizados.

os.chdir("C:\\bovespa")

2.4 - Layout do arquivo de cotações

Os arquivos zipados de cotações baixados do site da B3 contêm, internamente, um único arquivo-texto com n linhas dentro, contendo diversos campos de dados, onde n é o número total de cotações realizadas, nas datas de pregão presentes no arquivo.

Estas linhas contêm, colados um no outro sem nenhum separador, juntos, os dados da cotação presentes da linha.

Estes dados são separados através de sua posição e tamanho na linha, com o uso do layout que define as posições, tipos, tamanhos e decimais dos campos.

A descrição do layout está disponível no arquivo "SeriesHistoricas_Layout.pdf".

2.5 - Arquivo "SeriesHistoricas_Layout.pdf" (PDF do Layout)

Agora clique em "Como interpretar o arquivo?" e então clique em "Layout do arquivo de cotações" para baixar o arquivo "SeriesHistoricas_Layout.pdf".

Observe no canto inferior esquerdo o ícone do arquivo baixado.

Copie o arquivo, da pasta onde foi baixado (no Windows é a pasta Downloads), para a pasta de trabalho BOVESPA.

Abra este arquivo para ver o conteúdo do layout.

A seguir temos a sequência das páginas contidas no arquivo PDF com o layout dos arquivos de cotações.

2.6 - Preparação do arquivo CSV de layout

Criamos na pasta de trabalho BOVESPA um arquivo-texto no formato CSV, nomeado "bovespa_layout.csv", esquematizando, a partir das informações de layout no PDF da B3, os dados dos campos nas linhas de cotações dos arquivos zipados da B3.

Este arquivo pode ser baixado aqui.

Baixe o arquivo e copie para a pasta de trabalho BOVESPA.

Abra o arquivo no modo de leitura de texto ("rt") e imprima as linhas para ver o conteúdo do arquivo.

f = open("bovespa_layout.csv","rt",encoding='UTF-8')
line = f.readline()
while line:
    print(line)
    line = f.readline()
f.close()

Conteúdo do arquivo:

Leitura do arquivo de layout

Carregue na variável dfbvlay o dataframe do Pandas, a partir do arquivo-csv do layout.

Observe a declaração do formato "UTF-8" de texto e o uso do caracter ";" como separador das colunas usadas no layout.

dfbvlay = pd.read_csv("bovespa_layout.csv",encoding='UTF-8',sep=";")

Imprima o dataframe e veja o conteúdo do dataframe do layout de cotações.

print(dfbvlay)

Função cieda_b3_tipos_tamanhos_decimais

A função cieda_b3_tipos_tamanhos_decimais carrega em 3 listas - tipos, tamanhos e decimais - os dados de layout dos campos da variável fbvlay, a fim de otimizar o acesso a estes dados.

def cieda_b3_tipos_tamanhos_decimais(dfbvlay):
    tipos = []
    tamanhos = []
    decimais = []
    for row in dfbvlay.itertuples(index=True, name='Pandas'):
        tipos.append(row.TIPO)
        tamanhos.append(row.TAM)
        decimais.append(row.DEC)
    return tipos, tamanhos, decimais

Verifique o conteúdo das listas.

Carregue as listas com a função e as imprima para ver o conteúdo.

As listas são de mesmo tamanho, e têm correspondência de índices, formando conjuntos com o tipo, tamanho e decimais do campo.

tipos, tamanhos, decimais = cieda_b3_tipos_tamanhos_decimais(dfbvlay)

print("TIPOS    :", tipos)
print("TAMANHOS :", tamanhos)
print("DECIMAIS :", decimais)

2.7 - Carregamento da lista de cotações

Função insert_str

A função insert_str é auxiliar e serve para inserir um texto dentro de outro.

def insert_str(string, str_to_insert, index):
    return string[:index] + str_to_insert + string[index:]

Função cieda_b3_percorrer_linhas_cotacoes

A função cieda_b3_percorrer_linhas_cotacoes recebe o arquivo-zip ou o arquivo-texto dezipado (extraido do arquivo-zip) e percorre as linhas, decodificando os campos, utilizando o esquema do layout.

def cieda_b3_percorrer_linhas_cotacoes(arqcot, tipos, tamanhos, decimais):
    lista = [] # lista de linhas com colunas de campos inicia vazia
    linha = arqcot.readline() # primeira linha é lida do arquivo
    while linha: # enquanto houver linhas
        if isinstance(linha,bytes): # se a linha vier do arquivo-zip estará como uma sequência de bytes
            linha = linha.decode('UTF-8').strip() # a sequência de bytes é convertida para texto
        if linha[:2] == "01":                # os dois primeiros caracteres igual "01" indicam que a linha é de cotação
            cols = []                        # a lista de campos é iniciada vazia
            for colnum in range(len(tipos)): # enquanto houverem tipos, há campos 
                tipo = tipos[colnum]         # tipo do campo sendo processado
                tam = tamanhos[colnum]       # tamanho do campo na linha de texto
                str = linha[0:tam]           # é lida a porção da linha de texto com o dado do campo
                linha = linha[tam:]          # linha recebe o restante sem o campo atual
                if tipo == "X":              # o campo é alfanumérico?
                    cols.append(str.strip()) # o valor do campo é colocado na lista de campos sem brancos antes ou depois
                if tipo == "D":    # o campo é data?
                    ano = str[:4]  # parte AAAA do formato AAAAMMDD da data
                    mes = str[4:6] # parte MM   do formato AAAAMMDD da data
                    dia = str[6:]  # parte DD   do formato AAAAMMDD da data
                    cols.extend([  # a data é destrinchada em 6 campos de datas correspondentes
                        "{}-{}-{}".format(ano,mes,dia),    # "AAAA-MM-DD" texto
                        int(dia),                          # DD           inteiro
                        int(mes),                          # MM           inteiro
                        int(ano),                          # AAAA         inteiro
                        int(str),                          # AAAAMMDD     inteiro
                        int("{}{}".format(ano,mes)),       # AAAAMM       inteiro
                        "{}-{}-{}".format(dia,mes,ano)])   # "DD-MM-AAAA" texto
                elif tipo == "N": # o campo é numérico
                    dec = decimais[colnum] # número de casas decimais do campo numérico
                    if dec: # tem decimais?
                        str = insert_str(str,".",tam-dec) # inserir o "." no local correto
                        cols.append(float(str)) # incluir o campo numérico como um tipo real na lista de campos
                    else:
                        cols.append(int(str)) # incluir o campo numérico como um tipo inteiro na lista de campos
            lista.append(cols) # adicionar a lista de campos na lista de linhas de cotações
        linha = arqcot.readline() # ler a próxima linha de texto de cotação no arquivo zip ou txt.
    return lista # é retorna a lista de linhas de campos

Função cieda_b3_ler_lista_arq_txt_cot()

A função cieda_b3_ler_lista_arq_txt_cot() retorna a lista (do tipo list nativo do Python), com as linhas de dados das cotações lidas do arquivo-txt dezipado do arquivo-zip baixado.

Esta função executa 3 instruções em conjunto:

  • Cria as listas de tipos, tamanhos e decimais de layout das cotações.
  • Abre o arquivo no formato texto dezipado do arquivo-zip de cotações baixado do site da B3.
  • Percorre e retorna as linhas do arquivo-txt carregando a lista de linhas de campos, com os dados das cotações separados e tratados.
def cieda_b3_ler_lista_arq_txt_cot(dfbvlay, nome_arq_cot_bv):
    tipos, tamanhos, decimais = cieda_b3_tipos_tamanhos_decimais(dfbvlay)
    arqcot = open(nome_arq_cot_bv,"rt",encoding='UTF-8')
    return cieda_b3_percorrer_linhas_cotacoes(arqcot,tipos,tamanhos,decimais)

2.8 - Dataframe de tipos ajustados

A lista de linhas de campos retornada deve ser convertida para um dataframe do Pandas para trabalho.

Função cieda_b3_df_cot_converter_lista()

Primeiro convertemos a lista para o primeiro dataframe (que será posteriormente ajustado para economizar memória), usando a lista de dados das cotações e outra lista correspondente de nomes das colunas (columns) do dataframe.

def cieda_b3_df_cot_converter_lista(lista):
    colunas = [
        'TIPREG', 'DATPRE', 'DIAPRE', 'MESPRE', 'ANOPRE', 'AMDPRE', 'AMPRE', 'DMAPRE',
        'CODBDI', 'CODNEG', 'TPMERC', 'NOMRES', 'ESPECI', 'PRAZOT',
        'MODREF', 'PREABE', 'PREMAX', 'PREMIN', 'PREMED', 'PREULT',
        'PREOFC', 'PREOFV', 'TOTNEG', 'QUATOT', 'VOLTOT', 'PREEXE',
        'INDOPC', 'DATVEN', 'DIAVEN', 'MESVEN', 'ANOVEN', 'AMDVEN', 'AMVEN', 'DMAVEN',
        'FATCOT', 'PTOEXE', 'CODISI', 'DISMES']
    return pd.DataFrame(lista,columns=colunas)

Função cieda_b3_df_cot_ajustar()

A função cieda_b3_df_cot_ajustar() permite o ajuste dos tipos numéricos dos campos do dataframe.

Os tipos dos campos numéricos são convertidos, daqueles com representação binária de maior precisão, para outros com menor precisão.

Não ocorre alteração de valores, mesmo com a diminição da representação binária.

Ocorrem (1) diminuição do espaço ocupado de memória pelo dataframe e (2) aumento da velocidade de processamento.

def cieda_b3_df_cot_ajustar(df):
    return df.astype({
        'DIAPRE':'int8',
        'MESPRE':'int8',
        'ANOPRE':'int16',
        'AMDPRE':'int32',
        'AMPRE' :'int32',
        'TPMERC':'int8',
        'PREABE':'float16',
        'PREMAX':'float16',
        'PREMIN':'float16',
        'PREMED':'float16',
        'PREULT':'float16',
        'PREOFC':'float16',
        'PREOFV':'float16',
        'TOTNEG':'int32',
        'PREEXE':'float16',
        'INDOPC':'int16',
        'FATCOT':'int16',
        'PTOEXE':'float16',
        'DISMES':'int16',
        'DIAVEN':'int8',
        'MESVEN':'int8',
        'ANOVEN':'int16',
        'AMDVEN':'int32',
        'AMVEN' :'int32'})

Função cieda_b3_df_ler_arq_cot()

A função cieda_b3_df_ler_arq_cot() retorna o dataframe comprimido do arquivo de cotações.

Realiza 3 instruções em conjunto:

  • Carrega a lista de linhas de campos do arquivo de texto (.txt) de cotações dezipado do arquivo-zip de cotações baixado do site da B3.
  • Converte a lista para dataframe.
  • Ajusta o dataframe para tipos numéricos de menor precisão.
def cieda_b3_df_ler_arq_cot(dfbvlay, nome_arq_cot_bv):
    lista = cieda_b3_ler_lista_arq_txt_cot(dfbvlay,nome_arq_cot_bv)
    df =  cieda_b3_df_cot_converter_lista(lista)
    return cieda_b3_df_cot_ajustar(df)

Exemplo: Cotações do dia 12/02/2003

Declarada a função cieda_b3_df_ler_arq_cot, carregamos o dataframe ajustado a partir do arquivo-texto de demonstração "DemoCotacoesHistoricas12022003.txt", dezipado de dentro do arquivo-zip "SeriesHistoricas_ DemoCotacoesHistoricas12022003.zip".

O arquivo contém as cotações de diversos códigos de negociação (VALE3, PETR4, USIM3 etc), do dia 12/02/2003, entretanto com apenas uma linha de cotação por código de negociação, já que contém apenas um dia de prergão no seu conteúdo.

df_d12m2a3 = cieda_b3_df_ler_arq_cot(dfbvlay,"DemoCotacoesHistoricas12022003.txt")
print(df_d12m2a3)

2.9 - Função cieda_b3_col_data

A função cieda_b3_col_data recebe uma data de ano, ano/mês ou ano/mês/dia, ajustando o valor e selecionando a coluna de data em função desse valor de data.

def cieda_b3_col_data(data,limite=0,sufixo="PRE"):
    if data == -1:
        col = None
    elif data == -2:
        col = 'AMD'+sufixo
        data = limite
    elif data <= 99:
        col = 'ANO'+sufixo
        data += 2000
    elif data <= 9999:
        col = 'AM'+sufixo
        data += 200000
    elif data <= 99999999:
        col = 'AMD'+sufixo
        if data <= 999999:
            data += 20000000
    else:
        col = data = None
    return col, data

2.10 - Função cieda_b3_df_dp()

A função cieda_b3_df_dp() retorna um dataframe com os campos do datafame df com as linhas de cotações com datas entre da dataini e datafim.

def cieda_b3_df_dp(df=None, dataini=-1, datafim=-1, debug=False):
    # testar se os dados são valores inteiros representando ano/mes/dia
    ok1 = (isinstance(dataini, int) and isinstance(datafim, int))
    # testar se estes valores inteiros estão nas faixas permitidas
    ok2 = ((-2 <= dataini <= -1) or (dataini >= 0)) and ((-2 <= datafim <= -1) or (datafim >= 0))
    # retornar se as condições forem inválidas
    if not (ok1 and ok2):
        return None # None representa "argumentos inválidos"
        print("argumentos inválidos")
    # testes das faixas de datas
    # se os valores das datas inicial e final forem -1 ou -2 será utilizado todo o dataset
    colini, dataini = cieda_b3_col_data(dataini,0)
    colfim, datafim = cieda_b3_col_data(datafim,99999999)
    if colini:
        if colfim: # tem data inicial e final
            if debug: print("1")
            aux = df[(df[colini] >= dataini) & (df[colfim] <= datafim)]
        else: # sem data final basta a data inicial
            if debug: print("2")
            aux = df[(df[colini] == dataini)]
    else:
        if colfim: # sem data inicial basta a data final
            if debug: print("3")
            aux = df[(df[colfim] == datafim)]
        else: # sem data inicial e final retorna o dataframe todo
            if debug: print("4")
            aux = df
    if debug:
        print(aux)
        print('colini: ', colini)
        print('colfim: ', colfim)
        print('datini: ', dataini)
        print('datfim: ', datafim)
    return aux

2.11 - Função cieda_b3_df_cndp

A função cieda_b3_df_cndp retorna o subconjunto de dados dos códigos de negociação, em determinada faixa de datas, com colunas variáveis.

def cieda_b3_df_cndp(df=None,cols="",codneg="",dataini=-1,datafim=-1,debug=False):
    # testar se os dados são ano/mes AAMM
    ok1 = (isinstance(dataini, int) and isinstance(datafim, int))
    ok2 = (-2 <= dataini <= -1) or (dataini >= 0) and ((-2 <= datafim <= -1) or (datafim >= 0))
    if not (ok1 and ok2):
        print("argumentos inválidos")
        return
    codigos = codneg.split(",")
    colini, dataini = cieda_b3_col_data(dataini,0)
    colfim, datafim = cieda_b3_col_data(datafim,99999999)
    if colini:
        if colfim: # tem data inicial e final
            if debug: print("1")
            aux = df[(df['CODNEG'].isin(codigos)) & (df[colini] >= dataini) & (df[colfim] <= datafim)]
        else: # sem data final basta a data inicial
            if debug: print("2")
            aux = df[(df['CODNEG'].isin(codigos)) & (df[colini] == dataini)]
    else:
        if colfim: # sem data inicial basta a data final
            if debug: print("3")
            aux = df[(df['CODNEG'].isin(codigos)) & (df[colini] >= dataini) & (df[colfim] <= datafim)]
        else: # sem data inicial e final retorna o dataframe todo
            if debug: print("4")
            aux = df[df['CODNEG'].isin(codigos)]
    if cols:
        cols = cols.split(",")
        tam = len(cols)
        if tam == 1:
            aux = aux[cols[0]]
        else:
            if (tam == 2) and not(cols[1]):
                cols = cols[0]
                aux = aux[[cols]]
            else:
                aux = aux[cols]
    if debug:
        print(aux)
        print('cols:   ', cols)
        print('codneg: ', codigos)
        print('colini: ', colini)
        print('colfim: ', colfim)
        print('datini: ', dataini)
        print('datfim: ', datafim)
    return aux

2.12 - Função cndp

Atalho para função cieda_b3_df_cndp

def cndp(*args,**kwargs):
    return cieda_b3_df_cndp(*args,**kwargs)

2.13 - Subconjunto VALE3/PETR4 no dia 12/0203

Exemplo de subconjunto de códigos de negociação e data do pregão

df_d12m2a3_VALE3_PETR4 = cieda_b3_df_cndp(
    df_d12m2a3,
    "CODNEG,PREABE,PREMIN,PREMAX,PREULT",
    "VALE3,PETR4")
print(df_d12m2a3_VALE3_PETR4)

2.14 - Função cieda_b3_plot_cndp

A função cieda_b3_plot_cndp plota no gráfico a quantidade de pregões no eixo x e os valores da coluna de "col" no eixo y, dos códigos de negociação de "codneg".

def cieda_b3_plot_cndp(df,col,codneg):
    dfcn = df[df["CODNEG"] == codneg]         # retorna o dataframe de códigos de negociação e colunas desejadas
    x = [x+1 for x in list(range(len(dfcn)))] # x com as quantidades de pregões
    y = dfcn[col]                             # y com as colunas desejadas
    plt.plot(x,y,label=codneg)                # plota no gráfico pregões x valores das colunas

2.15 - Tamanho e fonte da figura

mpl.rc('figure', figsize=(16,12))
font = {'family' : 'Dejavu Sans',
        'weight' : 'bold',
        'size'   : 12}
mpl.rc('font', **font)

2.16 - Exemplo

Gráfico simples de um pregão

cieda_b3_plot_cndp(df_d12m2a3,"PREULT","VALE3")
plt.show()
NameError: name 'df_d12m2a3' is not defined --- cieda_b3_plot_cndp(df_d12m2a3,"PREULT","VALE3") hw._plt_show_(apenas_link=False) ---

2.17 - Função cieda_b3_ler_arquivo_zip_cotacoes()

A função cieda_b3_ler_arquivo_zip_cotacoes() retorna a lista de cotações extraida do arquivo-txt dentro do arquivo-zip baixado do site da B3.

def cieda_b3_ler_arquivo_zip_cotacoes(dfbvlay,nome_arq_cot_bv):
    tipos, tamanhos, decimais = cieda_b3_tipos_tamanhos_decimais(dfbvlay)
    arq_zip = open(nome_arq_cot_bv,"rb")
    meu_zip = ZipFile(BytesIO(arq_zip.read()))
    lista = None
    for nome_arq_zip in meu_zip.namelist():
        lista = cieda_b3_percorrer_linhas_cotacoes(meu_zip.open(nome_arq_zip,"r"),tipos,tamanhos,decimais)
        break
    return lista

2.18 - Função cieda_b3_df_ler_arq_zip_cot()

A função cieda_b3_df_ler_arq_zip_cot() retorna o dataframe ajustado de cotações da lista.

def cieda_b3_df_ler_arq_zip_cot(dfbvlay,nome_arq_cot_bv):
    lista = cieda_b3_ler_arquivo_zip_cotacoes(dfbvlay,nome_arq_cot_bv)
    df =  cieda_b3_df_cot_converter_lista(lista)
    return cieda_b3_df_cot_ajustar(df)

2.19 - Exemplo: dados de 2022 (de janeiro a setembro)

Carregamento das cotações do ano de 2022.

carregamento_leve = 1
#
if carregamento_leve:
    df_a22 = cieda_b3_df_ler_arq_zip_cot(dfbvlay,"COTAHIST_M082022.ZIP")
else:
    df_a22 = cieda_b3_df_ler_arq_zip_cot(dfbvlay,"COTAHIST_A2022.ZIP")

Carregamento das cotações de janeiro a setembro de 2022.

df_m1m9a22 = cieda_b3_df_dp(df_a22,2201,2209)

Imprima o dataframe "df_m1m9a22".

print(df_m1m9a22)

2.20 - Dataframe dos meses de julho a setembro de 2022

Obtemos o dataframe com os dados usando a data inicial e a data final com ano e mes na forma curta.

df_m7m9a22 = cieda_b3_df_dp(df_m1m9a22,2207,2209)

Imprimimos o dataframe e observamos o conteúdo.

print(df_m7m9a22)

2.21 - Dataframe com o mês de agosto de 2022

Obtemos o dataframe com os dados usando a data inicial com ano e mes na forma curta.

df_m8a22 = cieda_b3_df_dp(df_m7m9a22,2208)

Imprimimos o dataframe e observamos o conteúdo.

print(df_m8a22)

2.22 - Função cieda_b3_plot_col_codneg()

A função cieda_b3_plot_col_codneg() plota o dataframe com as colunas em col, dos campos das cotações, do código de negociação codneg.

def cieda_b3_plot_col_codneg(df,col,codneg):
    dfaux = df[df["CODNEG"] == codneg]
    x = [x+1 for x in list(range(len(dfaux)))]
    y = dfaux[col]
    plt.plot(x,y,label=codneg)

Função cieda_b3_show_grafico

A função cieda_b3_show_grafico mostra o gráfico utilizando os argumentos de titulo, xlabel, ylabel e legenda.

def cieda_b3_show_grafico(titulo="Sem título", xlabel="eixo x", ylabel="eixo y", legenda=False):
    plt.title(titulo)
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    if legenda:
        plt.legend()
    plt.show()

2.23 - Função cieda_b3_show_multi_cndp()

A função cieda_b3_show_multi_cndp() plota as séries e mostra o gráfico do dataframe de df, usando as colunas de col, os códigos de negociações de codnegs, e a faixa de datas de dataini a datafim.

def cieda_b3_show_multi_cndp(df, col, codnegs, dataini=-1, datafim=-1, sobrepor=False):
    dfaux = cieda_b3_df_cndp(df,"CODNEG,DMAPRE,"+col,codnegs,dataini,datafim)
    data_inicial = dfaux["DMAPRE"].iloc[0]
    data_final = dfaux["DMAPRE"].iloc[-1]
    xlabel = "Pregões de {} a {}".format(data_inicial,data_final)
    codnegs_unicos = dfaux["CODNEG"].unique()
    for codneg in codnegs_unicos:
        cieda_b3_plot_col_codneg(dfaux,col,codneg)
        if not sobrepor:
            cieda_b3_show_grafico("CODNEG: "+codneg, xlabel, col, True)
    if sobrepor:
        titulo = "CODNEG: "+", ".join(codnegs_unicos)
        cieda_b3_show_grafico(titulo, xlabel, col, True)

Exemplos dos meses 4 a 6 de 2022

Gráficos de linhas de diferentes campos do código de negociação VALE3 dos pregões dos meses entre abril a junho no ano de 2022.

VALE3 2022 PREÇO FECHAMENTO

Gráfico de linhas de preço de fechamento.

cieda_b3_show_multi_cndp(df_m7m9a22,"PREULT","VALE3")
NameError: name 'df_m7m9a22' is not defined --- cieda_b3_show_multi_cndp(df_m7m9a22,"PREULT","VALE3") ---

VALE3 2022 VOLUME TOTAL

Gráfico de linhas de volume total.

cieda_b3_show_multi_cndp(df_m7m9a22,"VOLTOT","VALE3")
NameError: name 'df_m7m9a22' is not defined --- cieda_b3_show_multi_cndp(df_m7m9a22,"VOLTOT","VALE3") ---

2.24 - Média Móvel Simples (MMS)

A média móvel é um importante indicador da categoria dos Rastreadores de Tendência.

Mede o valor médio do preço, volume ou outro indicador em um determinado período.

Sua representação gráfica geralmente é feita por meio de uma linha que se movimenta a cada novo dado recebido para cálculo.

Função cieda_b3_mms

def cieda_b3_mms(precos, taxa):
    return precos.rolling(taxa).mean()

Função cieda_b3_std

def cieda_b3_std(precos, taxa):
    return precos.rolling(taxa).std()

Função cieda_b3_show_cnpumms

def cieda_b3_show_cnpumms(df,codneg,dataini=-1,datafim=-1,taxa=21):
    df_aux_1 = cieda_b3_df_cndp(df,'DMAPRE,PREULT',codneg,dataini,datafim)
    df_aux_1.index = np.arange(df_aux_1.shape[0]) # Converter o index para um vetor [0, 1, 2, ...número de linhas]
    precos_fechamento = df_aux_1['PREULT'] # Usar apenas preços de fechamento
    mms = cieda_b3_mms(precos_fechamento, taxa)
    plt.title(codneg + ' MMS')
    plt.xlabel('Pregões')
    plt.ylabel('Preços fechamento')
    plt.plot(precos_fechamento, label='Preços fechamento')
    plt.plot(mms, label='MMS {} dias'.format(taxa))
    plt.legend()
    plt.show()

Exemplo: VALE3/2022

Teste com VALE3 no ano de 2022.

cieda_b3_show_cnpumms(df_m7m9a22,"VALE3")
NameError: name 'df_m7m9a22' is not defined --- cieda_b3_show_cnpumms(df_m7m9a22,"VALE3") ---

2.25 - Bandas de Bollinger

As bandas de Bollinger mantêm uma relação intensa com a volatilidade, podendo ajudar na antecipação de movimentos fortes, e na identificação de pontos de compra e venda.

Observando o gráfico de um ativo ao longo do tempo, é possível perceber períodos de alta volatilidade, e outros nos quais parece que compradores e vendedores fizeram um trato em favor da tranquilidade e da paz de espirito.

A análise detalhada do gráfico, no entanto, nos mostra mais.

O preço de um ativo dificilmente foge de uma determinada região, sendo constantemente atraído para uma zona de equilíbrio.

Essa zona pode ser identificada com a utilização de médias móveis.

A partir dessas observações, o analista técnico John Bollinger criou as bandas de Bollinger. Elas consistem em duas linhas, uma superior e outra inferior, traçadas a partir de uma determinada distância de uma média móvel.

Esse conceito é, basicamente, o mesmo de envelopes.

Nos envelopes, temos também duas linhas as quais são calculadas a partir de um determinado percentual de distância da média.

A diferença introduzida por Bollinger está na utilização do desvio padrão.

Função cieda_b3_mms_std_bb

A função cieda_b3_mms_std_bb retorna as listas da média móvel simples, desvio-padrão móvel e as bandas inferior e superior de Bollinger.

def cieda_b3_mms_std_bb(serie, taxa=21):
    mms = cieda_b3_mms(serie, taxa)
    std = cieda_b3_std(serie, taxa)
    bbsup = mms + std * 2   # Calcular banda superior
    bbinf = mms - std * 2 # Calcular banda inferior
    return mms, std, bbsup, bbinf

Função cieda_b3_serie_mms_std_bb_cndp

A função cieda_b3_serie_mms_std_bb_cndp retorna as listas mms, std, bbsup e bbinf, respectivamente as listas da média móvel simples, do desvio-padrão moveis e das bandas superior e inferior de Bollinger.

def cieda_b3_serie_mms_std_bb_cndp(df,col,codneg,dataini=-1,datafim=-1):
    dfaux = cieda_b3_df_cndp(df,"DMAPRE,"+col,codneg,dataini,datafim)
    dfaux.index = np.arange(dfaux.shape[0]) # Converter o index para um vetor [0, 1, 2, ...número de linhas]
    data_inicial = dfaux["DMAPRE"].iloc[0]
    data_final = dfaux["DMAPRE"].iloc[-1]
    serie = dfaux[col] # Usar apenas a coluna de "col"
    # mms = cieda_b3_mms(serie, 21) # Média Móvel Simples de 21 dias
    mms, std, bbsup, bbinf = cieda_b3_mms_std_bb(serie)
    return serie, mms, std, bbsup, bbinf, data_inicial, data_final

Função cieda_b3_plot_bb_cn

Função cieda_b3_plot_bb_cn plota a série, a média móvel simples e as bandas superior e inferior de Bollinger.

def cieda_b3_plot_bb_cn(serie, mms, std, bbsup, bbinf, taxa=21):
    plt.plot(serie, label="Preços fechamento")
    plt.plot(mms,   label="MMS {} dias".format(taxa))
    plt.plot(bbsup, label="Bollinger Superior", c="g")
    plt.plot(bbinf, label="Bollinger Inferior", c="r")

Função cieda_b3_show_bollinger_serie_cn

A função cieda_b3_show_bollinger_serie_cn mostra o gráfico com as bandas de Bollinger de uma série.

def cieda_b3_show_bollinger_serie_cn(codneg, data_inicial, data_final, serie, mms, std, bbsup, bbinf, taxa=21):
    cieda_b3_plot_bb_cn(serie, mms, std, bbsup, bbinf)
    cieda_b3_show_grafico(
        "Bandas de Bollinger de CODNEG: {}".format(codneg),
        "Pregões de {} a {}".format(data_inicial,data_final),
        "Preços fechamento",
        True)

Função cieda_b3_show_col_cn_bb

Preparação da série e apresentação do Gráfico com as bandas de Bollinger.

def cieda_b3_show_col_cn_bb(df,col,codneg,dataini=-1,datafim=-1):
    serie,mms,std,bbsup,bbinf,data_inicial,data_final = cieda_b3_serie_mms_std_bb_cndp(df,col,codneg,dataini,datafim)
    cieda_b3_show_bollinger_serie_cn(codneg,data_inicial,data_final,serie,mms,std,bbsup,bbinf)

VALE3/PREULT

Dos meses 8 e 9 de 2022

Se houverem poucos pregões do código de negociação na faixa de data definida o envelope de Bollinger não fica bem definido.

cieda_b3_show_col_cn_bb(df_m1m9a22,"PREULT","VALE3",2208,2209)
NameError: name 'df_m1m9a22' is not defined --- cieda_b3_show_col_cn_bb(df_m1m9a22,"PREULT","VALE3",2208,2209) ---

Dos meses 4 a 9 de 2022

Com uma faixa com mais de 4 meses de cotações permite boa definição do envelope de Bollinger.

cieda_b3_show_col_cn_bb(df_m1m9a22,"PREULT","VALE3",2204,2209)
NameError: name 'df_m1m9a22' is not defined --- cieda_b3_show_col_cn_bb(df_m1m9a22,"PREULT","VALE3",2204,2209) ---

Dos meses 1 a 9 de 2022

Quanto mais cotações melhor a definição do envelope de Bollinger.

cieda_b3_show_col_cn_bb(df_m1m9a22,"PREULT","VALE3",2201,2209)
NameError: name 'df_m1m9a22' is not defined --- cieda_b3_show_col_cn_bb(df_m1m9a22,"PREULT","VALE3",2201,2209) ---

2.26 - Gráficos de uma lista de códigos de negociação

Gráfico único: sobreposição das séries dos código de cotação em um único gráfico.

cieda_b3_show_multi_cndp(df_m7m9a22,"PREULT","VALE3,PETR3,PETR4,USIM3",sobrepor=True)
NameError: name 'df_m7m9a22' is not defined --- cieda_b3_show_multi_cndp(df_m7m9a22,"PREULT","VALE3,PETR3,PETR4,USIM3",sobrepor=True) ---

Gráficos separados: apresentação de gráficos separados para cada código de negociação.

cieda_b3_show_multi_cndp(df_m7m9a22,"PREULT","VALE3,PETR3,PETR4,USIM3")
NameError: name 'df_m7m9a22' is not defined --- cieda_b3_show_multi_cndp(df_m7m9a22,"PREULT","VALE3,PETR3,PETR4,USIM3") ---

2.27 - Histogramas

Histogramas são gráficos de visualização clássica, geralmente com barras, que representamm a distribuição de uma ou mais variáveis ​​contando o número de observações (frequências) que se enquadram em compartimentos discretos, denominados classes de frequências.

No histograma a base de cada uma das barras representa uma classe e a altura representa a quantidade ou frequência absoluta com que o valor de cada classe ocorre.

Ao mesmo tempo, pode ser utilizado como um indicador de dispersão de processos.

Os tipos de histogramas são: simétrico, distorcido à direita, distorcido à esquerda, bimodal, multimodal e achatado (platô)).

Função cieda_b3_hist_col_codneg()

A função cieda_b3_hist_col_codneg() plota o histograma do dataframe, da coluna em col e a série do código de negociação em codneg.

def cieda_b3_hist_col_codneg(df, col, codneg, bins=10, palette='pastel'):
    dfaux = df[df["CODNEG"] == codneg]
    # x = dfaux[col]
    # plt.hist(y,label=codneg)
    cm = sns.color_palette("plasma",bins) #Splitting the palette in the same amount of numbers bins  
    plot = sns.histplot(data=dfaux, x=col, bins=bins)
    for bin_,i in zip(plot.patches,cm):
        bin_.set_facecolor(i)

Função cieda_b3_show_hist_multi_cndp()

A função cieda_b3_show_hist_multi_cndp() plota o histograma e mostra o gráfico das séries do dataframe de df dos códigos de negociações de codnegs, usando s coluna de col e a faixa de datas de dataini a datafim.

def cieda_b3_show_hist_multi_cndp(df, col, codnegs, dataini=-1, datafim=-1, sobrepor=False):
    dfaux = cieda_b3_df_cndp(df,"CODNEG,DMAPRE,"+col,codnegs,dataini,datafim)
    data_inicial = dfaux["DMAPRE"].iloc[0]
    data_final = dfaux["DMAPRE"].iloc[-1]
    xlabel = "{} de {} a {}".format(col,data_inicial,data_final)
    codnegs_unicos = dfaux["CODNEG"].unique()
    for codneg in codnegs_unicos:
        cieda_b3_hist_col_codneg(df,col,codneg)
        cieda_b3_show_grafico("CODNEG: "+codneg, xlabel, "Frequência")

Histogramas da lista de códigos de negociação

Podem ser apresentados, em gráficos separados, os histogramas de múltiplos códigos de negociação, em lista, separados por vírgula, em faixas de datas determinadas.

Histogramas de último preço total dos meses 4 a 6 de 2022.

codnegs = "VALE3,PETR3,PETR4,USIM3"
#
cieda_b3_show_hist_multi_cndp(df_m7m9a22,"PREULT",codnegs)
NameError: name 'df_m7m9a22' is not defined --- codnegs = "VALE3,PETR3,PETR4,USIM3" # cieda_b3_show_hist_multi_cndp(df_m7m9a22,"PREULT",codnegs) ---

Histogramas de último preço total dos meses 1 a 9 de 2022.

cieda_b3_show_hist_multi_cndp(df_m1m9a22,"PREULT",codnegs)
NameError: name 'df_m1m9a22' is not defined --- cieda_b3_show_hist_multi_cndp(df_m1m9a22,"PREULT",codnegs) ---

Histogramas de volume total dos meses 4 a 6 de 2022.

cieda_b3_show_hist_multi_cndp(df_m7m9a22,"VOLTOT",codnegs)
NameError: name 'df_m7m9a22' is not defined --- cieda_b3_show_hist_multi_cndp(df_m7m9a22,"VOLTOT",codnegs) ---

Histogramas de volume total dos meses 1 a 9 de 2022.

cieda_b3_show_hist_multi_cndp(df_m1m9a22,"VOLTOT",codnegs)
NameError: name 'df_m1m9a22' is not defined --- cieda_b3_show_hist_multi_cndp(df_m1m9a22,"VOLTOT",codnegs) ---

2.28 - Considerações finais

O Python permite o acesso com facilidade, nos arquivos-zip baixados do site da B3, aos dados da Bovespa.

A Análise Técnica Básica (ATB) proporciona boa visão inicial das informações obtidas a partir dos dados das cotações nos arquivos.

As possibilidades de visualização de informações dos dados são muitas, e serão apresentadas continuamente nos capítulos seguintes, de acordo com o seguinte planejamento:

  • Análise Técnica Básica - Parte 2
  • Análise Técnica Intermediária - Parte 1
  • Análise Técnica Intermediária - Parte 2
  • Análise Técnica Avançada - Parte 1
  • Análise Técnica Avançada - Parte 2
  • O que vier

CONTATO:

Para receber a versão PDF, tirar dúvidas ou fazer contato conosco envie email para atendimento@cieda.com.br.

Arduino
Coautor
Betobyte
Autor
Autores
||| Áreas ||| Estatística ||| Python ||| Projetos ||| Dicas & Truques ||| Quantum ||| Estudos BOVESPA || Estudos BOVESPA || Aulas | Introdução (Apresentação do contexto) | ATB-1 (gráficos de linha, bollinger, histogramas) | ATB-2 (3D e correlações) | ATI-1 (Análise de padrões e consulta direta na B3) | ATI-2 (Banco de dados SQLite de cotações) |