English Русский 中文 Deutsch 日本語 Português
preview
Creación de una interfaz gráfica de usuario interactiva en MQL5 (Parte 1): Creación del panel

Creación de una interfaz gráfica de usuario interactiva en MQL5 (Parte 1): Creación del panel

MetaTrader 5Trading | 7 noviembre 2024, 10:43
828 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Introducción

¡Bienvenido a la primera entrega de nuestra completa guía sobre la creación de paneles personalizados de interfaz gráfica de usuario (GUI) en MetaQuotes Language 5 (MQL5)! Como operadores y desarrolladores, somos conscientes de la importancia de contar con interfaces eficaces y fáciles de usar para nuestras herramientas de negociación. En esta serie, nos sumergiremos en el mundo de MQL5 y exploraremos cómo crear potentes paneles GUI que mejoren su experiencia de trading.

En esta parte inicial, cubriremos los aspectos básicos: configuración del proyecto, diseño de la disposición del panel y adición de los controles esenciales. En la siguiente parte, haremos que el panel sea vivo, interactivo y receptivo. Tanto si eres un programador experimentado de MQL5 como si acabas de empezar, este artículo te proporcionará instrucciones paso a paso para ayudarte a crear un panel GUI funcional y visualmente atractivo. Conseguiremos lo anterior a través de los siguientes temas:

  1. Ilustración de elementos
  2. Ensamblaje del panel GUI en MQL5
  3. Conclusión

En este viaje, utilizaremos ampliamente MetaQuotes Language 5 (MQL5) como nuestro entorno de codificación base del Entorno de Desarrollo Integrado (IDE), y ejecutaremos los archivos en el terminal de trading MetaTrader 5 (MT5). Por lo tanto, contar con las versiones mencionadas anteriormente será de vital importancia. Empecemos.


Ilustración de elementos

Vamos a crear un panel GUI que incluya las herramientas de utilidad más comunes que cualquier operador puede necesitar, y por lo tanto queremos resumir y cubrir todo en esta serie. Por tanto, el número de elementos que deben tratarse es amplio, pero los agruparemos para facilitar su comprensión. Utilizaremos 4 elementos para el desarrollo de nuestra GUI y es a través de esto que la crearemos. El panel incluirá la creación de botones de negociación, rectángulos afilados, actualizaciones en directo, el uso de emojis, distintos estilos de fuente, etiquetas, partes móviles del panel y efectos hover. Para ilustrar todo esto, hemos utilizado un ejemplo a continuación.

EJEMPLO DE INTERFAZ GRÁFICA DE USUARIO


Ensamblaje del panel GUI en MQL5

Para crear el panel, nos basaremos en un asesor experto. Para crear un asesor experto (EA), en su terminal MetaTrader 5, haga clic en la pestaña Herramientas y marque MetaQuotes Language Editor, o simplemente pulse F4 en su teclado. También puede hacer clic en el icono IDE (Entorno de desarrollo integrado) de la barra de herramientas. Esto abrirá el entorno MetaQuotes Language Editor, que permite escribir robots comerciales, indicadores técnicos, scripts y bibliotecas de funciones.

IDE

Una vez abierto el MetaEditor, en la barra de herramientas, navega hasta la pestaña Archivo y marca Nuevo Archivo, o simplemente pulsa CTRL + N, para crear un nuevo documento. También puede hacer clic en el icono 'Nuevo' de la pestaña de herramientas. Aparecerá una ventana emergente del Asistente MQL.

NUEVO EA

En el Asistente que aparece, marque Asesor Experto (plantilla) y haga clic en 'Siguiente'.

ASISTENTE MQL5

En las propiedades generales del Asesor Experto, en la sección nombre, indique el nombre de archivo de su experto. Tenga en cuenta que para especificar o crear una carpeta si no existe, se utiliza la barra invertida antes del nombre del EA. Por ejemplo, aquí tenemos «Experts\» por defecto. Esto significa que nuestro EA se creará en la carpeta Experts y podremos encontrarlo allí. Las demás secciones son bastante sencillas, pero puede seguir el enlace que figura al final del Asistente para saber cómo realizar el proceso con precisión.

NOMBRE DEL EA

Después de proporcionar el nombre de archivo del Asesor Experto deseado, haga clic en 'Siguiente', luego en 'Siguiente' y luego en 'Finalizar'. Después de hacer todo eso, ahora estamos listos para codificar y programar nuestro panel GUI.

Primero, necesitaremos crear funciones para los 4 elementos que necesitaremos, es decir, la etiqueta del rectángulo, el botón, el campo de edición y las etiquetas de texto. Esto será de gran utilidad ya que nos permitirá reutilizar la misma función al crear características similares en lugar de tener que repetir todo el proceso al crear objetos similares. También nos ahorrará mucho tiempo y espacio haciendo que el proceso sea rápido, sencillo y con fragmentos de código breves.

Para crear la etiqueta del rectángulo, crearemos una función que tome 10 argumentos o parámetros.

//+------------------------------------------------------------------+
//|     Function to create rectangle label                           |
//+------------------------------------------------------------------+

bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {

...
}

La firma de la función lo ilustra todo. Es una función booleana que tiene el nombre "createRecLabel", lo que significa que devolverá dos indicadores booleanos, verdadero o falso, en caso de éxito o fracaso respectivamente. Para comprender fácilmente sus parámetros, los detallaremos y explicaremos individualmente a continuación.

  • objName: Este parámetro representa el nombre único del objeto de etiqueta de rectángulo. Sirve como identificador del elemento gráfico que se está creando.
  • xD y yD: Estos parámetros determinan las distancias X e Y desde la esquina donde se colocará la etiqueta del rectángulo. Piense en ellos como las coordenadas que definen la esquina superior izquierda del rectángulo en relación con el gráfico.
  • xS y yS: Estos parámetros especifican el ancho y la altura del rectángulo. El valor xS determina el ancho horizontal del rectángulo, mientras que yS controla su altura vertical.

DISTANCIA Y TAMAÑO

  • clrBg: El parámetro clrBg representa el color de fondo de la etiqueta del rectángulo. Elija un color que contraste bien con el fondo del gráfico o complemente otros elementos.
  • widthBorder: Este parámetro define el ancho del borde alrededor del rectángulo. Si desea un borde, establezca un valor positivo; de lo contrario, utilice cero para no tener borde.
  • clrBorder: Parámetro opcional para el color del borde. Si desea un borde, especifique un color (por ejemplo, clrNONE para ningún color de borde).
  • borderType: Especifique el tipo de borde para el rectángulo. Las opciones incluyen estilos planos, elevados u otros. Para un borde plano simple, utilice BORDER_FLAT.
  • borderStyle: Si elige un borde plano, este parámetro determina el estilo de línea (por ejemplo, sólida, discontinua). Utilice STYLE_SOLID para una línea continua.

En la firma de la función, deberías haber notado que algunos de los argumentos ya están inicializados con algún valor. El valor de inicialización representa el valor predeterminado que se asignará a ese parámetro en caso de que se ignore durante la llamada a la función. Por ejemplo, nuestro color de borde predeterminado es ninguno, lo que significa que si el valor del color no se especifica durante la llamada a la función, no se aplicará ningún color al borde de nuestra etiqueta de rectángulo. 

