English Русский 中文 Español Deutsch 日本語
preview
Desenvolvimento de um Kit de Ferramentas para análise de ação de preço (Parte 17): Ferramenta TrendLoom EA

Desenvolvimento de um Kit de Ferramentas para análise de ação de preço (Parte 17): Ferramenta TrendLoom EA

MetaTrader 5Sistemas de negociação |
21 3
Christian Benjamin
Christian Benjamin

Conteúdo



Introdução

Os métodos de análise de mercado e confirmação de entrada variam entre os analistas de tendência. Muitos traders analisam vários intervalos de tempo, como M1, M5 e M15 ou H1, H4 e W1, para validar suas entradas e aumentar a confiabilidade dos sinais. Em vez de alterar os intervalos de tempo para avaliar a tendência geral, basta pressionar um botão e obter uma atualização em tempo real ou receber atualizações automáticas. Você já viu um gráfico em um período gráfico menor indicando venda, entrou em uma operação e, em seguida, abriu um gráfico em um período gráfico maior apenas para descobrir uma tendência de compra?

O EA TrendLoom foi projetado para evitar esse erro. Ele possui um painel com sete botões que representam vários estilos de trading. Cada botão exibe três timeframes que são analisados em conjunto usando médias móveis para gerar sinais como BUY, SELL ou NEUTRAL. Essa ferramenta robusta fornece atualizações rápidas de confirmação e se atualiza continuamente com sinais relevantes conforme são detectados.


Visão Geral da Estratégia

O EA TrendLoom é estruturado como uma interface gráfica (painel). O painel contém sete botões, cada um correspondente a uma estratégia de trading específica
  • Foco no Curto Prazo (M1, M5, M15)
  • Scalping/Intraday (M5, M15, H1)
  • Swing Trading (M15, H1, H4)
  • Negociação de tendências (H1, H4, D1)
  • Confirmação de Tendência MTF (H1, H4, W1)
  • Scalper Curto / Tendência Média (M5, H1, D1)
  • Tendência de Longo Prazo (H1, D1, W1)

Vamos analisar como o EA gera um sinal de COMPRA, VENDA ou NEUTRO quando um botão é pressionado.

  • Coleta de Dados: Para cada um dos três períodos de tempo (por exemplo, M1, M5 e M15), o EA recupera o preço de fechamento da última vela totalmente concluída.
  • Cálculo da SMA: Para cada período, o EA calcula uma Média Móvel Simples (SMA) de 50 períodos. Essa SMA atua como referência para o preço atual.
Geração de Sinais Individuais: O EA compara o preço de fechamento com a SMA correspondente

  • Se o preço estiver acima da SMA, considera isso um sinal de alta e atribui um valor de +1.
  • Se o preço estiver abaixo da SMA, considera isso um sinal de baixa e atribui um valor de -1.
  • Quando o preço é igual à SMA, o sinal é neutro (0).

Combinando os Sinais

  • Os três sinais individuais (um de cada período) são somados.
  • Determinação do Sinal Final:
  • Se a soma for igual ou superior a 2, isso indica um forte impulso de alta. O EA retorna um sinal de "COMPRA".
  • Se a soma for -2 ou menos, isso indica forte impulso de baixa. O EA retorna um sinal de "VENDA".
  • Caso contrário, os sinais são mistos ou neutros, portanto o EA retorna "NEUTRO".

Vamos revisar o diagrama a seguir para entender melhor o processo.

Diagrama de Fluxo

Fig 1. Fluxograma


Implementação em MQL5

No topo, você notará os comentários de cabeçalho e as definições de propriedades do EA. Essas linhas funcionam como metadados para o EA, especificando seus direitos autorais, versão e vinculando-o à sua origem. A diretiva #property strict é usada para impor regras de compilação mais rigorosas, ajudando a prevenir erros comuns de codificação.

//+------------------------------------------------------------------+
//|                                                 TrendLoom EA.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.00"
#property strict

Em seguida, o código inclui vários arquivos de cabeçalho que fornecem controles de diálogo, botão, rótulo e painel. Também inclui controles de objetos de gráfico para exibir texto no gráfico. Essa inclusão modular permite que o EA utilize classes pré-construídas para a interface do usuário.

Isso inclui bibliotecas de referência de diretivas na pasta include do seu MetaEditor. Arquivos na subpasta Controls oferecem classes integradas para diálogos e botões. Eles também fornecem classes para rótulos e painéis. Esse design simplifica a construção de uma interface interativa sem reescrever código. O arquivo na subpasta ChartObjects (ChartObjectsTxtControls.mqh) permite exibir texto dinâmico no gráfico.

#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Label.mqh>
#include <Controls/Panel.mqh>
#include <ChartObjects/ChartObjectsTxtControls.mqh>  // Adjusted include path (singular folder)

Constantes para alinhamento de texto e um valor de cor são então definidos. Essa prática melhora a clareza e a facilidade de manutenção do código.

#ifndef ALIGN_LEFT
  #define ALIGN_LEFT   0
#endif
#ifndef ALIGN_CENTER
  #define ALIGN_CENTER 1
#endif
#ifndef ALIGN_RIGHT
  #define ALIGN_RIGHT  2
#endif

#define clrSilver 0xC0C0C0

O EA declara parâmetros de entrada que ajustam a aparência e a posição do painel e de seus botões. PanelX, PanelY e PanelWidth definem a geometria do painel, enquanto os parâmetros de cor definem o tema visual. As dimensões dos botões são controladas com btnWidth, btnHeight e btnSpacing, e o EA permite personalizar tanto o layout quanto as cores. Essa configuração oferece flexibilidade para adaptar a interface do usuário às suas necessidades.

//---- Input parameters -----------------------------------------------
input int    PanelX               = 10;
input int    PanelY               = 10;
input int    PanelWidth           = 250;
input int    btnWidth             = 220;
input int    btnHeight            = 30;
input int    btnSpacing           = 5;

input color  PanelBackgroundColor = clrDimGray;
input color  PanelHeaderColor     = clrBlueViolet;
input color  ButtonBgColor        = clrBlack;
input color  ButtonTextColor      = clrBlueViolet;
input color  AnalysisTextColor    = clrLime;

Arrays armazenam os nomes e textos dos botões, o que torna a atualização ou adição de novos botões rápida e simples. Esse design centraliza todas as informações relacionadas aos botões em um único local, de modo que modificações exigem apenas ajustes mínimos. Também melhora a consistência na interface do usuário e reduz a chance de erros. O método oferece flexibilidade para melhorias futuras e mantém o código limpo e organizado.

//---- Button Names and Texts (7 analysis options) --------------------
string buttonNames[7] =
  {
   "btnShortTerm",
   "btnScalping",
   "btnSwing",
   "btnTrend",
   "btnMTFTrend",
   "btnShortScalper",
   "btnLongTerm"
  };

string buttonTexts[7] =
  {
   "Short Term Focus\n(M1, M5, M15)",
   "Scalping/Intraday\n(M5, M15, H1)",
   "Swing Trading\n(M15, H1, H4)",
   "Trend Trading\n(H1, H4, D1)",
   "MTF Trend Confirm\n(H1, H4, W1)",
   "Short Scalper/Mid Trend\n(M5, H1, D1)",
   "Long Term Trend\n(H1, D1, W1)"
  };

Macros globais definem os nomes para o cabeçalho do painel e o rótulo de análise. Essas macros garantem consistência em todo o código e atuam como uma única fonte para esses identificadores. Ao centralizar esses nomes, atualizações nos componentes do painel tornam-se mais fáceis e reduzem o risco de erros de digitação. Essa abordagem simplifica a manutenção e garante um código consistente e claro.

// Global object names for panel header and analysis label
#define PANEL_BG "PanelBG"
#define PANEL_HEADER "PanelHeader"
#define ANALYSIS_LABEL "AnalysisResult"

O código declara então duas funções auxiliares: GetSMA calcula a média móvel simples e AnalyzeTimeframes realiza análises de mercado em vários períodos de tempo. Essas funções formam a lógica central da análise de mercado.

//--- Helper function declarations
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift);
string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3);

A classe personalizada CTrendLoomPanel herda de CAppDialog. Ela agrupa todos os elementos da interface do usuário, como o rótulo de cabeçalho, painel principal, botões e rótulo de resultado. Esse design cria uma interface modular que é mais fácil de gerenciar e expandir.

Criando o Painel

O método CreateTrendPanel primeiro cria uma janela de diálogo. Em seguida, configura um rótulo de cabeçalho com texto personalizado, cor, tamanho de fonte e estilo de fonte. O alinhamento é definido usando a função ObjectSetInteger.

bool CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2)
{
   if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2))
   {
      Print("Failed to create TrendLoom dialog.");
      return false;
   }
   if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30))
   {
      Print("Failed to create header label.");
      return false;
   }
   m_lblHeader.Text("TrendLoom EA");
   m_lblHeader.Color(PanelHeaderColor);
   m_lblHeader.FontSize(14);
   m_lblHeader.Font("Segoe UI");
   Add(m_lblHeader);
   if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER))
      Print("Failed to set header alignment");

O método continua criando o painel principal e calcula dinamicamente suas dimensões. Depois, cria cada botão e os posiciona um após o outro. Por fim, um rótulo de resultados é adicionado abaixo dos botões para exibir a saída da análise.

Manipulação de Eventos

O método OnEvent processa as interações do usuário. Ao clicar em um botão, ele chama AnalyzeTimeframes com os parâmetros de período de tempo apropriados. O resultado da análise é atualizado no painel e um alerta é exibido.

bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   if(sparam == "btnShortTerm")
   {
      string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15);
      string out = "Short Term Focus: " + res;
      UpdateResults(out);
      Alert(out);
      return true;
   }
   else if(sparam == "btnScalping")
   {
      string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1);
      string out = "Scalping/Intraday: " + res;
      UpdateResults(out);
      Alert(out);
      return true;
   }
   // Additional conditions for other buttons
   return false;
}

Atualizando a Interface

O método UpdateResults atualiza o rótulo de resultados com novos dados de análise. Em seguida, ele chama ChartRedraw para que as informações atualizadas apareçam imediatamente.

void UpdateResults(const string &result)
{
   m_lblResults.Text("Analysis Result: " + result);
   ChartRedraw();
}

Funções Centrais de Análise

Calculando a Média Móvel Simples (MMS)

A função GetSMA calcula a SMA criando um identificador de indicador com a função iMA. Ele copia os valores da SMA do buffer do indicador e, em seguida, libera o identificador para liberar recursos.
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift)
{
   int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE);
   if(handle == INVALID_HANDLE)
   {
      Print("Failed to create iMA handle for timeframe ", timeframe);
      return 0.0;
   }
   double sma[];
   if(CopyBuffer(handle, 0, shift, 1, sma) <= 0)
   {
      Print("Failed to copy buffer for timeframe ", timeframe);
      IndicatorRelease(handle);
      return 0.0;
   }
   double result = sma[0];
   IndicatorRelease(handle);
   return result;
}

Analisando múltiplos períodos de tempo

A função AnalyzeTimeframes recupera o preço de fechamento e a SMA para três períodos de tempo e atribui um sinal de alta quando o preço ultrapassa a SMA ou um sinal de baixa quando cai abaixo dela. O sistema soma os sinais individuais para produzir uma recomendação final: COMPRAR quando a soma for igual ou superior a 2, VENDER quando for igual ou inferior a -2 e NEUTRO caso contrário. Cada período de tempo é avaliado independentemente para capturar uma visão equilibrada das tendências de mercado, enquanto o parâmetro de deslocamento garante que apenas a última vela concluída seja usada para análise. A combinação de sinais de múltiplos períodos de tempo reduz o impacto do ruído transitório do mercado, e o ajuste do período da SMA refina ainda mais a sensibilidade dos sinais de negociação.

string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3)
{
   int period = 50;
   int shift  = 1; // last completed candle

   double price1 = iClose(_Symbol, tf1, shift);
   double sma1   = GetSMA(_Symbol, tf1, period, shift);
   int signal1   = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0);

   double price2 = iClose(_Symbol, tf2, shift);
   double sma2   = GetSMA(_Symbol, tf2, period, shift);
   int signal2   = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0);

   double price3 = iClose(_Symbol, tf3, shift);
   double sma3   = GetSMA(_Symbol, tf3, period, shift);
   int signal3   = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0);

   int sum = signal1 + signal2 + signal3;
   if(sum >= 2)
      return "BUY";
   else if(sum <= -2)
      return "SELL";
   else
      return "NEUTRAL";
}
As funções de ciclo de vida do EA lidam com inicialização, limpeza e processamento de eventos. A função OnInit cria o painel TrendLoom usando os parâmetros de entrada. Se a criação do painel falhar, o EA retorna um erro de inicialização.
int OnInit()
{
   if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400))
   {
      Print("Failed to create TrendLoom Panel.");
      return INIT_FAILED;
   }
   return INIT_SUCCEEDED;
}

