English Русский 中文 Deutsch 日本語 Português
preview
De novato a experto: depuración colaborativa en MQL5

De novato a experto: depuración colaborativa en MQL5

MetaTrader 5Ejemplos |
259 8
Clemence Benjamin
Clemence Benjamin

Contenido principal 


Introducción:

Normalmente, cada autor intenta abordar un problema específico desde el principio hasta el final de un artículo. Nuestro título de hoy es "Depuración", pero los animo a no tomarlo a la ligera, ya que exploraremos mucho más que los conceptos básicos del proceso. Compartiré las técnicas que he empleado a lo largo de los años en múltiples proyectos exitosos. En todas las áreas de programación de software, la depuración es un tema que no se puede pasar por alto. He notado que muchos autores se centran en presentar un producto final pulido sin compartir las dificultades que enfrentaron para lograr que el código funcione correctamente.

Ya sea en sistemas de redes neuronales, inteligencia artificial u otras disciplinas de software relacionadas, la depuración es esencial. Creo que la habilidad más valiosa que puedes desarrollar es la capacidad de resolver problemas a medida que surgen, y esta habilidad se convierte en una parte integral de ti para futuros desafíos de naturaleza similar. De este modo, la resolución de problemas puede generar un sólido conjunto de habilidades, transformando gradualmente a alguien en un experto.

Depuración colaborativa

Depuración colaborativa

Cuando me comprometí a escribir este artículo, estaba trabajando en un proyecto en el que encontré varios errores al intentar compilar el código. A veces, el depurador me presentaba 50 líneas de error para solucionar. A través de prueba y error, desarrollé una rutina para abordar errores que me permite resolver problemas en solo unos minutos, o segundos, y lograr que el programa funcione sin problemas.

Mi objetivo es que conozcas las tecnologías que pueden acelerar el proceso de depuración. En mi experiencia, una de las lecciones más valiosas que he aprendido es que dominar MQL5 puede ser rápido y efectivo cuando uno participa activamente en proyectos de depuración. He conservado un programa lleno de errores que revisaremos juntos y perfeccionaremos.

Uno de los retos más duraderos es que a mucha gente le cuesta soportar los extensos libros de MQL5 disponibles de forma gratuita, pero eso no los hace menos valiosos. Estos libros contienen conocimientos esenciales que van desde conceptos básicos de programación MQL5 hasta conceptos avanzados. Para lograr los mejores resultados, es aconsejable participar en proyectos activos y consultar estos libros para temas específicos relacionados con su trabajo en curso. A medida que complete estos proyectos, absorberá naturalmente una gran cantidad de conocimientos.

Normalmente, nuestros informes de errores se organizan en cuatro columnas, como se describe en la siguiente tabla.

Columna (Nombres) Explicación
Descripción Esta columna proporciona una breve explicación del error o advertencia encontrado en el código. Puede describir la naturaleza del problema, como errores de sintaxis, variables no declaradas, discrepancias de tipos u otros errores de codificación. Comprender la descripción ayuda al programador a identificar rápidamente el problema.
Archivo Aquí se indica el nombre del fichero donde se ha producido el error (por ejemplo D1 PriceMarker.mq5). En el caso de haber varios archivos en un proyecto, saber qué archivo contiene el problema es crucial para realizar una depuración y corrección efectivas.
Línea Especifica el número de línea exacto dentro del archivo indicado donde se encuentra el error. Esta localización permite al programador navegar rápidamente a la parte específica del código que requiere atención, reduciendo el tiempo necesario para localizar el problema.
Columna, Esto indica el número de columna específico en la línea donde se detectó el error. Aunque se hace referencia a ella con menos frecuencia que las columnas anteriores, puede ser particularmente útil para identificar errores que ocurren en declaraciones complejas o cuando la línea contiene muchos elementos (como múltiples llamadas de función o parámetros).

Normalmente se organizan de izquierda a derecha, como se muestra a continuación. También hemos incluido el informe de errores completo, que comprende 20 errores y 4 advertencias (ver la parte inferior del fragmento), para el programa que depuraremos en esta discusión, justo debajo del diseño de la tabla. Le resultará fácil identificar las características del informe. Si lee hasta el final, discutiremos cómo resolver los errores presentados en el fragmento de código a continuación.

Descripción Archivo Línea Columna

'D1 PriceMarker.mq5'                    1
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      70      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      70      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      71      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      71      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      72      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      72      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      73      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      73      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      74      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      74      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      75      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      75      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      76      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      76      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      77      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      77      5
'ObjectCreate' - wrong parameters count D1 PriceMarker.mq5      15      9
   built-in: bool ObjectCreate(long,const string,ENUM_OBJECT,int,datetime,double,...)   D1 PriceMarker.mq5      15      9
