English Русский 中文 Deutsch 日本語 Português
preview
Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 8): Panel de métricas

Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 8): Panel de métricas

MetaTrader 5Trading |
221 0
Christian Benjamin
Christian Benjamin

Contenido



Introducción

En las primeras etapas de nuestra serie, publicamos un artículo titulado «Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 3): Asesor Experto Analytics Master», en el que se exploraban métodos para recuperar y visualizar las métricas del mercado del día anterior. Este trabajo fundamental sentó las bases para el desarrollo de herramientas más sofisticadas. Nos complace presentar Metrics Board EA, una solución innovadora y de alta calidad que revoluciona el análisis de mercado dentro de MetaTrader 5. Esta herramienta funciona como una aplicación perfectamente integrada, que ofrece una interfaz optimizada y sencilla equipada con botones específicos para análisis avanzados, entre los que se incluyen:

  • Análisis alto/bajo: Detecte sin esfuerzo los niveles de precios críticos para evaluar las tendencias del mercado e identificar posibles reversiones.
  • Análisis de volumen: Analizar los volúmenes de negociación para evaluar el compromiso del mercado y las condiciones de liquidez.
  • Análisis de tendencias: Evalúe la fuerza direccional y la sostenibilidad mediante métricas precisas.
  • Análisis de volatilidad: Cuantificar las fluctuaciones del mercado para formular estrategias adaptadas a los distintos entornos comerciales.
  • Análisis de medias móviles: Supervise las tendencias dinámicas de los precios para comprender mejor el comportamiento del mercado.
  • Análisis de soporte/resistencia: Identifique los niveles de precios fundamentales para optimizar las entradas, salidas y estrategias de gestión de riesgos.

Cada botón ofrece datos en tiempo real con un simple clic, transformando datos complejos del mercado en información útil al instante. El Metrics Board EA funciona con algoritmos avanzados, lo que garantiza cálculos precisos y de alta velocidad que satisfacen las necesidades de los operadores profesionales. Al utilizar esta herramienta, los operadores pueden transformar datos de mercado complejos en información clara y útil. Este EA es un recurso clave para quienes desean perfeccionar sus estrategias de trading.


Descripción general del sistema

En esta sección, ofreceré una breve descripción general de la lógica del sistema. En la sección Desglose e implementación del código se ofrece una explicación detallada de los pasos. Sigamos los pasos que se indican a continuación:

  • Configuración de la clase: La clase crea un cuadro de diálogo con botones para diferentes análisis.
  • Gestión de eventos: Los clics en los botones activan los métodos de análisis correspondientes.
  • Análisis y visualización: Los datos del mercado se procesan y se muestran en el panel.
  • Cerrar: El botón «Cerrar» permite al usuario cerrar el panel de métricas.
Los pasos anteriores describen las etapas que nuestro asistente ejecutivo gestionará para lograr los resultados esperados. Cada etapa está cuidadosamente diseñada para garantizar una ejecución precisa, cubriendo todo, desde el análisis de mercado hasta la generación de información útil. Al seguir estas etapas, la EA garantiza un proceso fluido y eficiente. Consultemos también el siguiente diagrama para obtener una representación visual de todo el proceso.


Resumen de la lógica del EA

Figura 1. Resumen de la lógica del EA


Código MQL5

//+------------------------------------------------------------------+
//|                                                Metrics Board.mql5|
//|                                Copyright 2025, Christian Benjamin|
//|                                              https://www.mql5.com|
//+------------------------------------------------------------------+
#property copyright "2025, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.0"
#property strict

#include <Trade\Trade.mqh>
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Label.mqh>
#include <Controls\Panel.mqh>

// Metrics Board Class
class CMetricsBoard : public CAppDialog
  {
private:
   CButton           m_btnClose; // Close Button
   CButton           m_btnHighLowAnalysis;
   CButton           m_btnVolumeAnalysis;
   CButton           m_btnTrendAnalysis;
   CButton           m_btnVolatilityAnalysis;
   CButton           m_btnMovingAverage;
   CButton           m_btnSupportResistance;
   CPanel            m_panelResults;
   CLabel            m_lblResults;

public:
                     CMetricsBoard(void);
                    ~CMetricsBoard(void);
   virtual bool      Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2);
   virtual void      Minimize();
   virtual bool      Run(); // Declaration of Run method
   virtual bool      OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
   virtual bool      ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
   virtual void      Destroy(const int reason = REASON_PROGRAM); // Override Destroy method

