DEV Community

Cover image for Guia Completo: Construindo um Script Seguro para Análise de Dados no MetaTrader5 com Python
Henrique Vital
Henrique Vital

Posted on

Guia Completo: Construindo um Script Seguro para Análise de Dados no MetaTrader5 com Python

Bem-vindo! Este guia é destinado a iniciantes em Python que desejam criar um script para conectar-se ao MetaTrader5 (MT5), extrair dados de candles, analisar rompimentos e gerar estatísticas detalhadas. Vamos abordar cada parte do código, explicar sua lógica e implementar práticas de segurança para proteger suas credenciais sensíveis.


Índice

  1. Introdução
  2. Pré-requisitos
  3. Configurando o Ambiente
  4. Criando o Arquivo .env
  5. Entendendo o Script Python
  6. Executando o Script
  7. Boas Práticas e Dicas
  8. Conclusão

Introdução

Neste projeto, você criará um script em Python que realiza as seguintes tarefas:

  1. Conectar-se ao MetaTrader5 (MT5): Utiliza as credenciais fornecidas para acessar uma conta específica no MT5.
  2. Extrair Dados de Candles: Obtém dados históricos de candles para um ativo específico dentro de um período definido.
  3. Processar e Analisar Dados: Converte os dados em um DataFrame do pandas, filtra candles em horários específicos e calcula rompimentos.
  4. Gerar Relatórios: Salva os dados extraídos e as estatísticas em arquivos CSV e TXT para inspeção posterior.
  5. Manter Práticas de Segurança: Gerencia credenciais sensíveis usando variáveis de ambiente para evitar exposição no código.

Ao final deste guia, você terá um script funcional e seguro que automatiza a extração e análise de dados do MT5.


Pré-requisitos

Antes de começar, certifique-se de ter o seguinte:

  1. Conhecimento Básico de Python: Familiaridade com a sintaxe do Python e conceitos como funções, loops e módulos.
  2. Python Instalado: Verifique se você tem o Python 3.7 ou posterior instalado em seu computador. Você pode baixá-lo do site oficial do Python.
  3. Conta no MetaTrader5 (MT5): Acesse uma conta MT5, incluindo credenciais de login, senha e informações do servidor.
  4. Entendimento de Ambientes Virtuais: Embora opcional, usar ambientes virtuais é recomendado para gerenciar dependências.

Configurando o Ambiente

1. Criar um Diretório para o Projeto

Escolha um local em seu computador e crie um novo diretório para o seu projeto. Por exemplo:

mkdir mt5_data_analysis
cd mt5_data_analysis
Enter fullscreen mode Exit fullscreen mode

2. Configurar um Ambiente Virtual (Opcional, mas Recomendado)

Um ambiente virtual isola as dependências do seu projeto das de outros projetos Python em seu sistema.

  • Criar um Ambiente Virtual:

    python -m venv venv
    

    Este comando cria um ambiente virtual chamado venv dentro do diretório do seu projeto.

  • Ativar o Ambiente Virtual:

    • No Windows:

      venv\Scripts\activate
      
    • No macOS e Linux:

      source venv/bin/activate
      

    Após a ativação, o nome do ambiente virtual aparecerá no prompt do terminal, indicando que as dependências instaladas agora serão isoladas para este projeto.

3. Instalar Dependências Necessárias

Com o ambiente virtual ativado, instale as bibliotecas necessárias usando o pip:

pip install MetaTrader5 pandas python-dotenv
Enter fullscreen mode Exit fullscreen mode
  • MetaTrader5: Biblioteca para interagir com o MetaTrader5.
  • pandas: Biblioteca poderosa para análise e manipulação de dados.
  • python-dotenv: Biblioteca para carregar variáveis de ambiente a partir de um arquivo .env.

Além disso, para facilitar o gerenciamento de pacotes, é recomendável criar um arquivo requirements.txt:

pip freeze > requirements.txt
Enter fullscreen mode Exit fullscreen mode

Este arquivo registra todas as dependências do projeto, permitindo que outras pessoas (ou você mesmo em outra máquina) instalem facilmente as mesmas versões com:

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Criando o Arquivo .env

Para gerenciar informações sensíveis de forma segura, usaremos um arquivo .env que armazenará variáveis de ambiente. Este arquivo não deve ser versionado ou compartilhado.

1. Criar o Arquivo .env

No diretório raiz do seu projeto (mt5_data_analysis), crie um arquivo chamado .env e adicione as seguintes linhas, substituindo os valores pelos seus próprios:

# Credenciais do MetaTrader5 (MT5)
MT5_LOGIN=1520378657
MT5_PASSWORD=AA6=J?j67mU
MT5_SERVER=FTMO-Demo2
MT5_PATH=C:\Program Files\FTMO MetaTrader 5\terminal64.exe

# Configuração de Logging
LOG_FILE=app.log
Enter fullscreen mode Exit fullscreen mode

Notas Importantes:

  • MT5_LOGIN: Número de login da sua conta MT5.
  • MT5_PASSWORD: Senha da sua conta MT5.
  • MT5_SERVER: Nome do servidor MT5.
  • MT5_PATH: Caminho para o executável do MetaTrader5 no seu sistema. Certifique-se de ajustar este caminho conforme a instalação do MT5 em seu computador.
  • LOG_FILE: Nome do arquivo onde os logs serão salvos.

2. Atualizar o Arquivo .gitignore

Para garantir que o arquivo .env não seja versionado (especialmente se você estiver usando o Git), crie ou atualize o arquivo .gitignore no diretório raiz com o seguinte conteúdo:

# Arquivo de variáveis de ambiente
.env

# Diretório do ambiente virtual
venv/
Enter fullscreen mode Exit fullscreen mode

Isso impede que informações sensíveis sejam acidentalmente compartilhadas em repositórios públicos ou privados.


Entendendo o Script Python

Agora, vamos criar o script Python que conectará ao MT5, extrairá dados de candles, processará esses dados e gerará estatísticas detalhadas. Este script também implementará práticas de segurança para proteger suas credenciais.

1. Imports e Variáveis de Ambiente

Primeiro, importamos todas as bibliotecas necessárias e carregamos as variáveis de ambiente.

import os
import sys
import MetaTrader5 as mt5
import pandas as pd
from datetime import datetime, timedelta
import logging
from dotenv import load_dotenv
Enter fullscreen mode Exit fullscreen mode

Explicação dos Imports:

  • os: Interage com o sistema operacional, acessando variáveis de ambiente e caminhos de arquivos.
  • sys: Fornece acesso a variáveis e funções que interagem com o interpretador Python.
  • MetaTrader5 (mt5): Biblioteca para interagir com o MetaTrader5.
  • pandas: Biblioteca poderosa para análise e manipulação de dados.
  • datetime e timedelta: Trabalha com datas e horas.
  • logging: Gerencia o registro de mensagens de log para monitoramento e depuração.
  • dotenv: Carrega variáveis de ambiente de um arquivo .env.

Carregando Variáveis de Ambiente:

# Carrega variáveis de ambiente do arquivo .env
load_dotenv()
Enter fullscreen mode Exit fullscreen mode

Esta linha lê o arquivo .env e carrega as variáveis de ambiente nele definidas, permitindo que sejam acessadas via os.getenv().

2. Configuração de Logging

O logging é essencial para monitorar o funcionamento do seu script e depurar problemas. Vamos configurar o logging para registrar mensagens tanto no console quanto em um arquivo.

# Acessa as variáveis de ambiente para configuração
LOG_FILE = os.getenv('LOG_FILE', 'app.log')

# Configura o logging
logging.basicConfig(
    level=logging.INFO,  # Nível mínimo de severidade para registrar
    format='%(asctime)s - %(levelname)s - %(message)s',  # Formato das mensagens de log
    handlers=[
        logging.FileHandler(LOG_FILE),  # Registra logs em um arquivo
        logging.StreamHandler(sys.stdout)  # Exibe logs no console
    ]
)
logger = logging.getLogger(__name__)
Enter fullscreen mode Exit fullscreen mode

Detalhes da Configuração:

  • level: Define o nível mínimo de mensagens que serão registradas. INFO inclui INFO, WARNING, ERROR e CRITICAL.
  • format: Define como cada mensagem de log será formatada, incluindo o timestamp, o nível de severidade e a mensagem.
  • handlers: Define onde as mensagens de log serão enviadas. Aqui, estão sendo enviadas para um arquivo (app.log) e para o console.

3. Configuração das Contas MT5

Definimos as contas MT5 que o script utilizará para conectar e extrair dados.

# Configurações das contas MT5
CONTAS_MT5 = [
    {
        "login": os.getenv('MT5_LOGIN'),
        "senha": os.getenv('MT5_PASSWORD'),
        "servidor": os.getenv('MT5_SERVER'),
        "ativo": "US30.cash",  # Nome do ativo (Dow Jones)
        "periodo": mt5.TIMEFRAME_M1,  # Timeframe de 1 minuto
        "lote": 0.01  # Volume padrão das ordens (se aplicável)
    }
]

contas_ativas = []  # Lista para armazenar contas ativas
Enter fullscreen mode Exit fullscreen mode