A função OnDeinit realiza a limpeza destruindo o painel quando o EA é removido ou o gráfico é fechado.

void OnDeinit(const int reason)
{
   TrendPanel.Destroy(reason);
}

Por fim, a função OnChartEvent encaminha os eventos do gráfico para o manipulador de eventos do painel, garantindo que a interface permaneça responsiva.

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   TrendPanel.ChartEvent(id, lparam, dparam, sparam);
}

No seu MetaEditor, os arquivos necessários estão armazenados na pasta include. Para acessar os arquivos especificados conforme mostrado no trecho, consulte as subpastas conforme ilustrado nos diagramas abaixo. Essa organização garante que o compilador encontre os arquivos de controle de diálogo, botão, rótulo e painel na pasta include/Controls e os controles de objetos de gráfico na pasta include/ChartObjects.

#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Label.mqh>
#include <Controls/Panel.mqh>
#include <ChartObjects/ChartObjectsTxtControls.mqh>  // Adjusted include path (singular folder)

Etapa 1

Fig 2. Etapa 1

Etapa 2

Fig 3. Etapa 2


Código MQL5

//+------------------------------------------------------------------+
//|                                                 TrendLoom EA.mq5 |
//|                                  Copyright 2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.00"
#property strict

#include <Controls/Dialog.mqh>
#include <Controls/Button.mqh>
#include <Controls/Label.mqh>
#include <Controls/Panel.mqh>
#include <ChartObjects/ChartObjectsTxtControls.mqh>  // Adjusted include path (singular folder)

// Define alignment constants if not already defined
#ifndef ALIGN_LEFT
#define ALIGN_LEFT   0
#endif
#ifndef ALIGN_CENTER
#define ALIGN_CENTER 1
#endif
#ifndef ALIGN_RIGHT
#define ALIGN_RIGHT  2
#endif

#define clrSilver 0xC0C0C0

//---- Input parameters -----------------------------------------------
input int    PanelX               = 10;       // Top-left X coordinate of panel
input int    PanelY               = 10;       // Top-left Y coordinate of panel
input int    PanelWidth           = 250;      // Panel width (for longer text)
input int    btnWidth             = 220;      // Button width
input int    btnHeight            = 30;       // Button height
input int    btnSpacing           = 5;        // Spacing between buttons

input color  PanelBackgroundColor = clrDimGray;     // Panel background color
input color  PanelHeaderColor     = clrBlueViolet;  // Panel header text color

input color  ButtonBgColor        = clrBlack;       // Button background color
input color  ButtonTextColor      = clrBlueViolet;  // Button text color

input color  AnalysisTextColor    = clrLime;        // Analysis result text color

//---- Button Names and Texts (7 analysis options) --------------------
string buttonNames[7] =
  {
   "btnShortTerm",
   "btnScalping",
   "btnSwing",
   "btnTrend",
   "btnMTFTrend",
   "btnShortScalper",
   "btnLongTerm"
  };

string buttonTexts[7] =
  {
   "Short Term Focus\n(M1, M5, M15)",
   "Scalping/Intraday\n(M5, M15, H1)",
   "Swing Trading\n(M15, H1, H4)",
   "Trend Trading\n(H1, H4, D1)",
   "MTF Trend Confirm\n(H1, H4, W1)",
   "Short Scalper/Mid Trend\n(M5, H1, D1)",
   "Long Term Trend\n(H1, D1, W1)"
  };

// Global object names for panel header and analysis label
#define PANEL_BG "PanelBG"
#define PANEL_HEADER "PanelHeader"
#define ANALYSIS_LABEL "AnalysisResult"

//--- Helper function declarations
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift);
string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3);

