
Operar con el Calendario Económico MQL5 (Parte 4): Implementación de actualizaciones de noticias en tiempo real en el panel de control
Introducción
En este artículo continuamos con el desarrollo del panel del Calendario Económico de MetaQuotes Language 5 (MQL5), incorporando actualizaciones en tiempo real que permiten mostrar de forma continua los eventos económicos más relevantes. En el artículo anterior, diseñamos e implementamos un panel de control para filtrar las noticias según la actualidad, la importancia y la hora, lo que nos proporcionó una visión personalizada de los eventos relevantes. Ahora vamos más allá al habilitar actualizaciones en tiempo real, lo que garantiza que nuestro calendario muestre los datos más recientes para tomar decisiones oportunas. Los temas que trataremos incluyen:
Esta mejora transformará nuestro panel de control en una herramienta dinámica y en tiempo real que se actualizará continuamente con los últimos acontecimientos económicos. Al implementar la función de actualización en tiempo real, nos aseguraremos de que nuestro calendario siga siendo preciso y relevante, lo que facilitará la toma de decisiones comerciales oportunas en MetaTrader 5 o en la terminal de operaciones.
Implementación de actualizaciones de noticias en tiempo real en MQL5
Para implementar actualizaciones en tiempo real en nuestro panel de control, debemos asegurarnos de que los eventos de noticias se almacenen y comparen periódicamente para detectar cualquier cambio. Esto requiere mantener matrices para almacenar los datos de eventos actuales y anteriores, lo que nos permite identificar las actualizaciones y reflejarlas con precisión en el panel de control. De este modo, podemos garantizar que el panel de control se ajuste dinámicamente para mostrar los acontecimientos económicos más recientes en tiempo real. A continuación, definimos las matrices que utilizaremos para este fin:
string current_eventNames_data[]; string previous_eventNames_data[];
Aquí definimos dos matrices string, «current_eventNames_data» y «previous_eventNames_data», que utilizaremos para gestionar y comparar datos de eventos económicos para actualizaciones en tiempo real del panel de control. La matriz «current_eventNames_data» almacenará los últimos eventos recuperados del calendario económico, mientras que «previous_eventNames_data» contendrá los datos del último ciclo de actualización. Al comparar estas dos matrices, podemos identificar cualquier cambio o nueva incorporación a los eventos, lo que nos permite actualizar el panel de control de forma dinámica.
Utilizando estas matrices, tendremos que obtener los valores actuales de cada evento seleccionado en la sección de inicialización y almacenarlos en la matriz de datos actual, para luego copiarlos en la matriz anterior, que utilizaremos para realizar la comparación en el siguiente tick de precios.
ArrayResize(current_eventNames_data,ArraySize(current_eventNames_data)+1); current_eventNames_data[ArraySize(current_eventNames_data)-1] = event.name;
Aquí, ampliamos dinámicamente la matriz «current_eventNames_data» y le añadimos un nuevo nombre de evento. Utilizamos la función ArrayResize para aumentar el tamaño de la matriz en uno, creando espacio para una nueva entrada. Después de cambiar el tamaño, asignamos el nombre del evento al último índice de la matriz utilizando la expresión «current_eventNames_data[ArraySize(current_eventNames_data)-1]». Este proceso garantiza que cada nuevo nombre de evento recuperado del calendario económico se almacene en la matriz, lo que nos permite mantener una lista actualizada de eventos para su posterior procesamiento y comparación.
Sin embargo, antes de añadir los eventos a la matriz, debemos asegurarnos de empezar desde cero, lo que significa que necesitamos una matriz vacía.
ArrayFree(current_eventNames_data);
Aquí utilizamos la función ArrayFree para borrar todos los elementos de la matriz «current_eventNames_data», restableciéndola efectivamente a un estado vacío. Esto es esencial para garantizar que la matriz no conserve datos obsoletos de iteraciones anteriores, preparándola así para almacenar un nuevo conjunto de nombres de eventos durante el ciclo de procesamiento. Después de rellenar la matriz, debemos copiarla en el contenedor anterior y utilizarla más tarde para realizar la comparación.
Print("CURRENT EVENT NAMES DATA SIZE = ",ArraySize(current_eventNames_data)); ArrayPrint(current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (Before) = ",ArraySize(previous_eventNames_data)); ArrayCopy(previous_eventNames_data,current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (After) = ",ArraySize(previous_eventNames_data)); ArrayPrint(previous_eventNames_data);
Aquí registramos y gestionamos la transición de datos entre las matrices «current_eventNames_data» y «previous_eventNames_data». En primer lugar, utilizamos la función Print para mostrar el tamaño de la matriz «current_eventNames_data», lo que permite ver el número de nombres de eventos almacenados en ese momento. A continuación, llamamos a la función ArrayPrint para mostrar el contenido de la matriz y poder verificarlo. A continuación, registramos el tamaño de la matriz «previous_eventNames_data» antes de copiarla, lo que nos proporciona una referencia para la comparación.
Utilizando la función ArrayCopy, copiamos el contenido de «current_eventNames_data» en «previous_eventNames_data», transfiriendo de forma eficaz los nombres de los eventos más recientes para futuras comparaciones. A continuación, imprimimos el tamaño de la matriz «previous_eventNames_data» tras la operación de copia para confirmar que la actualización se ha realizado correctamente. Por último, llamamos a la función ArrayPrint para generar el contenido actualizado de «previous_eventNames_data», asegurándonos de que la transferencia de datos sea precisa y completa. Esos son los cambios que necesitamos en el controlador de eventos OnInit para almacenar los eventos iniciales. Para mayor claridad, vamos a resaltarlos.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(){ //--- ArrayFree(current_eventNames_data); //--- Loop through each calendar value up to the maximum defined total for (int i = 0; i < valuesTotal; i++){ //--- //--- Loop through calendar data columns for (int k=0; k<ArraySize(array_calendar); k++){ //--- //--- Prepare news data array with time, country, and other event details string news_data[ArraySize(array_calendar)]; news_data[0] = TimeToString(values[i].time,TIME_DATE); //--- Event date news_data[1] = TimeToString(values[i].time,TIME_MINUTES); //--- Event time news_data[2] = country.currency; //--- Event country currency //--- Determine importance color based on event impact color importance_color = clrBlack; if (event.importance == CALENDAR_IMPORTANCE_LOW){importance_color=clrYellow;} else if (event.importance == CALENDAR_IMPORTANCE_MODERATE){importance_color=clrOrange;} else if (event.importance == CALENDAR_IMPORTANCE_HIGH){importance_color=clrRed;} //--- Set importance symbol for the event news_data[3] = ShortToString(0x25CF); //--- Set event name in the data array news_data[4] = event.name; //--- Populate actual, forecast, and previous values in the news data array news_data[5] = DoubleToString(value.GetActualValue(),3); news_data[6] = DoubleToString(value.GetForecastValue(),3); news_data[7] = DoubleToString(value.GetPreviousValue(),3); //--- } ArrayResize(current_eventNames_data,ArraySize(current_eventNames_data)+1); current_eventNames_data[ArraySize(current_eventNames_data)-1] = event.name; } Print("CURRENT EVENT NAMES DATA SIZE = ",ArraySize(current_eventNames_data)); ArrayPrint(current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (Before) = ",ArraySize(previous_eventNames_data)); ArrayCopy(previous_eventNames_data,current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (After) = ",ArraySize(previous_eventNames_data)); ArrayPrint(previous_eventNames_data); //Print("Final News = ",news_filter_count); updateLabel(TIME_LABEL,"Server Time: "+TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS)+" ||| Total News: "+ IntegerToString(news_filter_count)+"/"+IntegerToString(allValues)); //--- return(INIT_SUCCEEDED); }
Aquí, solo hemos realizado los cambios que nos ayudarán a obtener los datos iniciales del evento. Los hemos resaltado en color amarillo para mayor claridad. A continuación, solo tenemos que actualizar los valores del panel de control cuando se detecten cambios durante la comparación. Para ello, crearemos una función personalizada que contendrá toda la lógica para las actualizaciones de eventos y el recálculo del panel de control, respectivamente.
//+------------------------------------------------------------------+ //| Function to update dashboard values | //+------------------------------------------------------------------+ void update_dashboard_values(){ //--- }
Aquí definimos la función «update_dashboard_values», que utilizaremos para gestionar la actualización dinámica del panel del calendario económico. Esta función contendrá la lógica central para comparar los datos de noticias almacenados, identificar cualquier cambio y aplicar las actualizaciones necesarias a la interfaz del panel de control. Al organizar esta funcionalidad en esta función dedicada, garantizaremos una estructura de código limpia y modular, lo que facilitará la gestión de futuras modificaciones o mejoras. A continuación, llamaremos a la función en el controlador de eventos OnTick de la siguiente manera.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick(){ //--- update_dashboard_values(); }
Aquí, simplemente llamamos a la función personalizada en cada tick para realizar las actualizaciones. Tras compilar y ejecutar el programa, obtenemos los siguientes resultados:
En la imagen, podemos ver que recopilamos todas las noticias en la matriz «actual», que luego copiamos en la nueva matriz «anterior» para su almacenamiento, lo que se ajusta perfectamente a lo que queremos. Ahora podemos proceder a utilizar estos datos copiados para realizar análisis adicionales. En la función, simplemente obtenemos los eventos actuales de la siguiente manera:
//--- Declare variables for tracking news events and status int totalNews = 0; bool isNews = false; MqlCalendarValue values[]; //--- Array to store calendar values //--- Define start and end time for calendar event retrieval datetime startTime = TimeTradeServer() - PeriodSeconds(PERIOD_H12); datetime endTime = TimeTradeServer() + PeriodSeconds(PERIOD_H12); //--- Set a specific country code filter (e.g., "US" for USD) string country_code = "US"; string currency_base = SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE); //--- Retrieve historical calendar values within the specified time range int allValues = CalendarValueHistory(values,startTime,endTime,NULL,NULL); //--- Print the total number of values retrieved and the array size //Print("TOTAL VALUES = ",allValues," || Array size = ",ArraySize(values)); //--- Define time range for filtering news events based on daily period datetime timeRange = PeriodSeconds(PERIOD_D1); datetime timeBefore = TimeTradeServer() - timeRange; datetime timeAfter = TimeTradeServer() + timeRange; //--- Print the furthest time look-back and current server time //Print("FURTHEST TIME LOOK BACK = ",timeBefore," >>> CURRENT = ",TimeTradeServer()); //--- Limit the total number of values to display int valuesTotal = (allValues <= 11) ? allValues : 11; string curr_filter[] = {"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD"}; int news_filter_count = 0; ArrayFree(current_eventNames_data); // Define the levels of importance to filter (low, moderate, high) ENUM_CALENDAR_EVENT_IMPORTANCE allowed_importance_levels[] = {CALENDAR_IMPORTANCE_LOW, CALENDAR_IMPORTANCE_MODERATE, CALENDAR_IMPORTANCE_HIGH}; //--- Loop through each calendar value up to the maximum defined total for (int i = 0; i < valuesTotal; i++){ MqlCalendarEvent event; //--- Declare event structure CalendarEventById(values[i].event_id,event); //--- Retrieve event details by ID MqlCalendarCountry country; //--- Declare country structure CalendarCountryById(event.country_id,country); //--- Retrieve country details by event's country ID MqlCalendarValue value; //--- Declare calendar value structure CalendarValueById(values[i].id,value); //--- Retrieve actual, forecast, and previous values //--- Check if the event’s currency matches any in the filter array (if the filter is enabled) bool currencyMatch = false; if (enableCurrencyFilter) { for (int j = 0; j < ArraySize(curr_filter); j++) { if (country.currency == curr_filter[j]) { currencyMatch = true; break; } } //--- If no match found, skip to the next event if (!currencyMatch) { continue; } } //--- Check importance level if importance filter is enabled bool importanceMatch = false; if (enableImportanceFilter) { for (int k = 0; k < ArraySize(allowed_importance_levels); k++) { if (event.importance == allowed_importance_levels[k]) { importanceMatch = true; break; } } //--- If importance does not match the filter criteria, skip the event if (!importanceMatch) { continue; } } //--- Apply time filter and set timeMatch flag (if the filter is enabled) bool timeMatch = false; if (enableTimeFilter) { datetime eventTime = values[i].time; if (eventTime <= TimeTradeServer() && eventTime >= timeBefore) { timeMatch = true; //--- Event is already released } else if (eventTime >= TimeTradeServer() && eventTime <= timeAfter) { timeMatch = true; //--- Event is yet to be released } //--- Skip if the event doesn't match the time filter if (!timeMatch) { continue; } } //--- If we reach here, the currency matches the filter news_filter_count++; //--- Increment the count of filtered events //--- Set alternating colors for each data row holder color holder_color = (news_filter_count % 2 == 0) ? C'213,227,207' : clrWhite; //--- Loop through calendar data columns for (int k=0; k<ArraySize(array_calendar); k++){ //--- Print event details for debugging //Print("Name = ",event.name,", IMP = ",EnumToString(event.importance),", COUNTRY = ",country.name,", TIME = ",values[i].time); //--- Skip event if currency does not match the selected country code // if (StringFind(_Symbol,country.currency) < 0) continue; //--- Prepare news data array with time, country, and other event details string news_data[ArraySize(array_calendar)]; news_data[0] = TimeToString(values[i].time,TIME_DATE); //--- Event date news_data[1] = TimeToString(values[i].time,TIME_MINUTES); //--- Event time news_data[2] = country.currency; //--- Event country currency //--- Determine importance color based on event impact color importance_color = clrBlack; if (event.importance == CALENDAR_IMPORTANCE_LOW){importance_color=clrYellow;} else if (event.importance == CALENDAR_IMPORTANCE_MODERATE){importance_color=clrOrange;} else if (event.importance == CALENDAR_IMPORTANCE_HIGH){importance_color=clrRed;} //--- Set importance symbol for the event news_data[3] = ShortToString(0x25CF); //--- Set event name in the data array news_data[4] = event.name; //--- Populate actual, forecast, and previous values in the news data array news_data[5] = DoubleToString(value.GetActualValue(),3); news_data[6] = DoubleToString(value.GetForecastValue(),3); news_data[7] = DoubleToString(value.GetPreviousValue(),3); } ArrayResize(current_eventNames_data,ArraySize(current_eventNames_data)+1); current_eventNames_data[ArraySize(current_eventNames_data)-1] = event.name; } //Print("Final News = ",news_filter_count); updateLabel(TIME_LABEL,"Server Time: "+TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS)+" ||| Total News: "+ IntegerToString(news_filter_count)+"/"+IntegerToString(allValues));
Este es solo el fragmento de código anterior que utilizamos durante la sección de inicialización, pero lo necesitamos en cada tick para obtener las actualizaciones. Sin embargo, lo repasaremos brevemente. Nos centramos en actualizar dinámicamente el panel de control con las últimas noticias económicas en cada tick y, para lograrlo, optimizamos la lógica eliminando la creación de objetos gráficos y, en su lugar, nos concentramos en gestionar los datos de los eventos de manera eficiente. Comenzamos definiendo variables para realizar un seguimiento del recuento total de noticias y filtrar criterios como la moneda, la importancia y los intervalos de tiempo. Estos filtros garantizan que solo se tengan en cuenta los eventos relevantes para su posterior procesamiento.
Recorremos los valores del calendario recuperados, aplicando los filtros para identificar los eventos que coinciden con las condiciones especificadas. Para cada evento coincidente, extraemos detalles clave como el nombre del evento, la hora, la moneda y el nivel de importancia. Estos detalles se almacenan en la matriz «current_eventNames_data», cuyo tamaño se modifica dinámicamente para dar cabida a nuevas entradas. Esta matriz es crucial para el seguimiento de los eventos y nos permite identificar los cambios entre los ticks comparándolos con los datos anteriores. Por último, actualizamos la etiqueta del panel para reflejar el total de eventos filtrados y la hora actual del servidor, lo que garantiza que el panel siempre refleje los datos de eventos más recientes sin crear objetos innecesarios. Este enfoque captura y actualiza de manera eficiente la información sobre noticias económicas en tiempo real.
A continuación, debemos realizar un seguimiento de si se producen cambios en las matrices de almacenamiento utilizando los datos recién adquiridos. Para ello, utilizamos una función personalizada.
//+------------------------------------------------------------------+ //| Function to compare two string arrays and detect changes | //+------------------------------------------------------------------+ bool isChangeInStringArrays(string &arr1[], string &arr2[]) { bool isChange = false; int size1 = ArraySize(arr1); // Get the size of the first array int size2 = ArraySize(arr2); // Get the size of the second array // Check if sizes are different if (size1 != size2) { Print("Arrays have different sizes. Size of Array 1: ", size1, ", Size of Array 2: ", size2); isChange = true; return (isChange); } // Loop through the arrays and compare corresponding elements for (int i = 0; i < size1; i++) { // Compare the strings at the same index in both arrays if (StringCompare(arr1[i], arr2[i]) != 0) { // If strings are different // Action when strings differ at the same index Print("Change detected at index ", i, ": '", arr1[i], "' vs '", arr2[i], "'"); isChange = true; return (isChange); } } // If no differences are found, you can also log this as no changes detected //Print("No changes detected between arrays."); return (isChange); }
Aquí definimos la función booleana «isChangeInStringArrays», que compara dos matrices de cadenas, «arr1» y «arr2», para detectar cualquier cambio entre ellas. Comenzamos determinando los tamaños de ambas matrices utilizando la función ArraySize y almacenamos estos tamaños en «size1» y «size2». Si los tamaños de las matrices difieren, imprimimos los tamaños respectivos, establecemos el indicador «isChange» en verdadero y devolvemos verdadero, lo que indica un cambio. Si los tamaños son iguales, procedemos a comparar los elementos de las matrices utilizando un bucle for. Para cada índice, utilizamos la función StringCompare para comprobar si las cadenas (strings) de ambos matrices son idénticas. Si alguna cadena difiere, imprimimos los detalles del cambio y establecemos «isChange» en verdadero, devolviendo verdadero para indicar la actualización. Si no se encuentran diferencias después del bucle, la función devuelve falso, lo que indica que no hay cambios. Este enfoque es esencial para detectar actualizaciones, como noticias nuevas o actualizadas, que debemos reflejar en el panel de control.
Una vez que contamos con la función, podemos utilizarla para actualizar los eventos.
if (isChangeInStringArrays(previous_eventNames_data,current_eventNames_data)){ Print("CHANGES IN EVENT NAMES DETECTED. UPDATE THE DASHBOARD VALUES"); ObjectsDeleteAll(0,DATA_HOLDERS); ObjectsDeleteAll(0,ARRAY_NEWS); ArrayFree(current_eventNames_data); //--- }
Aquí, comprobamos si ha habido algún cambio entre las matrices «previous_eventNames_data» y «current_eventNames_data» llamando a la función «isChangeInStringArrays». Si la función devuelve verdadero, lo que indica que se han detectado cambios, imprimimos el mensaje «CHANGES IN EVENT NAMES DETECTED. UPDATE THE DASHBOARD VALUES». A continuación, eliminamos todos los objetos relacionados con los contenedores de datos y las matrices de noticias del gráfico utilizando la función ObjectsDeleteAll, especificando los identificadores «DATA_HOLDERS» y «ARRAY_NEWS» como prefijos de los objetos. Hacemos esto para eliminar cualquier información obsoleta antes de actualizar el panel de control con los datos más recientes del evento. Por último, liberamos la memoria utilizada por la matriz «current_eventNames_data» utilizando la función ArrayFree, asegurándonos de que la matriz se borra en preparación para la próxima actualización. A continuación, actualizamos los datos de los eventos como de costumbre, pero esta vez creamos los contenedores de datos y actualizamos los eventos de noticias en el nuevo panel de control. Esta es la lógica:
if (isChangeInStringArrays(previous_eventNames_data,current_eventNames_data)){ Print("CHANGES IN EVENT NAMES DETECTED. UPDATE THE DASHBOARD VALUES"); ObjectsDeleteAll(0,DATA_HOLDERS); ObjectsDeleteAll(0,ARRAY_NEWS); ArrayFree(current_eventNames_data); //--- Initialize starting y-coordinate for displaying news data int startY = 162; //--- Loop through each calendar value up to the maximum defined total for (int i = 0; i < valuesTotal; i++){ MqlCalendarEvent event; //--- Declare event structure CalendarEventById(values[i].event_id,event); //--- Retrieve event details by ID MqlCalendarCountry country; //--- Declare country structure CalendarCountryById(event.country_id,country); //--- Retrieve country details by event's country ID MqlCalendarValue value; //--- Declare calendar value structure CalendarValueById(values[i].id,value); //--- Retrieve actual, forecast, and previous values //--- Check if the event’s currency matches any in the filter array (if the filter is enabled) bool currencyMatch = false; if (enableCurrencyFilter) { for (int j = 0; j < ArraySize(curr_filter); j++) { if (country.currency == curr_filter[j]) { currencyMatch = true; break; } } //--- If no match found, skip to the next event if (!currencyMatch) { continue; } } //--- Check importance level if importance filter is enabled bool importanceMatch = false; if (enableImportanceFilter) { for (int k = 0; k < ArraySize(allowed_importance_levels); k++) { if (event.importance == allowed_importance_levels[k]) { importanceMatch = true; break; } } //--- If importance does not match the filter criteria, skip the event if (!importanceMatch) { continue; } } //--- Apply time filter and set timeMatch flag (if the filter is enabled) bool timeMatch = false; if (enableTimeFilter) { datetime eventTime = values[i].time; if (eventTime <= TimeTradeServer() && eventTime >= timeBefore) { timeMatch = true; //--- Event is already released } else if (eventTime >= TimeTradeServer() && eventTime <= timeAfter) { timeMatch = true; //--- Event is yet to be released } //--- Skip if the event doesn't match the time filter if (!timeMatch) { continue; } } //--- If we reach here, the currency matches the filter news_filter_count++; //--- Increment the count of filtered events //--- Set alternating colors for each data row holder color holder_color = (news_filter_count % 2 == 0) ? C'213,227,207' : clrWhite; //--- Create rectangle label for each data row holder createRecLabel(DATA_HOLDERS+string(news_filter_count),62,startY-1,716,26+1,holder_color,1,clrNONE); //--- Initialize starting x-coordinate for each data entry int startX = 65; //--- Loop through calendar data columns for (int k=0; k<ArraySize(array_calendar); k++){ //--- Print event details for debugging //Print("Name = ",event.name,", IMP = ",EnumToString(event.importance),", COUNTRY = ",country.name,", TIME = ",values[i].time); //--- Skip event if currency does not match the selected country code // if (StringFind(_Symbol,country.currency) < 0) continue; //--- Prepare news data array with time, country, and other event details string news_data[ArraySize(array_calendar)]; news_data[0] = TimeToString(values[i].time,TIME_DATE); //--- Event date news_data[1] = TimeToString(values[i].time,TIME_MINUTES); //--- Event time news_data[2] = country.currency; //--- Event country currency //--- Determine importance color based on event impact color importance_color = clrBlack; if (event.importance == CALENDAR_IMPORTANCE_LOW){importance_color=clrYellow;} else if (event.importance == CALENDAR_IMPORTANCE_MODERATE){importance_color=clrOrange;} else if (event.importance == CALENDAR_IMPORTANCE_HIGH){importance_color=clrRed;} //--- Set importance symbol for the event news_data[3] = ShortToString(0x25CF); //--- Set event name in the data array news_data[4] = event.name; //--- Populate actual, forecast, and previous values in the news data array news_data[5] = DoubleToString(value.GetActualValue(),3); news_data[6] = DoubleToString(value.GetForecastValue(),3); news_data[7] = DoubleToString(value.GetPreviousValue(),3); //--- Create label for each news data item if (k == 3){ createLabel(ARRAY_NEWS+IntegerToString(i)+" "+array_calendar[k],startX,startY-(22-12),news_data[k],importance_color,22,"Calibri"); } else { createLabel(ARRAY_NEWS+IntegerToString(i)+" "+array_calendar[k],startX,startY,news_data[k],clrBlack,12,"Calibri"); } //--- Increment x-coordinate for the next column startX += buttons[k]+3; } ArrayResize(current_eventNames_data,ArraySize(current_eventNames_data)+1); current_eventNames_data[ArraySize(current_eventNames_data)-1] = event.name; //--- Increment y-coordinate for the next row of data startY += 25; //Print(startY); //--- Print current y-coordinate for debugging } Print("CURRENT EVENT NAMES DATA SIZE = ",ArraySize(current_eventNames_data)); ArrayPrint(current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (Before) = ",ArraySize(previous_eventNames_data)); ArrayPrint(previous_eventNames_data); ArrayFree(previous_eventNames_data); ArrayCopy(previous_eventNames_data,current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (After) = ",ArraySize(previous_eventNames_data)); ArrayPrint(previous_eventNames_data); }
Aquí actualizamos el panel de control basándonos en los datos recién adquiridos para garantizar que las actualizaciones en tiempo real surtan efecto. Utilizando la lógica de copia, registramos los datos en el contenedor de datos «anterior» para poder utilizar los datos actuales en la siguiente comprobación. Hemos destacado la lógica que se encarga de eso, pero analicémosla más a fondo.
Print("CURRENT EVENT NAMES DATA SIZE = ",ArraySize(current_eventNames_data)); ArrayPrint(current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (Before) = ",ArraySize(previous_eventNames_data)); ArrayPrint(previous_eventNames_data); ArrayFree(previous_eventNames_data); ArrayCopy(previous_eventNames_data,current_eventNames_data); Print("PREVIOUS EVENT NAMES DATA SIZE (After) = ",ArraySize(previous_eventNames_data)); ArrayPrint(previous_eventNames_data);
Aquí, comenzamos imprimiendo el tamaño actual de la matriz «current_eventNames_data» utilizando la función ArraySize y mostrando su contenido con la función ArrayPrint. Esto nos ayudará a inspeccionar el conjunto actual de nombres de eventos que estamos rastreando. A continuación, imprimimos el tamaño de la matriz «previous_eventNames_data» antes de que se actualice, seguido de la impresión de su contenido.
A continuación, liberamos la memoria utilizada por «previous_eventNames_data» con la función ArrayFree, asegurándonos de que se borren todos los datos anteriores almacenados en la matriz para evitar problemas de memoria. Después de liberar la memoria, utilizamos la función ArrayCopy para copiar el contenido de la matriz «current_eventNames_data» en «previous_eventNames_data», actualizándola efectivamente con los nombres de los eventos más recientes.
Por último, imprimimos el tamaño actualizado de la matriz «previous_eventNames_data» y su contenido para confirmar que la matriz ahora contiene los nombres de los eventos más recientes. Esto garantiza que los nombres de los eventos anteriores se actualicen correctamente para futuras comparaciones. Al ejecutar el programa, obtenemos el siguiente resultado.
Actualizaciones de tiempo.
Actualización de eventos.
Actualización del panel de control.
En la imagen podemos ver que los datos recién registrados se actualizan con precisión en el panel de control. Para reconfirmar esto, podemos esperar nuevamente un tiempo e intentar ver si podemos realizar un seguimiento de estos datos, y con el que registra los datos actualizados. Aquí está el resultado.
Actualización de datos de eventos.
Actualización del panel de control.
En la imagen podemos ver que, una vez que se producen cambios con respecto a los datos almacenados anteriormente, estos se detectan y actualizan de acuerdo con los datos recién registrados y se almacenan para su futura consulta. Los datos almacenados se utilizan para actualizar la interfaz del panel de control en tiempo real, mostrando las noticias de actualidad y confirmando así el éxito de nuestro objetivo.
Conclusión
En conclusión, hemos implementado un sistema robusto para supervisar y detectar cambios en los eventos del Calendario económico de MQL5 comparando los datos de eventos almacenados previamente con las actualizaciones recién recuperadas. Este mecanismo de comparación garantiza que cualquier diferencia en los nombres o detalles de los eventos se identifique rápidamente, lo que activa la actualización de nuestro panel de control para mantener la precisión y la relevancia. Al filtrar los datos según la moneda, la importancia y el tiempo, perfeccionamos aún más el proceso para centrarnos en los eventos más impactantes, al tiempo que actualizamos dinámicamente la interfaz.
En las próximas partes de esta serie, partiremos de esta base para integrar las noticias económicas en las estrategias de negociación, lo que permitirá aplicaciones prácticas de los datos. Además, nuestro objetivo es mejorar la funcionalidad del panel de control introduciendo movilidad y capacidad de respuesta, lo que garantizará una experiencia más fluida e interactiva para los operadores. Manténgase al tanto.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/16386
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Los usuarios probablemente estarán interesados en saber que los mismos temas se han cubierto a fondo en el libro de algotrading (y el sitio no muestra esto de alguna manera en las sugerencias automáticas), incluyendo el seguimiento y guardado de los cambios de eventos, filtrado de eventos por múltiples condiciones (con diferentes operadores lógicos) para el conjunto ampliado de campos, la visualización personalizable sobre la marcha subconjunto calendario en un panel en el gráfico, y la incrustación para el comercio en EAs con el apoyo de la transferencia de archivo completo del calendario en el probador.