Explicação dos Campos:

  • login: Número de login da conta MT5.
  • senha: Senha da conta MT5.
  • servidor: Nome do servidor MT5.
  • ativo: Símbolo do ativo a ser analisado (por exemplo, "US30.cash").
  • periodo: Timeframe dos dados de candles (por exemplo, mt5.TIMEFRAME_M1 para 1 minuto).
  • lote: Volume padrão das ordens, caso o script seja expandido para enviar ordens (não utilizado neste script específico, mas mantido para futuras funcionalidades).

4. Conexão com o MetaTrader5

Estabelecemos a conexão com o MT5 utilizando as credenciais fornecidas.

# Inicializa a conexão com o MetaTrader 5
if not mt5.initialize(path=os.getenv('MT5_PATH')):
    logger.error("Falha ao inicializar o MetaTrader 5")
    mt5.shutdown()
    sys.exit()

# Itera sobre todas as contas configuradas para realizar login
for conta in CONTAS_MT5:
    if not mt5.login(int(conta['login']), password=conta['senha'], server=conta['servidor']):
        logger.error(f"Falha ao fazer login no MetaTrader 5 para a conta {conta['login']}")
        logger.error(f"Erro: {mt5.last_error()}")
        mt5.shutdown()
        sys.exit()
    else:
        contas_ativas.append(conta)
        logger.info(f"Conectado à conta: {conta['login']} no servidor: {conta['servidor']}")
Enter fullscreen mode Exit fullscreen mode

Detalhes do Processo:

  1. Inicialização do MT5:

    • Utiliza o caminho para o executável do MT5 (MT5_PATH) para inicializar a conexão.
    • Se a inicialização falhar, registra um erro, encerra a conexão e finaliza o script.
  2. Login nas Contas MT5:

    • Itera sobre cada conta definida em CONTAS_MT5.
    • Tenta fazer login usando o login, senha e servidor fornecidos.
    • Se o login falhar, registra um erro, encerra a conexão e finaliza o script.
    • Se o login for bem-sucedido, adiciona a conta à lista contas_ativas e registra uma mensagem de sucesso.

5. Extração de Dados de Candles

Extraímos os dados históricos de candles para o ativo e período definidos.

# Define o ativo e o período de análise
ativo = contas_ativas[0]['ativo']  # Nome do ativo (por exemplo, "US30.cash")
periodo = contas_ativas[0]['periodo']  # Timeframe (por exemplo, mt5.TIMEFRAME_M1)
data_inicio = datetime(2024, 7, 15)  # Data inicial
data_fim = datetime.now()  # Data final (hoje)

logger.info(f"Extraindo dados de candles para {ativo} de {data_inicio} até {data_fim}")

# Pega os dados históricos de candles entre as datas especificadas
dados_candles = mt5.copy_rates_range(ativo, periodo, data_inicio, data_fim)

# Verifica se os dados foram retornados
if dados_candles is None:
    logger.error("Falha ao copiar dados de candles. Verifique a conexão e os parâmetros.")
    mt5.shutdown()
    sys.exit()

# Converte os dados para um DataFrame para melhor visualização
df = pd.DataFrame(dados_candles)

# Verifica se o DataFrame está vazio
if df.empty:
    logger.error("Nenhum dado foi retornado. Verifique a conexão com o MetaTrader 5 e a disponibilidade do ativo.")
    mt5.shutdown()
    sys.exit()

logger.info(f"Dados de candles extraídos: {df.shape[0]} registros")
Enter fullscreen mode Exit fullscreen mode

Detalhes do Processo:

  1. Definição dos Parâmetros:

    • ativo: Símbolo do ativo a ser analisado.
    • periodo: Timeframe dos candles (por exemplo, 1 minuto).
    • data_inicio: Data inicial para a extração dos dados.
    • data_fim: Data final para a extração dos dados (geralmente a data atual).
  2. Extração dos Dados:

    • Utiliza a função mt5.copy_rates_range para obter os dados de candles dentro do intervalo de datas especificado.
    • Converte os dados retornados em um DataFrame do pandas para facilitar a manipulação e análise.
    • Verifica se os dados foram extraídos com sucesso. Se não, encerra o script com uma mensagem de erro.

6. Processamento e Análise de Dados

Processamos os dados extraídos, filtrando candles em horários específicos e calculando rompimentos.

# Salva o DataFrame como CSV para inspeção
df.to_csv('dados_us30.csv', index=False)
logger.info("Dados salvos em 'dados_us30.csv'")