'ObjectCreate' - wrong parameters count D1 PriceMarker.mq5      27      9
   built-in: bool ObjectCreate(long,const string,ENUM_OBJECT,int,datetime,double,...)   D1 PriceMarker.mq5      27      9
'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5      37      5
',' - unexpected token  D1 PriceMarker.mq5      37      28
'labelName' - some operator expected    D1 PriceMarker.mq5      37      19
'+' - illegal operation use     D1 PriceMarker.mq5      37      36
',' - unexpected token  D1 PriceMarker.mq5      37      69
result of expression not used   D1 PriceMarker.mq5      37      43
',' - unexpected token  D1 PriceMarker.mq5      37      73
expression has no effect        D1 PriceMarker.mq5      37      71
',' - unexpected token  D1 PriceMarker.mq5      37      82
expression has no effect        D1 PriceMarker.mq5      37      76
')' - unexpected token  D1 PriceMarker.mq5      37      87
expression has no effect        D1 PriceMarker.mq5      37      84
'OBJPROP_Y' - undeclared identifier     D1 PriceMarker.mq5      41      36
'ObjectSetInteger' - no one of the overloads can be applied to the function call        D1 PriceMarker.mq5      41      5
could be one of 2 function(s)   D1 PriceMarker.mq5      41      5
   built-in: bool ObjectSetInteger(long,const string,ENUM_OBJECT_PROPERTY_INTEGER,long) D1 PriceMarker.mq5      41      5
   built-in: bool ObjectSetInteger(long,const string,ENUM_OBJECT_PROPERTY_INTEGER,int,long)     D1 PriceMarker.mq5      41      5
20 errors, 4 warnings           21      5

A continuación se presentan algunos términos comunes que conviene comprender al hablar de este tema:

  • Sintaxis: se refiere al conjunto específico de reglas que dictan cómo deben escribirse los programas (como algoritmos de trading, indicadores y scripts) para que la plataforma MetaTrader 5 los entienda y ejecute correctamente.
  • Error: se refiere a un error o un problema en el código que impide que se ejecute correctamente. Los errores se pueden clasificar en varios tipos: errores de sintaxis, errores de tiempo de ejecución, errores lógicos, errores de tipo y errores de compilación.


¿Qué es la depuración?

Estoy seguro de que la mayoría de ustedes están familiarizados con este término vibrante, pero es esencial que los principiantes comprendan el concepto en detalle. Ahora definiré un error para que puedas entender mejor el proceso de depuración.

  • Error:

Un error o defecto en un programa o sistema informático que provoca que se comporte de manera inesperada o incorrecta. 

  • Depuración:

Es el proceso de identificar, aislar y corregir errores o fallos en un programa o sistema informático con el objetivo de garantizar que el programa se comporte como se espera y produzca los resultados correctos en diversas condiciones.

Depuración en el contexto de la programación MQL5

A continuación se presentan algunos aspectos de la depuración relacionados específicamente con MQL5:

 1. Tipos comunes de errores en MQL5:

  • Errores de sintaxis: errores en la estructura del código MQL5 que impiden que el script se compile.

Este ejemplo muestra un error de sintaxis simple donde falta el paréntesis de cierre para la función Print(). Como resultado, el script no podrá compilarse, lo que resalta la necesidad de verificar cuidadosamente la estructura del código.

void OnStart()
{
    Print("Hello, World!" // Missing closing parenthesis
}
  • Errores lógicos: problemas en los que el código se compila y se ejecuta, pero produce señales comerciales incorrectas o se comporta de manera inesperada.

Aquí hay un error lógico en el que las condiciones activan erróneamente una orden de compra. El programador pretendía aprovechar una lógica más compleja que depende de las condiciones del mercado, pero la implementación actual conduce a transacciones innecesarias.

void OnTick()
{
    double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double targetPrice = currentPrice + 100; // Intended to use a different logic

    // Mistakenly placing a buy when conditions aren't right
    if (currentPrice < targetPrice) // Logic Error
    {
        OrderSend(_Symbol, OP_BUY, 0.1, currentPrice, 3, 0, 0, "Buy order", 0, 0, clrGreen);
    }
}
  • Errores de tiempo de ejecución: errores que ocurren durante la ejecución, como intentar acceder a una matriz fuera de los límites o no manejar correctamente las órdenes comerciales.
En este ejemplo, se intenta acceder al sexto elemento de una matriz que solo tiene cinco índices válidos. Esto generará un error de tiempo de ejecución, lo que ilustra la importancia de verificar los límites cuando se trabaja con matrices.
void OnStart()
{
    double prices[5];
    
    // Attempt to access out-of-range index (e.g., index 5)
    double value = prices[5]; // Runtime error: Array out of range
}

2. Herramientas de depuración en MQL5:

  • MetaEditor: este es el entorno de desarrollo integrado (IDE) para MQL5. Proporciona resaltado de sintaxis, finalización de código e indicación de errores que pueden ayudar a identificar errores de sintaxis rápidamente.
El código, a continuación, permite establecer un punto de interrupción en el cálculo de la variable result. Al depurar en el MetaEditor, puede inspeccionar las variables en este punto para confirmar que están establecidas como se esperaba, facilitando la ejecución línea por línea para analizar el flujo del programa.
void OnStart()
{
    double startValue = 10.0;

    // Set a breakpoint here to inspect value
    double result = startValue * 2;

    Print("Result: ", result); // Check the value of result
}
  • Sentencias de impresión: Uso de la función Print() para dar salida a valores de variables y registros de flujo de ejecución en el registro de Expertos. Esta es una forma sencilla de rastrear problemas.
En este fragmento de código de ejemplo, utilizamos la función Print() para registrar los precios de compra y venta actuales. Este enfoque es beneficioso para rastrear los valores de las variables durante la ejecución y puede ayudar a diagnosticar errores lógicos comparando los valores esperados con los reales.
void OnTick()
{
    double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    
    // Logging prices for debugging
    Print("Bid: ", bidPrice, ", Ask: ", askPrice);
}
  • Comentarios en el código: Deshabilitar temporalmente secciones de código para aislar el área problemática.
En este ejemplo, se comenta una línea de código para centrarse en la lógica alternativa. Esta técnica es útil para aislar errores y probar diferentes secciones del código sin eliminarlos por completo.
void OnTick()
{
    // double result = SomeFunction(); // Temporarily disabling this line
    
    // Run alternate logic while debugging
    Print("Running alternative logic.");
}
3. Usando el depurador en MetaEditor:

MetaEditor incluye un depurador integrado que permite:
  • Puntos de interrupción: establecer puntos de interrupción en su código le permite pausar la ejecución en líneas específicas e inspeccionar valores de variables.
  • Ejecución paso a paso: puede recorrer el código línea por línea para observar cómo cambian las variables y cómo sigue el flujo de la lógica.
  • Expresiones de observación: monitorización de los valores de variables específicas durante la ejecución del código.
 4. Pruebas y optimización:
  • Probador de estrategias: MQL5 proporciona un probador de estrategias que le permite realizar pruebas retrospectivas de estrategias comerciales utilizando datos históricos. Ayuda a simular operaciones y analiza el rendimiento, lo que puede revelar errores ocultos.
  • Optimización: puede optimizar los parámetros para mejorar el rendimiento de su algoritmo comercial, lo que también puede resaltar posibles errores en la lógica o la ejecución.
 5. Manejo de errores:
  • Manejo de códigos de error específicos de MQL5, como la comprobación de los valores de retorno de funciones relacionadas con operaciones comerciales. Entre las funciones más comunes se incluyen las funciones de ejecución de órdenes (OrderSend, OrderClose, etc.), en las que un tratamiento adecuado de los errores puede evitar bloqueos o resultados no deseados.

Mejores prácticas para la depuración en MQL5:

1. Modularidad del código: Escribe código modular dividiéndolo en funciones. Esto hace que sea más fácil probar y depurar componentes individuales. 2. Documentar el código: Comente su código para explicar lo que hace cada parte, lo que puede ayudar cuando se revisa el código después de algún tiempo. 3. Pruebas periódicas: Pruebe con frecuencia el código durante el desarrollo en lugar de esperar a que todo esté completo. Esto ayuda a detectar errores de forma temprana.


Implementación de la depuración en MQL5

No hace mucho tiempo, mi amigo y yo creamos un borrador de un script para dibujar líneas de precios etiquetadas para la vela diaria anterior (D1), marcando niveles de precios críticos como Máximo, Mínimo, Apertura y Cierre. Ésta es la versión que he reservado para este artículo. 

Normalmente, al escribir como experto, MetaEditor proporciona plantillas y sugerencias de parámetros para ayudar a los desarrolladores y reducir las posibilidades de errores, siempre que los detalles se ingresen de acuerdo con la sintaxis del lenguaje correcta. Sin embargo, hay casos en los que es posible recibir código de un foro que esté plagado de errores. A continuación se muestra un fragmento de código de nuestro programa de script con errores:

//+------------------------------------------------------------------+
//|                                               D1 PriceMarker.mq5 |
//|                                Copyright 2024, Clemence Benjamin |
//|             https://www.mql5.com/en/users/billionaire2024/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Clemence Benjamin"
#property link      "https://www.mql5.com/en/users/billionaire2024/seller"
#property version   "1.00"
#property strict

// Function to create a price line with a label
void CreatePriceLine(string name, double price, color clr, string label)
{
    // Create a horizontal line
    if(!ObjectCreate(name, OBJ_HLINE, 0, 0, price))
    {
        Print("Failed to create line: ", GetLastError());
        return;
    }
    
    // Set line properties
    ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
    ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);

    // Create a label for the price
    string labelName = name + "_label";
    if(!ObjectCreate(labelName, OBJ_LABEL, 0, 0, 0))
    {
        Print("Failed to create label: ", GetLastError());
        return;
    }

    // Set label properties
    ObjectSetInteger(0, labelName, OBJPROP_XSIZE, 70);
    ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
    ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
    ObjectSetText(labelName, label + ": " + DoubleToString(price, 2), 10, "Arial", clr);

    // Position the label
    double yPos = price; // Positioning along the price axis
    ObjectSetInteger(0, labelName, OBJPROP_Y, yPos);
    ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 5);
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
{
    // Get the previous D1 candle's open, high, low, and close prices
    datetime prevCandleTime = iTime(NULL, PERIOD_D1, 1);
    double openPrice = iOpen(NULL, PERIOD_D1, 1);
    double highPrice = iHigh(NULL, PERIOD_D1, 1);
    double lowPrice = iLow(NULL, PERIOD_D1, 1);
    double closePrice = iClose(NULL, PERIOD_D1, 1);

    // Draw labeled price lines for open, high, low, and close prices
    CreatePriceLine("PrevCandle_Open", openPrice, clrBlue, "Open");
    CreatePriceLine("PrevCandle_High", highPrice, clrRed, "High");
    CreatePriceLine("PrevCandle_Low", lowPrice, clrGreen, "Low");
    CreatePriceLine("PrevCandle_Close", closePrice, clrOrange, "Close");
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Remove the drawn price lines and labels upon indicator deinitialization
    ObjectDelete("PrevCandle_Open");
    ObjectDelete("PrevCandle_High");
    ObjectDelete("PrevCandle_Low");
    ObjectDelete("PrevCandle_Close");
    ObjectDelete("PrevCandle_Open_label");
    ObjectDelete("PrevCandle_High_label");
    ObjectDelete("PrevCandle_Low_label");
    ObjectDelete("PrevCandle_Close_label");
}