private:
   bool              CreateButtons(void);
   bool              CreateResultsPanel(void);
   void              OnClickButtonClose(); // New close button handler
   void              PerformHighLowAnalysis(void);
   void              PerformVolumeAnalysis(void);
   void              PerformTrendAnalysis(void);
   void              PerformVolatilityAnalysis(void);
   void              PerformMovingAverageAnalysis(void);
   void              PerformSupportResistanceAnalysis(void);
   double            CalculateMovingAverage(int period);
  };

CMetricsBoard::CMetricsBoard(void) {}

CMetricsBoard::~CMetricsBoard(void) {}

// Override Destroy method
void CMetricsBoard::Destroy(const int reason)
  {
// Call base class Destroy method to release resources
   CAppDialog::Destroy(reason);
  }

//+------------------------------------------------------------------+
//| Create a control dialog                                          |
//+------------------------------------------------------------------+
bool CMetricsBoard::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
  {
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2))
     {
      Print("Failed to create CAppDialog instance.");
      return false; // Failed to create the dialog
     }

   if(!CreateResultsPanel())
     {
      Print("Failed to create results panel.");
      return false; // Failed to create the results panel
     }

   if(!CreateButtons())
     {
      Print("Failed to create buttons.");
      return false; // Failed to create buttons
     }

   Show(); // Show the dialog after creation
   return true; // Successfully created the dialog
  }

//+------------------------------------------------------------------+
//| Minimize the control window                                      |
//+------------------------------------------------------------------+
void CMetricsBoard::Minimize()
  {
   CAppDialog::Minimize();
  }

//+------------------------------------------------------------------+
//| Run the control.                                                 |
//+------------------------------------------------------------------+
bool CMetricsBoard::Run()
  {
// Assuming Run makes the dialog functional
   if(!Show())
     {
      Print("Failed to show the control.");
      return false; // Could not show the control
     }
// Additional initialization or starting logic can be added here
   return true; // Successfully run the control
  }

//+------------------------------------------------------------------+
//| Create the results panel                                         |
//+------------------------------------------------------------------+
bool CMetricsBoard::CreateResultsPanel(void)
  {
   if(!m_panelResults.Create(0, "ResultsPanel", 0, 10, 10, 330, 60))
      return false;

   m_panelResults.Color(clrLightGray);
   Add(m_panelResults);

   if(!m_lblResults.Create(0, "ResultsLabel", 0, 15, 15, 315, 30))
      return false;

   m_lblResults.Text("Results will be displayed here.");
   m_lblResults.Color(clrBlack);
   m_lblResults.FontSize(12);
   Add(m_lblResults);

   return true;
  }

//+------------------------------------------------------------------+
//| Create buttons for the panel                                     |
//+------------------------------------------------------------------+
bool CMetricsBoard::CreateButtons(void)
  {
   int x = 20;
   int y = 80;
   int buttonWidth = 300;
   int buttonHeight = 30;
   int spacing = 15;

// Create Close Button
   if(!m_btnClose.Create(0, "CloseButton", 0, x, y, x + buttonWidth, y + buttonHeight))
      return false;

   m_btnClose.Text("Close Panel");
   Add(m_btnClose);
   y += buttonHeight + spacing;

   struct ButtonData
     {
      CButton        *button;
      string         name;
      string         text;
     };

   ButtonData buttons[] =
     {
        {&m_btnHighLowAnalysis, "HighLowButton", "High/Low Analysis"},
        {&m_btnVolumeAnalysis, "VolumeButton", "Volume Analysis"},
        {&m_btnTrendAnalysis, "TrendButton", "Trend Analysis"},
        {&m_btnVolatilityAnalysis, "VolatilityButton", "Volatility Analysis"},
        {&m_btnMovingAverage, "MovingAverageButton", "Moving Average"},
        {&m_btnSupportResistance, "SupportResistanceButton", "Support/Resistance"}
     };

   for(int i = 0; i < ArraySize(buttons); i++)
     {
      if(!buttons[i].button.Create(0, buttons[i].name, 0, x, y, x + buttonWidth, y + buttonHeight))
         return false;

      buttons[i].button.Text(buttons[i].text);
      Add(buttons[i].button);
      y += buttonHeight + spacing;
     }

   return true;
  }