# Verifica se a coluna 'time' existe
if 'time' not in df.columns:
    logger.warning("A coluna 'time' não foi encontrada. Verifique o nome correto da coluna de tempo.")
    # Tenta encontrar uma coluna que possa ser a de tempo
    time_columns = df.select_dtypes(include=['int64', 'float64']).columns
    if len(time_columns) > 0:
        time_column = time_columns[0]
        logger.info(f"Usando a coluna '{time_column}' como coluna de tempo.")
        df['time'] = pd.to_datetime(df[time_column], unit='s')
    else:
        logger.error("Nenhuma coluna numérica encontrada para usar como tempo.")
        mt5.shutdown()
        sys.exit()
else:
    df['time'] = pd.to_datetime(df['time'], unit='s')

# Filtra os candles das 16:29 e 16:30 (horário MT5)
hora1 = datetime.strptime("16:29", "%H:%M").time()
hora2 = datetime.strptime("16:30", "%H:%M").time()

df_1629 = df[df['time'].dt.time == hora1]
df_1630 = df[df['time'].dt.time == hora2]

# Exibe os resultados filtrados
logger.info(f"Candles das {hora1} encontradas: {df_1629.shape[0]}")
logger.info(f"Candles das {hora2} encontradas: {df_1630.shape[0]}")

# Verifica se há dados suficientes para análise
if df_1629.empty or df_1630.empty:
    logger.error("Não há candles suficientes para realizar a análise.")
    mt5.shutdown()
    sys.exit()
Enter fullscreen mode Exit fullscreen mode

Detalhes do Processo:

  1. Salvando Dados para Inspeção:

    • Salva o DataFrame extraído em um arquivo CSV (dados_us30.csv) para que você possa inspecionar os dados manualmente, se necessário.
  2. Verificação e Conversão da Coluna de Tempo:

    • Verifica se a coluna 'time' existe no DataFrame.
    • Se não existir, tenta identificar uma coluna numérica que possa representar o tempo e converte para um formato datetime.
    • Se não encontrar nenhuma coluna adequada, encerra o script com uma mensagem de erro.
  3. Filtrando Candles em Horários Específicos:

    • Define os horários de interesse: 16:29 e 16:30.
    • Filtra os candles que correspondem a esses horários.
    • Verifica se há candles suficientes para realizar a análise. Se não houver, encerra o script.

7. Geração de Estatísticas

Calculamos os rompimentos entre os candles das 16:29 e 16:30 e categorizamos esses rompimentos em diferentes faixas.

# Inicializa contadores para as estatísticas
stats = {
    '0': 0,
    '0-500': 0,
    '500-1000': 0,
    '1000-1500': 0,
    '1500-2000': 0,
    '2000-2500': 0,
    '2500-3000': 0,
    '3000-3500': 0,
    '3500+': 0
}

# Inicializa contadores para as novas estatísticas
rompimentos_um_lado = 0
rompimentos_dois_lados = 0
sem_rompimentos = 0

# Inicializa uma lista para armazenar os detalhes dos rompimentos
detalhes_rompimentos = []

# Calcula os rompimentos do candle das 16:30 em relação ao das 16:29
for i in range(min(len(df_1629), len(df_1630))):
    data = df_1629.iloc[i]['time'].date()
    max_1629 = df_1629.iloc[i]['high']
    min_1629 = df_1629.iloc[i]['low']
    max_1630 = df_1630.iloc[i]['high']
    min_1630 = df_1630.iloc[i]['low']

    rompimento_baixo = (min_1629 - min_1630) * 100 if min_1630 < min_1629 else 0
    rompimento_cima = (max_1630 - max_1629) * 100 if max_1630 > max_1629 else 0

    logger.info(f"Dia {data} -> Rompimento Baixo: {rompimento_baixo:.2f}, Rompimento Cima: {rompimento_cima:.2f}")

    # Adiciona os detalhes à lista
    detalhes_rompimentos.append({
        'data': data,
        'rompimento_baixo': rompimento_baixo,
        'rompimento_cima': rompimento_cima
    })

    # Atualiza as estatísticas para rompimento baixo e cima
    for rompimento in [rompimento_baixo, rompimento_cima]:
        if rompimento == 0:
            stats['0'] += 1
        elif 0 < rompimento <= 500:
            stats['0-500'] += 1
        elif 500 < rompimento <= 1000:
            stats['500-1000'] += 1
        elif 1000 < rompimento <= 1500:
            stats['1000-1500'] += 1
        elif 1500 < rompimento <= 2000:
            stats['1500-2000'] += 1
        elif 2000 < rompimento <= 2500:
            stats['2000-2500'] += 1
        elif 2500 < rompimento <= 3000:
            stats['2500-3000'] += 1
        elif 3000 < rompimento <= 3500:
            stats['3000-3500'] += 1
        else:
            stats['3500+'] += 1

    # Atualiza as novas estatísticas
    if rompimento_baixo > 0 and rompimento_cima > 0:
        rompimentos_dois_lados += 1
    elif rompimento_baixo > 0 or rompimento_cima > 0:
        rompimentos_um_lado += 1
    else:
        sem_rompimentos += 1