Dentro del cuerpo de la función, alojado entre llaves ({}), definimos nuestros procedimientos de creación de objetos. 

    // Create a rectangle label object
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false); // Return false if object creation fails
    }

Comenzamos utilizando una declaración if para verificar si el objeto no se ha creado. Se utiliza la función ObjectCreate, un booleano que toma 6 argumentos. Esta función crea un objeto con el nombre, tipo y coordenadas iniciales especificados en la subventana del gráfico especificada. En primer lugar, especificamos la ventana del gráfico, 0 significa que el objeto se creará en la ventana principal. A continuación, proporcionamos el nombre del objeto. Es el nombre que se asignará de forma exclusiva a un objeto concreto. El tipo de objeto que queremos crear es del tipo «OBJ_RECTANGLE_LABEL», es decir, un objeto para crear y diseñar la interfaz gráfica personalizada. A continuación, procedemos a proporcionar la subventana, 0 para la subventana actual. Por último, proporcionamos los valores de tiempo y precio como cero (0), ya que no los adjuntaremos al gráfico sino a las coordenadas de la ventana del gráfico. Los píxeles se utilizan para establecer el mapeado.

Si la creación del objeto falla, en última instancia la función «ObjectCreate» devuelve false, claramente no tiene sentido continuar, volvemos con un error. En este caso, informamos del error imprimiéndolo en el diario junto al código de error y devolviendo false. Podría haber un error anterior y, por lo tanto, para obtener el último error, necesitamos borrar el error anterior. Esto se consigue llamando a la función «ResetLastError», que es una función MQL5 incorporada, justo antes de nuestra lógica de creación de objetos. 

    ResetLastError(); // Reset any previous error codes

El propósito de la función es poner a cero el valor de la variable predefinida «_LastError», que almacena el código de error de la última operación que encontró un error. Al llamarlo, nos aseguramos de que cualquier código de error anterior se borra antes de proceder con las siguientes operaciones. Este paso es esencial porque nos permite tratar los nuevos errores de forma independiente, sin interferencias de estados de error anteriores.

Si no volvemos hasta este punto, significa que hemos creado el objeto, y por lo tanto podemos continuar con la actualización de propiedades del objeto. Una función incorporada «ObjectSet...» establece el valor de la propiedad del objeto correspondiente. La propiedad del objeto debe ser de tipo datetime, integer, color, boolean o character.

    // Set properties for the rectangle label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Rectangle background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType); // Border type
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle); // Border style (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // Border width (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // Border color (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Not a background object
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

Concentrémonos en la primera propiedad lógica.

    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner

Aquí, utilizamos la función incorporada «ObjectSetInteger» y pasamos los parámetros respectivamente. Los parámetros son los que se describen a continuación.

  • Chart id: Es el identificador del gráfico. «0» se refiere al gráfico actual (ID del gráfico). Estamos ajustando las propiedades de un objeto dentro de este gráfico.
  • Name: Es el nombre del objeto. «objName» representa el nombre único asignado al objeto etiqueta rectángulo.
  • Property id: Es el ID de la propiedad del objeto y su valor puede ser uno de los valores de la enumeración «ENUM_OBJECT_PROPERTY_INTEGER». «OBJPROP_XDISTANCE» especifica que estamos modificando la propiedad de distancia X.
  • Property value: Es el valor de la propiedad. El valor asignado a «xD» determina a qué distancia a la derecha (o a la izquierda, si es negativo) se situará horizontalmente la esquina superior izquierda de nuestra etiqueta rectangular desde el borde izquierdo del gráfico.

Del mismo modo, establecemos las demás propiedades utilizando el mismo formato. «OBJPROP_YDISTANCE» configura la propiedad de distancia Y de la etiqueta rectángulo. El valor «yD» determina a qué distancia vertical del borde superior del gráfico se situará la esquina superior izquierda de la etiqueta rectangular. En otras palabras, controla la colocación vertical de la etiqueta dentro del área del gráfico. Establece la distancia Y desde la esquina. "OBJPROP_XSIZE" y “OBJPROP_YSIZE” establecen la anchura y la altura del rectángulo respectivamente. 

Para posicionar nuestro objeto, utilizamos la propiedad «OBJPROP_CORNER» para determinar la esquina en la que queremos que se encuentre nuestro objeto en la ventana del gráfico.

    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner

La propiedad sólo puede ser de 4 tipos:

  • CORNER_LEFT_UPPER: El centro de coordenadas se encuentra en la esquina superior izquierda del gráfico.
  • CORNER_LEFT_LOWER: El centro de coordenadas está en la esquina inferior izquierda del gráfico.
  • CORNER_RIGHT_LOWER: El centro de coordenadas se encuentra en la esquina inferior derecha del gráfico.
  • CORNER_RIGHT_UPPER: El centro de coordenadas se encuentra en la esquina superior derecha del gráfico.

En una representación fotográfica, esto es lo que tenemos.

ESQUINAS

El resto de las propiedades son sencillas. Les hemos añadido comentarios para facilitar su comprensión. A continuación, basta con redibujar el gráfico para que los cambios surtan efecto automáticamente sin tener que esperar a que se produzca un cambio en las cotizaciones o en los eventos del gráfico. 

    ChartRedraw(0); // Redraw the chart

Por último, devolvemos true para indicar que la creación y actualización de las propiedades del objeto ha sido un éxito.

    return (true); // Return true if object creation and property settings are successful

El código completo de la función responsable de la creación de un objeto rectángulo en la ventana del gráfico es el siguiente.

bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {
    ResetLastError(); // Reset any previous error codes
    
    // Create a rectangle label object
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false); // Return false if object creation fails
    }
    
    // Set properties for the rectangle label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Rectangle background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType); // Border type
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle); // Border style (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // Border width (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // Border color (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Not a background object
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected
    
    ChartRedraw(0); // Redraw the chart
    
    return (true); // Return true if object creation and property settings are successful
}

Para crear un objeto botón, se utiliza el mismo enfoque de función. El código para crear una función de botón personalizada es el siguiente.

//+------------------------------------------------------------------+
//|     Function to create button                                    |
//+------------------------------------------------------------------+