//+------------------------------------------------------------------+
//| Handle events for button clicks                                  |
//+------------------------------------------------------------------+
bool CMetricsBoard::OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   if(id == CHARTEVENT_OBJECT_CLICK)
     {
      Print("Event ID: ", id, ", Event parameter (sparam): ", sparam);

      if(sparam == "CloseButton") // Handle close button click
        {
         OnClickButtonClose(); // Call to new close button handler
         return true; // Event processed
        }
      else
         if(sparam == "HighLowButton")
           {
            Print("High/Low Analysis Button Clicked");
            m_lblResults.Text("Performing High/Low Analysis...");
            PerformHighLowAnalysis();
            return true; // Event processed
           }
         else
            if(sparam == "VolumeButton")
              {
               Print("Volume Analysis Button Clicked");
               m_lblResults.Text("Performing Volume Analysis...");
               PerformVolumeAnalysis();
               return true; // Event processed
              }
            else
               if(sparam == "TrendButton")
                 {
                  Print("Trend Analysis Button Clicked");
                  m_lblResults.Text("Performing Trend Analysis...");
                  PerformTrendAnalysis();
                  return true; // Event processed
                 }
               else
                  if(sparam == "VolatilityButton")
                    {
                     Print("Volatility Analysis Button Clicked");
                     m_lblResults.Text("Performing Volatility Analysis...");
                     PerformVolatilityAnalysis();
                     return true; // Event processed
                    }
                  else
                     if(sparam == "MovingAverageButton")
                       {
                        Print("Moving Average Analysis Button Clicked");
                        m_lblResults.Text("Calculating Moving Average...");
                        PerformMovingAverageAnalysis();
                        return true; // Event processed
                       }
                     else
                        if(sparam == "SupportResistanceButton")
                          {
                           Print("Support/Resistance Analysis Button Clicked");
                           m_lblResults.Text("Calculating Support/Resistance...");
                           PerformSupportResistanceAnalysis();
                           return true; // Event processed
                          }
     }

   return false; // If we reach here, the event was not processed
  }

//+------------------------------------------------------------------+
//| Handle chart events                                              |
//+------------------------------------------------------------------+
bool CMetricsBoard::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   Print("ChartEvent ID: ", id, ", lparam: ", lparam, ", dparam: ", dparam, ", sparam: ", sparam);

   if(id == CHARTEVENT_OBJECT_CLICK)
     {
      return OnEvent(id, lparam, dparam, sparam);
     }

   return false;
  }