Enter fullscreen mode Exit fullscreen mode

Detalhes do Processo:

  1. Inicialização de Contadores:

    • stats: Dicionário que categoriza os rompimentos em diferentes faixas.
    • rompimentos_um_lado, rompimentos_dois_lados, sem_rompimentos: Contadores adicionais para categorizar os rompimentos de formas específicas.
    • detalhes_rompimentos: Lista para armazenar detalhes de cada rompimento.
  2. Cálculo dos Rompimentos:

    • Itera sobre cada par de candles das 16:29 e 16:30.
    • Calcula o rompimento abaixo (rompimento_baixo) e acima (rompimento_cima).
    • Multiplica por 100 para converter em uma escala mais legível.
    • Adiciona os detalhes do rompimento à lista detalhes_rompimentos.
    • Atualiza os contadores no dicionário stats com base no valor do rompimento.
    • Atualiza os contadores adicionais para categorizar os rompimentos de formas específicas.

8. Salvando Resultados

Geramos um relatório com todas as estatísticas calculadas e salvamos em um arquivo de texto.

# Cria uma string com todas as estatísticas
estatisticas = f"""
Total de dias analisados: {len(df_1629)}

Detalhes dos Rompimentos:
"""

for detalhe in detalhes_rompimentos:
    estatisticas += f"Data: {detalhe['data']}, Rompimento Baixo: {detalhe['rompimento_baixo']:.2f}, Rompimento Cima: {detalhe['rompimento_cima']:.2f}\n"

estatisticas += f"""
Estatisticas de Rompimentos 16:29 a 16:30 :
Rompimentos = 0: {stats['0']}
Rompimentos > 0 e <= 500: {stats['0-500']}
Rompimentos > 500 e <= 1000: {stats['500-1000']}
Rompimentos > 1000 e <= 1500: {stats['1000-1500']}
Rompimentos > 1500 e <= 2000: {stats['1500-2000']}
Rompimentos > 2000 e <= 2500: {stats['2000-2500']}
Rompimentos > 2500 e <= 3000: {stats['2500-3000']}
Rompimentos > 3000 e <= 3500: {stats['3000-3500']}
Rompimentos > 3500: {stats['3500+']}

Estatisticas adicionais:
Candles rompidos somente de um lado: {rompimentos_um_lado}
Candles rompidos dos dois lados: {rompimentos_dois_lados}
Candles não rompidos de nenhum lado: {sem_rompimentos}
"""

# Imprime as estatísticas no console
print(estatisticas)
logger.info("Estatísticas calculadas e impressas no console.")

# Obtenha o nome do arquivo atual e mude a extensão para .txt
nome_arquivo_atual = os.path.basename(sys.argv[0])
nome_arquivo_base = os.path.splitext(nome_arquivo_atual)[0]
nome_arquivo_txt = f"{nome_arquivo_base}.txt"

# Salve as estatísticas em um arquivo de texto
with open(nome_arquivo_txt, 'w') as arquivo:
    arquivo.write(estatisticas)

logger.info(f"Estatísticas salvas no arquivo: {os.path.abspath(nome_arquivo_txt)}")
Enter fullscreen mode Exit fullscreen mode

Detalhes do Processo:

  1. Criação da String de Estatísticas:

    • Compila todas as estatísticas em uma única string formatada para fácil leitura.
  2. Impressão no Console:

    • Exibe as estatísticas no console para visualização imediata.
  3. Salvando em Arquivo de Texto:

    • Determina o nome do arquivo atual (nome_arquivo_atual) e altera a extensão para .txt.
    • Salva as estatísticas no arquivo de texto, permitindo que você consulte os resultados posteriormente.

9. Encerramento da Conexão

Finalizamos a conexão com o MT5 para liberar recursos.

# Desconecta o MetaTrader 5
mt5.shutdown()
logger.info("Conexão com o MetaTrader 5 encerrada.")
Enter fullscreen mode Exit fullscreen mode

Detalhes do Processo:

  • mt5.shutdown(): Fecha a conexão com o MT5 de forma ordenada.
  • Log: Registra uma mensagem indicando que a conexão foi encerrada.

Script Python Completo com Práticas de Segurança

A seguir, apresentamos o script completo incorporando todas as práticas discutidas, especialmente a gestão segura de credenciais usando variáveis de ambiente.

import os
import sys
import MetaTrader5 as mt5
import pandas as pd
from datetime import datetime, timedelta
import logging
from dotenv import load_dotenv

# Carrega variáveis de ambiente do arquivo .env
load_dotenv()

# Acessa as variáveis de ambiente para configuração
MT5_LOGIN = os.getenv('MT5_LOGIN')
MT5_PASSWORD = os.getenv('MT5_PASSWORD')
MT5_SERVER = os.getenv('MT5_SERVER')
MT5_PATH = os.getenv('MT5_PATH')
LOG_FILE = os.getenv('LOG_FILE', 'app.log')

# Configura logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(LOG_FILE),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)

# Configurações das contas MT5
CONTAS_MT5 = [
    {
        "login": MT5_LOGIN,
        "senha": MT5_PASSWORD,
        "servidor": MT5_SERVER,
        "ativo": "US30.cash",  # Nome do ativo (Dow Jones)
        "periodo": mt5.TIMEFRAME_M1,  # Timeframe de 1 minuto
        "lote": 0.01  # Volume padrão das ordens (se aplicável)
    }
]

contas_ativas = []  # Lista para armazenar contas ativas

# Inicializa a conexão com o MetaTrader 5
if not mt5.initialize(path=MT5_PATH):
    logger.error("Falha ao inicializar o MetaTrader 5")
    mt5.shutdown()
    sys.exit()

# Itera sobre todas as contas configuradas para realizar login
for conta in CONTAS_MT5:
    if not mt5.login(int(conta['login']), password=conta['senha'], server=conta['servidor']):
        logger.error(f"Falha ao fazer login no MetaTrader 5 para a conta {conta['login']}")
        logger.error(f"Erro: {mt5.last_error()}")
        mt5.shutdown()
        sys.exit()
    else:
        contas_ativas.append(conta)
        logger.info(f"Conectado à conta: {conta['login']} no servidor: {conta['servidor']}")

# Define o ativo e o período de análise
ativo = contas_ativas[0]['ativo']  # Nome do ativo (por exemplo, "US30.cash")
periodo = contas_ativas[0]['periodo']  # Timeframe (por exemplo, mt5.TIMEFRAME_M1)
data_inicio = datetime(2024, 7, 15)  # Data inicial
data_fim = datetime.now()  # Data final (hoje)

logger.info(f"Extraindo dados de candles para {ativo} de {data_inicio} até {data_fim}")

# Pega os dados históricos de candles entre as datas especificadas
dados_candles = mt5.copy_rates_range(ativo, periodo, data_inicio, data_fim)

# Verifica se os dados foram retornados
if dados_candles is None:
    logger.error("Falha ao copiar dados de candles. Verifique a conexão e os parâmetros.")
    mt5.shutdown()
    sys.exit()

# Converte os dados para um DataFrame para melhor visualização
df = pd.DataFrame(dados_candles)

# Verifica se o DataFrame está vazio
if df.empty:
    logger.error("Nenhum dado foi retornado. Verifique a conexão com o MetaTrader 5 e a disponibilidade do ativo.")
    mt5.shutdown()
    sys.exit()

logger.info(f"Dados de candles extraídos: {df.shape[0]} registros")

# Salva o DataFrame como CSV para inspeção
df.to_csv('dados_us30.csv', index=False)
logger.info("Dados salvos em 'dados_us30.csv'")

# Verifica se a coluna 'time' existe
if 'time' not in df.columns:
    logger.warning("A coluna 'time' não foi encontrada. Verifique o nome correto da coluna de tempo.")
    # Tenta encontrar uma coluna que possa ser a de tempo
    time_columns = df.select_dtypes(include=['int64', 'float64']).columns
    if len(time_columns) > 0:
        time_column = time_columns[0]
        logger.info(f"Usando a coluna '{time_column}' como coluna de tempo.")
        df['time'] = pd.to_datetime(df[time_column], unit='s')
    else:
        logger.error("Nenhuma coluna numérica encontrada para usar como tempo.")
        mt5.shutdown()
        sys.exit()
else:
    df['time'] = pd.to_datetime(df['time'], unit='s')

# Filtra os candles das 16:29 e 16:30 (horário MT5)
hora1 = datetime.strptime("16:29", "%H:%M").time()
hora2 = datetime.strptime("16:30", "%H:%M").time()

df_1629 = df[df['time'].dt.time == hora1]
df_1630 = df[df['time'].dt.time == hora2]

# Exibe os resultados filtrados
logger.info(f"Candles das {hora1} encontradas: {df_1629.shape[0]}")
logger.info(f"Candles das {hora2} encontradas: {df_1630.shape[0]}")