//+------------------------------------------------------------------+                                                                                                            

(i) Localización de un error

He descubierto que el depurador integrado de MetaEditor es bastante fácil de usar cuando intento compilar un programa defectuoso. La mayoría de los errores se detectan al hacer clic en el botón Compilar o Creación de perfiles en tiempo real en MetaEditor. Sin embargo, existen algunos errores de rendimiento que no impiden la compilación del programa; estos solo pueden identificarse en la plataforma o en el probador cuando se intenta ejecutar el programa.

Un desarrollador puede escribir el programa entero desde cero y luego depurarlo, o simplemente depurar un programa preexistente. En la imagen a continuación, aprovechamos el compilador y depurador integrados en MetaEditor para obtener un resumen de errores (ver la parte inferior de la ventana de la caja de herramientas en la imagen). Al hacer doble clic en una línea de error, el cursor se mueve y resalta la línea de código correspondiente con el error. Rara vez he notado errores en el código hasta que presiono el botón Compilar, momento en el que el depurador informa cualquier problema que surja.

Localización de errores

Localización de errores en MetaEditor

A veces el programa se compilará correctamente, pero es posible que no produzca el resultado deseado. En tales casos, es aconsejable identificar posibles errores consultando los registros de expertos y las impresiones del diario disponibles en la ventana de la caja de herramientas de la plataforma MetaTrader 5. Estos registros pueden brindar información valiosa sobre lo que podría estar fallando durante la ejecución, lo que le ayudará a solucionar problemas de manera eficaz.

(ii) 3 técnicas de depuración

A menudo, los errores pueden surgir de errores tipográficos o del uso incorrecto de términos, y el depurador normalmente proporciona explicaciones y sugerencias parciales para una solución. Si puede comprender estos mensajes, generalmente será sencillo volver a revisar el código y realizar las correcciones necesarias. Sin embargo, hay situaciones más complejas que pueden ser difíciles de diagnosticar y pueden requerir conocimientos más profundos procedentes de libros de referencia o de la experiencia de la comunidad.