//+------------------------------------------------------------------+
//| Analysis operations                                              |
//+------------------------------------------------------------------+
void CMetricsBoard::PerformHighLowAnalysis(void)
  {
   double high = iHigh(Symbol(), PERIOD_H1, 0);
   double low = iLow(Symbol(), PERIOD_H1, 0);

   Print("Retrieved High: ", high, ", Low: ", low);

   if(high == 0 || low == 0)
     {
      m_lblResults.Text("Failed to retrieve high/low values.");
      return;
     }

   string result = StringFormat("High: %.5f, Low: %.5f", high, low);
   m_lblResults.Text(result);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMetricsBoard::PerformVolumeAnalysis(void)
  {
   double volume = iVolume(Symbol(), PERIOD_H1, 0);
   Print("Retrieved Volume: ", volume);

   if(volume < 0)
     {
      m_lblResults.Text("Failed to retrieve volume.");
      return;
     }

   string result = StringFormat("Volume (Last Hour): %.1f", volume);
   m_lblResults.Text(result);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMetricsBoard::PerformTrendAnalysis(void)
  {
   double ma = CalculateMovingAverage(14);
   Print("Calculated 14-period MA: ", ma);

   if(ma <= 0)
     {
      m_lblResults.Text("Not enough data for moving average calculation.");
      return;
     }

   string result = StringFormat("14-period MA: %.5f", ma);
   m_lblResults.Text(result);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMetricsBoard::PerformVolatilityAnalysis(void)
  {
   int atr_period = 14;
   int atr_handle = iATR(Symbol(), PERIOD_H1, atr_period);

   if(atr_handle == INVALID_HANDLE)
     {
      m_lblResults.Text("Failed to get ATR handle.");
      return;
     }

   double atr_value[];
   if(CopyBuffer(atr_handle, 0, 0, 1, atr_value) < 0)
     {
      m_lblResults.Text("Failed to copy ATR value.");
      IndicatorRelease(atr_handle);
      return;
     }

   string result = StringFormat("ATR (14): %.5f", atr_value[0]);
   m_lblResults.Text(result);
   IndicatorRelease(atr_handle);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMetricsBoard::PerformMovingAverageAnalysis(void)
  {
   double ma = CalculateMovingAverage(50);
   Print("Calculated 50-period MA: ", ma);

   if(ma <= 0)
     {
      m_lblResults.Text("Not enough data for moving average calculation.");
      return;
     }

   string result = StringFormat("50-period MA: %.5f", ma);
   m_lblResults.Text(result);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CMetricsBoard::PerformSupportResistanceAnalysis(void)
  {
   double support = iLow(Symbol(), PERIOD_H1, 1);
   double resistance = iHigh(Symbol(), PERIOD_H1, 1);
   Print("Retrieved Support: ", support, ", Resistance: ", resistance);

   if(support == 0 || resistance == 0)
     {
      m_lblResults.Text("Failed to retrieve support/resistance levels.");
      return;
     }

   string result = StringFormat("Support: %.5f, Resistance: %.5f", support, resistance);
   m_lblResults.Text(result);
  }

//+------------------------------------------------------------------+
//| Calculate moving average                                         |
//+------------------------------------------------------------------+
double CMetricsBoard::CalculateMovingAverage(int period)
  {
   if(period <= 0)
      return 0;

   double sum = 0.0;
   int bars = Bars(Symbol(), PERIOD_H1);

   if(bars < period)
     {
      return 0;
     }

   for(int i = 0; i < period; i++)
     {
      sum += iClose(Symbol(), PERIOD_H1, i);
     }
   return sum / period;
  }

// Implementation of OnClickButtonClose
void CMetricsBoard::OnClickButtonClose()
  {
   Print("Close button clicked. Closing the Metrics Board...");
   Destroy();  // This method destroys the panel
  }

CMetricsBoard ExtDialog;

//+------------------------------------------------------------------+
//| Initialize the application                                       |
//+------------------------------------------------------------------+
int OnInit()
  {
   if(!ExtDialog.Create(0, "Metrics Board", 0, 10, 10, 350, 500))
     {
      Print("Failed to create Metrics Board.");
      return INIT_FAILED;
     }

   if(!ExtDialog.Run()) // Call Run to make the dialog functional
     {
      Print("Failed to run Metrics Board.");
      return INIT_FAILED; // Call to Run failed
     }

   return INIT_SUCCEEDED;
  }

//+------------------------------------------------------------------+
//| Deinitialize the application                                     |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ExtDialog.Destroy(reason); // Properly call Destroy method
  }

//+------------------------------------------------------------------+
//| Handle chart events                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {
   ExtDialog.ChartEvent(id, lparam, dparam, sparam);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+


Desglose e implementación del código

  • Encabezado y metadatos
La primera parte del código es la sección de encabezado y metadatos. Esta sección proporciona información básica sobre el script, incluyendo detalles sobre derechos de autor, enlaces, versiones y reglas estrictas de compilación.
//+------------------------------------------------------------------+
//|                                                Metrics Board.mql5|
//|                                Copyright 2025, Christian Benjamin|
//|                                              https://www.mql5.com|
//+------------------------------------------------------------------+
#property copyright "2025, MetaQuotes Software Corp."
#property link      "https://www.mql5.com/en/users/lynnchris"
#property version   "1.0"
#property strict
El bloque de comentarios describe el propósito del script y proporciona los créditos, lo cual es esencial para identificar la autoría y garantizar la atribución adecuada para los futuros usuarios. Las directivas #property sirven para definir diversas características del script, como la información sobre derechos de autor, un enlace al autor o a la documentación, el número de versión y la configuración del modo estricto, que ayuda a detectar posibles problemas durante la compilación.
  • Incluir las librerías necesarias

A continuación, incluimos las bibliotecas necesarias para nuestra aplicación. Estas librerías proporcionan funcionalidades predefinidas que simplifican la codificación.

#include <Trade\Trade.mqh>
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Label.mqh>
#include <Controls\Panel.mqh>

Aquí incorporamos las librerías relacionadas con las operaciones comerciales y los controles de la interfaz de usuario. Por ejemplo, Trade.mqh es fundamental para ejecutar funciones comerciales, mientras que Dialog.mqh, Button.mqh, Label.mqh, y Panel.mqh se utilizan para crear y gestionar los componentes de la interfaz de usuario del panel de métricas.

  • Definición de clase
Tras las inclusiones de la librería, definimos la clase principal para el panel de métricas. La clase CMetricsBoard hereda de CAppDialog, lo que nos permite utilizar las funcionalidades de diálogo. Declaramos varias variables miembro privadas, principalmente botones y paneles, que se utilizarán para interactuar con la aplicación. Cada botón corresponde a una función de análisis, y los resultados se mostrarán en un panel denominado m_panelResults.

class CMetricsBoard : public CAppDialog
{
private:
   CButton           m_btnClose; 
   CButton           m_btnHighLowAnalysis;
   CButton           m_btnVolumeAnalysis;
   CButton           m_btnTrendAnalysis;
   CButton           m_btnVolatilityAnalysis;
   CButton           m_btnMovingAverage;
   CButton           m_btnSupportResistance;
   CPanel            m_panelResults;
   CLabel            m_lblResults;

La clase también incluye un constructor y un destructor.

public:
                     CMetricsBoard(void);
                    ~CMetricsBoard(void);

CMetricsBoard::CMetricsBoard(void) {}

CMetricsBoard::~CMetricsBoard(void) {}

El constructor inicializa la clase y el destructor se define (aunque en este caso está vacío) para garantizar que se realice cualquier limpieza necesaria cuando se destruya una instancia de CMetricsBoard . Esto es esencial para gestionar los recursos de manera eficiente.

  • Creación del cuadro de diálogo

El método Create se encarga de construir todo el cuadro de diálogo de control. En este método, primero intentamos crear el cuadro de diálogo a través de la clase base (CAppDialog::Create). Si falla, registramos un error y devolvemos falso. A continuación, creamos un panel de resultados y botones, comprobando de nuevo si hay posibles fallos. Por último, si todos los pasos se han realizado correctamente, mostramos el cuadro de diálogo y devolvemos verdadero.

bool CMetricsBoard::Create(const long chart, const string name, const int subwin, const int x1, const int y1, const int x2, const int y2)
{
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2))
   {
      Print("Failed to create CAppDialog instance.");
      return false; 
   }

   if(!CreateResultsPanel())
   {
      Print("Failed to create results panel.");
      return false; 
   }

   if(!CreateButtons())
   {
      Print("Failed to create buttons.");
      return false; 
   }

   Show(); 
   return true; 
}

Ahora aparece el cuadro de diálogo Run. El método Run es esencial para que el cuadro de diálogo funcione.

bool CMetricsBoard::Run()
{
   if(!Show())
   {
      Print("Failed to show the control.");
      return false; 
   }
   return true; 
}

Aquí, mostramos el cuadro de diálogo utilizando el método Show. Si falla la visualización del cuadro de diálogo, se muestra un mensaje de error y se devuelve false.

  • Creación del panel de resultados

El método CreateResultsPanel construye el panel donde se mostrarán los resultados del análisis. Inicialmente, creamos el panel de resultados y establecemos sus propiedades, como el color y las dimensiones. A continuación, añadimos este panel al cuadro de diálogo. También creamos una etiqueta dentro del panel para mostrar los resultados y personalizamos su apariencia antes de añadirla al panel. Este método devuelve verdadero si la creación se ha realizado correctamente.

bool CMetricsBoard::CreateResultsPanel(void)
{
   if(!m_panelResults.Create(0, "ResultsPanel", 0, 10, 10, 330, 60))
      return false;

   m_panelResults.Color(clrLightGray);
   Add(m_panelResults);

   if(!m_lblResults.Create(0, "ResultsLabel", 0, 15, 15, 315, 30))
      return false;

   m_lblResults.Text("Results will be displayed here.");
   m_lblResults.Color(clrBlack);
   m_lblResults.FontSize(12);
   Add(m_lblResults);

   return true;
}

  • Creación de botones

El método CreateButtons se encarga de inicializar los botones interactivos del cuadro de diálogo.

bool CMetricsBoard::CreateButtons(void)
{
   int x = 20;
   int y = 80;
   int buttonWidth = 300;
   int buttonHeight = 30;
   int spacing = 15;

   if(!m_btnClose.Create(0, "CloseButton", 0, x, y, x + buttonWidth, y + buttonHeight))
      return false;

   m_btnClose.Text("Close Panel");
   Add(m_btnClose);
   y += buttonHeight + spacing;

   struct ButtonData
   {
      CButton        *button;
      string         name;
      string         text;
   };

   ButtonData buttons[] =
   {
      {&m_btnHighLowAnalysis, "HighLowButton", "High/Low Analysis"},
      {&m_btnVolumeAnalysis, "VolumeButton", "Volume Analysis"},
      {&m_btnTrendAnalysis, "TrendButton", "Trend Analysis"},
      {&m_btnVolatilityAnalysis, "VolatilityButton", "Volatility Analysis"},
      {&m_btnMovingAverage, "MovingAverageButton", "Moving Average"},
      {&m_btnSupportResistance, "SupportResistanceButton", "Support/Resistance"}
   };

   for(int i = 0; i < ArraySize(buttons); i++)
   {
      if(!buttons[i].button.Create(0, buttons[i].name, 0, x, y, x + buttonWidth, y + buttonHeight))
         return false;

      buttons[i].button.Text(buttons[i].text);
      Add(buttons[i].button);
      y += buttonHeight + spacing;
   }

   return true;
}

En esta implementación, definimos las coordenadas iniciales, las dimensiones y el espaciado de nuestros botones. Creamos cada botón, primero para cerrar el panel, añadiéndolo al cuadro de diálogo. A continuación, utilizamos una matriz de estructuras ButtonData, lo que nos permite recorrer eficazmente las definiciones de los botones. Cada botón se configura con el texto correspondiente y se añade al cuadro de diálogo. El método concluye devolviendo verdadero si todos los botones se han creado correctamente.

  • Gestión de eventos

1. Clics en botones

El método OnEvent procesa los eventos generados por la interacción del usuario, como los clics en botones.

bool CMetricsBoard::OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   if(id == CHARTEVENT_OBJECT_CLICK)
   {
      Print("Event ID: ", id, ", Event parameter (sparam): ", sparam);

      if(sparam == "CloseButton") 
      {
         OnClickButtonClose(); 
         return true; 
      }
      // ... Handling for other button clicks
   }

   return false; 
}

Cuando se produce un evento, primero comprobamos si se trata de un evento de clic en un botón. Imprimimos los detalles del evento con fines de depuración y reaccionamos a clics específicos en botones llamando a las funciones de manejo correspondientes. Imprimimos los detalles del evento con fines de depuración y reaccionamos a clics específicos en botones llamando a las funciones de manejo correspondientes.

2. Eventos gráficos

El método ChartEvent tiene una finalidad similar, pero se centra específicamente en los eventos relacionados con los gráficos.

bool CMetricsBoard::ChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
   Print("ChartEvent ID: ", id, ", lparam: ", lparam, ", dparam: ", dparam, ", sparam: ", sparam);

   if(id == CHARTEVENT_OBJECT_CLICK)
   {
      return OnEvent(id, lparam, dparam, sparam);
   }

   return false;
}

Este método captura cualquier clic en los objetos del gráfico y pasa el evento al método OnEvent para su posterior procesamiento.

  • Operaciones de análisis

Los siguientes métodos implementan los distintos tipos de análisis de mercado que puede realizar nuestro Panel de métricas. Por ejemplo, PerformHighLowAnalysis recupera los precios máximos y mínimos para un período definido:

void CMetricsBoard::PerformHighLowAnalysis(void)
{
   double high = iHigh(Symbol(), PERIOD_H1, 0);
   double low = iLow(Symbol(), PERIOD_H1, 0);

   Print("Retrieved High: ", high, ", Low: ", low);

   if(high == 0 || low == 0)
   {
      m_lblResults.Text("Failed to retrieve high/low values.");
      return;
   }

   string result = StringFormat("High: %.5f, Low: %.5f", high, low);
   m_lblResults.Text(result);
}

En este método, utilizamos funciones integradas para recuperar los precios más altos y más bajos de la última hora. Si se realiza correctamente, los resultados se muestran en la etiqueta. Si no es así, se muestra un mensaje de error.

Se aplica una lógica similar a otras funciones de análisis, como PerformVolumeAnalysis, PerformTrendAnalysis, PerformVolatilityAnalysis, PerformMovingAverageAnalysis y PerformSupportResistanceAnalysis. Cada método recupera datos específicos para su tipo de análisis y actualiza la interfaz de usuario en consecuencia.

  • Calcular la media móvil

Uno de los métodos de utilidad incluidos es CalculateMovingAverage, que calcula la media móvil durante un período determinado. Este método suma los precios de cierre durante el período especificado y los divide entre ese número para determinar la media. Comprueba que la entrada sea válida y que haya datos suficientes antes de realizar el cálculo.

double CMetricsBoard::CalculateMovingAverage(int period)
{
   if(period <= 0)
      return 0;

   double sum = 0.0;
   int bars = Bars(Symbol(), PERIOD_H1);

   if(bars < period)
   {
      return 0;
   }

   for(int i = 0; i < period; i++)
   {
      sum += iClose(Symbol(), PERIOD_H1, i);
   }
   return sum / period;
}
  • Comprueba que la entrada sea válida y que haya datos suficientes antes de realizar el cálculo.

Comprueba que la entrada sea válida y que haya datos suficientes antes de realizar el cálculo.

CMetricsBoard ExtDialog;

int OnInit()
{
   if(!ExtDialog.Create(0, "Metrics Board", 0, 10, 10, 350, 500))
   {
      Print("Failed to create Metrics Board.");
      return INIT_FAILED;
   }

   if(!ExtDialog.Run())
   {
      Print("Failed to run Metrics Board.");
      return INIT_FAILED;
   }

   return INIT_SUCCEEDED;
}

En la función OnInit, inicializamos el panel de métricas llamando al método Create. Si tiene éxito, procedemos a ejecutarlo. Los errores se registran según corresponda, con la función indicando el éxito o el fracaso.

El proceso de desinicialización garantiza que los recursos se liberen correctamente cuando se elimina el EA.

void OnDeinit(const int reason)
{
   ExtDialog.Destroy(reason); // Properly call Destroy method
}

  • Gestión de eventos de gráficos

Por último, definimos la función OnChartEvent para gestionar los eventos relacionados con los gráficos. Esto integra las interacciones del usuario directamente en la funcionalidad de la aplicación. Este método captura los eventos del gráfico y los pasa al método ChartEvent de nuestra instancia CMetricsBoard .

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


Incluyendo librerías

Si compila su código sin incluir las librerías mencionadas en la sección anterior, es posible que encuentre errores. Para resolver esto, abra MetaEditor y vaya al panel Navegador. Desplácese hacia abajo hasta la sección «Include», donde podrá acceder a las librerías necesarias. Abra las subcarpetas necesarias, seleccione los archivos pertinentes y compílelos individualmente. Asegúrate de que las librerías estén correctamente referenciadas en tu código utilizando la directiva #include al principio de tu script. Este paso garantiza que todas las dependencias se carguen correctamente, evitando posibles errores de compilación. El siguiente GIF ilustra cómo acceder e incluir librerías en MetaEditor.

Incluyendo librerías

Figura 2. Incluyendo librerías

En MQL5, una librería de inclusión le permite integrar código externo, funciones o clases en su programa, mejorando su funcionalidad y permitiendo la reutilización de código de diversas fuentes. Al incluir una librería, obtienes acceso a las funciones, clases o variables definidas en ella, lo que las hace disponibles para su uso en tu script, asesor experto o indicador. La mayoría de las librerías de MQL5 están integradas y proporcionan soluciones listas para usar para tareas comunes, como funciones de trading, indicadores técnicos y mucho más.


Resultados

Después de compilar correctamente el EA, ahora puede ir a MetaTrader 5 y adjuntar el EA a un gráfico. Repasemos los resultados que obtuvimos durante las pruebas.

RESULTADOS

Figura 3. Resultados

De acuerdo con el diagrama anterior, es evidente que el EA del panel de métricas ofrece una funcionalidad óptima, respondiendo eficazmente a cada pulsación de botón. Esta capacidad garantiza que el EA proporcione las métricas necesarias en tiempo real, mejorando la interacción del usuario y el rendimiento.

  • Registro del EA

También podemos revisar el registro de Expertos en MetaTrader 5 para observar la interacción entre los botones pulsados y los eventos en el gráfico. Dado que nuestro EA incluye una función de registro integrada, capturará estas interacciones. Echemos un vistazo a la información registrada y analicemos lo que se ha registrado. 

EXPERTOS EN EL REGISTRO

Figura 4. Registro de expertos


Conclusión

El Metrics Board EA cuenta con una interfaz de panel dinámica y fácil de usar integrada directamente en MetaTrader 5, que incorpora la función de dibujo de objetos. Su integración fluida da la impresión de trabajar con controles nativos de MetaTrader 5, ofreciendo una experiencia comparable a usar una aplicación incorporada. En mi opinión, marca un avance significativo en las herramientas comerciales, ofreciendo funcionalidad y facilidad de uso que superan las capacidades de algunos scripts de análisis que desarrollé anteriormente. Al permitir a los usuarios centrarse en información específica con un solo clic, se garantiza que solo se muestren los datos necesarios, agilizando el proceso de análisis. Si bien esos scripts anteriores cumplieron eficazmente sus propósitos, Metrics Board EA lleva el análisis de mercado a un nivel superior de eficiencia y accesibilidad.

Las características principales de Metrics Board EA incluyen:

Característica Ventaja
Análisis alto/bajo Identifica rápidamente niveles de mercado significativos para ayudar a los comerciantes.
Seguimiento del volumen Proporciona actualizaciones actualizadas sobre el volumen comercial para un mejor contexto del mercado.
Identificación de tendencias Simplifica el proceso de reconocimiento de las tendencias actuales del mercado.
Niveles de soporte/resistencia Identifica con precisión zonas de precios cruciales para el trading estratégico.

Esta herramienta permite a los operadores analizar los mercados de forma eficaz y tomar mejores decisiones. Su diseño sencillo simplifica los análisis complejos, lo que permite a los usuarios centrarse en perfeccionar sus estrategias. De cara al futuro, existe la posibilidad de ampliar sus capacidades añadiendo nuevas funciones y mejorando aún más la interfaz.

Fecha Nombre de la herramienta  Descripción Versión  Actualizaciones  Notas
01/10/24 Chart Projector Script para superponer la acción del precio del día anterior con efecto fantasma. 1.0 Lanzamiento inicial Primera herramienta en Lynnchris Tool Chest
18/11/24 Analytical Comment Proporciona información del día anterior en formato tabular y anticipa la dirección futura del mercado. 1.0 Lanzamiento inicial Segunda herramienta en Lynnchris Tool Chest
27/11/24 Analytics Master Actualización periódica de los indicadores del mercado cada dos horas.  1.01 Segundo lanzamiento Tercera herramienta en Lynnchris Tool Chest
02/12/24 Analytics Forecaster  Actualización periódica de los indicadores del mercado cada dos horas con integración de Telegram. 1.1 Tercera edición Herramienta número 4
09/12/24 Volatility Navigator EA que analiza las condiciones del mercado utilizando los indicadores Bandas de Bollinger, RSI y ATR. 1.0 Lanzamiento inicial Herramienta número 5
19/12/24 Mean Reversion Signal Reaper  Analiza el mercado utilizando la estrategia de reversión a la media y proporciona señales.  1.0  Lanzamiento inicial  Herramienta número 6 
09/01/25  Signal Pulse  Analizador de múltiples marcos temporales. 1.0  Lanzamiento inicial  Herramienta número 7 
17/01/25  Metrics Board  Panel con botón para análisis.  1.0  Lanzamiento inicial Herramienta número 8 

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

Archivos adjuntos |
Metrics_Board.mq5 (15.92 KB)
Simulación de mercado (Parte 05): Creación de la clase C_Orders (II) Simulación de mercado (Parte 05): Creación de la clase C_Orders (II)
En este artículo, explicaré cómo Chart Trade, junto con el asesor experto, gestionará la solicitud de cierre de todas las posiciones abiertas del usuario. Parece sencillo, pero hay algunos factores que complican la situación y que es necesario saber gestionar.
Algoritmo de búsqueda circular — Circle Search Algorithm (CSA) Algoritmo de búsqueda circular — Circle Search Algorithm (CSA)
Este trabajo presenta un nuevo algoritmo metaheurístico de optimización CSA (Circle Search Algorithm) basado en las propiedades geométricas del círculo. El algoritmo usa el principio de desplazamiento de puntos por tangentes para encontrar la solución óptima combinando fases de exploración global y explotación local.
Simulación de mercado (Parte 06): Transfiriendo información desde MetaTrader 5 hacia Excel Simulación de mercado (Parte 06): Transfiriendo información desde MetaTrader 5 hacia Excel
A muchas personas, especialmente a los no programadores, les resulta muy difícil transferir información entre MetaTrader 5 y otros programas. Uno de esos programas es Excel. Muchos utilizan Excel para gestionar y controlar sus riesgos, ya que es un programa muy bueno y fácil de aprender, incluso para quienes no son programadores de VBA. A continuación, voy a mostrar cómo establecer la comunicación entre MetaTrader 5 y Excel (un método muy sencillo).
Cómo publicar código en CodeBase: Guía práctica Cómo publicar código en CodeBase: Guía práctica
En este artículo, analizaremos el proceso de publicación de diferentes tipos de programas para el terminal en la biblioteca de código fuente MQL5 usando ejemplos reales.