Desenvolvimento de um sistema de monitoramento de entradas de swing (EA)
Conteúdo:
- Introdução
- Um breve resumo do BTCUSD de 2021 a 2024
- Desenvolvimento de EA para Monitoramento de Entrada de Balanço
- Etapa 1: Compreendendo a estratégia EMA 100
- Etapa 2: Indicador de Monitoramento
- Etapa 3: Desenvolvimento de EA
- Testes e Otimização
- Resultados e Análise
- Conclusão
Introdução
BTCUSD é um dos pares de negociação mais proeminentes, com uma perspectiva significativa de longo prazo. Hoje, nós o selecionamos como exemplo para orientar nosso processo de desenvolvimento.
O preço do Bitcoin é caracterizado por alta volatilidade, impulsionada pelo sentimento do mercado, fatores macroeconômicos e cenários regulatórios em evolução. Identificar níveis de entrada lucrativos em meio a essas flutuações é uma tarefa desafiadora, especialmente para traders que dependem apenas de análise manual. Por exemplo, nos últimos dois anos, o preço do BTC variou de mínimas em torno de US$ 16.000 até sua máxima histórica de US$ 99.645,39 em novembro de 2024. Durante esse período, diversas oportunidades-chave de entrada surgiram ao redor da EMA 100, oferecendo insights valiosos para estratégias de negociação de longo prazo.
A solução para o desafio acima é desenvolver um EA de monitoramento em MQL5 para sinais de entrada de longo prazo. Este EA irá:
- Monitorar continuamente os movimentos de preço de um determinado par.
- Utilizar a EMA 100 como um suporte ou resistência dinâmico para identificar potenciais oportunidades de entrada.
- Alertar os traders quando condições específicas, como toques ou rejeições no nível da EMA 100, forem atendidas.
Esta ferramenta automatizará a análise, permitindo que os traders se concentrem na tomada de decisões em vez do monitoramento constante.
A imagem abaixo destaca os principais níveis de suporte para o BTC alinhados com a EMA de 100 dias.

BTCUSD, H4: Bitcoin vs Dólar Americano: Recuperação de Preço na EMA de 100
Um breve resumo do BTCUSD de 2021 a 2024
Entre 2021 e 2024, o Bitcoin experimentou mudanças dramáticas de preço. Após uma forte queda em 2022, fechando abaixo de US$ 20.000 devido ao aumento das taxas de juros e à desaceleração do mercado, ele se recuperou em 2023, iniciando o ano em US$ 16.530 e terminando em US$ 42.258. Em 2024, o Bitcoin disparou após as aprovações dos ETFs Spot de Bitcoin e um corte na taxa de juros pelo Federal Reserve dos EUA, atingindo o pico de US$ 99.645,39 em novembro.
No momento da escrita, o par está sendo negociado aproximadamente a US$ 97.300, representando um aumento significativo de 146,5% em comparação ao seu preço há um ano. Sua máxima histórica, de acordo com CoinGecko, foi US$ 99.645,39, registrada no início de dezembro de 2024.