//------------------------------------------------------------------------------
// CTrendLoomPanel class - A modern, modular panel for TrendLoom EA
//------------------------------------------------------------------------------
class CTrendLoomPanel : public CAppDialog
  {
private:
   CLabel            m_lblHeader;
   CPanel            m_panelMain;
   CButton           m_btnShortTerm;
   CButton           m_btnScalping;
   CButton           m_btnSwing;
   CButton           m_btnTrend;
   CButton           m_btnMTFTrend;
   CButton           m_btnShortScalper;
   CButton           m_btnLongTerm;
   CLabel            m_lblResults;

public:
   // Create the TrendLoom Panel dialog
   bool              CreateTrendPanel(const long chart, const string name, const int x1, const int y1, const int x2, const int y2)
     {
      if(!CAppDialog::Create(chart, name, 0, x1, y1, x2, y2))
        {
         Print("Failed to create TrendLoom dialog.");
         return false;
        }
      // Create header label
      if(!m_lblHeader.Create(0, "TrendLoomHeader", 0, 10, 10, x2 - x1 - 20, 30))
        {
         Print("Failed to create header label.");
         return false;
        }
      m_lblHeader.Text("TrendLoom EA");
      m_lblHeader.Color(PanelHeaderColor);
      m_lblHeader.FontSize(14);
      m_lblHeader.Font("Segoe UI");
      Add(m_lblHeader);
      // Set header text alignment to center using ObjectSetInteger
      if(!ObjectSetInteger(0L, m_lblHeader.Name(), OBJPROP_ALIGN, (long)ALIGN_CENTER))
         Print("Failed to set header alignment");

      // Create main panel background
      int panelBottom = 50 + (btnHeight + btnSpacing) * 7 + btnSpacing;
      if(!m_panelMain.Create(0, "TrendLoomPanel", 0, 10, 50, x2 - x1 - 10, panelBottom))
        {
         Print("Failed to create main panel.");
         return false;
        }
      m_panelMain.Color(PanelBackgroundColor);
      m_panelMain.BorderType(BORDER_RAISED);
      m_panelMain.ColorBorder(clrSilver);
      Add(m_panelMain);

      // Starting coordinates for buttons
      int btnX = 20; // relative to dialog
      int btnY = 60;
      int buttonWidth = btnWidth;
      int buttonHeight = btnHeight;

      // Create each button with a modern look
      if(!m_btnShortTerm.Create(0, buttonNames[0], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnShortTerm.Text(buttonTexts[0]);
      m_btnShortTerm.Font("Segoe UI");
      m_btnShortTerm.FontSize(12);
      m_btnShortTerm.Color(ButtonBgColor);
      Add(m_btnShortTerm);
      btnY += buttonHeight + btnSpacing;

      if(!m_btnScalping.Create(0, buttonNames[1], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnScalping.Text(buttonTexts[1]);
      m_btnScalping.Font("Segoe UI");
      m_btnScalping.FontSize(12);
      m_btnScalping.Color(ButtonBgColor);
      Add(m_btnScalping);
      btnY += buttonHeight + btnSpacing;

      if(!m_btnSwing.Create(0, buttonNames[2], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnSwing.Text(buttonTexts[2]);
      m_btnSwing.Font("Segoe UI");
      m_btnSwing.FontSize(12);
      m_btnSwing.Color(ButtonBgColor);
      Add(m_btnSwing);
      btnY += buttonHeight + btnSpacing;

      if(!m_btnTrend.Create(0, buttonNames[3], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnTrend.Text(buttonTexts[3]);
      m_btnTrend.Font("Segoe UI");
      m_btnTrend.FontSize(12);
      m_btnTrend.Color(ButtonBgColor);
      Add(m_btnTrend);
      btnY += buttonHeight + btnSpacing;

      if(!m_btnMTFTrend.Create(0, buttonNames[4], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnMTFTrend.Text(buttonTexts[4]);
      m_btnMTFTrend.Font("Segoe UI");
      m_btnMTFTrend.FontSize(12);
      m_btnMTFTrend.Color(ButtonBgColor);
      Add(m_btnMTFTrend);
      btnY += buttonHeight + btnSpacing;

      if(!m_btnShortScalper.Create(0, buttonNames[5], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnShortScalper.Text(buttonTexts[5]);
      m_btnShortScalper.Font("Segoe UI");
      m_btnShortScalper.FontSize(12);
      m_btnShortScalper.Color(ButtonBgColor);
      Add(m_btnShortScalper);
      btnY += buttonHeight + btnSpacing;

      if(!m_btnLongTerm.Create(0, buttonNames[6], 0, btnX, btnY, btnX + buttonWidth, btnY + buttonHeight))
         return false;
      m_btnLongTerm.Text(buttonTexts[6]);
      m_btnLongTerm.Font("Segoe UI");
      m_btnLongTerm.FontSize(12);
      m_btnLongTerm.Color(ButtonBgColor);
      Add(m_btnLongTerm);
      btnY += buttonHeight + btnSpacing;

      // Create results label below the buttons
      if(!m_lblResults.Create(0, "TrendResults", 0, btnX, btnY, btnX + buttonWidth, btnY + 30))
         return false;
      m_lblResults.Text("Analysis Result: [Waiting for Input]");
      m_lblResults.Font("Segoe UI");
      m_lblResults.FontSize(12);
      m_lblResults.Color(AnalysisTextColor);
      Add(m_lblResults);
      // Set results text alignment to left using ObjectSetInteger
      if(!ObjectSetInteger(0L, m_lblResults.Name(), OBJPROP_ALIGN, (long)ALIGN_LEFT))
         Print("Failed to set results alignment");

      Show();
      return true;
     }

   // Process events (button clicks)
   bool              OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
     {
      if(sparam == "btnShortTerm")
        {
         string res = AnalyzeTimeframes(PERIOD_M1, PERIOD_M5, PERIOD_M15);
         string out = "Short Term Focus: " + res;
         UpdateResults(out);
         Alert(out);
         return true;
        }
      else
         if(sparam == "btnScalping")
           {
            string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_M15, PERIOD_H1);
            string out = "Scalping/Intraday: " + res;
            UpdateResults(out);
            Alert(out);
            return true;
           }
         else
            if(sparam == "btnSwing")
              {
               string res = AnalyzeTimeframes(PERIOD_M15, PERIOD_H1, PERIOD_H4);
               string out = "Swing Trading: " + res;
               UpdateResults(out);
               Alert(out);
               return true;
              }
            else
               if(sparam == "btnTrend")
                 {
                  string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_D1);
                  string out = "Trend Trading: " + res;
                  UpdateResults(out);
                  Alert(out);
                  return true;
                 }
               else
                  if(sparam == "btnMTFTrend")
                    {
                     string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_H4, PERIOD_W1);
                     string out = "MTF Trend Confirm: " + res;
                     UpdateResults(out);
                     Alert(out);
                     return true;
                    }
                  else
                     if(sparam == "btnShortScalper")
                       {
                        string res = AnalyzeTimeframes(PERIOD_M5, PERIOD_H1, PERIOD_D1);
                        string out = "Short Scalper/Mid Trend: " + res;
                        UpdateResults(out);
                        Alert(out);
                        return true;
                       }
                     else
                        if(sparam == "btnLongTerm")
                          {
                           string res = AnalyzeTimeframes(PERIOD_H1, PERIOD_D1, PERIOD_W1);
                           string out = "Long Term Trend: " + res;
                           UpdateResults(out);
                           Alert(out);
                           return true;
                          }
      return false;
     }

   bool              ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
     {
      return OnEvent(id, lparam, dparam, sparam);
     }

   // Update the results label and refresh the chart
   void              UpdateResults(const string &result)
     {
      m_lblResults.Text("Analysis Result: " + result);
      ChartRedraw();
     }
  };

// Global instance of the TrendLoom Panel
CTrendLoomPanel TrendPanel;

//------------------------------------------------------------------------------
// Helper functions (core analysis logic)
//------------------------------------------------------------------------------
double GetSMA(string symbol, ENUM_TIMEFRAMES timeframe, int period, int shift)
  {
   int handle = iMA(symbol, timeframe, period, 0, MODE_SMA, PRICE_CLOSE);
   if(handle == INVALID_HANDLE)
     {
      Print("Failed to create iMA handle for timeframe ", timeframe);
      return 0.0;
     }
   double sma[];  // dynamic array to store SMA values
   if(CopyBuffer(handle, 0, shift, 1, sma) <= 0)
     {
      Print("Failed to copy buffer for timeframe ", timeframe);
      IndicatorRelease(handle);
      return 0.0;
     }
   double result = sma[0];
   IndicatorRelease(handle);
   return result;
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string AnalyzeTimeframes(ENUM_TIMEFRAMES tf1, ENUM_TIMEFRAMES tf2, ENUM_TIMEFRAMES tf3)
  {
   int period = 50;
   int shift  = 1; // last completed candle

   double price1 = iClose(_Symbol, tf1, shift);
   double sma1   = GetSMA(_Symbol, tf1, period, shift);
   int signal1   = (price1 > sma1) ? 1 : (price1 < sma1 ? -1 : 0);

   double price2 = iClose(_Symbol, tf2, shift);
   double sma2   = GetSMA(_Symbol, tf2, period, shift);
   int signal2   = (price2 > sma2) ? 1 : (price2 < sma2 ? -1 : 0);

   double price3 = iClose(_Symbol, tf3, shift);
   double sma3   = GetSMA(_Symbol, tf3, period, shift);
   int signal3   = (price3 > sma3) ? 1 : (price3 < sma3 ? -1 : 0);

   int sum = signal1 + signal2 + signal3;
   if(sum >= 2)
      return "BUY";
   else
      if(sum <= -2)
         return "SELL";
      else
         return "NEUTRAL";
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(!TrendPanel.CreateTrendPanel(0, "TrendLoom Panel", PanelX, PanelY, PanelX + PanelWidth + 20, PanelY + 400))
     {
      Print("Failed to create TrendLoom Panel.");
      return INIT_FAILED;
     }
   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   TrendPanel.Destroy(reason);
  }

//+------------------------------------------------------------------+
//| Chart Event Handler                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   TrendPanel.ChartEvent(id, lparam, dparam, sparam);
  }
//+------------------------------------------------------------------+


Resultados

É extremamente importante que todo trader teste minuciosamente seus sistemas antes de utilizá-los em operações reais. Os testes envolvem a análise retrospectiva de dados históricos para verificar como o sistema teria se comportado sem arriscar quaisquer fundos. Você também pode usar contas demo em tempo real para observar o desempenho real em tempo real. Esse processo ajuda a ajustar e desenvolver uma ferramenta mais confiável que você possa usar com segurança em uma conta real. Pessoalmente, prefiro dedicar um tempo significativo testando e refinando o EA para obter resultados mais robustos.

Nesta seção, apresento os resultados dos testes do EA em execução no gráfico. Eu o testei no Volatility 75 (1s) e ele produziu resultados excelentes e lucrativos. Todos os botões funcionam conforme esperado e as análises são atualizadas quase instantaneamente quando você pressiona um botão. Vamos revisar o primeiro teste abaixo.

Fig 4. Teste Volatility 75 (1s)

Abaixo está um diagrama que ilustra como o mercado se comportou após a execução de uma operação com base no sinal fornecido. Este diagrama dá continuidade à operação mostrada no GIF acima. Utilizei o período de tempo M1 para oferecer uma visão mais ampla das negociações.

Fig 5. Teste V 75 (1s)


Conclusão

Após criar e testar o EA, posso confirmar com confiança que ele tem um impacto positivo na análise de mercado. Seu processamento rápido de sinais e avaliação da tendência geral produziram resultados poderosos em índices de volatilidade. No entanto, esta ferramenta serve como um auxílio complementar, e não como o provedor final de sinais. Incentivo você a testá-la minuciosamente e ajustar os parâmetros de acordo com suas preferências. Você também pode modificá-la para personalizar a aparência dos botões. Use-a para confirmar sua estratégia geral; tenho observado que ela é eficaz dessa forma.

Data Nome da Ferramenta  Descrição Versão  Atualizações  Notas
01/10/24 Projetor de gráficos Script para sobrepor a ação de preço do dia anterior com efeito fantasma. 1.0 Lançamento Inicial Ferramenta número 1
18/11/24 Comentário Analítico Ele fornece informações do dia anterior em formato tabular, além de antecipar a direção futura do mercado. 1.0 Lançamento Inicial Ferramenta número 2
27/11/24 Mestre em Análise Atualização regular das métricas de mercado a cada duas horas  1.01 Segunda Versão Ferramenta número 3
02/12/24 Previsor Analítico  Atualização regular das métricas de mercado a cada duas horas com integração ao Telegram 1.1 Terceira Edição Ferramenta número 4
09/12/24 Navegador de Volatilidade O EA analisa as condições de mercado utilizando os indicadores Bollinger Bands, RSI e ATR 1.0 Lançamento Inicial Ferramenta número 5
19/12/24 Reversão à Média Ceifador de Sinal  Analisa o mercado utilizando estratégia de reversão à média e fornece sinal  1.0  Lançamento Inicial  Ferramenta número 6 
9/01/25  Pulso de sinal  Analisador de múltiplos períodos de tempo 1.0  Lançamento Inicial  Ferramenta número 7 
17/01/25  Quadro de Métricas  Painel com botão para análise  1.0  Lançamento Inicial Ferramenta número 8 
21/01/25 Fluxo externo Análises por meio de bibliotecas externas 1.0  Lançamento Inicial Ferramenta número 9 
27/01/25 VWAP Preço Médio Ponderado por Volume   1.3  Lançamento Inicial  Ferramenta número 10 
02/02/25  Heikin Ashi  Suavização de tendências e identificação de sinais de reversão  1.0  Lançamento Inicial  Ferramenta número 11
04/02/25  FibVWAP  Geração de sinais por meio de análise em Python  1.0  Lançamento Inicial  Ferramenta número 12
14/02/25  DIVERGÊNCIA RSI  Divergências entre ação do Preço e RSI  1.0  Lançamento Inicial  Ferramenta número 13 
17/02/25  Parada e Reversão Parabólicas (PSAR)  Automação da estratégia PSAR 1.0 Lançamento Inicial  Ferramenta número 14
20/02/25  Quarters Drawer Script  Desenho dos níveis de quartis no gráfico  1.0  Lançamento Inicial  Ferramenta número 15 
27/02/25  Detector de Intrusão Detectar e alertar quando o preço atingir os níveis de quartis. 1.0   Lançamento Inicial Ferramenta número 16 
27/02/25  Ferramenta TrendLoom  Painel de análise de múltiplos períodos de tempo 1.0 Lançamento Inicial Ferramenta número 17

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/17329

Arquivos anexados |
TrendLoom_EA.mq5 (26.63 KB)
Últimos Comentários | Ir para discussão (3)
linfo2
linfo2 | 21 mar. 2025 em 03:01
Uau, fantástico, posso ver que há muito esforço nisso, obrigado por compartilhar sua abordagem e seu código
Christian Benjamin
Christian Benjamin | 21 mar. 2025 em 11:21
linfo2 #:
Uau, fantástico, posso ver que há muito esforço nisso, obrigado por compartilhar sua abordagem e seu código
De nada. Obrigado também por entrar em contato👏.
gardee005
gardee005 | 25 mar. 2025 em 16:49
Gosto muito de seu trabalho, tenho acompanhado. boa variedade de ideias, com implementação. obrigado!
Caminhe em novos trilhos: Personalize indicadores no MQL5 Caminhe em novos trilhos: Personalize indicadores no MQL5
Vou agora listar todas as possibilidades novas e recursos do novo terminal e linguagem. Elas são várias, e algumas novidades valem a discussão em um artigo separado. Além disso, não há códigos aqui escritos com programação orientada ao objeto, é um tópico muito importante para ser simplesmente mencionado em um contexto como vantagens adicionais para os desenvolvedores. Neste artigo vamos considerar os indicadores, sua estrutura, desenho, tipos e seus detalhes de programação em comparação com o MQL4. Espero que este artigo seja útil tanto para desenvolvedores iniciantes quanto para experientes, talvez alguns deles encontrem algo novo.
Otimização por Comunidade de Cientistas - Community of Scientist Optimization (CoSO): Teoria Otimização por Comunidade de Cientistas - Community of Scientist Optimization (CoSO): Teoria
Os segredos da otimização eficiente de estratégias de trading em abordagens metaheurísticas. Community of Scientist Optimization é um novo algoritmo populacional inspirado nos mecanismos de funcionamento da comunidade de cientistas. Diferentemente das metáforas naturais tradicionais, o CoSO modela aspectos únicos da atividade científica humana: a publicação de resultados em periódicos, a competição por financiamentos de pesquisa e a formação de grupos de pesquisa.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Desenvolvimento do Kit de Ferramentas de Análise de Price Action (Parte 16): Introduzindo a Teoria dos Quartis (II) — EA Intrusion Detector Desenvolvimento do Kit de Ferramentas de Análise de Price Action (Parte 16): Introduzindo a Teoria dos Quartis (II) — EA Intrusion Detector
Em nosso artigo anterior, apresentamos um script simples chamado "The Quarters Drawer." Com base nessa fundação, agora estamos dando o próximo passo ao criar um Expert Advisor (EA) de monitoramento para acompanhar esses quartis e fornecer supervisão em relação a possíveis reações do mercado nesses níveis. Junte-se a nós enquanto exploramos o processo de desenvolvimento de uma ferramenta de detecção de zonas neste artigo.