# Verifica se há dados suficientes para análise
if df_1629.empty or df_1630.empty:
    logger.error("Não há candles suficientes para realizar a análise.")
    mt5.shutdown()
    sys.exit()

# Inicializa contadores para as estatísticas
stats = {
    '0': 0,
    '0-500': 0,
    '500-1000': 0,
    '1000-1500': 0,
    '1500-2000': 0,
    '2000-2500': 0,
    '2500-3000': 0,
    '3000-3500': 0,
    '3500+': 0
}

# Inicializa contadores para as novas estatísticas
rompimentos_um_lado = 0
rompimentos_dois_lados = 0
sem_rompimentos = 0

# Inicializa uma lista para armazenar os detalhes dos rompimentos
detalhes_rompimentos = []

# Calcula os rompimentos do candle das 16:30 em relação ao das 16:29
for i in range(min(len(df_1629), len(df_1630))):
    data = df_1629.iloc[i]['time'].date()
    max_1629 = df_1629.iloc[i]['high']
    min_1629 = df_1629.iloc[i]['low']
    max_1630 = df_1630.iloc[i]['high']
    min_1630 = df_1630.iloc[i]['low']

    rompimento_baixo = (min_1629 - min_1630) * 100 if min_1630 < min_1629 else 0
    rompimento_cima = (max_1630 - max_1629) * 100 if max_1630 > max_1629 else 0

    logger.info(f"Dia {data} -> Rompimento Baixo: {rompimento_baixo:.2f}, Rompimento Cima: {rompimento_cima:.2f}")

    # Adiciona os detalhes à lista
    detalhes_rompimentos.append({
        'data': data,
        'rompimento_baixo': rompimento_baixo,
        'rompimento_cima': rompimento_cima
    })

    # Atualiza as estatísticas para rompimento baixo e cima
    for rompimento in [rompimento_baixo, rompimento_cima]:
        if rompimento == 0:
            stats['0'] += 1
        elif 0 < rompimento <= 500:
            stats['0-500'] += 1
        elif 500 < rompimento <= 1000:
            stats['500-1000'] += 1
        elif 1000 < rompimento <= 1500:
            stats['1000-1500'] += 1
        elif 1500 < rompimento <= 2000:
            stats['1500-2000'] += 1
        elif 2000 < rompimento <= 2500:
            stats['2000-2500'] += 1
        elif 2500 < rompimento <= 3000:
            stats['2500-3000'] += 1
        elif 3000 < rompimento <= 3500:
            stats['3000-3500'] += 1
        else:
            stats['3500+'] += 1

    # Atualiza as novas estatísticas
    if rompimento_baixo > 0 and rompimento_cima > 0:
        rompimentos_dois_lados += 1
    elif rompimento_baixo > 0 or rompimento_cima > 0:
        rompimentos_um_lado += 1
    else:
        sem_rompimentos += 1

# Cria uma string com todas as estatísticas
estatisticas = f"""
Total de dias analisados: {len(df_1629)}

Detalhes dos Rompimentos:
"""

for detalhe in detalhes_rompimentos:
    estatisticas += f"Data: {detalhe['data']}, Rompimento Baixo: {detalhe['rompimento_baixo']:.2f}, Rompimento Cima: {detalhe['rompimento_cima']:.2f}\n"

estatisticas += f"""
Estatisticas de Rompimentos 16:29 a 16:30 :
Rompimentos = 0: {stats['0']}
Rompimentos > 0 e <= 500: {stats['0-500']}
Rompimentos > 500 e <= 1000: {stats['500-1000']}
Rompimentos > 1000 e <= 1500: {stats['1000-1500']}
Rompimentos > 1500 e <= 2000: {stats['1500-2000']}
Rompimentos > 2000 e <= 2500: {stats['2000-2500']}
Rompimentos > 2500 e <= 3000: {stats['2500-3000']}
Rompimentos > 3000 e <= 3500: {stats['3000-3500']}
Rompimentos > 3500: {stats['3500+']}

Estatisticas adicionais:
Candles rompidos somente de um lado: {rompimentos_um_lado}
Candles rompidos dos dois lados: {rompimentos_dois_lados}
Candles não rompidos de nenhum lado: {sem_rompimentos}
"""

# Imprime as estatísticas no console
print(estatisticas)
logger.info("Estatísticas calculadas e impressas no console.")

# Obtenha o nome do arquivo atual e mude a extensão para .txt
nome_arquivo_atual = os.path.basename(sys.argv[0])
nome_arquivo_base = os.path.splitext(nome_arquivo_atual)[0]
nome_arquivo_txt = f"{nome_arquivo_base}.txt"

# Salve as estatísticas em um arquivo de texto
with open(nome_arquivo_txt, 'w') as arquivo:
    arquivo.write(estatisticas)