Gráfico diário de preços do BTCUSD para 2021-2024
Desenvolvimento de um Sistema de Monitoramento de Entrada de Balanço (EA)
Organizei o processo de desenvolvimento em três etapas para otimizar nosso avanço rumo à criação de um Expert Advisor totalmente funcional. A primeira etapa envolve compreender a Média Móvel que estamos utilizando, que forma a base para o desenvolvimento de nosso indicador personalizado. Este indicador servirá como uma ferramenta independente e também estabelecerá os fundamentos necessários para construir nosso Expert Advisor de Monitoramento nas etapas seguintes.
Etapa 1: Compreendendo a estratégia EMA 100
A Média Móvel Exponencial (EMA) é um indicador amplamente utilizado que atribui maior peso aos dados recentes. A EMA 100, em particular, é um nível crítico no trading de pares, frequentemente atuando como forte suporte ou resistência. Muitas oportunidades lucrativas de entrada no Bitcoin ocorreram historicamente quando o preço reagiu à EMA 100, especialmente durante períodos de alta volatilidade.
Etapa 2: Indicador de Monitoramento
Como estamos utilizando a Média Móvel Exponencial (EMA), um recurso nativo do terminal MetaTrader 5, decidi primeiro desenvolver um indicador de monitoramento que aproveite essas ferramentas integradas. Essa abordagem simplifica o processo de identificação de áreas-chave de interesse durante a ação do preço. Com base na minha experiência, o indicador é capaz de enviar alertas via notificações do terminal, push notifications e até e-mail.
No entanto, ele não possui capacidade de lidar com web requests para serviços avançados de alerta, como integração com redes sociais populares. Para superar essa limitação, avançaremos para o Passo 3, onde o indicador será aprimorado e transformado em um Expert Advisor (EA). Essa transformação permitirá funcionalidades mais robustas, incluindo comunicação contínua via Telegram, garantindo um sistema de monitoramento abrangente e eficiente.
Aqui está a divisão do desenvolvimento do nosso indicador de Monitoramento;
Properties and Metadata:
Esta seção define metadados essenciais para o Expert Advisor (EA), incluindo o detentor dos direitos autorais, um link para o perfil do autor, o número da versão e uma breve descrição do propósito do Indicador. Essas informações são cruciais para documentação, ajudando os usuários a compreender rapidamente o criador e a funcionalidade pretendida.
#property copyright "Clemence Benjamin" #property link "https://www.mql5.com/en/users/billionaire2024/seller" #property version "1.0" #property description "EMA 100 Monitoring Indicator"
Nesta parte, configuramos as representações visuais que aparecerão no gráfico de negociação. A diretiva #property indicator_chart_window indica que o EA operará dentro da janela principal do gráfico. Ao definir dois buffers de indicador (indicator_buffers 2), preparamos a exibição de dois sinais distintos. As propriedades indicator_type1 e indicator_type2 especificam que ambos os indicadores serão visualizados como setas, com cores distintas (laranja e azul) e rótulos indicando “Look for EMA 100 bounce”. Esta configuração melhora a clareza para os traders, oferecendo sinais visuais imediatos sobre potenciais oportunidades de negociação baseadas na interação do preço com a Média Móvel Exponencial (EMA).
///Properties and Settings #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_type1 DRAW_ARROW #property indicator_width1 5 #property indicator_color1 0xFFAA00 #property indicator_label1 "Look for EMA 100 bounce " #property indicator_type2 DRAW_ARROW #property indicator_width2 5 #property indicator_color2 0x0000FF #property indicator_label2 "Look for EMA 100 bounce "
Esta seção define os buffers do indicador que armazenam valores para os sinais gerados pelo EA. Buffer1 e Buffer2 são declarados como arrays do tipo double, que armazenarão dados para os dois tipos de sinais relacionados aos movimentos de preço e à EMA. As constantes PLOT_MAXIMUM_BARS_BACK e OMIT_OLDEST_BARS são configuradas para gerenciar quantos candles históricos serão processados, garantindo que o programa funcione de maneira eficiente sem sobrecarregar o sistema com dados antigos. Essa escolha de design ajuda a manter o desempenho enquanto fornece informações relevantes e oportunas ao usuário.
#define PLOT_MAXIMUM_BARS_BACK 5000 #define OMIT_OLDEST_BARS 50 //--- indicator buffers double Buffer1[]; double Buffer2[];
Nesta parte, definimos parâmetros de entrada configuráveis pelo usuário que aumentam a flexibilidade do EA. O input int EMA_Period = 100; permite que os usuários especifiquem o período para o cálculo da Média Móvel Exponencial, tornando o EA adaptável a várias estratégias de negociação. Além disso, flags como Audible_Alerts e Push_Notifications são definidas como true por padrão, permitindo alertas e notificações em tempo real para eventos significativos do mercado. Outras variáveis como Low, High e MA_handle também são declaradas, armazenando dados de preço e lidando com cálculos de média móvel, desempenhando um papel essencial nas operações do EA.
input int EMA_Period = 100; datetime time_alert; //used when sending alert bool Audible_Alerts = true; bool Push_Notifications = true; double myPoint; //initialized in OnInit double Low[]; int MA_handle; double MA[]; double High[];
Alerta Função:
A função myAlert foi projetada para centralizar a gestão de alertas dentro do EA. Ela recebe dois parâmetros: type, que especifica a natureza do alerta (por exemplo, “print”, “error”, “indicator”), e message, que contém o texto do alerta. Ela recebe dois parâmetros: type, que especifica a natureza do alerta (por exemplo, “print”, “error”, “indicator”), e message, que contém o texto do alerta. Essa abordagem melhora a organização e legibilidade do código, permitindo manutenção mais fácil. Ao fornecer alertas audíveis e push notifications, esta função garante que os usuários permaneçam informados sobre movimentos importantes do mercado, o que é fundamental para decisões de negociação oportunas.
void myAlert(string type, string message) { if(type == "print") Print(message); else if(type == "error") { Print(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "order") { } else if(type == "modify") { } else if(type == "indicator") { Print(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Audible_Alerts) Alert(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } }
Função de inicialização:
A função OnInit é o ponto de entrada quando o EA é carregado. Ela inicializa os buffers do indicador e configura os cálculos para a Média Móvel Exponencial. O uso de SetIndexBuffer vincula os buffers definidos aos plots do indicador, garantindo que os valores possam ser exibidos no gráfico. A função também verifica a criação bem-sucedida do identificador da média móvel (MA_handle), fornecendo tratamento de erros que aumenta a robustez. Se ocorrer qualquer problema durante a inicialização, mensagens de erro claras são exibidas, permitindo que os usuários solucionem o problema de forma eficaz. Essa configuração detalhada é essencial para que o EA funcione corretamente desde o início.
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, Buffer1); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(0, PLOT_ARROW, 233); SetIndexBuffer(1, Buffer2); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(1, PLOT_ARROW, 234); //initialize myPoint myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; } MA_handle = iMA(NULL, PERIOD_CURRENT, EMA_Period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle < 0) { Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } return(INIT_SUCCEEDED); }
Função de cálculo:
A função OnCalculate é o coração do EA, onde reside a lógica para cálculo dos valores do indicador. Ela processa os dados de mercado recebidos, recupera informações de preço e calcula a média móvel. A função começa determinando quantas taxas precisam ser processadas com base no total e nas taxas previamente calculadas. Em seguida, inicializa os buffers e recupera os dados necessários, como preços baixos e altos, antes de entrar no loop principal. Esse loop percorre os dados de preço, verificando condições para gerar sinais de negociação com base na relação entre o preço e a EMA. A eficiência dessa função é crucial, pois permite que o EA responda dinamicamente às mudanças do mercado em tempo real.
int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { int limit = rates_total - prev_calculated; //--- counting from 0 to rates_total ArraySetAsSeries(Buffer1, true); ArraySetAsSeries(Buffer2, true); //--- initial zero if(prev_calculated < 1) { ArrayInitialize(Buffer1, EMPTY_VALUE); ArrayInitialize(Buffer2, EMPTY_VALUE); } else limit++; datetime Time[]; if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total); ArraySetAsSeries(Low, true); if(BarsCalculated(MA_handle) <= 0) return(0); if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total); ArraySetAsSeries(MA, true); if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total); ArraySetAsSeries(High, true); if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total); ArraySetAsSeries(Time, true);
Lógica principal:
Dentro da função OnCalculate, o loop principal de lógica analisa os movimentos de preço em relação à EMA. Ele verifica condições específicas, como quando o preço mínimo cruza abaixo da EMA ou quando o preço máximo cruza acima dela. Quando essas condições são atendidas, os respectivos buffers (Buffer1 para um toque abaixo da EMA e Buffer2 para um toque acima) são preenchidos com os preços mínimos ou máximos atuais, e alertas são acionados para o usuário. Esse mecanismo é fundamental para fornecer sinais de negociação acionáveis, permitindo que os traders tomem decisões informadas com base na análise técnica. A abordagem clara e estruturada para definir valores de indicadores garante que os usuários recebam informações oportunas e relevantes sobre potenciais oportunidades de negociação.
//--- main loop for(int i = limit-1; i >= 0; i--) { if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation //Indicator Buffer 1 if(Low[i] < MA[i] && Low[i+1] > MA[i+1] //Candlestick Low crosses below Moving Average ) { Buffer1[i] = Low[i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Look for EMA 100 bounce "); //Alert on next bar open time_alert = Time[1]; } else { Buffer1[i] = EMPTY_VALUE; } //Indicator Buffer 2 if(High[i] > MA[i] && High[i+1] < MA[i+1] //Candlestick High crosses above Moving Average ) { Buffer2[i] = High[i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Look for EMA 100 bounce "); //Alert on next bar open time_alert = Time[1]; } else { Buffer2[i] = EMPTY_VALUE; } } return(rates_total); } //+------------------------------------------------------------------+
O código completo dos indicadores está aqui, sem erros:
#property copyright "Clemence Benjamin" #property link "https://www.mql5.com/en/users/billionaire2024/seller" #property version "1.0" #property description "EMA 100 Monitoring Indicator" //--- indicator settings #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 #property indicator_type1 DRAW_ARROW #property indicator_width1 5 #property indicator_color1 0xFFAA00 #property indicator_label1 "Look for EMA 100 bounce " #property indicator_type2 DRAW_ARROW #property indicator_width2 5 #property indicator_color2 0x0000FF #property indicator_label2 "Look for EMA 100 bounce " #define PLOT_MAXIMUM_BARS_BACK 5000 #define OMIT_OLDEST_BARS 50 //--- indicator buffers double Buffer1[]; double Buffer2[]; input int EMA_Period = 100; datetime time_alert; //used when sending alert bool Audible_Alerts = true; bool Push_Notifications = true; double myPoint; //initialized in OnInit double Low[]; int MA_handle; double MA[]; double High[]; void myAlert(string type, string message) { if(type == "print") Print(message); else if(type == "error") { Print(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "order") { } else if(type == "modify") { } else if(type == "indicator") { Print(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Audible_Alerts) Alert(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | EMA 100 Monitor @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { SetIndexBuffer(0, Buffer1); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(0, PLOT_ARROW, 233); SetIndexBuffer(1, Buffer2); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, MathMax(Bars(Symbol(), PERIOD_CURRENT)-PLOT_MAXIMUM_BARS_BACK+1, OMIT_OLDEST_BARS+1)); PlotIndexSetInteger(1, PLOT_ARROW, 234); //initialize myPoint myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; } MA_handle = iMA(NULL, PERIOD_CURRENT, EMA_Period, 0, MODE_SMA, PRICE_CLOSE); if(MA_handle < 0) { Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { int limit = rates_total - prev_calculated; //--- counting from 0 to rates_total ArraySetAsSeries(Buffer1, true); ArraySetAsSeries(Buffer2, true); //--- initial zero if(prev_calculated < 1) { ArrayInitialize(Buffer1, EMPTY_VALUE); ArrayInitialize(Buffer2, EMPTY_VALUE); } else limit++; datetime Time[]; if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total); ArraySetAsSeries(Low, true); if(BarsCalculated(MA_handle) <= 0) return(0); if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total); ArraySetAsSeries(MA, true); if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total); ArraySetAsSeries(High, true); if(CopyTime(Symbol(), Period(), 0, rates_total, Time) <= 0) return(rates_total); ArraySetAsSeries(Time, true); //--- main loop for(int i = limit-1; i >= 0; i--) { if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation //Indicator Buffer 1 if(Low[i] < MA[i] && Low[i+1] > MA[i+1] //Candlestick Low crosses below Moving Average ) { Buffer1[i] = Low[i]; //Set indicator value at Candlestick Low if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Look for EMA 100 bounce "); //Alert on next bar open time_alert = Time[1]; } else { Buffer1[i] = EMPTY_VALUE; } //Indicator Buffer 2 if(High[i] > MA[i] && High[i+1] < MA[i+1] //Candlestick High crosses above Moving Average ) { Buffer2[i] = High[i]; //Set indicator value at Candlestick High if(i == 1 && Time[1] != time_alert) myAlert("indicator", "Look for EMA 100 bounce "); //Alert on next bar open time_alert = Time[1]; } else { Buffer2[i] = EMPTY_VALUE; } } return(rates_total); } //+------------------------------------------------------------------+
Etapa 3: Desenvolvimento de EA
Nesta seção, orientaremos você pelo desenvolvimento de um Expert Advisor (EA) simples, porém eficaz, para Monitoramento de Entradas Swing usando MQL5. Este EA foi projetado para monitorar os preços do mercado, com foco particular no Bitcoin como exemplo, e enviar alertas com base em condições predefinidas.
Para simplificar esse processo, omitiremos os detalhes de metadados, pois eles foram explicados detalhadamente durante a fase de desenvolvimento do indicador. Vamos dividir o código passo a passo, garantindo que cada parte seja fácil de entender e implementar.
1. Parâmetros de entrada:
input string IndicatorName = "ema100_monitoring_indicator"; // Name of the custom indicator input bool EnableTerminalAlerts = true; input bool EnablePushNotifications = true; input bool EnableTelegramAlerts = false; input string TelegramBotToken = "YOUR_BOT_TOKEN"; // Replace with your bot token input string TelegramChatID = "YOUR_CHAT_ID"; // Replace with your chat ID
Nesta parte, definimos vários parâmetros de entrada personalizáveis que aumentam a flexibilidade e usabilidade do EA. O parâmetro IndicatorName permite especificar o nome do indicador personalizado que desejamos monitorar, com o padrão "Bitcoin Monitor". Os flags booleanos—EnableTerminalAlerts, EnablePushNotifications e EnableTelegramAlerts—permitem ajustar nossas preferências de alerta. Por exemplo, podemos escolher receber notificações diretamente no terminal de negociação, em nossos dispositivos móveis ou via Telegram. Além disso, devemos inserir nosso token do bot Telegram e o chat ID para habilitar alertas do Telegram. Essa personalização permite que outros usuários otimizem sua experiência de negociação de acordo com suas preferências e necessidades.
2. Alças indicadoras:
int indicatorHandle = INVALID_HANDLE; int emaHandle = INVALID_HANDLE;
Esta seção declara as variáveis necessárias para gerenciar os indicadores usados no EA. As variáveis indicatorHandle e emaHandle armazenarão referências para o indicador personalizado e para a Média Móvel Exponencial (EMA), respectivamente. Ambos os identificadores são inicializados como INVALID_HANDLE, indicando que ainda não foram atribuídos. Essa configuração é crucial para a funcionalidade do EA, pois permite que o programa interaja com os indicadores especificados e recupere dados relevantes do mercado para análise.
3. Função de alerta:
void AlertMessage(string message) { if (EnableTerminalAlerts) Alert(message); if (EnablePushNotifications) SendNotification(message); if (EnableTelegramAlerts) SendTelegramMessage(message); }
A função AlertMessage desempenha um papel vital na gestão das notificações de alerta dentro do EA. Ela recebe como parâmetro uma string, message, que contém o texto do alerta a ser enviado. A função verifica as preferências do usuário para tipos de alerta—alertas no terminal, notificações push e Telegram messages—e envia a mensagem de acordo com essas configurações. Ao centralizar a gestão de alertas nessa função, o código torna-se mais organizado e fácil de manter. Essa funcionalidade é particularmente importante para traders que dependem de notificações oportunas para tomar decisões informadas com base nos movimentos do mercado.
4. Alerta do Telegram:
void SendTelegramMessage(string message) { if (EnableTelegramAlerts) { string url = "https://api.telegram.org/bot" + TelegramBotToken + "/sendMessage?chat_id=" + TelegramChatID + "&text=" + message; int timeout = 5000; ResetLastError(); char postData[]; uchar result[]; string response; int res = WebRequest("GET", url, NULL, timeout, postData, result, response); if (res != 200) { Print("Telegram WebRequest failed. Error: ", GetLastError(), ", HTTP Code: ", res); } else { Print("Telegram message sent successfully: ", response); } } }
Para facilitar a comunicação com os usuários, a função SendTelegramMessage é implementada. Essa função constrói uma URL que utiliza a API do Telegram para enviar mensagens a um chat especificado. Ela primeiro verifica se os alertas via Telegram estão habilitados. Se estiverem, a função prepara e envia uma requisição GET ao servidor do Telegram com a URL construída, incluindo o token do bot e o chat ID. A função também lida com possíveis erros durante a requisição, fornecendo feedback ao usuário caso a mensagem falhe ao ser enviada. Esse recurso permite que os usuários recebam alertas diretamente no Telegram, aumentando a acessibilidade e conveniência.
5. Função de inicialização:
int OnInit() { Print("Bitcoin Monitoring EA started."); // Attach the custom indicator to the chart indicatorHandle = iCustom(_Symbol, _Period, IndicatorName); if (indicatorHandle == INVALID_HANDLE) { Print("Failed to attach indicator: ", IndicatorName, ". Error: ", GetLastError()); return(INIT_FAILED); } // Attach built-in EMA 100 to the chart emaHandle = iMA(_Symbol, _Period, 100, 0, MODE_EMA, PRICE_CLOSE); if (emaHandle == INVALID_HANDLE) { Print("Failed to create EMA 100. Error: ", GetLastError()); return(INIT_FAILED); } // Add EMA 100 to the terminal chart if (!ChartIndicatorAdd(0, 0, emaHandle)) { Print("Failed to add EMA 100 to the chart. Error: ", GetLastError()); } return(INIT_SUCCEEDED); }
A função OnInit é executada quando o EA é carregado pela primeira vez. Ela é responsável por configurar os indicadores necessários e garantir que o EA esteja pronto para operação. Dentro dessa função, o indicador personalizado é anexado ao gráfico usando seu nome, e o identificador é verificado para confirmar a anexação bem-sucedida. Se a anexação falhar, uma mensagem de erro é exibida para ajudar a diagnosticar o problema. Além disso, a função cria uma EMA com período de 100 e verifica sua criação bem-sucedida antes de adicioná-la ao gráfico. A inicialização adequada é crucial para a funcionalidade do EA, pois garante que todos os componentes estejam configurados corretamente e prontos para processar os dados do mercado.
6. Função de desinicialização:
void OnDeinit(const int reason) { Print(" EA stopped."); if (indicatorHandle != INVALID_HANDLE) { IndicatorRelease(indicatorHandle); } if (emaHandle != INVALID_HANDLE) { IndicatorRelease(emaHandle); } }
A função OnDeinit é chamada quando o EA é removido do gráfico ou quando o terminal é fechado. Sua principal finalidade é liberar recursos e prevenir vazamentos de memória. Essa função verifica se os identificadores dos indicadores são válidos e, caso sejam, libera-os para liberar recursos do sistema. A função também exibe uma mensagem indicando que o EA foi encerrado, fornecendo aos usuários um feedback claro sobre o status do EA. A desinicialização adequada é essencial para manter desempenho ideal e garantir que o ambiente de negociação permaneça livre de resíduos desnecessários.
7. Lógica principal:
void OnTick() { static datetime lastAlertTime = 0; // Prevent repeated alerts for the same signal if (indicatorHandle == INVALID_HANDLE || emaHandle == INVALID_HANDLE) return; double buffer1[], buffer2[]; ArraySetAsSeries(buffer1, true); ArraySetAsSeries(buffer2, true); // Read data from the custom indicator if (CopyBuffer(indicatorHandle, 0, 0, 1, buffer1) < 0) { Print("Failed to copy Buffer1. Error: ", GetLastError()); return; } if (CopyBuffer(indicatorHandle, 1, 0, 1, buffer2) < 0) { Print("Failed to copy Buffer2. Error: ", GetLastError()); return; } // Check for signals in Buffer1 if (buffer1[0] != EMPTY_VALUE && TimeCurrent() != lastAlertTime) { string message = "Signal detected: Look for EMA 100 bounce (Low). Symbol: " + _Symbol; AlertMessage(message); lastAlertTime = TimeCurrent(); } // Check for signals in Buffer2 if (buffer2[0] != EMPTY_VALUE && TimeCurrent() != lastAlertTime) { string message = "Signal detected: Look for EMA 100 bounce (High). Symbol: " + _Symbol; AlertMessage(message); lastAlertTime = TimeCurrent(); } // Debugging EMA 100 value double emaValueArray[]; ArraySetAsSeries(emaValueArray, true); // Ensure it's set as series if (CopyBuffer(emaHandle, 0, 0, 1, emaValueArray) > 0) { Print("EMA 100 Current Value: ", emaValueArray[0]); } else { Print("Failed to read EMA 100 buffer. Error: ", GetLastError()); } }
A função OnTick contém a lógica central do EA, sendo executada sempre que o mercado recebe um novo tick de dados. Essa função verifica a validade dos identificadores do indicador antes de prosseguir com seus cálculos. Ela inicializa arrays para armazenar dados do indicador personalizado e recupera os valores mais recentes dos buffers do indicador. Se um sinal for detectado em qualquer um dos buffers, a função aciona um alerta por meio da função AlertMessage, notificando os usuários sobre potenciais oportunidades de negociação. Além disso, a função recupera o valor atual da EMA para fins de depuração, oferecendo transparência sobre o funcionamento do EA. Essa análise em tempo real permite que o EA responda rapidamente às mudanças do mercado, tornando-se uma ferramenta valiosa para traders.
Nosso código EA completo:
//+------------------------------------------------------------------+ //| Bitcoin Monitoring Expert Advisor | //| Copyright 2024, Clemence Benjamin | //| https://www.mql5.com/en/users/billionaire2024/seller | //+------------------------------------------------------------------+ #property copyright "Clemence Benjamin" #property link "https://www.mql5.com/en/users/billionaire2024/seller" #property version "1.0" #property description "BTCUSD Monitoring Expert Advisor" //--- Input parameters input string IndicatorName = "ema100_monitoring_indicator"; // Name of the custom indicator input bool EnableTerminalAlerts = true; input bool EnablePushNotifications = true; input bool EnableTelegramAlerts = false; input string TelegramBotToken = "YOUR_BOT_TOKEN"; // Replace with your bot token input string TelegramChatID = "YOUR_CHAT_ID"; // Replace with your chat ID //--- Indicator handles int indicatorHandle = INVALID_HANDLE; int emaHandle = INVALID_HANDLE; //--- Alert function void AlertMessage(string message) { if (EnableTerminalAlerts) Alert(message); if (EnablePushNotifications) SendNotification(message); if (EnableTelegramAlerts) SendTelegramMessage(message); } //--- Telegram Alerting void SendTelegramMessage(string message) { if (EnableTelegramAlerts) { string url = "https://api.telegram.org/bot" + TelegramBotToken + "/sendMessage?chat_id=" + TelegramChatID + "&text=" + message; int timeout = 5000; ResetLastError(); char postData[]; uchar result[]; string response; int res = WebRequest("GET", url, NULL, timeout, postData, result, response); if (res != 200) { Print("Telegram WebRequest failed. Error: ", GetLastError(), ", HTTP Code: ", res); } else { Print("Telegram message sent successfully: ", response); } } } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("Bitcoin Monitoring EA started."); // Attach the custom indicator to the chart indicatorHandle = iCustom(_Symbol, _Period, IndicatorName); if (indicatorHandle == INVALID_HANDLE) { Print("Failed to attach indicator: ", IndicatorName, ". Error: ", GetLastError()); return(INIT_FAILED); } // Attach built-in EMA 100 to the chart emaHandle = iMA(_Symbol, _Period, 100, 0, MODE_EMA, PRICE_CLOSE); if (emaHandle == INVALID_HANDLE) { Print("Failed to create EMA 100. Error: ", GetLastError()); return(INIT_FAILED); } // Add EMA 100 to the terminal chart if (!ChartIndicatorAdd(0, 0, emaHandle)) { Print("Failed to add EMA 100 to the chart. Error: ", GetLastError()); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Print("Bitcoin Monitoring EA stopped."); if (indicatorHandle != INVALID_HANDLE) { IndicatorRelease(indicatorHandle); } if (emaHandle != INVALID_HANDLE) { IndicatorRelease(emaHandle); } } void OnTick() { static datetime lastAlertTime = 0; // Prevent repeated alerts for the same signal if (indicatorHandle == INVALID_HANDLE || emaHandle == INVALID_HANDLE) return; double buffer1[], buffer2[]; ArraySetAsSeries(buffer1, true); ArraySetAsSeries(buffer2, true); // Read data from the custom indicator if (CopyBuffer(indicatorHandle, 0, 0, 1, buffer1) < 0) { Print("Failed to copy Buffer1. Error: ", GetLastError()); return; } if (CopyBuffer(indicatorHandle, 1, 0, 1, buffer2) < 0) { Print("Failed to copy Buffer2. Error: ", GetLastError()); return; } // Check for signals in Buffer1 if (buffer1[0] != EMPTY_VALUE && TimeCurrent() != lastAlertTime) { string message = "Signal detected: Look for EMA 100 bounce (Low). Symbol: " + _Symbol; AlertMessage(message); lastAlertTime = TimeCurrent(); } // Check for signals in Buffer2 if (buffer2[0] != EMPTY_VALUE && TimeCurrent() != lastAlertTime) { string message = "Signal detected: Look for EMA 100 bounce (High). Symbol: " + _Symbol; AlertMessage(message); lastAlertTime = TimeCurrent(); } // Debugging EMA 100 value double emaValueArray[]; ArraySetAsSeries(emaValueArray, true); // Ensure it's set as series if (CopyBuffer(emaHandle, 0, 0, 1, emaValueArray) > 0) { Print("EMA 100 Current Value: ", emaValueArray[0]); } else { Print("Failed to read EMA 100 buffer. Error: ", GetLastError()); } }
Testes e Otimização
Após compilar o código com sucesso, prosseguimos para testá-lo utilizando o Strategy Tester no terminal MetaTrader 5. Abaixo estão algumas imagens ilustrando o processo de teste e os resultados.

Especialista em monitoramento de Bitcoin: executando o Testador de Estratégia
Demonstramos com sucesso as capacidades de monitoramento em tempo real do EA durante a execução do Strategy Tester. A seguir, uma ilustração mostrando o processo e o desempenho do EA em ação.

Monitoramento das mudanças de preço do BTC no Tick: Ano de 2022
Resultados e Análise
Visualizamos com sucesso o desempenho do indicador observando sua interação com a EMA 100 em timeframes mais altos, particularmente H4 e D1. O sistema demonstra sua capacidade de enviar alertas de três maneiras distintas, incluindo notificações via Telegram. O preço respeitou consistentemente a EMA selecionada, como evidenciado pelas ilustrações apresentadas. A imagem abaixo captura a execução simultânea do EA e do indicador no terminal MetaTrader 5, destacando sua integração e funcionalidade.

Adicionando o EA e o indicador ao gráfico.
Conclusão
The Monitoring EA, we developed in this article, serves as a valuable tool for every trader. By automating price monitoring and integrating strategies like the EMA 100, it reduces the manual effort required to identify trading opportunities. While we developed it for BTCUSD, it can be extended to other instruments or customized for additional indicators. This project saved a motivational foundational simple for beginners to get started. The sky is the limit, so go ahead and try different approaches.
Download the attached EA and Indicator, back-test it with your preferred settings, and refine it to suit your trading strategy. Stay ahead in the dynamic world of trading by combining technical analysis with automation. Please note that this system is designed exclusively for monitoring and alerting purposes, with no trading features integrated at this stage. For about Telegram credentials, visit these article: Link 1 and Link 2
Table of attached files:
| Arquivo | Descrição |
|---|---|
| ema100_monitoring_indicator.mq5 | Custom indicator based on EMA 100 bounce strategy |
| bitcoin_monitoring_expert.mq5 | Expert Advisor to enable Telegram alerting functionality via WebRequest and also monitors continuously. |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16563
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.
Reimaginando Estratégias Clássicas (Parte 13): Minimizando o Atraso em Cruzamentos de Médias Móveis
Automatização de estratégias de trading com MQL5 (Parte 13): Criação de um algoritmo de negociação para o padrão "Cabeça e Ombros"
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso