English Русский 中文 Deutsch 日本語
preview
Herramientas de trading de MQL5 (Parte 3): Creación de un panel de control con análisis de múltiples marcos temporales para el trading estratégico

Herramientas de trading de MQL5 (Parte 3): Creación de un panel de control con análisis de múltiples marcos temporales para el trading estratégico

MetaTrader 5Trading |
34 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Introducción

En nuestro artículo anterior, la parte 2, mejoramos una herramienta de asistencia al trading en MetaQuotes Language 5 (MQL5) añadiéndole una retroalimentación visual dinámica para aumentar la interactividad. Ahora, nos centramos en desarrollar un panel de control con escáner multitemporal para ofrecer señales de trading en tiempo real que ayuden en la toma de decisiones estratégicas. Presentamos una interfaz basada en cuadrícula con señales controladas por indicadores y un botón de cierre, y estos avances se desarrollan en los siguientes apartados:

  1. El plan del panel de control del escáner
  2. Implementación en MQL5
  3. Backtesting
  4. Conclusión

Estas secciones nos guían hacia la creación de un panel de control de operaciones intuitivo y potente.


El plan del panel de control del escáner

Nuestro objetivo es crear un panel de control multitemporal que proporcione señales de trading claras y en tiempo real para mejorar la toma de decisiones estratégicas. El panel de control contará con un diseño en cuadrícula que mostrará señales de compra y venta en distintos marcos temporales, lo que nos permitirá evaluar rápidamente las condiciones del mercado sin tener que cambiar de gráfico. Se incluirá un botón de cierre para permitir cerrar fácilmente el panel, lo que garantizará una experiencia de usuario limpia y flexible que se adapte a nuestras necesidades de negociación.

Incorporaremos señales de indicadores clave, entre los que se incluyen el Índice de Fuerza Relativa (RSI), el Oscilador Estocástico (STOCH), el Commodity Channel Index (CCI), el Índice Direccional Medio (ADX) y el Awesome Oscillator (AO), diseñados para identificar posibles oportunidades de negociación con umbrales de fuerza personalizables. Sin embargo, la elección de los indicadores o los datos de acción del precio que se utilicen depende de usted. Esta configuración nos ayudará a detectar tendencias y cambios de tendencia en diferentes marcos temporales, lo que permite aplicar estrategias tanto a corto como a largo plazo. Nuestro objetivo es crear una herramienta intuitiva y optimizada que proporcione información útil sin dejar de ser fácil de usar, allanando el camino para futuras mejoras como alertas automatizadas o indicadores adicionales. A continuación puede verse una vista previa del resultado previsto.

PLAN DE IMPLEMENTACIÓN


Implementación en MQL5

Para crear el programa en MQL5, tendremos que definir los metadatos del programa y, a continuación, definir algunas constantes de nombre de objetos, que nos ayudarán a referirnos a los objetos del panel de control y a gestionarlos fácilmente.

//+------------------------------------------------------------------+
//|                             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

Comenzamos por definir el marco de la interfaz de usuario para nuestro panel de control del escáner de múltiples marcos temporales utilizando la directiva #define para crear constantes como «MAIN_PANEL» y «HEADER_PANEL» para los rectángulos del panel principal y del encabezado, y «HEADER_PANEL_ICON», «HEADER_PANEL_TEXT» y «CLOSE_BUTTON» para el icono, el título y el botón de cierre del encabezado.

Definimos los identificadores para la estructura de cuadrícula del panel de control. Para el símbolo, establecemos «SYMBOL_RECTANGLE» y «SYMBOL_TEXT», mientras que los prefijos «TIMEFRAME_RECTANGLE» y «TIMEFRAME_TEXT» se encargan de las filas de los marcos temporales. Utilizamos los prefijos «HEADER_RECTANGLE» y «HEADER_TEXT» para los encabezados de columna, y prefijos como «RSI_RECTANGLE», «STOCH_RECTANGLE» y «BUY_RECTANGLE», junto con los correspondientes «RSI_TEXT», «STOCH_TEXT» y «BUY_TEXT», para las celdas de indicadores y señales.

Configuramos los tamaños con «WIDTH_TIMEFRAME» (90 píxeles), «WIDTH_INDICATOR» (70 píxeles), «WIDTH_SIGNAL» (90 píxeles) y «HEIGHT_RECTANGLE» (25 píxeles). Definimos los colores utilizando «COLOR_WHITE» y «COLOR_BLACK» para el texto y los bordes, «COLOR_LIGHT_GRAY» («C'230,230,230'») para los fondos de las señales y «COLOR_DARK_GRAY» («C'105,105,105'») para los indicadores, lo que garantiza un diseño uniforme y claro. A continuación, debemos definir algunas variables globales más que utilizaremos a lo largo del 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

Aquí declaramos la variable booleana «panel_is_visible» y le asignamos el valor «true», lo que determina si el panel de control se muestra en el gráfico. Esta opción nos permite activar o desactivar la visibilidad del panel de control según sea necesario, sobre todo cuando no necesitamos actualizaciones de datos. A continuación, definimos la matriz «timeframes_array» utilizando el tipo ENUM_TIMEFRAMES, en la que se enumeran los periodos desde «PERIOD_M1» (1 minuto) hasta «PERIOD_W1» (semanal). Esta matriz especifica los marcos temporales que analizará el panel de control, lo que nos permite examinar las señales del mercado en múltiples horizontes temporales de forma estructurada. Si no necesitas algunos de estos marcos temporales o quieres ajustarlos, basta con modificar las enumeraciones.

Para almacenar los datos de los indicadores, creamos las matrices de tipo double «rsi_values», «stochastic_values», «cci_values», «adx_values» y «ao_values». Estas matrices contienen los valores calculados para el Índice de Fuerza Relativa, el Oscilador Estocástico, el Commodity Channel Index (CCI), el Índice Direccional Medio (ADX) y el Oscilador Awesome, respectivamente, lo que nos permite procesar y mostrar de forma eficaz las señales de trading para cada marco temporal. Ahora podemos definir algunas funciones auxiliares que utilizaremos para formatear el nombre del marco temporal mostrado y para apoyar la lógica de señalización, tal y como se indica a continuación.

//+------------------------------------------------------------------+
//| 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
}

Aquí definimos la función «truncate_timeframe_name», que toma un parámetro entero «timeframe_index» para dar formato a los nombres de los marcos temporales con vistas a su visualización. En el interior, utilizamos la función StringSubstr para extraer una subcadena del resultado de la función EnumToString aplicada a «timeframes_array[timeframe_index]», a partir de la posición 7, y la almacenamos en «timeframe_string». A continuación, devolvemos «timeframe_string», que proporciona un nombre de intervalo de tiempo claro y fácil de leer para el usuario.

Creamos la función «calculate_signal_strength» para determinar las señales de compra o venta en función de los valores del indicador. Inicializamos la variable entera «signal_strength» con el valor cero para contar las condiciones que se cumplen. En el caso del Índice de Fuerza Relativa, incrementamos «signal_strength» si «is_buy» es verdadero y «rsi» es inferior a 40 (sobreventa) o si «is_buy» es falso y «rsi» supera 60 (sobrecompra). Del mismo modo, comprobamos los indicadores «stochastic» (por debajo de 40 o por encima de 60), «CCI» (por debajo de -70 o por encima de 70) y «ao» (positivo para comprar, negativo para vender), incrementando el valor de «signal_strength» cada vez que se cumple una de estas condiciones.

También evaluamos el índice de dirección medio (ADX) y aumentamos el valor de «signal_strength» si «adx» supera 40, lo que indica una tendencia fuerte tanto en situaciones de compra como de venta. Si «signal_strength» alcanza un valor de 3 o más, devolvemos «Strong Buy» si «is_buy» es verdadero, o «Strong Sell» en caso contrario. Si el valor es 2, devolvemos «Buy» o «Sell», y si es inferior, devolvemos «Neutral», lo que permite una clasificación clara de las señales en el panel de control. A continuación, ya podemos definir las funciones que nos permitirán crear los 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 la creación de los objetos, definimos la función «create_rectangle» con los parámetros «object_name», «x_distance», «y_distance», «x_size», «y_size», «background_color» y «border_color». Utilizamos la función ResetLastError, creamos un OBJ_RECTANGLE_LABEL con la función ObjectCreate y, si falla, registramos los errores con la función «Print», devolviendo el valor false.

Configuramos las propiedades del rectángulo mediante la función ObjectSetInteger para la posición, el tamaño, «CORNER_RIGHT_UPPER», «background_color», «border_color» y «BORDER_FLAT», asegurándonos de que se muestre en primer plano. Utilizamos la función ChartRedraw y devolvemos «true». Para el texto, definimos la función «create_label» con los parámetros «object_name», «text», «x_distance», «y_distance», «font_size», «text_color» y «font».

Utilizamos la función «ResetLastError», creamos un «OBJ_LABEL» con la función «ObjectCreate» y registramos los errores si falla. Utilizamos la función «ObjectSetInteger» para la posición, el tamaño, el color y «ANCHOR_CENTER», y la función ObjectSetString para «text» y «font». Utilizamos la función «ChartRedraw» y devolvemos «true». Con estas funciones, ya podemos crear los objetos de panel iniciales que nos servirán de punto de partida en el controlador 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
}

En el controlador de eventos OnInit, inicializamos la interfaz de usuario del panel de control del escáner de múltiples marcos temporales. Utilizamos la función «create_rectangle» para dibujar el «MAIN_PANEL» en la posición (632, 40) con un tamaño de 617 x 374 píxeles en «C’30,30,30’» y el «HEADER_PANEL» en la misma posición con una altura de 27 píxeles en «C’60,60,60’». Utilizamos la función «create_label» para añadir el «HEADER_PANEL_ICON» con un carácter Wingdings en la posición (620, 54). Utilizamos los caracteres predeterminados de MQL5 y empleamos la función CharToString para convertir el código del carácter en una cadena. Este es el código de carácter que hemos utilizado, el 91, pero puedes usar el que prefieras.

MQL5 WINGDINGS

A continuación, creamos el «HEADER_PANEL_TEXT» con «TimeframeScanner» en (527, 52) y el «CLOSE_BUTTON» en (32, 54), pero esta vez usamos una fuente distinta y asignamos la letra «r» a la cadena. Aquí tienes una muestra de los diferentes símbolos tipográficos que puedes utilizar.

FUENTE DE SÍMBOLOS

Configuramos la visualización del símbolo utilizando la función «create_rectangle» para el tipo «SYMBOL_RECTANGLE» en la posición (630, 75), con un tamaño de «WIDTH_TIMEFRAME» por «HEIGHT_RECTANGLE», en color gris. Utilizamos la función «create_label» para colocar el «SYMBOL_TEXT» en la posición (585, 85) junto al símbolo actual. Para los encabezados, definimos la matriz «header_names» con títulos como «BUY» y «RSI», y utilizamos un bucle para crear «HEADER_RECTANGLE» en y=75 con desplazamientos en el eje x basados en «WIDTH_SIGNAL» y «WIDTH_INDICATOR», y etiquetas «HEADER_TEXT» en y=85 utilizando la función «create_label».

Creamos la tabla de marcos temporales recorriendo el array «timeframes_array». Utilizamos la función «create_rectangle» para «TIMEFRAME_RECTANGLE» en x=630, con desplazamientos en y a partir de (75 + «HEIGHT_RECTANGLE») ajustados en -(1 + «timeframe_index»), y coloreado con «timeframe_background». Utilizamos la función «create_label» para «TIMEFRAME_TEXT» con los nombres generados por la función «truncate_timeframe_name». En las celdas, utilizamos un bucle para crear «BUY_RECTANGLE», «RSI_RECTANGLE», etc., con la función «create_rectangle», utilizando «cell_background», y añadimos etiquetas «-/-» con la función «create_label». Inicializamos matrices de indicadores como «rsi_values» mediante la función ArraySetAsSeries, configurándolas como series temporales para el tratamiento de datos. Devolvemos INIT_SUCCEEDED para confirmar que la inicialización se ha realizado correctamente, estableciendo el diseño y la estructura de datos del panel de control. Tras la compilación, obtenemos el siguiente resultado.

PANEL DE CONTROL ESTÁTICO

