English Русский 中文 Español Deutsch 日本語
preview
Ferramentas de Trading em MQL5 (Parte 3): Construindo um Painel de Scanner Multitemporal para Negociação Estratégica

Ferramentas de Trading em MQL5 (Parte 3): Construindo um Painel de Scanner Multitemporal para Negociação Estratégica

MetaTrader 5 — Negociação |
38 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Introdução

Em nosso artigo anterior, Parte 2, aprimoramos uma ferramenta de assistência à negociação desenvolvida em MetaQuotes Language 5 (MQL5), adicionando feedback visual dinâmico para melhorar a interatividade. Agora, nosso foco será desenvolver um painel de scanner multitemporal capaz de fornecer sinais de negociação em tempo real para fornecer sinais para a tomada de decisão estratégicas. Apresentaremos uma interface baseada em grade, com sinais gerados por indicadores e um botão de fechamento, abordando esses avanços nos seguintes tópicos:

  1. Plano do Painel de Scanner
  2. Implementação em MQL5
  3. Backtesting
  4. Conclusão

Essas seções nos orientarão no desenvolvimento de um painel de scanner multitemporal intuitivo e robusto.


Plano do Painel de Scanner

Nosso objetivo é criar um painel de scanner multitemporal que forneça sinais de negociação claros e em tempo real, aprimorando a tomada de decisões estratégicas. O painel terá uma estrutura em grade, exibindo sinais de compra e venda em diferentes tempos gráficos, permitindo avaliar rapidamente as condições do mercado sem precisar alternar entre gráficos. Também incluiremos um botão de fechamento para permitir que o painel seja ocultado facilmente, garantindo uma experiência de uso organizada e flexível, adaptada às nossas necessidades de negociação.

Incorporaremos sinais de indicadores importantes, incluindo o Índice de Força Relativa (RSI), o Oscilador Estocástico (STOCH), o Índice de Canal de Commodities (CCI), o Índice Direcional Médio (ADX) e o Awesome Oscillator (AO), concebidos para identificar possíveis oportunidades de negociação com limites de intensidade personalizáveis. No entanto, a escolha dos indicadores ou da leitura da ação do preço fica a seu critério. Essa configuração nos ajudará a identificar tendências e reversões em diferentes tempos gráficos, oferecendo suporte tanto para estratégias de curto quanto de longo prazo. Nosso objetivo é desenvolver uma ferramenta otimizada e intuitiva, que forneça informações práticas para orientar decisões e seja fácil de utilizar, abrindo caminho para futuras melhorias, como alertas automatizados ou indicadores adicionais. Abaixo, apresentamos uma visualização do que pretendemos construir.

PLANO DE IMPLEMENTAÇÃO


Implementação em MQL5

Para desenvolver o programa em MQL5, precisaremos definir os metadados do programa e, em seguida, algumas constantes para os nomes dos objetos, que nos ajudarão a referenciar e gerenciar facilmente os elementos do painel.

//+------------------------------------------------------------------+
//|                             TimeframeScanner Dashboard EA.mq5    |
//|                           Copyright 2025, Allan Munene Mutiiria. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link      "https://t.me/Forex_Algo_Trader"
#property version   "1.00"

// Define identifiers and properties for UI elements
#define MAIN_PANEL              "PANEL_MAIN"                     //--- Main panel rectangle identifier
#define HEADER_PANEL            "PANEL_HEADER"                   //--- Header panel rectangle identifier
#define HEADER_PANEL_ICON       "PANEL_HEADER_ICON"              //--- Header icon label identifier
#define HEADER_PANEL_TEXT       "PANEL_HEADER_TEXT"              //--- Header title label identifier
#define CLOSE_BUTTON            "BUTTON_CLOSE"                   //--- Close button identifier
#define SYMBOL_RECTANGLE        "SYMBOL_HEADER"                  //--- Symbol rectangle identifier
#define SYMBOL_TEXT             "SYMBOL_TEXT"                    //--- Symbol text label identifier
#define TIMEFRAME_RECTANGLE     "TIMEFRAME_"                     //--- Timeframe rectangle prefix
#define TIMEFRAME_TEXT          "TIMEFRAME_TEXT_"                //--- Timeframe text label prefix
#define HEADER_RECTANGLE        "HEADER_"                        //--- Header rectangle prefix
#define HEADER_TEXT             "HEADER_TEXT_"                   //--- Header text label prefix
#define RSI_RECTANGLE           "RSI_"                           //--- RSI rectangle prefix
#define RSI_TEXT                "RSI_TEXT_"                      //--- RSI text label prefix
#define STOCH_RECTANGLE         "STOCH_"                         //--- Stochastic rectangle prefix
#define STOCH_TEXT              "STOCH_TEXT_"                    //--- Stochastic text label prefix
#define CCI_RECTANGLE           "CCI_"                           //--- CCI rectangle prefix
#define CCI_TEXT                "CCI_TEXT_"                      //--- CCI text label prefix
#define ADX_RECTANGLE           "ADX_"                           //--- ADX rectangle prefix
#define ADX_TEXT                "ADX_TEXT_"                      //--- ADX text label prefix
#define AO_RECTANGLE            "AO_"                            //--- AO rectangle prefix
#define AO_TEXT                 "AO_TEXT_"                       //--- AO text label prefix
#define BUY_RECTANGLE           "BUY_"                           //--- Buy rectangle prefix
#define BUY_TEXT                "BUY_TEXT_"                      //--- Buy text label prefix
#define SELL_RECTANGLE          "SELL_"                          //--- Sell rectangle prefix
#define SELL_TEXT               "SELL_TEXT_"                     //--- Sell text label prefix
#define WIDTH_TIMEFRAME         90                               //--- Width of timeframe and symbol rectangles
#define WIDTH_INDICATOR         70                               //--- Width of indicator rectangles
#define WIDTH_SIGNAL            90                               //--- Width of BUY/SELL signal rectangles
#define HEIGHT_RECTANGLE        25                               //--- Height of all rectangles
#define COLOR_WHITE             clrWhite                         //--- White color for text and backgrounds
#define COLOR_BLACK             clrBlack                         //--- Black color for borders and text
#define COLOR_LIGHT_GRAY        C'230,230,230'                   //--- Light gray color for signal backgrounds
#define COLOR_DARK_GRAY         C'105,105,105'                   //--- Dark gray color for indicator backgrounds