En mi experiencia, suelo utilizar algunas estrategias al depurar problemas complejos. Clasifico estos pasos en tres enfoques principales, aunque esta lista no es exhaustiva; está destinada específicamente al propósito de esta discusión. Permítame explicarle cada paso del procedimiento en detalle.

1. Revisando la documentación:

Ayuda significativamente a depurar programas MQL5 al proporcionar claridad sobre la sintaxis, el uso de funciones y los mensajes de error. Ofrece explicaciones detalladas y ejemplos que ayudan a identificar implementaciones incorrectas y mejoran la comprensión de las funciones integradas. Además, la documentación a menudo incluye información sobre errores comunes, mejores prácticas y soluciones alternativas, lo que permite a los desarrolladores solucionar problemas de manera efectiva y optimizar su código para un mejor rendimiento. Para este proyecto, mira la imagen a continuación para ver cómo accedemos fácilmente a la documentación.

Revisando la documentación

Revisando la documentación

Informe de error:

'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      70      5

Sugerencia de solución:

   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      70      5

Situación actual:

   ObjectDelete("PrevCandle_Open");

A partir de la sugerencia de solución, es evidente que la función ObjectDelete espera dos parámetros, pero actualmente estamos proporcionando sólo uno. Esta discrepancia indica dónde está el problema y podemos abordarlo en consecuencia. Según la documentación, la función ObjectDelete en MQL5 requiere dos parámetros:

  1. Name: el nombre del objeto a eliminar, especificado como una cadena.
  2. Chart_id: El ID del gráfico del que debe eliminarse el objeto, especificado como un número entero. Si se omite, la función toma como valor predeterminado el gráfico actual.