En la imagen podemos ver que el panel de control ya está listo. Ahora solo nos queda añadir los valores de los indicadores y utilizarlos para el análisis. Ya tenemos una función para el análisis, solo necesitamos obtener los datos. Para lograrlo fácilmente, creamos una función que se encarga de toda la lógica de actualización 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 gestionar fácilmente la actualización de los valores del panel de control, implementamos la función «updateIndicators» para actualizar los valores de los indicadores y las señales. Recorremos la matriz «timeframes_array» utilizando el índice «timeframe_index» y procesamos cada intervalo de tiempo. Utilizamos las funciones iRSI, «iStochastic», «iCCI», iADX y «iAO» para crear identificadores de indicadores como «rsi_indicator_handle» para el símbolo y el intervalo de tiempo actuales, configurando parámetros como un RSI de 14 períodos y un CCI de 20 períodos. Todos los ajustes de los indicadores se pueden personalizar para adaptarlos a tus necesidades, así que no te limites a los valores predeterminados.

A continuación, comprobamos si algún identificador, como «rsi_indicator_handle», es igual a INVALID_HANDLE, lo que indicaría un error en la creación. En ese caso, utilizamos la función «Print» para registrar el error junto con el resultado de la función «truncate_timeframe_name» y pasamos al siguiente intervalo de tiempo. Utilizamos la función CopyBuffer para obtener los valores más recientes y almacenarlos en matrices como «rsi_values»; si alguno falla, registramos el error y continuamos. Actualizamos las etiquetas de los indicadores mediante la función «update_label». Por ejemplo, establecemos «rsi_text_color» en función de «rsi_values[0]» (azul si es <30, rojo si es >70, y «COLOR_WHITE» en los demás casos) y actualizamos «RSI_TEXT» con el valor formateado de la función «DoubleToString». Repetimos este proceso para «stochastic_values», «cci_values», «adx_values» y «ao_values», aplicando la lógica de colores (por ejemplo, verde para los «ao_values» positivos).

Calculamos las señales utilizando la función «calculate_signal_strength», a la que pasamos «rsi_values[0]» y otros parámetros, para obtener «buy_signal» y «sell_signal». Establecemos «buy_background» (por ejemplo, en verde para «Strong Buy») y utilizamos la función «update_rectangle» para «BUY_RECTANGLE», actualizando «BUY_TEXT» con «update_label». Hacemos lo mismo con «sell_background» y «SELL_TEXT». Por último, utilizamos la función IndicatorRelease para liberar referencias como «rsi_indicator_handle», lo que garantiza una gestión eficiente de los recursos. Las funciones auxiliares que hemos utilizado se definen a continuación.

//+------------------------------------------------------------------+
//| 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 la función «update_rectangle», que toma como parámetros «object_name» y «background_color» para modificar el aspecto de un rectángulo. Utilizamos la función ObjectFind para localizar el rectángulo y guardamos el resultado en «found». Si «found» es menor que 0, lo que indica que el objeto no se ha encontrado, utilizamos la función ResetLastError, registramos el error con la función «Print» y «GetLastError», y devolvemos «false». Actualizamos el fondo del rectángulo utilizando la función «ObjectSetInteger» para establecer «OBJPROP_BGCOLOR» en «background_color». Utilizamos la función ChartRedraw para actualizar el gráfico y devolvemos «true» si la operación se ha realizado correctamente. Para las actualizaciones de texto, definimos la función «update_label» con los parámetros «object_name», «text» y «text_color».

Utilizamos la función «ObjectFind» para comprobar si la etiqueta existe y, si el valor de «found» es negativo, utilizamos la función «ResetLastError», registramos el error con la función «Print» y devolvemos «false». Utilizamos la función ObjectSetString para establecer «OBJPROP_TEXT» en «text» y la función ObjectSetInteger para establecer «OBJPROP_COLOR» en «text_color». Utilizamos la función «ChartRedraw» para actualizar el gráfico y devolvemos «true», lo que permite actualizar las etiquetas de forma dinámica. Ahora podemos llamar a la función de actualización en cada tick para actualizar el panel de control.

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

Aquí, en el controlador de eventos OnTick, simplemente llamamos a la función «updateIndicators» si el panel está visible para aplicar las actualizaciones. Por último, debemos eliminar los objetos que hemos creado para que desaparezcan del gráfico cuando ya no los necesitemos.

//+------------------------------------------------------------------+
//| 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
}

Por último, implementamos el proceso de limpieza mediante la función OnDeinit, que se ejecuta cuando se elimina el asesor experto. Utilizamos la función ObjectDelete para eliminar elementos individuales de la interfaz de usuario, empezando por el rectángulo «MAIN_PANEL», seguido de «HEADER_PANEL», «HEADER_PANEL_ICON», «HEADER_PANEL_TEXT» y «CLOSE_BUTTON», asegurándonos de que los componentes del panel principal y del encabezado se eliminen del gráfico.

Eliminamos sistemáticamente todos los objetos del panel de control utilizando la función ObjectsDeleteAll para cada tipo de elemento. Eliminamos todos los rectángulos y etiquetas asociados a «SYMBOL_RECTANGLE» y «SYMBOL_TEXT», «TIMEFRAME_RECTANGLE» y «TIMEFRAME_TEXT», así como «HEADER_RECTANGLE» y «HEADER_TEXT», con lo que se borran las visualizaciones de símbolos, marcos temporales y encabezados. También eliminamos los objetos relacionados con los indicadores, entre los que se incluyen «RSI_RECTANGLE», «STOCH_RECTANGLE», «CCI_RECTANGLE», «ADX_RECTANGLE» y «AO_RECTANGLE», junto con sus respectivas etiquetas de texto, como «RSI_TEXT».

Completamos la limpieza utilizando la función «ObjectsDeleteAll» para eliminar todos los objetos «BUY_RECTANGLE» y «SELL_RECTANGLE», junto con sus etiquetas «BUY_TEXT» y «SELL_TEXT», eliminando así todos los elementos relacionados con las señales. Por último, utilizamos la función ChartRedraw para actualizar el gráfico, garantizando así un estado visual limpio tras la desinicialización. Por último, debemos ocuparnos del botón de cierre para que, al hacer clic en él, se cierre el panel de control y se desactiven las actualizaciones posteriores.

//+------------------------------------------------------------------+
//| 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
      }
   }
}

En el controlador de eventos OnChartEvent, detectamos los clics sobre objetos cuando el identificador del evento es CHARTEVENT_OBJECT_CLICK, y el objeto en el que se ha hecho clic es el botón de cierre, y reproducimos un sonido de alerta mediante la función PlaySound para avisar al usuario de que el panel se va a desactivar; a continuación, desactivamos la visibilidad del panel y utilizamos la misma lógica que usamos para borrar el gráfico en OnDeinit para borrar el panel de control. Tras la compilación, obtenemos el siguiente resultado.

PANEL DE CONTROL ACTUALIZADO

En la imagen podemos ver que el panel de control se ha actualizado con los datos de los indicadores y las señales de trading mostradas. Lo que queda ahora es probar el funcionamiento del proyecto, y eso se aborda en la sección siguiente.


Backtesting

Hemos realizado el backtesting, y a continuación se muestra la visualización compilada en un único archivo GIF (Graphics Interchange Format).

GIF DE PRUEBA


Conclusión

En conclusión, hemos desarrollado un panel de control con escáner para múltiples marcos temporales en MQL5, que integra un diseño de cuadrícula estructurado, señales de indicadores en tiempo real y un botón de cierre interactivo para mejorar las decisiones estratégicas de trading. Hemos mostrado el diseño y la implementación de estas funciones, garantizando su eficacia mediante una inicialización sólida y actualizaciones dinámicas adaptadas a nuestras necesidades operativas. Puedes personalizar este panel de control según tus preferencias, lo que mejorará considerablemente tu capacidad para supervisar las señales del mercado y actuar en consecuencia en distintos marcos temporales.

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/18319

Archivos adjuntos |
Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Aplicación del modelo de Grey en el análisis técnico de series temporales financieras Aplicación del modelo de Grey en el análisis técnico de series temporales financieras
En este artículo exploraremos el modelo de Grey, una herramienta prometedora que puede ampliar las capacidades de los tráders. Asimismo, analizaremos algunas opciones para aplicar este modelo al análisis técnico y a la elaboración de estrategias de negociación.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Detección y clasificación de patrones fractales mediante aprendizaje automático Detección y clasificación de patrones fractales mediante aprendizaje automático
En este artículo, nos familiarizaremos con el fascinante tema del análisis fractal y la previsión de mercado mediante el aprendizaje automático. Estos serán solo los primeros pasos para explorar las diversas estructuras fractales que se forman en los gráficos de precios financieros. Así, utilizaremos la correlación para encontrar patrones y el algoritmo CatBoost para clasificar dichos patrones.