bool createButton(string objName, int xD, int yD, int xS, int yS,
                  string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                  color clrBg = clrNONE, color clrBorder = clrNONE,
                  string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the button object
    if (!ObjectCreate(0, objName, OBJ_BUTTON, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the button! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the button
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the button
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the button
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the button
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Button state (not pressed)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the button
    ChartRedraw(0);

    return (true); // Button creation successful
}

Las diferencias en el código son que un objeto rectángulo no podría llevar un texto en él pero un botón sí incluye un texto descriptivo de la funcionalidad del botón en caso de que sea necesario. Por lo tanto, para los parámetros de entrada, consideramos las propiedades del texto, en nuestro caso el valor del texto, el color, el tamaño de la fuente y el nombre de la fuente. El tipo de borde para nuestro botón es estático y por lo tanto nos deshacemos de sus propiedades y mantenemos sólo el color del borde. 

El tipo de objeto que creamos es «OBJ_BUTTON», lo que significa que creamos un objeto gráfico botón. Sus puntos de anclaje se fijan en píxeles. La propiedad de borde que mantenemos es el color del borde y reemplazamos el resto con las propiedades de entrada de texto.

Para crear el botón del campo de edición se utiliza la misma lógica. 

//+------------------------------------------------------------------+
//|     Function to create edit field                                |
//+------------------------------------------------------------------+

bool createEdit(string objName, int xD, int yD, int xS, int yS,
                string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                color clrBg = clrNONE, color clrBorder = clrNONE,
                string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the edit object
    if (!ObjectCreate(0, objName, OBJ_EDIT, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the edit! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the edit field
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the edit field
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the edit field
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Default text in the edit field
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // Text alignment (left-aligned)
    ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // Edit field is not read-only
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Edit field state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the edit field
    ChartRedraw(0);

    return (true); // Edit field creation successful
}

La principal diferencia en el código con respecto a la creación de una función de botón es, en primer lugar, el tipo de objeto. Utilizamos «OBJ_EDIT» para indicar que queremos crear un botón editable. A continuación, a las propiedades del campo, añadimos la propiedad de alineación horizontal del texto, que puede ser a la derecha, a la izquierda o al centro. En nuestro caso, elegimos alinear el texto horizontalmente a la izquierda. 

    ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // Text alignment (left-aligned)

La última diferencia es la propiedad que permite editar el texto del objeto. Para habilitar la edición, establecemos el valor de la propiedad «OBJPROP_READONLY» a false.

    ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // Edit field is not read-only

El resto de los argumentos se mantienen. 

Por último, necesitamos la función del último elemento, que es la etiqueta de texto. La etiqueta de texto elimina la necesidad de un objeto de fondo y, por lo tanto, su implementación es bastante más sencilla que la del resto de las funciones. Sólo necesitamos el texto y por eso nos concentramos en las propiedades del texto. Su código es el siguiente.

//+------------------------------------------------------------------+
//|     Function to create text label                                |
//+------------------------------------------------------------------+

bool createLabel(string objName, int xD, int yD,
                 string txt, color clrTxt = clrBlack, int fontSize = 12,
                 string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the label object
    if (!ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the label
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Label state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the label
    ChartRedraw(0);

    return (true); // Label creation successful
}

Las principales diferencias en esta estructura de código con respecto a la función del botón son las propiedades de tamaño y borde del objeto. En la firma de la función, nos deshacemos de los tamaños de los objetos, así como de las propiedades de los bordes. Definimos nuestro tipo de objeto como «OBJ_LABEL» para indicar que dibujamos etiquetas según las coordenadas de etiqueta definidas en la ventana del gráfico. Por último, nos deshacemos de los parámetros de tamaño y borde y ya está. Así de fácil. 

Ahora que tenemos las funciones que necesitamos para crear una GUI, usémoslas para crear el panel. Necesitaremos nombres de objeto y para gestionar fácilmente la interacción de los nombres de objeto, es mucho más fácil definir macros. 

#define MAIN_REC "MAIN_REC"

Usamos la palabra clave #define para definir una macro llamada «MAIN_REC» con el valor «MAIN_REC» para almacenar fácilmente nuestro nombre base del rectángulo principal, en lugar de tener que volver a escribir el nombre repetidamente en cada instancia en la que creamos el nivel, lo que nos ahorra mucho tiempo y reduce las posibilidades de proporcionar erróneamente el nombre. Básicamente, las macros se utilizan para sustituir texto durante la compilación.

Nuestro código se basará principalmente en la sección de inicialización de expertos, ya que queremos crear el panel en la instancia de inicialización. Así, el manejador de eventos OnInit albergará la mayor parte de la estructura del código. 

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit(){

   ...
   
   return(INIT_SUCCEEDED);
}

La función OnInit es un manejador de eventos que se llama en la instancia de inicialización del experto para hacer las inicializaciones necesarias si es necesario. 

A continuación, llamamos a la función para crear una etiqueta rectangular escribiendo su nombre y proporcionando sus parámetros.

   createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack);

Aquí, el nombre de nuestro rectángulo es «MAIN_REC» como en la definición de la macro. Nuestra distancia a lo largo del eje x, la escala de fecha y hora, desde la esquina superior izquierda de la ventana del gráfico es de 10 píxeles, y la distancia a lo largo del eje y, la escala de precios, es de 30 píxeles. La anchura es de 250 píxeles y la altura de 400 píxeles, respectivamente. Elegimos que nuestro color de fondo sea blanco, con un ancho de borde de 1 y un color de borde negro. Para conseguir que los píxeles tengan un rango aproximado, puede reducir la escala del gráfico a 0 y el número de barras entre dos coordenadas del retículo será igual al número de píxeles de la escala horizontal. A modo de ejemplo, esto es lo que queremos decir.

PUNTO DE MIRA

Los demás parámetros se han omitido, lo que significa que se aplicarán automáticamente los valores por defecto, es decir, el tipo de borde será plano y el estilo de línea será una línea continua sólida. Tras la recopilación, esto es lo que tenemos actualmente.

PANEL1

Aunque tuviéramos todos los parámetros con los valores por defecto que se indican a continuación, los resultados serían siempre los mismos.

   createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack,BORDER_FLAT,STYLE_SOLID);

Para crear un subcuadro, volvemos a declarar una macro para el mismo explícitamente.

#define MAIN_SUB_REC "MAIN_SUB_REC"

A continuación, llamamos a la misma función para crear el subchasis. Queremos que nuestro marco esté dentro del marco del panel base y por lo tanto requerirá que utilicemos un color ligeramente diferente. Para ello, utilizamos un color azul claro y un margen de 5 píxeles.

   createRecLabel(MAIN_SUB_REC,15,35,240,390,clrLightBlue,1,clrNONE);

Como queremos un margen de 5 píxeles, empujamos desde la izquierda 5 píxeles y en la parte superior 5 píxeles. Por lo tanto, la distancia del eje x será la inicial 10, más un margen de 5, lo que equivale a 15 píxeles. Lo mismo se hace para la escala del eje y. Esto significa que también será necesario reducir el tamaño en 5 píxeles, pero espere un segundo, también necesitamos un margen de 5 píxeles a la derecha del panel. Por lo tanto, se necesita una reducción de 5 píxeles en cada lado, para dos lados. Por lo tanto, el número total de píxeles necesarios es 5 multiplicado por 2, lo que equivale a 10 píxeles. Por lo tanto, una reducción de 10 píxeles en el tamaño del subrectángulo dará como resultado 250 - 10 = 240 píxeles de ancho y 400 - 10 = 390 píxeles de alto del subrectángulo del marco. Aquí están los resultados que obtuvimos.

PANEL2

El color azul claro no es tan atractivo a la vista, por eso optamos por un color más oscuro. Para tener más control sobre el color utilizado, representamos el color de fondo en literales. Esto tomará el formato "C'000,000,000'" donde los triples ceros pueden ser cualquier número del 0 al 255. El formato adoptado es el RGB (Rojo, Verde, Azul). Los tres valores representan los componentes rojo, verde y azul, respectivamente, en una escala de 0 a 255. Por lo tanto, 245.245.245 se traduce en un tono casi blanco. 

   createRecLabel(MAIN_SUB_REC,15,35,240,390,C'245,245,245',1,clrNONE);

Establecemos el color del borde en ninguno para crear una combinación de colores más atractiva. Siempre se recomienda compilar el programa y verificar el resultado cada vez que se agrega un nuevo elemento GUI. A continuación se muestran los resultados que obtenemos.

PANEL3

Para crear líneas de límite verticales y horizontales, definimos dos macros más.

#define MAIN_LINE_UP "MAIN_LINE_UP"
#define MAIN_LINE_DN "MAIN_LINE_DN"

Se utiliza la misma estructura pero esta vez utilizamos un tipo de borde elevado. Esto ignorará el uso del color del borde y dará como resultado una ilusión de límite.

   createRecLabel(MAIN_LINE_UP,15,35,240,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createRecLabel(MAIN_LINE_DN,15,35-1,1,390+1,C'245,245,245',1,clrNONE,BORDER_RAISED);

Esto es lo que obtenemos.

PANEL4

Hasta este punto, la configuración de nuestros marcos, márgenes y límites para nuestro panel GUI está completa. Luego procedemos a agregar las demás utilidades del panel como botones responsivos, títulos, campos de edición y etiquetas además de sus propiedades y efectos. 

Para empezar, vamos a darle un título al panel. 

#define LABEL_NAME "LABEL_NAME"
...
   createLabel(LABEL_NAME,25,35,"DashBoard v1.0",clrBlue,14,"Cooper Black");

Primero, definimos una macro para el nombre del título y llamamos a la función responsable de crear etiquetas escribiendo su nombre. Luego proporcionamos las distancias del eje x y del eje y como 25 y 35 píxeles respectivamente. La entrada de texto que elegimos es "DashBoard v1.0" que indica el tipo de panel y la versión inicial. Al mismo tiempo, proporcionamos el color del texto en azul con un tamaño de fuente de 14 y el tipo de fuente "Cooper Black". En cuanto al tipo de fuente, el valor no distingue entre mayúsculas y minúsculas. No tendrá ningún efecto utilizar mayúsculas o minúsculas o una mezcla de ambas. Podría ser "cooper black" o "COOPER BLACK" también. Lo único que importa es que proporciones el nombre de fuente correcto. Abrimos la compilación y obtenemos los siguientes resultados.

TÍTULO DEL PANEL 5

¿Has notado que el tipo de fuente puede cambiar? Añadamos azúcar a la música y veamos cómo queda la melodía. Algunos tipos de fuentes contienen íconos y emojis. Ahora MQL5 acepta e incorpora algunos de ellos. Algunos ejemplos de fuentes son "Webdings", "Wingdings", "Wingdings 2" y "Wingdings 3". Hay muchos más pero elegimos utilizar los mencionados anteriormente. Esto significa que podemos hacer que el panel sea elegante usando estos íconos y fuentes emoji. Estos son los siguientes:

FUENTES

Agregamos tres íconos que preceden al nombre del panel: un corazón, una herramienta de reparación y un ícono de ambulancia. Por supuesto, puedes elegirlos según tu gusto. Esto requiere una definición de tres macros nuevamente para contener nuestros nombres de íconos y luego usarlos en la creación de los íconos. Aquí está la lógica.

#define ICON_HEART "ICON_HEART"
#define ICON_TOOL "ICON_TOOL"
#define ICON_CAR "ICON_CAR"

...
   createLabel(ICON_HEART,190,35,"Y",clrRed,15,"Webdings");

Se utiliza la misma función, con las distancias de los ejes, el color y el tamaño de la fuente. Sin embargo, puedes notar que nuestro nombre de fuente ahora ha cambiado a "Webdings" y nuestro valor de texto es "Y" mayúscula. Esto no significa que mostraremos "Y" como nuestra salida. Mostramos el icono respectivo que corresponde a ese determinado personaje. En cuanto a la fuente, el ícono debajo del carácter es el que se muestra a continuación: el ícono del corazón.

ICONO DE CORAZÓN

El valor del texto distingue entre mayúsculas y minúsculas porque, como puede ver, el ícono debajo de la "y" minúscula es diferente al de la "Y" mayúscula. Al compilar esto es lo que obtenemos. 

PANEL6

Los otros dos iconos ahora se pueden agregar de la misma manera que el icono anterior.

   createLabel(ICON_TOOL,210,35,"@",clrBlue,15,"Webdings");
   createLabel(ICON_CAR,230,35,"h",clrBlack,15,"Webdings");

Luego se utiliza la misma implementación para agregar los demás objetos de utilidad al gráfico. A continuación se muestra la lógica.

#define LINE1 "LINE1"
#define BTN_CLOSE "BTN_CLOSE"
#define BTN_MARKET "BTN_MARKET"
#define BTN_PROFIT "BTN_PROFIT"
#define BTN_LOSS "BTN_LOSS"
#define BTN_PENDING "BTN_PENDING"
#define LINE2 "LINE2"

...

   createRecLabel(LINE1,15+10,60,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createLabel(BTN_CLOSE,25,65,"Close",clrBlack,13,"Impact");
   createLabel(BTN_MARKET,70,65,"Market",clrDarkRed,13,"Impact");
   createLabel(BTN_PROFIT,125,65,"Profit",clrGreen,13,"Impact");
   createLabel(BTN_LOSS,170,65,"Loss",clrRed,13,"Impact");
   createLabel(BTN_PENDING,205,65,"Pend'n",clrDarkGray,13,"Impact");
   createRecLabel(LINE2,15+10,87,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
  

Definimos los nombres de los macro objetos y llamamos a las respectivas funciones personalizadas para crear los objetos. Se crea una instancia de dos líneas de límite verticales y se intercalan los botones de utilidad de etiqueta. Las etiquetas son Close, Market, Profit, Loss, y Pending, adaptadas a "Pend'n" para acomodar la redacción dentro de los límites del marco. Estos tienen como objetivo cerrar todas las órdenes de mercado y pendientes, cerrar solo las órdenes de mercado, cerrar solo las posiciones que están en ganancias, cerrar solo las posiciones que están en pérdidas y eliminar las órdenes pendientes respectivamente. Al compilar obtenemos este resultado.

PANEL7

Hasta este punto, hemos creado con éxito la sección de encabezado de nuestro panel. Ahora procedemos a crear las utilidades de los botones. Primero, concentrémonos en el botón de volumen de operaciones. Nuestro botón tendrá una etiqueta y un menú desplegable.

#define BTN_LOTS "BTN_LOTS"
#define LABEL_LOTS "LABEL_LOTS"
#define ICON_DROP_DN1 "ICON_DROP_DN1"

La definición de las macros está realizada. Luego creamos un botón llamando a la función button.

   createButton(BTN_LOTS,25,95,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');

Nuevamente, proporcionamos las distancias x e y de los botones con un tamaño de 130 píxeles y 25 píxeles de ancho y alto respectivamente. En cuanto al texto, podríamos proporcionar un valor, pero decidimos no hacerlo porque queríamos obtener control sobre la posición del texto, por lo que lo dejamos en blanco o nulo. Finalmente, se utilizan representaciones de color literales para establecer el fondo y el borde del botón. Como decidimos omitir la etiqueta del botón predeterminada, creamos una nueva etiqueta de texto que debe estar en las proximidades del botón a través de la siguiente función.

   createLabel(LABEL_LOTS,25+10,95+5,"LotSize",clrBlack,9);

Ahora ya estás familiarizado con la función y conoces los parámetros que se pasan. Para el ícono desplegable, utilizamos un tipo de fuente que proporciona el ícono.

   createLabel(ICON_DROP_DN1,130,95+5,CharToString(240),C'070,070,070',20,"Wingdings 3");

Puede observar que en el argumento de texto, convertimos un carácter en una cadena, que es otra forma de proporcionar el código de carácter correspondiente en lugar de la cadena; esto es útil si ya conoce el código del símbolo. Para crear el botón de edición del campo se adopta el mismo procedimiento. 

#define EDIT_LOTS "EDIT_LOTS"
#define BTN_P1 "BTN_P1"
#define BTN_M1 "BTN_M1"

...

   createEdit(EDIT_LOTS,165,95,60,25,"0.01",clrBlack,14,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P1,225,95,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M1,225,95+12,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");


Definimos los nombres de las macros como de costumbre y llamamos a las funciones. Para crear el botón de edición se utiliza el tamaño de 60 y 25 píxeles de ancho y alto respectivamente. El texto predeterminado se establece en 0,01 con un color de texto negro, un tamaño de fuente de 14 y un tipo de fuente "Callibri". El fondo del botón se establece en blanco con un tono de color casi oscuro como color del borde. Para los volúmenes de incremento y disminución del volumen comercial, utilizamos el tipo de fuente "Webdings" y los valores de texto "5" y "6" respectivamente. En cuanto a la compilación, aquí está el hito que tenemos.

PANEL8

Este es un buen progreso. Para crear las otras utilidades de botones de stop loss y take profit, se aplica la misma lógica a través del código a continuación. 

#define BTN_SL "BTN_SL"
#define LABEL_SL "LABEL_SL"
#define ICON_DROP_DN2 "ICON_DROP_DN2"
#define EDIT_SL "EDIT_SL"
#define BTN_P2 "BTN_P2"
#define BTN_M2 "BTN_M2"

#define BTN_TP "BTN_TP"
#define LABEL_TP "LABEL_TP"
#define ICON_DROP_DN3 "ICON_DROP_DN3"
#define EDIT_TP "EDIT_TP"
#define BTN_P3 "BTN_P3"
#define BTN_M3 "BTN_M3"

...

   createButton(BTN_SL,25,95+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_SL,35,95+30,"SL Pips",clrBlack,14);
   createLabel(ICON_DROP_DN2,130,100+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_SL,165,95+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P2,225,95+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M2,225,107+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");

   createButton(BTN_TP,25,95+30+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_TP,35,95+30+30,"TP Pips",clrBlack,14);
   createLabel(ICON_DROP_DN3,130,100+30+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_TP,165,95+30+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P3,225,95+30+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M3,225,107+30+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   

Se definen las macros de utilidad y las respectivas funciones llamadas para la creación de las mismas. Este código no difiere en lógica del inicial que utilizamos para crear los botones de volumen de trading. Al compilar deberías obtener este resultado.

PANEL 9

#define BTN_BUY "BTN_BUY"
#define LABEL_BUY "LABEL_BUY"
#define LABEL_BUY_PRICE "LABEL_BUY_PRICE"
#define BTN_OVERLAY "BTN_OVERLAY"
#define BTN_SPREAD "BTN_SPREAD"

#define BTN_SELL "BTN_SELL"
#define LABEL_SELL "LABEL_SELL"
#define LABEL_SELL_PRICE "LABEL_SELL_PRICE"

#define BTN_CONTACT "BTN_CONTACT"

...

   
   createRecLabel(BTN_SELL,25,335,105,60,clrRed,1,clrNONE);
   createLabel(LABEL_SELL,35,335,"Sell",clrWhite,15,"ARIAL black");
   createLabel(LABEL_SELL_PRICE,35,335+30,DoubleToString(Bid(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_BUY,140,335,105,60,clrGreen,1,clrNONE);
   createLabel(LABEL_BUY,150+35,335,"Buy",clrWhite,15,"ARIAL black");
   createLabel(LABEL_BUY_PRICE,150,335+30,DoubleToString(Ask(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_OVERLAY,90,335,90,25,C'245,245,245',0,clrNONE);
   createButton(BTN_SPREAD,95,335,80,20,(string)Spread(),clrBlack,13,clrWhite,clrBlack);
   createButton(BTN_CONTACT,25,335+62,230-10,25,"https://t.me/Forex_Algo_Trader",clrBlack,10,clrNONE,clrBlack);
   

Para crear el botón de compra, venta, superposición, un botón de información adicional y un botón de spread, se implementa el código anterior. Lo único adicional que cambia es el texto de los precios de compra y venta, así como el valor del spread. Se llaman funciones personalizadas adicionales, Bid, Ask y Spread, para completar los valores. Las funciones de oferta y demanda devuelven un valor de datos de tipo doble y, por lo tanto, para convertir el doble en cadena, se llama a una función "DoubleToString" incorporada. Para la propagación, convertimos el valor entero a la cadena directamente. Las funciones personalizadas son las siguientes.

double Ask(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits));}
double Bid(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits));}
int Spread(){return((int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));}

Las funciones devuelven los tipos de datos de información del símbolo correspondiente. Al compilar obtenemos el siguiente resultado.

PANEL10

Ahora procedemos a crear algunos botones extras que usaremos para ilustrar cómo se puede crear un botón con bordes afilados y un duplicado de éste que usaremos para automatizar el efecto de desplazamiento.

#define BTN_SHARP "BTN_SHARP"
#define LABEL_SHARP "LABEL_SHARP"
#define BTN_HOVER "BTN_HOVER"
#define LABEL_HOVER "LABEL_HOVER"

...

   createRecLabel(BTN_SHARP,25,190,220,35,C'220,220,220',2,C'100,100,100');
   createLabel(LABEL_SHARP,25+20,190+5,"Sharp Edged Button",clrBlack,12,"ARIAL black");
   //createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'050,050,255');
   createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'100,100,100');
   createLabel(LABEL_HOVER,25+50,230+5,"Hover Effect",clrBlack,12,"ARIAL black");

A continuación se muestra el logro.

PANEL11

Hay algo de espacio extra que se puede usar para otras utilidades, pero llenémoslo con algunos emojis y caracteres icónicos.

#define LABEL_EXTRA1 "LABEL_EXTRA1"
#define LABEL_EXTRA2 "LABEL_EXTRA2"
#define LABEL_EXTRA3 "LABEL_EXTRA3"
#define LABEL_EXTRA4 "LABEL_EXTRA4"

...

   createLabel(LABEL_EXTRA1,25,290,"_",clrBlack,25,"WEBDINGS");
   createLabel(LABEL_EXTRA2,25+40,290,"J",clrBlack,25,"WINGDINGS");
   createLabel(LABEL_EXTRA3,25+40+40,290,"{",clrBlack,25,"WINGDINGS 2");
   createLabel(LABEL_EXTRA4,25+40+40+40,290,"G",clrBlack,25,"WINGDINGS 3");

Una vez que se hace clic en el botón de volumen de operaciones, queremos tener algunas instancias para la creación de una lista desplegable desde la cual podamos elegir diferentes opciones. Necesitamos tener 3 opciones y también un ícono para poder arrastrar la lista a otro lugar lejos del punto de creación inicial. Se utiliza la misma lógica.

#define BTN_DROP_DN "BTN_DROP_DN"
#define LABEL_OPT1 "LABEL_OPT1"
#define LABEL_OPT2 "LABEL_OPT2"
#define LABEL_OPT3 "LABEL_OPT3"
#define ICON_DRAG "ICON_DRAG"

...

void createDropDown(){
   createRecLabel(BTN_DROP_DN,25,95+25,130,70,clrWhite,2,clrBlack);
   createLabel(LABEL_OPT1,25+10,95+25,"LotSize",clrBlack,12,"stencil");
   createLabel(LABEL_OPT2,25+10,95+25+20,"Risk Percent %",clrBlack,12,"calibri Italic");
   createLabel(LABEL_OPT3,25+10,95+25+20+20,"Money Balance",clrBlack,12,"Arial bold");
   createLabel(ICON_DRAG,25+10+95,95+25,"d",clrRoyalBlue,15,"webdings");
}

Aquí, creamos los botones y las etiquetas en una función personalizada para que llamemos a la función una vez que se haga clic en el volumen de negociación. Sin embargo, para mostrar las posiciones de las utilidades, llamamos a la función pero luego comentaremos la función llamada.

   createDropDown();

El logro final es el siguiente.

PANEL12. PARTE FINAL 1

Por último, debemos destruir y eliminar los objetos creados una vez que el asesor experto se elimina del gráfico. Para lograr esto se crea otra función para eliminar los objetos creados.

void destroyPanel(){
   ObjectDelete(0,MAIN_REC);
   ObjectDelete(0,MAIN_SUB_REC);
   ObjectDelete(0,MAIN_LINE_UP);
   
   //... other objects
   
   ChartRedraw(0);
}

Se utiliza una función personalizada vacía, lo que significa que no devuelve nada. La función incorporada "ObjectDelete" se utiliza para eliminar los objetos respectivos tal como se pasan. Toma dos argumentos, el ID del gráfico, 0 para el gráfico actual y el nombre del objeto que se va a eliminar. Esto se llama durante la función de desinicialización experta.

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

El siguiente es el código fuente completo responsable de la creación del panel GUI como se ilustra en MQL5 para MetaTrader 5 (MT5).

//+------------------------------------------------------------------+
//|                                             DASHBOARD PART 1.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

//--- DEFINE MACRO PROPERTIES

#define MAIN_REC "MAIN_REC"
#define MAIN_SUB_REC "MAIN_SUB_REC"
#define MAIN_LINE_UP "MAIN_LINE_UP"
#define MAIN_LINE_DN "MAIN_LINE_DN"
#define LABEL_NAME "LABEL_NAME"
#define ICON_HEART "ICON_HEART"
#define ICON_TOOL "ICON_TOOL"
#define ICON_CAR "ICON_CAR"
#define LINE1 "LINE1"
#define BTN_CLOSE "BTN_CLOSE"
#define BTN_MARKET "BTN_MARKET"
#define BTN_PROFIT "BTN_PROFIT"
#define BTN_LOSS "BTN_LOSS"
#define BTN_PENDING "BTN_PENDING"
#define LINE2 "LINE2"

#define BTN_LOTS "BTN_LOTS"
#define LABEL_LOTS "LABEL_LOTS"
#define ICON_DROP_DN1 "ICON_DROP_DN1"
#define EDIT_LOTS "EDIT_LOTS"
#define BTN_P1 "BTN_P1"
#define BTN_M1 "BTN_M1"

#define BTN_SL "BTN_SL"
#define LABEL_SL "LABEL_SL"
#define ICON_DROP_DN2 "ICON_DROP_DN2"
#define EDIT_SL "EDIT_SL"
#define BTN_P2 "BTN_P2"
#define BTN_M2 "BTN_M2"

#define BTN_TP "BTN_TP"
#define LABEL_TP "LABEL_TP"
#define ICON_DROP_DN3 "ICON_DROP_DN3"
#define EDIT_TP "EDIT_TP"
#define BTN_P3 "BTN_P3"
#define BTN_M3 "BTN_M3"

#define BTN_BUY "BTN_BUY"
#define LABEL_BUY "LABEL_BUY"
#define LABEL_BUY_PRICE "LABEL_BUY_PRICE"
#define BTN_OVERLAY "BTN_OVERLAY"
#define BTN_SPREAD "BTN_SPREAD"

#define BTN_SELL "BTN_SELL"
#define LABEL_SELL "LABEL_SELL"
#define LABEL_SELL_PRICE "LABEL_SELL_PRICE"

#define BTN_CONTACT "BTN_CONTACT"

#define BTN_SHARP "BTN_SHARP"
#define LABEL_SHARP "LABEL_SHARP"
#define BTN_HOVER "BTN_HOVER"
#define LABEL_HOVER "LABEL_HOVER"

#define LABEL_EXTRA1 "LABEL_EXTRA1"
#define LABEL_EXTRA2 "LABEL_EXTRA2"
#define LABEL_EXTRA3 "LABEL_EXTRA3"
#define LABEL_EXTRA4 "LABEL_EXTRA4"

#define BTN_DROP_DN "BTN_DROP_DN"
#define LABEL_OPT1 "LABEL_OPT1"
#define LABEL_OPT2 "LABEL_OPT2"
#define LABEL_OPT3 "LABEL_OPT3"
#define ICON_DRAG "ICON_DRAG"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit(){

   createRecLabel(MAIN_REC,10,30,250,400,clrWhite,1,clrBlack);
   createRecLabel(MAIN_SUB_REC,15,35,240,390,C'245,245,245',1,clrNONE);
   createRecLabel(MAIN_LINE_UP,15,35,240,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createRecLabel(MAIN_LINE_DN,15,35-1,1,390+1,C'245,245,245',1,clrNONE,BORDER_RAISED);

   createLabel(LABEL_NAME,25,35,"DashBoard v1.0",clrBlue,14,"Cooper Black");
   
   createLabel(ICON_HEART,190,35,"Y",clrRed,15,"Webdings");
   createLabel(ICON_TOOL,210,35,"@",clrBlue,15,"Webdings");
   createLabel(ICON_CAR,230,35,"h",clrBlack,15,"Webdings");
   createRecLabel(LINE1,15+10,60,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   createLabel(BTN_CLOSE,25,65,"Close",clrBlack,13,"Impact");
   createLabel(BTN_MARKET,70,65,"Market",clrDarkRed,13,"Impact");
   createLabel(BTN_PROFIT,125,65,"Profit",clrGreen,13,"Impact");
   createLabel(BTN_LOSS,170,65,"Loss",clrRed,13,"Impact");
   createLabel(BTN_PENDING,205,65,"Pend'n",clrDarkGray,13,"Impact");
   createRecLabel(LINE2,15+10,87,240-10,1,C'245,245,245',1,clrNONE,BORDER_RAISED);
   
   createButton(BTN_LOTS,25,95,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_LOTS,25+10,95+5,"LotSize",clrBlack,9);
   //createLabel(ICON_DROP_DN1,150,75,CharToString(100),clrBlack,12,"Wingdings");
   createLabel(ICON_DROP_DN1,130,95+5,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_LOTS,165,95,60,25,"0.01",clrBlack,14,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P1,225,95,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M1,225,95+12,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");

   createButton(BTN_SL,25,95+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_SL,35,95+30,"SL Pips",clrBlack,14);
   createLabel(ICON_DROP_DN2,130,100+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_SL,165,95+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P2,225,95+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M2,225,107+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");

   createButton(BTN_TP,25,95+30+30,130,25,"",clrBlack,12,C'210,210,210',C'150,150,150');
   createLabel(LABEL_TP,35,95+30+30,"TP Pips",clrBlack,14);
   createLabel(ICON_DROP_DN3,130,100+30+30,CharToString(240),C'070,070,070',20,"Wingdings 3");
   createEdit(EDIT_TP,165,95+30+30,60,25,"100.0",clrBlack,13,clrWhite,C'100,100,100',"Callibri");
   createButton(BTN_P3,225,95+30+30,20,12,"5",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   createButton(BTN_M3,225,107+30+30,20,12,"6",clrBlack,12,clrLightGray,C'100,100,100',"Webdings");
   
   createRecLabel(BTN_SELL,25,335,105,60,clrRed,1,clrNONE);
   createLabel(LABEL_SELL,35,335,"Sell",clrWhite,15,"ARIAL black");
   createLabel(LABEL_SELL_PRICE,35,335+30,DoubleToString(Bid(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_BUY,140,335,105,60,clrGreen,1,clrNONE);
   createLabel(LABEL_BUY,150+35,335,"Buy",clrWhite,15,"ARIAL black");
   createLabel(LABEL_BUY_PRICE,150,335+30,DoubleToString(Ask(),_Digits),clrWhite,13,"ARIAL black");
   createRecLabel(BTN_OVERLAY,90,335,90,25,C'245,245,245',0,clrNONE);
   createButton(BTN_SPREAD,95,335,80,20,(string)Spread(),clrBlack,13,clrWhite,clrBlack);
   createButton(BTN_CONTACT,25,335+62,230-10,25,"https://t.me/Forex_Algo_Trader",clrBlack,10,clrNONE,clrBlack);
   
   createRecLabel(BTN_SHARP,25,190,220,35,C'220,220,220',2,C'100,100,100');
   createLabel(LABEL_SHARP,25+20,190+5,"Sharp Edged Button",clrBlack,12,"ARIAL black");
   //createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'050,050,255');
   createRecLabel(BTN_HOVER,25,230,220,35,C'220,220,220',3,C'100,100,100');
   createLabel(LABEL_HOVER,25+50,230+5,"Hover Effect",clrBlack,12,"ARIAL black");

   createLabel(LABEL_EXTRA1,25,290,"_",clrBlack,25,"WEBDINGS");
   createLabel(LABEL_EXTRA2,25+40,290,"J",clrBlack,25,"WINGDINGS");
   createLabel(LABEL_EXTRA3,25+40+40,290,"{",clrBlack,25,"WINGDINGS 2");
   createLabel(LABEL_EXTRA4,25+40+40+40,290,"G",clrBlack,25,"WINGDINGS 3");
   
   // createDropDown();
   
   return(INIT_SUCCEEDED);
}

double Ask(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits));}
double Bid(){return(NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits));}
int Spread(){return((int)SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---
   destroyPanel();
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(){

}
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|     Function to create rectangle label                           |
//+------------------------------------------------------------------+

bool createRecLabel(string objName, int xD, int yD, int xS, int yS,
                    color clrBg, int widthBorder, color clrBorder = clrNONE,
                    ENUM_BORDER_TYPE borderType = BORDER_FLAT, ENUM_LINE_STYLE borderStyle = STYLE_SOLID) {
    ResetLastError(); // Reset any previous error codes
    
    // Create a rectangle label object
    if (!ObjectCreate(0, objName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) {
        Print(__FUNCTION__, ": failed to create rec label! Error code = ", _LastError);
        return (false); // Return false if object creation fails
    }
    
    // Set properties for the rectangle label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the rectangle
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Rectangle background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_TYPE, borderType); // Border type
    ObjectSetInteger(0, objName, OBJPROP_STYLE, borderStyle); // Border style (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, widthBorder); // Border width (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBorder); // Border color (only if borderType is flat)
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Not a background object
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected
    
    ChartRedraw(0); // Redraw the chart
    
    return (true); // Return true if object creation and property settings are successful
}

//+------------------------------------------------------------------+
//|     Function to create button                                    |
//+------------------------------------------------------------------+

bool createButton(string objName, int xD, int yD, int xS, int yS,
                  string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                  color clrBg = clrNONE, color clrBorder = clrNONE,
                  string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the button object
    if (!ObjectCreate(0, objName, OBJ_BUTTON, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the button! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the button
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the button
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the button
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the button
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Button state (not pressed)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the button
    ChartRedraw(0);

    return (true); // Button creation successful
}

//+------------------------------------------------------------------+
//|     Function to create edit field                                |
//+------------------------------------------------------------------+

bool createEdit(string objName, int xD, int yD, int xS, int yS,
                string txt = "", color clrTxt = clrBlack, int fontSize = 12,
                color clrBg = clrNONE, color clrBorder = clrNONE,
                string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the edit object
    if (!ObjectCreate(0, objName, OBJ_EDIT, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the edit! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the edit field
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_XSIZE, xS); // Width of the edit field
    ObjectSetInteger(0, objName, OBJPROP_YSIZE, yS); // Height of the edit field
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Default text in the edit field
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, clrBg); // Background color
    ObjectSetInteger(0, objName, OBJPROP_BORDER_COLOR, clrBorder); // Border color
    ObjectSetInteger(0, objName, OBJPROP_ALIGN, ALIGN_LEFT); // Text alignment (left-aligned)
    ObjectSetInteger(0, objName, OBJPROP_READONLY, false); // Edit field is not read-only
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Edit field state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the edit field
    ChartRedraw(0);

    return (true); // Edit field creation successful
}

//+------------------------------------------------------------------+
//|     Function to create text label                                |
//+------------------------------------------------------------------+

bool createLabel(string objName, int xD, int yD,
                 string txt, color clrTxt = clrBlack, int fontSize = 12,
                 string font = "Arial Rounded MT Bold") {
    // Reset any previous errors
    ResetLastError();

    // Attempt to create the label object
    if (!ObjectCreate(0, objName, OBJ_LABEL, 0, 0, 0)) {
        // Print an error message if creation fails
        Print(__FUNCTION__, ": failed to create the label! Error code = ", _LastError);
        return (false);
    }

    // Set properties for the label
    ObjectSetInteger(0, objName, OBJPROP_XDISTANCE, xD); // X distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_YDISTANCE, yD); // Y distance from the corner
    ObjectSetInteger(0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); // Positioning corner
    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the label
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrTxt); // Text color
    ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, fontSize); // Font size
    ObjectSetString(0, objName, OBJPROP_FONT, font); // Font name
    ObjectSetInteger(0, objName, OBJPROP_BACK, false); // Transparent background
    ObjectSetInteger(0, objName, OBJPROP_STATE, false); // Label state (not active)
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false); // Not selectable
    ObjectSetInteger(0, objName, OBJPROP_SELECTED, false); // Not selected

    // Redraw the chart to display the label
    ChartRedraw(0);

    return (true); // Label creation successful
}

//+------------------------------------------------------------------+
//|     Function to create the drop down utilities                   |
//+------------------------------------------------------------------+

void createDropDown(){
   createRecLabel(BTN_DROP_DN,25,95+25,130,70,clrWhite,2,clrBlack);
   createLabel(LABEL_OPT1,25+10,95+25,"LotSize",clrBlack,12,"stencil");
   createLabel(LABEL_OPT2,25+10,95+25+20,"Risk Percent %",clrBlack,12,"calibri Italic");
   createLabel(LABEL_OPT3,25+10,95+25+20+20,"Money Balance",clrBlack,12,"Arial bold");
   createLabel(ICON_DRAG,25+10+95,95+25,"d",clrRoyalBlue,15,"webdings");
}

//+------------------------------------------------------------------+
//|    Function to destroy the entire GUI Panel                      |
//+------------------------------------------------------------------+

void destroyPanel(){
   ObjectDelete(0,MAIN_REC);
   ObjectDelete(0,MAIN_SUB_REC);
   ObjectDelete(0,MAIN_LINE_UP);
   ObjectDelete(0,MAIN_LINE_DN);
   ObjectDelete(0,BTN_LOTS);
   ObjectDelete(0,LABEL_NAME);
   ObjectDelete(0,LABEL_LOTS);
   ObjectDelete(0,ICON_HEART);
   ObjectDelete(0,ICON_TOOL);
   ObjectDelete(0,ICON_CAR);
   ObjectDelete(0,ICON_DROP_DN1);
   ObjectDelete(0,LINE1);
   ObjectDelete(0,BTN_CLOSE);
   ObjectDelete(0,BTN_MARKET);
   ObjectDelete(0,BTN_PROFIT);
   ObjectDelete(0,BTN_LOSS);
   ObjectDelete(0,BTN_PENDING);
   ObjectDelete(0,LINE2);
   ObjectDelete(0,EDIT_LOTS);
   ObjectDelete(0,BTN_P1);
   ObjectDelete(0,BTN_M1);
   
   ObjectDelete(0,BTN_SL);
   ObjectDelete(0,LABEL_SL);
   ObjectDelete(0,ICON_DROP_DN2);
   ObjectDelete(0,EDIT_SL);
   ObjectDelete(0,BTN_P2);
   ObjectDelete(0,BTN_M2);
   
   ObjectDelete(0,BTN_TP);
   ObjectDelete(0,LABEL_TP);
   ObjectDelete(0,ICON_DROP_DN3);
   ObjectDelete(0,EDIT_TP);
   ObjectDelete(0,BTN_P3);
   ObjectDelete(0,BTN_M3);
   
   ObjectDelete(0,BTN_BUY);
   ObjectDelete(0,LABEL_BUY);
   ObjectDelete(0,LABEL_BUY_PRICE);
   ObjectDelete(0,BTN_OVERLAY);
   ObjectDelete(0,BTN_SPREAD);
   
   ObjectDelete(0,BTN_SELL);
   ObjectDelete(0,LABEL_SELL);
   ObjectDelete(0,LABEL_SELL_PRICE);
   
   ObjectDelete(0,BTN_CONTACT);
   
   ObjectDelete(0,BTN_SHARP);
   ObjectDelete(0,LABEL_SHARP);
   ObjectDelete(0,BTN_HOVER);
   ObjectDelete(0,LABEL_HOVER);
   
   ObjectDelete(0,LABEL_EXTRA1);
   ObjectDelete(0,LABEL_EXTRA2);
   ObjectDelete(0,LABEL_EXTRA3);
   ObjectDelete(0,LABEL_EXTRA4);
   
   ObjectDelete(0,BTN_DROP_DN);
   ObjectDelete(0,LABEL_OPT1);
   ObjectDelete(0,LABEL_OPT2);
   ObjectDelete(0,LABEL_OPT3);
   ObjectDelete(0,ICON_DRAG);
   
   ChartRedraw(0);
}


Conclusión

En conclusión, se puede ver que la creación de paneles GUI no es tan compleja como se percibe. El proceso implica una serie de pasos que van desde la definición de las dimensiones del panel, es decir, decidir la posición, el tamaño y la apariencia del panel que puede utilizar coordenadas absolutas o coordenadas relativas al gráfico, pasando por la creación de varios objetos gráficos como botones, etiquetas, campos de edición y etiquetas rectangulares especificando sus propiedades (color, texto, fuente, etc.), hasta la implementación en manejadores de eventos para la creación de los paneles y las interacciones del usuario.

En esta primera parte se ha presentado con éxito la creación del panel. La segunda parte dará vida al panel haciéndolo sensible. Por ejemplo, haremos que los botones respondan a los clics, actualizaremos las cotizaciones en cada tick, haremos que la lista desplegable se pueda arrastrar, añadiremos efectos hover a los botones y mucho más. Esperamos que este artículo le haya resultado útil para la creación de paneles GUI, y que los conocimientos aquí ilustrados puedan utilizarse para crear paneles GUI más complejos y extravagantes.


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

Archivos adjuntos |
Características del Wizard MQL5 que debe conocer (Parte 25): Pruebas y operaciones en múltiples marcos temporales Características del Wizard MQL5 que debe conocer (Parte 25): Pruebas y operaciones en múltiples marcos temporales
Las estrategias que se basan en múltiples marcos de tiempo no se pueden probar en los Asesores Expertos ensamblados por defecto debido a la arquitectura de código MQL5 utilizada en las clases de ensamblaje. Exploramos una posible solución a esta limitación para las estrategias que buscan utilizar múltiples marcos temporales en un estudio de caso con la media móvil cuadrática.
Algoritmo de evolución del caparazón de tortuga (Turtle Shell Evolution Algorithm, TSEA) Algoritmo de evolución del caparazón de tortuga (Turtle Shell Evolution Algorithm, TSEA)
Hoy hablaremos sobre un algoritmo de optimización único inspirado en la evolución del caparazón de las tortugas. El algoritmo TSEA emula la formación gradual de los sectores de piel queratinizada que representan soluciones óptimas a un problema. Las mejores soluciones se vuelven más "duras" y se encuentran más cerca de la superficie exterior, mientras que las menos exitosas permanecen "blandas" y se hallan en el interior. El algoritmo utiliza la clusterización de soluciones según su calidad y distancia, lo cual permite conservar las opciones menos acertadas y aporta flexibilidad y adaptabilidad.
Gestor de riesgos para el trading algorítmico Gestor de riesgos para el trading algorítmico
Los objetivos de este artículo son: demostrar por qué el uso del gestor de riesgos es algo imprescindible, adaptar los principios del riesgo controlado en el trading algorítmico en una clase aparte, de modo que todo el mundo pueda comprobar de forma independiente la eficacia del enfoque de racionamiento del riesgo en el trading intradía y la inversión en los mercados financieros. En este artículo, detallaremos la escritura de una clase de gestor de riesgos para el trading algorítmico como continuación del artículo anterior sobre la escritura de un gestor de riesgos para el trading manual.
Desarrollamos un asesor experto multidivisa (Parte 10): Creación de objetos a partir de una cadena Desarrollamos un asesor experto multidivisa (Parte 10): Creación de objetos a partir de una cadena
El plan de desarrollo del EA comprende varias etapas con resultados intermedios almacenados en una base de datos. Solo se pueden recuperar desde allí como cadenas o números, no como objetos. Así que necesitaremos una forma de recrear en el EA los objetos deseados a partir de las cadenas leídas de la base de datos.