Para resolver este problema, tenemos que asegurarnos de que pasamos ambos parámetros al llamar a ObjectDelete. Al hacerlo, alineamos nuestra llamada de función con la sintaxis esperada y, de este modo, eliminamos el error.

    Resolución:

    ObjectDelete(0, "PrevCandle_Open");

    Ahora, mirando a través del código principal, nos damos cuenta de que hay varias instancias de la función ObjectDelete. Utilizando la información que hemos recopilado de nuestra investigación, podemos realizar los ajustes necesarios en todos ellos. Al asegurarnos de proporcionar ambos parámetros necesarios para cada instancia, podemos resolver estos errores de manera efectiva.

    Consulte la imagen a continuación para ver cómo logramos reducir el número total de errores en 10. Esto indica un progreso significativo en la depuración de nuestro script y demuestra la importancia de un examen y corrección exhaustivos basados en una documentación adecuada.

    Función ObjectDelete resuelta

    Se ha resuelto el error de la función ObjectDelete

    ¡Esta hecho! Cuando encuentre un error, es una buena práctica presionar el botón Compilar después de cada intento de solución. Esto le permite verificar si el error aún persiste y le ayuda a identificar cualquier problema restante.

    Ahora, pasemos a nuestro próximo error.

    Informe de error:

    'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5      29      5
    'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5      29      5
    ',' - unexpected token  D1 PriceMarker.mq5      29      28
    'labelName' - some operator expected    D1 PriceMarker.mq5      29      19
    '+' - illegal operation use     D1 PriceMarker.mq5      29      36
    ',' - unexpected token  D1 PriceMarker.mq5      29      69
    result of expression not used   D1 PriceMarker.mq5      29      43
    ',' - unexpected token  D1 PriceMarker.mq5      29      73
    expression has no effect        D1 PriceMarker.mq5      29      71
    ',' - unexpected token  D1 PriceMarker.mq5      29      82
    expression has no effect        D1 PriceMarker.mq5      29      76
    ')' - unexpected token  D1 PriceMarker.mq5      29      87
    expression has no effect        D1 PriceMarker.mq5      29      84

    Esta vez, reuní varios informes porque, si los revisa, los errores ocurren en la misma línea. A menudo, esto indica un problema común que debe abordarse en esa parte específica del código. Echemos un vistazo más de cerca a la línea en cuestión para identificar el problema subyacente y determinar las correcciones necesarias.

    Sugerencias de solución:

    En este escenario, encontramos los siguientes errores: (identificador no declarado, operador esperado, expresión sin efecto y token inesperado).

    Situación actual:

    ObjectSetText(labelName, label + ": " + DoubleToString(price, 2), 10, "Arial", clr);
                
    

    He revisado la documentación y no he encontrado ninguna referencia a ObjectSetText. Sin embargo, cuando empecé a escribir ObjectSet..., aparecieron varias sugerencias, siendo ObjectSetString la mejor opción. Esta función resultó ser la correcta y funcionó como se esperaba.

    Podéis ver nuestros esfuerzos reflejados a continuación.

    ObjectSetText no disponible en la documentación

    ObjectSetText no disponible en la documentación


    ObjectSetString

    ObjectSetString

    ObjectSetString; parámetros de las funciones según la documentación:

    bool  ObjectSetString(
       long                            chart_id,          // chart identifier
       string                          name,              // object name
       ENUM_OBJECT_PROPERTY_STRING     prop_id,           // property
       int                             prop_modifier,     // modifier
       string                          prop_value         // value
       );

    Resolución:

    Realizando los ajustes necesarios, similares a los que hicimos para el primer error, pudimos resolver casi todos los problemas. Ahora sólo quedan unas pocas líneas por corregir. Centrémonos en esos ajustes finales para aclarar por completo los errores restantes.

     ObjectSetString(0, labelName, OBJPROP_TEXT, label + ": " + DoubleToString(price, 2));

    Quedan algunos errores por corregir:

    Faltan 2 errores

    2 errores restantes

    Finalmente, arreglamos los errores restantes:

    ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, price); // Position label at the price level

    Debía ser OBJPROP_YDISTANCE, no OBJPROP_Y..

    Se eliminaron los errores y el programa ahora se compila.

    Depuración exitosa con la referencia a la Documentación

    Nuestro código limpio final está aquí:

    //+------------------------------------------------------------------+
    //|                                               D1 PriceMarker.mq5 |
    //|                                Copyright 2024, Clemence Benjamin |
    //|             https://www.mql5.com/en/users/billionaire2024/seller |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/en/users/billionaire2024/seller"
    #property version   "1.00"
    #property strict
    
    
    // Function to create a price line with a label
    void CreatePriceLine(string name, double price, color clr, string label)
    {
        // Create a horizontal line
        if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price))
        {
            Print("Failed to create line: ", GetLastError());
            return;
        }
        
        // Set line properties
        ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
        ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
    
        // Create a label for the price
        string labelName = name + "_label";
        if(!ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0))
        {
            Print("Failed to create label: ", GetLastError());
            return;
        }
    
        // Set label properties
        ObjectSetInteger(0, labelName, OBJPROP_XSIZE, 70);
        ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
        ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
        ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, price); // Position label at the price level
        ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 5);
        
        // Set the text of the label
        ObjectSetString(0, labelName, OBJPROP_TEXT, label + ": " + DoubleToString(price, 2));
    }
    
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    void OnInit()
    {
        // Get the previous D1 candle's open, high, low, and close prices
        datetime prevCandleTime = iTime(NULL, PERIOD_D1, 1);
        double openPrice = iOpen(NULL, PERIOD_D1, 1);
        double highPrice = iHigh(NULL, PERIOD_D1, 1);
        double lowPrice = iLow(NULL, PERIOD_D1, 1);
        double closePrice = iClose(NULL, PERIOD_D1, 1);
    
        // Draw labeled price lines for open, high, low, and close prices
        CreatePriceLine("PrevCandle_Open", openPrice, clrBlue, "Open");
        CreatePriceLine("PrevCandle_High", highPrice, clrRed, "High");
        CreatePriceLine("PrevCandle_Low", lowPrice, clrGreen, "Low");
        CreatePriceLine("PrevCandle_Close", closePrice, clrOrange, "Close");
    }
    
    //+------------------------------------------------------------------+
    //| Custom indicator deinitialization function                       |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
        // Remove the drawn price lines and labels upon indicator deinitialization
        ObjectDelete(0, "PrevCandle_Open");
        ObjectDelete(0, "PrevCandle_High");
        ObjectDelete(0, "PrevCandle_Low");
        ObjectDelete(0, "PrevCandle_Close");
        ObjectDelete(0, "PrevCandle_Open_label");
        ObjectDelete(0, "PrevCandle_High_label");
        ObjectDelete(0, "PrevCandle_Low_label");
        ObjectDelete(0, "PrevCandle_Close_label");
    }
    
    //+------------------------------------------------------------------+

    D1 PriceMarker, es un programa script MQL5 que diseñamos para mejorar el análisis técnico en un gráfico de operaciones dibujando líneas horizontales en los precios máximo, mínimo, de apertura y cierre de la vela diaria (D1) anterior. Al inicializarse, el script recupera estos cuatro puntos de precio y utiliza una función auxiliar para crear líneas de precios correspondientes en distintos colores (azul para apertura, rojo para alto, verde para bajo y naranja para cierre), cada una acompañada de un texto etiquetado que indica el valor del precio. Cuando se elimina el script del gráfico, se limpia automáticamente eliminando todas las líneas y etiquetas dibujadas, lo que garantiza un espacio de trabajo ordenado para el comerciante.

    2. Depuración con IA:

    Entiendo que todos están ansiosos por aprender cómo utilizamos los modelos de IA disponibles, por lo que abordaré brevemente este tema para guardarlo para una discusión más profunda más adelante. Tenemos la suerte de que la mayoría de estos modelos pueden entender la sintaxis con mayor rapidez y precisión que nosotros. Sin embargo, es importante tener en cuenta que a veces pueden producir resultados inesperados y pueden requerir una supervisión humana más cercana para guiar sus próximos pasos. Sin embargo, son herramientas excelentes cuando se usan sabiamente y he resuelto muchos desafíos de codificación considerando cuidadosamente sus sugerencias.

    Básicamente, al crear un mensaje de IA, debes comenzar proporcionando el programa que quieres depurar. Luego, al utilizar la capacidad de copiar líneas de error del informe de MetaEditor, puede pegar esas líneas en el mensaje, lo que permite que la IA lo ayude con el proceso de depuración. Si bien este método puede producir resultados exitosos, también puede generar más complicaciones, por lo que es esencial pensar de manera crítica y hacer un esfuerzo adicional más allá de lo que sugiere la IA. Los resultados que obtuvimos anteriormente son consistentes con lo que otras herramientas de depuración deberían producir, siempre que se utilicen de manera efectiva.

    Errores de copia

    Copiando errores en indicaciones para IA (AI prompts)

    3. Visitando el foro:

    De manera similar a lo que hicimos anteriormente, los miembros del foro necesitan información para proporcionar información de depuración valiosa. Participar en debates sobre los desafíos de la codificación es una forma fantástica de aprender de otros expertos. Al enviar su programa, invita a otros a compartir sus sabias sugerencias y soluciones. Este enfoque colaborativo no sólo le ayuda a resolver sus problemas, sino que también mejora los conocimientos y las habilidades de todos.

    Programa en MetaTrader 5:

    D1 PriceMarker

    D1 PriceMarker script 


    Conclusión

    El trabajo en equipo en la programación MQL5 demuestra ser una práctica esencial para mejorar el desarrollo de algoritmos de trading robustos, como se ilustra a lo largo de nuestro viaje en la creación del script D1 PriceMarker. El proceso de depuración se basó en gran medida en los informes de errores y en la exhaustiva documentación de referencia de MQL5, lo que nos permitió identificar y resolver sistemáticamente los problemas que surgían durante el desarrollo.

    Este método facilitó la resolución de errores específicos y fomentó una comprensión más profunda del entorno de programación. Además, abordamos brevemente el potencial de aprovechar la inteligencia artificial como ayuda futura en la depuración, destacando su capacidad para brindar información y recomendaciones que podrían agilizar el proceso de depuración.

    El apoyo de la comunidad, especialmente a través del foro MQL5, desempeña un papel inestimable, ya que nos permite buscar consejo y compartir conocimientos con otros desarrolladores experimentados. Al adoptar estos enfoques colaborativos y basados en recursos, podemos mejorar significativamente la eficacia de nuestros esfuerzos de depuración, lo que en última instancia conduce al desarrollo de soluciones comerciales más confiables e innovadoras en el panorama competitivo del comercio algorítmico. ¡Feliz comercio, muchachos!

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

    Archivos adjuntos |
    D1_PriceMarker.mq5 (3.31 KB)
    Clemence Benjamin
    Clemence Benjamin | 13 oct 2024 en 04:52
    Alain Verleyen #:

    Buen artículo para principiantes, un poco prolijo en mi opinión. Algunas observaciones :

    • Deberías decir claramente que cuando tienes una lista de errores, SIEMPRE tienes que empezar a comprobar el primero de la lista. Es la forma más eficaz de tratar los errores y evitar perder tiempo con errores secundarios.
    • Deberías proporcionar la versión "con errores" del "D1_PriceMarker.mq5", para que la gente pueda practicar por sí misma siguiendo tu artículo.

    • Esto es claramente un error lógico, un 'Y_DISTANCE' es un valor entero (posición de pixel en la pantalla) y tu proporcionaste un 'price' doble.
    • Apenas te he visto activo en el foro, ni para preguntar ni para responder.
    • No lo entiendo. ¿Dónde está la "parte colaborativa"? ¿Me he perdido algo?

    Gracias por tu comentario, Alain Verleyen. Aprecio sinceramente tus ideas, sobre todo como moderador, y estoy de acuerdo en que la claridad es esencial, especialmente para los principiantes.

    1. Tienes toda la razón sobre la importancia de abordar el primer error de la lista.
    2. Es una sugerencia excelente. Aunque no incluí el archivo fuente en el artículo, los lectores pueden encontrar y copiar la versión "con errores" del " D1_PriceMarker.mq5 " en este enlace.
    3. Gracias por señalar el error lógico relativo a Y_DISTANCE.
    4. En cuanto al aspecto colaborativo, mi intención era animar a los lectores a interactuar entre sí en los comentarios o en el foro para compartir sus propias experiencias y soluciones de depuración. Trabajaré para mejorar mi visibilidad en el foro.

    Valoro sinceramente vuestras críticas constructivas y vuestro compromiso. Debates como éste son vitales para nuestro crecimiento y mejora colectivos.

    Gerard William G J B M Dinh Sy
    Gerard William G J B M Dinh Sy | 13 oct 2024 en 08:52

    Buenos días

    Lo que los traders de algo pueden no darse cuenta.

    Es que pasarán muy poco tiempo codificando indicadores milagrosos o EAs prodigiosamente rentables.

    La realidad es que principalmente pasarán tiempo corrigiendo, mejorando sus códigos y por lo tanto depurando.

    Si no disponen de herramientas potentes, pasarán rápidamente días, que ya serían buenos, buscando los errores de sus códigos.

    Bazarbay83 Jumaev
    Bazarbay83 Jumaev | 16 may 2025 en 10:05
    Hola a todos ¿qué herramienta os parece más potente?
    Vitaly Muzichenko
    Vitaly Muzichenko | 16 may 2025 en 11:16
    Bazarbay83 Jumaev #:
    Hola a todos ¿qué instrumento consideráis potente?

    Kit de batería.

    Vinicius Pereira De Oliveira
    Vinicius Pereira De Oliveira | 18 ago 2025 en 12:15
    Bazarbay83 Jumaev # Hola a todos, ¿qué herramienta os parece más potente?

    Hola, ¡bienvenido al foro MQL5! Respecto a tu pregunta, no se permiten recomendaciones de productos del mercado. Usted tendrá que hacer su propia investigación. ¡¡¡Mucha suerte!!! 😊

    Redes neuronales en el trading: Modelo hiperbólico de difusión latente (HypDiff) Redes neuronales en el trading: Modelo hiperbólico de difusión latente (HypDiff)
    El artículo estudiará formas de codificar los datos de origen en un espacio latente hiperbólico mediante procesos de difusión anisotrópica. Esto ayudará a preservar con mayor precisión las características topológicas de la situación actual del mercado y mejorará la calidad de su análisis.
    Entrenamos un perceptrón multicapa usando el algoritmo de Levenberg-Marquardt Entrenamos un perceptrón multicapa usando el algoritmo de Levenberg-Marquardt
    Este artículo le presentaremos una implementación del algoritmo Levenberg-Marquardt para el entrenamiento de redes neuronales de propagación directa. Asimismo, realizaremos un análisis comparativo del rendimiento usando algoritmos de la biblioteca scikit-learn Python. También discutiremos preliminarmente los métodos de aprendizaje más sencillos como el descenso de gradiente, el descenso de gradiente con impulso y el descenso de gradiente estocástico.
    Asesores Expertos Auto-Optimizables con MQL5 y Python (Parte V): Modelos profundos de Markov Asesores Expertos Auto-Optimizables con MQL5 y Python (Parte V): Modelos profundos de Markov
    En esta discusión, aplicaremos una cadena de Markov simple en un indicador RSI, para observar cómo se comporta el precio después de que el indicador pasa por niveles clave. Concluimos que las señales de compra y venta más fuertes en el par NZDJPY se generan cuando el RSI está en el rango 11-20 y 71-80, respectivamente. Demostraremos cómo puedes manipular tus datos para crear estrategias comerciales óptimas que se aprenden directamente de los datos que tienes. Además, demostraremos cómo entrenar una red neuronal profunda para aprender a utilizar la matriz de transición de manera óptima.
    Análisis del impacto del clima en las divisas de los países agrícolas usando Python Análisis del impacto del clima en las divisas de los países agrícolas usando Python
    ¿Cómo se relacionan el clima y el mercado de divisas? La teoría económica clásica no ha reconocido durante mucho tiempo la influencia de estos factores en el comportamiento del mercado. Pero ahora las cosas han cambiado. Hoy intentaremos encontrar conexiones entre el estado del tiempo y la posición de las divisas agrarias en el mercado.