Começaremos estabelecendo a estrutura da interface do usuário para nosso painel de scanner multitemporal, utilizando a diretiva #define para criar constantes como "MAIN_PANEL" e "HEADER_PANEL", que representam os retângulos do painel principal e do cabeçalho, além de "HEADER_PANEL_ICON", "HEADER_PANEL_TEXT" e "CLOSE_BUTTON", correspondentes ao ícone, ao título e ao botão de fechamento do cabeçalho.

Definiremos identificadores para a estrutura em grade do painel. Para o símbolo, utilizaremos "SYMBOL_RECTANGLE" e "SYMBOL_TEXT", enquanto os prefixos "TIMEFRAME_RECTANGLE" e "TIMEFRAME_TEXT" serão responsáveis pelas linhas dos tempos gráficos. Utilizaremos os prefixos "HEADER_RECTANGLE" e "HEADER_TEXT" para os cabeçalhos das colunas, além de prefixos como "RSI_RECTANGLE", "STOCH_RECTANGLE" e "BUY_RECTANGLE", com seus correspondentes "RSI_TEXT", "STOCH_TEXT" e "BUY_TEXT", para as células dos indicadores e dos sinais.

Configuraremos as dimensões utilizando "WIDTH_TIMEFRAME" (90 pixels), "WIDTH_INDICATOR" (70 pixels), "WIDTH_SIGNAL" (90 pixels) e "HEIGHT_RECTANGLE" (25 pixels). Definiremos as cores utilizando "COLOR_WHITE" e "COLOR_BLACK" para textos e bordas, "COLOR_LIGHT_GRAY" ("C'230,230,230'") para os fundos dos sinais e "COLOR_DARK_GRAY" ("C'105,105,105'") para os indicadores, garantindo uma disposição uniforme e clara dos elementos. Em seguida, precisaremos definir algumas variáveis globais adicionais que utilizaremos ao longo do programa.

bool panel_is_visible = true;                                    //--- Flag to control panel visibility

// Define the timeframes to be used
ENUM_TIMEFRAMES timeframes_array[] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M20, PERIOD_M30, 
                                      PERIOD_H1, PERIOD_H2, PERIOD_H3, PERIOD_H4, PERIOD_H8, 
                                      PERIOD_H12, PERIOD_D1, PERIOD_W1}; //--- Array of timeframes for scanning

// Global variables for indicator values
double rsi_values[];                                             //--- Array to store RSI values
double stochastic_values[];                                      //--- Array to store Stochastic signal line values
double cci_values[];                                             //--- Array to store CCI values
double adx_values[];                                             //--- Array to store ADX values
double ao_values[];                                              //--- Array to store AO values

Aqui, declaramos a variável booleana "panel_is_visible" e atribuímos a ela o valor true, que determina se o painel será exibido no gráfico. Essa variável de controle permite alternar a visibilidade do painel conforme necessário, especialmente quando não precisamos atualizar os dados. Em seguida, definimos o array "timeframes_array" utilizando o tipo ENUM_TIMEFRAMES, listando os tempos gráficos de "PERIOD_M1" (1 minuto) até "PERIOD_W1" (semanal). Esse array especifica os tempos gráficos que serão analisados pelo painel, permitindo monitorar os sinais do mercado em diferentes horizontes temporais de maneira estruturada. Se você não precisar de alguns desses períodos ou quiser ajustá-los, basta modificar os valores da enumeração.

Para armazenar os dados dos indicadores, criamos os arrays do tipo double "rsi_values", "stochastic_values", "cci_values", "adx_values" e "ao_values". Esses arrays armazenam, respectivamente, os valores calculados do Índice de Força Relativa, do Oscilador Estocástico, do Índice de Canal de Commodities (CCI), do Índice Direcional Médio e do Awesome Oscillator, permitindo processar e exibir com eficiência os sinais de negociação de cada período gráfico. Agora, para definir funções auxiliares para formatar os nomes dos timeframes e tratar o símbolo obtido do gráfico, conforme apresentado a seguir.

//+------------------------------------------------------------------+
//| Truncate timeframe enum to display string                        |
//+------------------------------------------------------------------+
string truncate_timeframe_name(int timeframe_index)              //--- Function to format timeframe name
{
   string timeframe_string = StringSubstr(EnumToString(timeframes_array[timeframe_index]), 7); //--- Extract timeframe name
   return timeframe_string;                                      //--- Return formatted name
}

//+------------------------------------------------------------------+
//| Calculate signal strength for buy/sell                           |
//+------------------------------------------------------------------+
string calculate_signal_strength(double rsi, double stochastic, double cci, double adx, double ao, bool is_buy) //--- Function to compute signal strength
{
   int signal_strength = 0;                                      //--- Initialize signal strength counter
   
   if(is_buy && rsi < 40) signal_strength++;                     //--- Increment for buy if RSI is oversold
   else if(!is_buy && rsi > 60) signal_strength++;               //--- Increment for sell if RSI is overbought
   
   if(is_buy && stochastic < 40) signal_strength++;              //--- Increment for buy if Stochastic is oversold
   else if(!is_buy && stochastic > 60) signal_strength++;        //--- Increment for sell if Stochastic is overbought
   
   if(is_buy && cci < -70) signal_strength++;                    //--- Increment for buy if CCI is oversold
   else if(!is_buy && cci > 70) signal_strength++;               //--- Increment for sell if CCI is overbought
   
   if(adx > 40) signal_strength++;                               //--- Increment if ADX indicates strong trend
   
   if(is_buy && ao > 0) signal_strength++;                       //--- Increment for buy if AO is positive
   else if(!is_buy && ao < 0) signal_strength++;                 //--- Increment for sell if AO is negative
   
   if(signal_strength >= 3) return is_buy ? "Strong Buy" : "Strong Sell"; //--- Return strong signal if 3+ conditions met
   if(signal_strength >= 2) return is_buy ? "Buy" : "Sell";      //--- Return regular signal if 2 conditions met
   return "Neutral";                                             //--- Return neutral if insufficient conditions
}

Aqui, definimos a função "truncate_timeframe_name", que recebe um parâmetro inteiro chamado "timeframe_index" para formatar os nomes dos tempos gráficos que serão exibidos. Dentro dela, utilizamos a função StringSubstr para extrair uma substring do resultado retornado pela função EnumToString, aplicada a "timeframes_array[timeframe_index]", começando na posição 7, e armazenamos o resultado em "timeframe_string". Em seguida, retornamos "timeframe_string", fornecendo um nome de período gráfico limpo e facilmente compreensível pelo usuário.