logger.info(f"Estatísticas salvas no arquivo: {os.path.abspath(nome_arquivo_txt)}")

# Desconecta o MetaTrader 5
mt5.shutdown()
logger.info("Conexão com o MetaTrader 5 encerrada.")
Enter fullscreen mode Exit fullscreen mode

Executando o Script

Após configurar o ambiente e criar o arquivo analyze_mt5.py, siga os passos abaixo para executar o script.

1. Ativar o Ambiente Virtual

Se você configurou um ambiente virtual, ative-o:

  • No Windows:

    venv\Scripts\activate
    
  • No macOS e Linux:

    source venv/bin/activate
    

2. Executar o Script

No diretório do seu projeto, execute o seguinte comando:

python analyze_mt5.py
Enter fullscreen mode Exit fullscreen mode

O que esperar:

  • Logs no Console: Você verá mensagens informando sobre o status da conexão com o MT5, extração de dados e cálculo de estatísticas.
  • Arquivo de Log: Todas as mensagens de log também serão gravadas no arquivo app.log (ou outro definido em LOG_FILE).
  • Arquivo CSV: Os dados de candles serão salvos em dados_us30.csv para inspeção manual.
  • Arquivo TXT: As estatísticas calculadas serão salvas em um arquivo de texto com o mesmo nome do script (por exemplo, analyze_mt5.txt).

3. Encerrando o Script

O script encerra automaticamente após concluir todas as operações. Se desejar interromper o script manualmente antes que ele termine, pressione Ctrl+C no terminal onde o script está sendo executado. No entanto, como o script executa todas as operações de forma síncrona e termina após a conclusão, isso normalmente não será necessário.


Boas Práticas e Dicas

  1. Manutenção da Segurança:

    • Nunca compartilhe seu arquivo .env ou exponha suas credenciais em repositórios públicos.
    • Use Ambientes Virtuais para isolar as dependências do projeto.
  2. Monitoramento e Logs:

    • Revise regularmente os logs (app.log) para identificar e resolver possíveis problemas.
    • Implementar Rotação de Logs: Para evitar que o arquivo de log cresça indefinidamente, considere implementar rotação usando bibliotecas como logging.handlers.
  3. Testes em Ambiente de Demonstração:

    • Antes de operar em contas reais, teste seu script em ambientes de demonstração para garantir que tudo funcione conforme o esperado.
    • Verifique os Dados: Assegure-se de que os dados extraídos estão corretos e que os cálculos de estatísticas estão precisos.
  4. Gerenciamento de Erros:

    • Tratamento Robusto de Exceções: Certifique-se de que todas as possíveis exceções sejam tratadas para evitar que o script pare inesperadamente.
    • Alertas: Considere implementar alertas (por exemplo, enviando mensagens de log críticas para seu email) para notificá-lo sobre falhas graves.
  5. Atualizações de Dependências:

    • Mantenha suas bibliotecas atualizadas para aproveitar melhorias de segurança e correções de bugs.
    • Verifique as Documentações: Consulte as documentações oficiais das bibliotecas para entender mudanças ou atualizações.
  6. Escalabilidade:

    • Adicionar Mais Ativos: Atualize o script para suportar mais ativos além de "US30.cash" conforme sua necessidade.
    • Automatizar Tarefas: Se desejar realizar análises regularmente, considere agendar a execução do script usando ferramentas como cron no Linux ou Agendador de Tarefas no Windows.
  7. Documentação e Comentários:

    • Comente Seu Código: Mantenha comentários atualizados e relevantes para facilitar futuras manutenções.
    • Documente Configurações: Mantenha um documento com detalhes sobre como configurar e executar o script.

Conclusão

Parabéns! Você criou um script em Python que conecta ao MetaTrader5, extrai dados de candles, processa e analisa esses dados, e gera estatísticas detalhadas. Além disso, implementou práticas de segurança essenciais para proteger suas credenciais e garantir a integridade do seu projeto.

Próximos Passos:

  • Expandir Funcionalidades: Adicione mais funcionalidades, como diferentes tipos de análises, visualizações gráficas ou integração com outras plataformas.
  • Interface de Usuário: Considere criar uma interface gráfica ou um dashboard para monitorar os resultados das análises de forma mais intuitiva.
  • Automatizar Deployments: Se desejar que o script funcione continuamente, explore opções de deployment em servidores ou serviços de nuvem.

Recursos Adicionais:


🔒 Fique Seguro e Boas Análises! 🔒

A segurança das suas credenciais é fundamental para proteger suas contas e dados. Sempre siga as melhores práticas para garantir a integridade e confidencialidade das suas informações.

Top comments (0)