Criamos a função "calculate_signal_strength" para determinar os sinais de compra ou venda com base nos valores dos indicadores. Inicializamos a variável inteira "signal_strength" com zero para contar quantas condições são atendidas. Para o Índice de Força Relativa, incrementamos "signal_strength" se "is_buy" for true e "rsi" estiver abaixo de 40 (sobrevenda), ou se "is_buy" for false e "rsi" estiver acima de 60 (sobrecompra). Da mesma forma, verificamos "stochastic" (abaixo de 40 ou acima de 60), "CCI" (abaixo de -70 ou acima de 70) e "ao" (positivo para compra e negativo para venda), incrementando "signal_strength" para cada condição atendida.

Também avaliamos o Índice Direcional Médio, incrementando "signal_strength" se "adx" ultrapassar 40, indicando uma tendência forte tanto nos cenários de compra quanto nos de venda. Se "signal_strength" atingir 3 ou mais, retornaremos “Strong Buy” quando "is_buy" for true, ou “Strong Sell” caso contrário. Se o valor for 2, retornaremos “Buy” ou “Sell”; para valores inferiores, retornaremos “Neutral”, permitindo uma classificação clara dos sinais no painel. Por fim, podemos definir as funções que permitirão criar os objetos.

//+------------------------------------------------------------------+
//| Create a rectangle for the UI                                    |
//+------------------------------------------------------------------+
bool create_rectangle(string object_name, int x_distance, int y_distance, int x_size, int y_size, 
                      color background_color, color border_color = COLOR_BLACK) //--- Function to create a rectangle
{
   ResetLastError();                                                            //--- Reset error code
   if(!ObjectCreate(0, object_name, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {            //--- Create rectangle object
      Print(__FUNCTION__, ": failed to create Rectangle: ERR Code: ", GetLastError()); //--- Log creation failure
      return(false);                                                            //--- Return failure
   }
   ObjectSetInteger(0, object_name, OBJPROP_XDISTANCE, x_distance);             //--- Set x position
   ObjectSetInteger(0, object_name, OBJPROP_YDISTANCE, y_distance);             //--- Set y position
   ObjectSetInteger(0, object_name, OBJPROP_XSIZE, x_size);                     //--- Set width
   ObjectSetInteger(0, object_name, OBJPROP_YSIZE, y_size);                     //--- Set height
   ObjectSetInteger(0, object_name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);        //--- Set corner to top-right
   ObjectSetInteger(0, object_name, OBJPROP_BGCOLOR, background_color);         //--- Set background color
   ObjectSetInteger(0, object_name, OBJPROP_BORDER_COLOR, border_color);        //--- Set border color
   ObjectSetInteger(0, object_name, OBJPROP_BORDER_TYPE, BORDER_FLAT);          //--- Set flat border style
   ObjectSetInteger(0, object_name, OBJPROP_BACK, false);                       //--- Set to foreground
   
   ChartRedraw(0);                                                              //--- Redraw chart
   return(true);                                                                //--- Return success
}

//+------------------------------------------------------------------+
//| Create a text label for the UI                                   |
//+------------------------------------------------------------------+
bool create_label(string object_name, string text, int x_distance, int y_distance, int font_size = 12, 
                  color text_color = COLOR_BLACK, string font = "Arial Rounded MT Bold") //--- Function to create a label
{
   ResetLastError();                                                               //--- Reset error code
   if(!ObjectCreate(0, object_name, OBJ_LABEL, 0, 0, 0)) {                         //--- Create label object
      Print(__FUNCTION__, ": failed to create Label: ERR Code: ", GetLastError()); //--- Log creation failure
      return(false);                                                               //--- Return failure
   }
   ObjectSetInteger(0, object_name, OBJPROP_XDISTANCE, x_distance);                //--- Set x position
   ObjectSetInteger(0, object_name, OBJPROP_YDISTANCE, y_distance);                //--- Set y position
   ObjectSetInteger(0, object_name, OBJPROP_CORNER, CORNER_RIGHT_UPPER);           //--- Set corner to top-right
   ObjectSetString(0, object_name, OBJPROP_TEXT, text);                            //--- Set label text
   ObjectSetString(0, object_name, OBJPROP_FONT, font);                            //--- Set font
   ObjectSetInteger(0, object_name, OBJPROP_FONTSIZE, font_size);                  //--- Set font size
   ObjectSetInteger(0, object_name, OBJPROP_COLOR, text_color);                    //--- Set text color
   ObjectSetInteger(0, object_name, OBJPROP_ANCHOR, ANCHOR_CENTER);                //--- Center text
   
   ChartRedraw(0);                                                                 //--- Redraw chart
   return(true);                                                                   //--- Return success
}

Para permitir a criação dos objetos, definimos a função "create_rectangle" com os parâmetros "object_name", "x_distance", "y_distance", "x_size", "y_size", "background_color" e "border_color". Utilizamos a função ResetLastError, criamos um objeto do tipo OBJ_RECTANGLE_LABEL por meio da função ObjectCreate e, caso a criação falhe, registramos o erro utilizando a função "Print" e retornamos false.

Definimos as propriedades do retângulo utilizando a função ObjectSetInteger para configurar a posição, as dimensões, "CORNER_RIGHT_UPPER", "background_color", "border_color" e "BORDER_FLAT", garantindo que o objeto seja exibido em primeiro plano. Em seguida, utilizamos a função ChartRedraw e retornamos true. Para os textos, definimos a função "create_label" com os parâmetros "object_name", "text", "x_distance", "y_distance", "font_size", "text_color" e "font".

Utilizamos a função "ResetLastError", criamos um objeto do tipo "OBJ_LABEL" por meio da função "ObjectCreate" e registramos os erros caso a criação falhe. Utilizamos a função "ObjectSetInteger" para configurar a posição, o tamanho, a cor e "ANCHOR_CENTER", e a função ObjectSetString para definir "text" e "font". Em seguida, utilizamos a função "ChartRedraw" e retornamos true. Com essas funções disponíveis, podemos criar os objetos iniciais do painel, estabelecendo um ponto de partida no manipulador de eventos "OnInit".

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()                                                                             //--- Initialize EA
{
   create_rectangle(MAIN_PANEL, 632, 40, 617, 374, C'30,30,30', BORDER_FLAT);            //--- Create main panel background
   create_rectangle(HEADER_PANEL, 632, 40, 617, 27, C'60,60,60', BORDER_FLAT);           //--- Create header panel background
   create_label(HEADER_PANEL_ICON, CharToString(91), 620, 54, 18, clrAqua, "Wingdings"); //--- Create header icon
   create_label(HEADER_PANEL_TEXT, "TimeframeScanner", 527, 52, 13, COLOR_WHITE);        //--- Create header title
   create_label(CLOSE_BUTTON, CharToString('r'), 32, 54, 18, clrYellow, "Webdings");     //--- Create close button

   // Create header rectangle and label
   create_rectangle(SYMBOL_RECTANGLE, 630, 75, WIDTH_TIMEFRAME, HEIGHT_RECTANGLE, clrGray); //--- Create symbol rectangle
   create_label(SYMBOL_TEXT, _Symbol, 585, 85, 11, COLOR_WHITE); //--- Create symbol label
   
   // Create summary and indicator headers (rectangles and labels)
   string header_names[] = {"BUY", "SELL", "RSI", "STOCH", "CCI", "ADX", "AO"};            //--- Define header titles
   for(int header_index = 0; header_index < ArraySize(header_names); header_index++) {     //--- Loop through headers
      int x_offset = (630 - WIDTH_TIMEFRAME) - (header_index < 2 ? header_index * WIDTH_SIGNAL : 2 * WIDTH_SIGNAL + (header_index - 2) * WIDTH_INDICATOR) + (1 + header_index); //--- Calculate x position
      int width = (header_index < 2 ? WIDTH_SIGNAL : WIDTH_INDICATOR);                     //--- Set width based on header type
      create_rectangle(HEADER_RECTANGLE + IntegerToString(header_index), x_offset, 75, width, HEIGHT_RECTANGLE, clrGray);             //--- Create header rectangle
      create_label(HEADER_TEXT + IntegerToString(header_index), header_names[header_index], x_offset - width/2, 85, 11, COLOR_WHITE); //--- Create header label
   }
   
   // Create timeframe rectangles and labels, and summary/indicator cells
   for(int timeframe_index = 0; timeframe_index < ArraySize(timeframes_array); timeframe_index++) {            //--- Loop through timeframes
      // Highlight current timeframe
      color timeframe_background = (timeframes_array[timeframe_index] == _Period) ? clrLimeGreen : clrGray;    //--- Set background color for current timeframe
      color timeframe_text_color = (timeframes_array[timeframe_index] == _Period) ? COLOR_BLACK : COLOR_WHITE; //--- Set text color for current timeframe
      
      create_rectangle(TIMEFRAME_RECTANGLE + IntegerToString(timeframe_index), 630, (75 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), WIDTH_TIMEFRAME, HEIGHT_RECTANGLE, timeframe_background);   //--- Create timeframe rectangle
      create_label(TIMEFRAME_TEXT + IntegerToString(timeframe_index), truncate_timeframe_name(timeframe_index), 585, (85 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), 11, timeframe_text_color); //--- Create timeframe label
                  
      // Create summary and indicator cells
      for(int header_index = 0; header_index < ArraySize(header_names); header_index++) { //--- Loop through headers for cells
         string cell_rectangle_name, cell_text_name;                                      //--- Declare cell name and label variables
         color cell_background = (header_index < 2) ? COLOR_LIGHT_GRAY : COLOR_BLACK;     //--- Set cell background color
         switch(header_index) {                                   //--- Select cell type
            case 0: cell_rectangle_name = BUY_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = BUY_TEXT + IntegerToString(timeframe_index); break;     //--- Buy cell
            case 1: cell_rectangle_name = SELL_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = SELL_TEXT + IntegerToString(timeframe_index); break;   //--- Sell cell
            case 2: cell_rectangle_name = RSI_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = RSI_TEXT + IntegerToString(timeframe_index); break;     //--- RSI cell
            case 3: cell_rectangle_name = STOCH_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = STOCH_TEXT + IntegerToString(timeframe_index); break; //--- Stochastic cell
            case 4: cell_rectangle_name = CCI_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = CCI_TEXT + IntegerToString(timeframe_index); break;     //--- CCI cell
            case 5: cell_rectangle_name = ADX_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = ADX_TEXT + IntegerToString(timeframe_index); break;     //--- ADX cell
            case 6: cell_rectangle_name = AO_RECTANGLE + IntegerToString(timeframe_index); cell_text_name = AO_TEXT + IntegerToString(timeframe_index); break;       //--- AO cell
         }
         int x_offset = (630 - WIDTH_TIMEFRAME) - (header_index < 2 ? header_index * WIDTH_SIGNAL : 2 * WIDTH_SIGNAL + (header_index - 2) * WIDTH_INDICATOR) + (1 + header_index);        //--- Calculate x position
         int width = (header_index < 2 ? WIDTH_SIGNAL : WIDTH_INDICATOR); //--- Set width based on cell type
         create_rectangle(cell_rectangle_name, x_offset, (75 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), width, HEIGHT_RECTANGLE, cell_background); //--- Create cell rectangle
         create_label(cell_text_name, "-/-", x_offset - width/2, (85 + HEIGHT_RECTANGLE) + timeframe_index * HEIGHT_RECTANGLE - (1 + timeframe_index), 10, COLOR_WHITE);                  //--- Create cell label
      }
   }
   
   // Initialize indicator arrays
   ArraySetAsSeries(rsi_values, true);                       //--- Set RSI array as timeseries
   ArraySetAsSeries(stochastic_values, true);                //--- Set Stochastic array as timeseries
   ArraySetAsSeries(cci_values, true);                       //--- Set CCI array as timeseries
   ArraySetAsSeries(adx_values, true);                       //--- Set ADX array as timeseries
   ArraySetAsSeries(ao_values, true);                        //--- Set AO array as timeseries
    
   return(INIT_SUCCEEDED);                                   //--- Return initialization success
}

No manipulador de eventos OnInit, inicializamos a interface do usuário do painel de scanner multitemporal. Utilizamos a função "create_rectangle" para desenhar o "MAIN_PANEL" na posição (632, 40), com dimensões de 617x374 pixels e cor “C’30,30,30’”, e o "HEADER_PANEL" na mesma posição, com altura de 27 pixels e cor “C’60,60,60’”. Utilizamos a função "create_label" para adicionar o "HEADER_PANEL_ICON" com um caractere da fonte Wingdings na posição (620, 54). Utilizamos os caracteres padrão do MQL5 e a função CharToString para converter o código do caractere em uma string. O código do caractere que utilizamos é 91, mas você pode escolher qualquer outro de sua preferência.

WINGDINGS DO MQL5

Em seguida, criamos o "HEADER_PANEL_TEXT" com o texto “TimeframeScanner” na posição (527, 52) e o "CLOSE_BUTTON" na posição (32, 54). Desta vez, porém, utilizamos uma fonte diferente e convertemos a letra "r" em string. Abaixo, apresentamos uma visualização dos diferentes símbolos de fonte que você pode utilizar.

FONTE DE SÍMBOLOS

Configuramos a exibição do símbolo utilizando a função "create_rectangle" para criar o "SYMBOL_RECTANGLE" na posição (630, 75), com dimensões definidas por "WIDTH_TIMEFRAME" e "HEIGHT_RECTANGLE", na cor cinza. Utilizamos a função "create_label" para posicionar o "SYMBOL_TEXT" em (585, 85), exibindo o símbolo atual. Para os cabeçalhos, definimos o array "header_names" com títulos como “BUY” e “RSI” e percorremos seus elementos em um laço para criar os objetos "HEADER_RECTANGLE" na coordenada y=75, com deslocamentos horizontais baseados em "WIDTH_SIGNAL" e "WIDTH_INDICATOR", além dos rótulos "HEADER_TEXT" na coordenada y=85, utilizando a função "create_label".

Construímos a grade dos tempos gráficos percorrendo o array "timeframes_array" em um laço. Utilizamos a função "create_rectangle" para criar os objetos "TIMEFRAME_RECTANGLE" na coordenada x=630, com deslocamentos verticais a partir de (75 + "HEIGHT_RECTANGLE"), ajustados por -(1 + "timeframe_index"), e com a cor definida por "timeframe_background". Utilizamos a função "create_label" para criar os objetos "TIMEFRAME_TEXT", com os nomes obtidos pela função "truncate_timeframe_name". Para as células, percorremos um laço para criar "BUY_RECTANGLE", "RSI_RECTANGLE" e outros objetos semelhantes utilizando a função "create_rectangle", com "cell_background", e adicionamos rótulos “-/-” por meio da função "create_label". Inicializamos os arrays dos indicadores, como "rsi_values", utilizando a função ArraySetAsSeries, configurando-os como séries temporais para o processamento dos dados. Retornamos INIT_SUCCEEDED para confirmar que a inicialização foi concluída com sucesso, estabelecendo a estrutura visual e a organização dos dados do painel. Após a compilação, obtemos o seguinte resultado.

PAINEL ESTÁTICO

Pela imagem, podemos observar que o painel está pronto. Agora, precisamos apenas adicionar os valores dos indicadores e utilizá-los na análise. Já temos uma função responsável pela análise; precisamos apenas obter os dados. Para facilitar esse processo, criaremos uma função responsável por toda a lógica de atualização dinâmica.

//+------------------------------------------------------------------+
//| Update indicator values                                          |
//+------------------------------------------------------------------+
void updateIndicators()                                                                               //--- Update dashboard indicators
{
   for(int timeframe_index = 0; timeframe_index < ArraySize(timeframes_array); timeframe_index++) {   //--- Loop through timeframes
      // Initialize indicator handles
      int rsi_indicator_handle = iRSI(_Symbol, timeframes_array[timeframe_index], 14, PRICE_CLOSE);   //--- Create RSI handle
      int stochastic_indicator_handle = iStochastic(_Symbol, timeframes_array[timeframe_index], 14, 3, 3, MODE_SMA, STO_LOWHIGH); //--- Create Stochastic handle
      int cci_indicator_handle = iCCI(_Symbol, timeframes_array[timeframe_index], 20, PRICE_TYPICAL); //--- Create CCI handle
      int adx_indicator_handle = iADX(_Symbol, timeframes_array[timeframe_index], 14);                //--- Create ADX handle
      int ao_indicator_handle = iAO(_Symbol, timeframes_array[timeframe_index]);                      //--- Create AO handle
      
      // Check for valid handles
      if(rsi_indicator_handle == INVALID_HANDLE || stochastic_indicator_handle == INVALID_HANDLE || 
         cci_indicator_handle == INVALID_HANDLE || adx_indicator_handle == INVALID_HANDLE || 
         ao_indicator_handle == INVALID_HANDLE) {                                                             //--- Check if any handle is invalid
         Print("Failed to create indicator handle for timeframe ", truncate_timeframe_name(timeframe_index)); //--- Log failure
         continue;                                                                                            //--- Skip to next timeframe
      }
      
      // Copy indicator values
      if(CopyBuffer(rsi_indicator_handle, 0, 0, 1, rsi_values) <= 0 ||                            //--- Copy RSI value
         CopyBuffer(stochastic_indicator_handle, 1, 0, 1, stochastic_values) <= 0 ||              //--- Copy Stochastic signal line value
         CopyBuffer(cci_indicator_handle, 0, 0, 1, cci_values) <= 0 ||                            //--- Copy CCI value
         CopyBuffer(adx_indicator_handle, 0, 0, 1, adx_values) <= 0 ||                            //--- Copy ADX value
         CopyBuffer(ao_indicator_handle, 0, 0, 1, ao_values) <= 0) {                              //--- Copy AO value
         Print("Failed to copy buffer for timeframe ", truncate_timeframe_name(timeframe_index)); //--- Log copy failure
         continue;                                                                                //--- Skip to next timeframe
      }
      
      // Update RSI
      color rsi_text_color = (rsi_values[0] < 30) ? clrBlue : (rsi_values[0] > 70) ? clrRed : COLOR_WHITE;         //--- Set RSI text color
      update_label(RSI_TEXT + IntegerToString(timeframe_index), DoubleToString(rsi_values[0], 2), rsi_text_color); //--- Update RSI label
      
      // Update Stochastic (Signal Line only)
      color stochastic_text_color = (stochastic_values[0] < 20) ? clrBlue : (stochastic_values[0] > 80) ? clrRed : COLOR_WHITE;    //--- Set Stochastic text color
      update_label(STOCH_TEXT + IntegerToString(timeframe_index), DoubleToString(stochastic_values[0], 2), stochastic_text_color); //--- Update Stochastic label
      
      // Update CCI
      color cci_text_color = (cci_values[0] < -100) ? clrBlue : (cci_values[0] > 100) ? clrRed : COLOR_WHITE;      //--- Set CCI text color
      update_label(CCI_TEXT + IntegerToString(timeframe_index), DoubleToString(cci_values[0], 2), cci_text_color); //--- Update CCI label
      
      // Update ADX
      color adx_text_color = (adx_values[0] > 25) ? clrBlue : COLOR_WHITE;                                         //--- Set ADX text color
      update_label(ADX_TEXT + IntegerToString(timeframe_index), DoubleToString(adx_values[0], 2), adx_text_color); //--- Update ADX label
      
      // Update AO
      color ao_text_color = (ao_values[0] > 0) ? clrGreen : (ao_values[0] < 0) ? clrRed : COLOR_WHITE;          //--- Set AO text color
      update_label(AO_TEXT + IntegerToString(timeframe_index), DoubleToString(ao_values[0], 2), ao_text_color); //--- Update AO label
      
      // Update Buy/Sell signals
      string buy_signal = calculate_signal_strength(rsi_values[0], stochastic_values[0], cci_values[0], 
                                                   adx_values[0], ao_values[0], true);                          //--- Calculate buy signal
      string sell_signal = calculate_signal_strength(rsi_values[0], stochastic_values[0], cci_values[0], 
                                                    adx_values[0], ao_values[0], false);                        //--- Calculate sell signal
      
      color buy_text_color = (buy_signal == "Strong Buy") ? COLOR_WHITE : COLOR_WHITE;                          //--- Set buy text color
      color buy_background = (buy_signal == "Strong Buy") ? clrGreen : 
                            (buy_signal == "Buy") ? clrSeaGreen : COLOR_DARK_GRAY;                              //--- Set buy background color
      update_rectangle(BUY_RECTANGLE + IntegerToString(timeframe_index), buy_background);                       //--- Update buy rectangle
      update_label(BUY_TEXT + IntegerToString(timeframe_index), buy_signal, buy_text_color);                    //--- Update buy label
      
      color sell_text_color = (sell_signal == "Strong Sell") ? COLOR_WHITE : COLOR_WHITE;                       //--- Set sell text color
      color sell_background = (sell_signal == "Strong Sell") ? clrRed : 
                             (sell_signal == "Sell") ? clrSalmon : COLOR_DARK_GRAY;                             //--- Set sell background color
      update_rectangle(SELL_RECTANGLE + IntegerToString(timeframe_index), sell_background);                     //--- Update sell rectangle
      update_label(SELL_TEXT + IntegerToString(timeframe_index), sell_signal, sell_text_color);                 //--- Update sell label
      
      // Release indicator handles
      IndicatorRelease(rsi_indicator_handle);                   //--- Release RSI handle
      IndicatorRelease(stochastic_indicator_handle);            //--- Release Stochastic handle
      IndicatorRelease(cci_indicator_handle);                   //--- Release CCI handle
      IndicatorRelease(adx_indicator_handle);                   //--- Release ADX handle
      IndicatorRelease(ao_indicator_handle);                    //--- Release AO handle
   }
}

Para facilitar o gerenciamento da atualização dos valores do painel, implementamos a função "updateIndicators", responsável por atualizar os valores dos indicadores e os sinais. Percorremos o array "timeframes_array" utilizando "timeframe_index", processando cada período gráfico. Utilizamos as funções iRSI, "iStochastic", "iCCI", iADX e "iAO" para criar os handles dos indicadores, como "rsi_indicator_handle", para o símbolo e o período gráfico atuais, configurando parâmetros como um RSI de 14 períodos e um CCI de 20 períodos. Todas as configurações dos indicadores podem ser personalizadas de acordo com suas necessidades. Portanto, não é necessário se limitar aos valores padrão.

Em seguida, verificamos se algum handle, como "rsi_indicator_handle", é igual a INVALID_HANDLE, indicando uma falha na criação. Se isso ocorrer, utilizamos a função "Print" para registrar o erro, incluindo o resultado retornado pela função "truncate_timeframe_name", e passamos para o próximo período gráfico. Utilizamos a função CopyBuffer para recuperar os valores mais recentes e armazená-los em arrays como "rsi_values". Se alguma operação falhar, registramos o erro e continuamos o processamento. Atualizamos a exibição dos indicadores utilizando a função "update_label". Por exemplo, definimos "rsi_text_color" com base em "rsi_values[0]" (azul se for inferior a 30, vermelho se for superior a 70 e "COLOR_WHITE" nos demais casos) e atualizamos "RSI_TEXT" com o valor formatado pela função "DoubleToString". Repetimos esse procedimento para "stochastic_values", "cci_values", "adx_values" e "ao_values", aplicando as regras de cores correspondentes (por exemplo, verde para valores positivos de "ao_values").

Calculamos os sinais utilizando a função "calculate_signal_strength", passando "rsi_values[0]" e os demais valores dos indicadores para obter "buy_signal" e "sell_signal". Definimos "buy_background" (por exemplo, verde para “Strong Buy”) e utilizamos a função "update_rectangle" para atualizar "BUY_RECTANGLE", além de atualizar "BUY_TEXT" por meio de "update_label". Fazemos o mesmo para "sell_background" e "SELL_TEXT". Por fim, utilizamos a função IndicatorRelease para liberar os handles, como "rsi_indicator_handle", garantindo um gerenciamento eficiente dos recursos. As funções auxiliares que utilizamos estão definidas a seguir.

//+------------------------------------------------------------------+
//| Update rectangle background color                                |
//+------------------------------------------------------------------+
bool update_rectangle(string object_name, color background_color)//--- Function to update rectangle color
{
   int found = ObjectFind(0, object_name);                       //--- Find rectangle object
   if(found < 0) {                                               //--- Check if object not found
      ResetLastError();                                          //--- Reset error code
      Print("UNABLE TO FIND THE RECTANGLE: ", object_name, ". ERR Code: ", GetLastError()); //--- Log error
      return(false);                                             //--- Return failure
   }
   ObjectSetInteger(0, object_name, OBJPROP_BGCOLOR, background_color); //--- Set background color
   
   ChartRedraw(0);                                               //--- Redraw chart
   return(true);                                                 //--- Return success
}

//+------------------------------------------------------------------+
//| Update label text and color                                      |
//+------------------------------------------------------------------+
bool update_label(string object_name, string text, color text_color) //--- Function to update label
{
   int found = ObjectFind(0, object_name);                       //--- Find label object
   if(found < 0) {                                               //--- Check if object not found
      ResetLastError();                                          //--- Reset error code
      Print("UNABLE TO FIND THE LABEL: ", object_name, ". ERR Code: ", GetLastError()); //--- Log error
      return(false);                                             //--- Return failure
   }
   ObjectSetString(0, object_name, OBJPROP_TEXT, text);          //--- Set label text
   ObjectSetInteger(0, object_name, OBJPROP_COLOR, text_color);  //--- Set text color
   
   ChartRedraw(0);                                               //--- Redraw chart
   return(true);                                                 //--- Return success
}

Definimos a função "update_rectangle", que recebe os parâmetros "object_name" e "background_color" para modificar a aparência de um retângulo. Utilizamos a função ObjectFind para localizar o retângulo, armazenando o resultado em "found". Se "found" for menor que 0, indicando que o objeto não foi encontrado, utilizamos a função ResetLastError, registramos o erro por meio das funções "Print" e "GetLastError" e retornamos false. Atualizamos o fundo do retângulo utilizando a função "ObjectSetInteger" para definir a propriedade "OBJPROP_BGCOLOR" com o valor de "background_color". Utilizamos a função ChartRedraw para atualizar o gráfico e retornamos true para indicar que a operação foi concluída com sucesso. Para atualizar os textos, definimos a função "update_label" com os parâmetros "object_name", "text" e "text_color".

Utilizamos a função "ObjectFind" para verificar se o rótulo existe. Se "found" for negativo, utilizamos a função "ResetLastError", registramos o erro por meio da função "Print" e retornamos false. Utilizamos a função ObjectSetString para definir "OBJPROP_TEXT" com o valor de "text" e a função ObjectSetInteger para definir "OBJPROP_COLOR" com o valor de "text_color". Utilizamos a função "ChartRedraw" para atualizar o gráfico e retornamos true, permitindo a atualização dinâmica dos rótulos. Agora, podemos chamar a função de atualização a cada tick para manter os dados do painel atualizados.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()                                                    //--- Handle tick events
{
   if (panel_is_visible) {                                       //--- Check if panel is visible
      updateIndicators();                                        //--- Update indicators
   }
}

Aqui, no manipulador de eventos OnTick, simplesmente chamamos a função "updateIndicators" quando o painel estiver visível, para aplicar as atualizações. Por fim, precisamos excluir os objetos que criamos, garantindo que sejam removidos do gráfico quando não forem mais necessários.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)                                  //--- Deinitialize EA
{
   ObjectDelete(0, MAIN_PANEL);                                  //--- Delete main panel
   ObjectDelete(0, HEADER_PANEL);                                //--- Delete header panel
   ObjectDelete(0, HEADER_PANEL_ICON);                           //--- Delete header icon
   ObjectDelete(0, HEADER_PANEL_TEXT);                           //--- Delete header title
   ObjectDelete(0, CLOSE_BUTTON);                                //--- Delete close button

   ObjectsDeleteAll(0, SYMBOL_RECTANGLE);                        //--- Delete all symbol rectangles
   ObjectsDeleteAll(0, SYMBOL_TEXT);                             //--- Delete all symbol labels
   ObjectsDeleteAll(0, TIMEFRAME_RECTANGLE);                     //--- Delete all timeframe rectangles
   ObjectsDeleteAll(0, TIMEFRAME_TEXT);                          //--- Delete all timeframe labels
   ObjectsDeleteAll(0, HEADER_RECTANGLE);                        //--- Delete all header rectangles
   ObjectsDeleteAll(0, HEADER_TEXT);                             //--- Delete all header labels
   ObjectsDeleteAll(0, RSI_RECTANGLE);                           //--- Delete all RSI rectangles
   ObjectsDeleteAll(0, RSI_TEXT);                                //--- Delete all RSI labels
   ObjectsDeleteAll(0, STOCH_RECTANGLE);                         //--- Delete all Stochastic rectangles
   ObjectsDeleteAll(0, STOCH_TEXT);                              //--- Delete all Stochastic labels
   ObjectsDeleteAll(0, CCI_RECTANGLE);                           //--- Delete all CCI rectangles
   ObjectsDeleteAll(0, CCI_TEXT);                                //--- Delete all CCI labels
   ObjectsDeleteAll(0, ADX_RECTANGLE);                           //--- Delete all ADX rectangles
   ObjectsDeleteAll(0, ADX_TEXT);                                //--- Delete all ADX labels
   ObjectsDeleteAll(0, AO_RECTANGLE);                            //--- Delete all AO rectangles
   ObjectsDeleteAll(0, AO_TEXT);                                 //--- Delete all AO labels
   ObjectsDeleteAll(0, BUY_RECTANGLE);                           //--- Delete all buy rectangles
   ObjectsDeleteAll(0, BUY_TEXT);                                //--- Delete all buy labels
   ObjectsDeleteAll(0, SELL_RECTANGLE);                          //--- Delete all sell rectangles
   ObjectsDeleteAll(0, SELL_TEXT);                               //--- Delete all sell labels
   
   ChartRedraw(0);                                               //--- Redraw chart
}

Para finalizar, implementamos o processo de limpeza utilizando a função OnDeinit, executada quando o Expert Advisor é removido. Utilizamos a função ObjectDelete para remover individualmente os elementos da interface, começando pelo retângulo "MAIN_PANEL", seguido de "HEADER_PANEL", "HEADER_PANEL_ICON", "HEADER_PANEL_TEXT" e "CLOSE_BUTTON", garantindo que o painel principal e os componentes do cabeçalho sejam removidos do gráfico.

Removemos sistematicamente todos os objetos do painel utilizando a função ObjectsDeleteAll para cada tipo de elemento. Excluímos todos os retângulos e rótulos associados a "SYMBOL_RECTANGLE" e "SYMBOL_TEXT", "TIMEFRAME_RECTANGLE" e "TIMEFRAME_TEXT", além de "HEADER_RECTANGLE" e "HEADER_TEXT", removendo as informações exibidas sobre o símbolo, os tempos gráficos e os cabeçalhos. Também removemos os objetos relacionados aos indicadores, incluindo "RSI_RECTANGLE", "STOCH_RECTANGLE", "CCI_RECTANGLE", "ADX_RECTANGLE" e "AO_RECTANGLE", juntamente com seus respectivos rótulos de texto, como "RSI_TEXT".

Concluímos a limpeza utilizando a função "ObjectsDeleteAll" para excluir todos os objetos "BUY_RECTANGLE" e "SELL_RECTANGLE", juntamente com seus rótulos "BUY_TEXT" e "SELL_TEXT", removendo todos os elementos relacionados aos sinais. Por fim, utilizamos a função ChartRedraw para atualizar o gráfico, garantindo que ele fique visualmente limpo após a desinicialização. Também precisamos configurar o botão de fechamento para que, ao ser clicado, o painel seja fechado e as atualizações posteriores sejam desativadas.

//+------------------------------------------------------------------+
//| Expert chart event handler                                       |
//+------------------------------------------------------------------+
void OnChartEvent(const int       event_id,                      //--- Event ID
                  const long&     long_param,                    //--- Long parameter
                  const double&   double_param,                  //--- Double parameter
                  const string&   string_param)                  //--- String parameter
{
   if (event_id == CHARTEVENT_OBJECT_CLICK) {                    //--- Check for object click event
      if (string_param == CLOSE_BUTTON) {                        //--- Check if close button clicked
         Print("Closing the panel now");                         //--- Log panel closure
         PlaySound("alert.wav");                                 //--- Play alert sound
         panel_is_visible = false;                               //--- Hide panel
         
         ObjectDelete(0, MAIN_PANEL);                            //--- Delete main panel
         ObjectDelete(0, HEADER_PANEL);                          //--- Delete header panel
         ObjectDelete(0, HEADER_PANEL_ICON);                     //--- Delete header icon
         ObjectDelete(0, HEADER_PANEL_TEXT);                     //--- Delete header title
         ObjectDelete(0, CLOSE_BUTTON);                          //--- Delete close button
      
         ObjectsDeleteAll(0, SYMBOL_RECTANGLE);                  //--- Delete all symbol rectangles
         ObjectsDeleteAll(0, SYMBOL_TEXT);                       //--- Delete all symbol labels
         ObjectsDeleteAll(0, TIMEFRAME_RECTANGLE);               //--- Delete all timeframe rectangles
         ObjectsDeleteAll(0, TIMEFRAME_TEXT);                    //--- Delete all timeframe labels
         ObjectsDeleteAll(0, HEADER_RECTANGLE);                  //--- Delete all header rectangles
         ObjectsDeleteAll(0, HEADER_TEXT);                       //--- Delete all header labels
         ObjectsDeleteAll(0, RSI_RECTANGLE);                     //--- Delete all RSI rectangles
         ObjectsDeleteAll(0, RSI_TEXT);                          //--- Delete all RSI labels
         ObjectsDeleteAll(0, STOCH_RECTANGLE);                   //--- Delete all Stochastic rectangles
         ObjectsDeleteAll(0, STOCH_TEXT);                        //--- Delete all Stochastic labels
         ObjectsDeleteAll(0, CCI_RECTANGLE);                     //--- Delete all CCI rectangles
         ObjectsDeleteAll(0, CCI_TEXT);                          //--- Delete all CCI labels
         ObjectsDeleteAll(0, ADX_RECTANGLE);                     //--- Delete all ADX rectangles
         ObjectsDeleteAll(0, ADX_TEXT);                          //--- Delete all ADX labels
         ObjectsDeleteAll(0, AO_RECTANGLE);                      //--- Delete all AO rectangles
         ObjectsDeleteAll(0, AO_TEXT);                           //--- Delete all AO labels
         ObjectsDeleteAll(0, BUY_RECTANGLE);                     //--- Delete all buy rectangles
         ObjectsDeleteAll(0, BUY_TEXT);                          //--- Delete all buy labels
         ObjectsDeleteAll(0, SELL_RECTANGLE);                    //--- Delete all sell rectangles
         ObjectsDeleteAll(0, SELL_TEXT);                         //--- Delete all sell labels
         
         ChartRedraw(0);                                         //--- Redraw chart
      }
   }
}

No manipulador de eventos OnChartEvent, monitoramos os cliques nos objetos quando o identificador do evento corresponde a CHARTEVENT_OBJECT_CLICK. Quando o objeto clicado é o botão de fechamento, reproduzimos um som de alerta utilizando a função PlaySound para informar ao usuário que o painel está sendo desativado. Em seguida, desativamos a visibilidade do painel e utilizamos a mesma lógica de limpeza empregada em OnDeinit para remover todos os elementos do painel. Após a compilação, obtemos o seguinte resultado.

PAINEL ATUALIZADO

Pela imagem, podemos observar que o painel foi atualizado com os dados dos indicadores e a indicação das direções de negociação. Agora, resta testar o funcionamento do projeto, o que será abordado na próxima seção.


Backtesting

Realizamos os testes e, a seguir, apresentamos uma visualização consolidada em um único arquivo GIF animado.

GIF DOS TESTES


Conclusão

Concluindo, desenvolvemos um painel de scanner multitemporal em MQL5, integrando uma estrutura organizada em grade, sinais de indicadores em tempo real e um botão de fechamento interativo para aprimorar as decisões estratégicas de negociação. Demonstramos o planejamento e a implementação desses recursos, garantindo sua eficácia por meio de uma inicialização consistente ou assegurando seu funcionamento com uma inicialização adequada. Você pode personalizar esse painel de acordo com suas preferências, melhorando significativamente sua capacidade de monitorar os sinais do mercado e agir com base neles em diferentes tempos gráficos.

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

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.
Ciência de Dados e ML (Parte 42): Previsão de Séries Temporais no Mercado Forex com ARIMA em Python Ciência de Dados e ML (Parte 42): Previsão de Séries Temporais no Mercado Forex com ARIMA em Python
ARIMA, sigla para Modelo Autorregressivo Integrado de Médias Móveis, é um poderoso modelo estatístico tradicional de previsão de séries temporais. Com a capacidade de identificar picos e flutuações nos dados de uma série temporal, esse modelo pode prever com precisão os próximos valores. Neste artigo, vamos entender o que é o ARIMA, como funciona, como utilizá-lo para prever os próximos preços do mercado com alta precisão e muito mais.
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.
Machine Learning e Data Science (Parte 45): Previsão de séries temporais no Forex com o modelo PROPHET do Facebook Machine Learning e Data Science (Parte 45): Previsão de séries temporais no Forex com o modelo PROPHET do Facebook
O modelo Prophet, desenvolvido pelo Facebook, permite prever séries temporais e identificar tendências, padrões sazonais e efeitos de feriados com o mínimo de ajustes manuais. Esse método é amplamente utilizado na previsão de demanda e no planejamento empresarial. Neste artigo, vamos investigar a eficácia do modelo Prophet na previsão da volatilidade de instrumentos cambiais e avaliar se ele também pode ser aplicado fora do contexto tradicional de negócios.