English Русский 中文 Deutsch 日本語 Português
preview
Operar con el Calendario Económico MQL5 (Parte 1): Dominar las funciones del Calendario Económico MQL5

Operar con el Calendario Económico MQL5 (Parte 1): Dominar las funciones del Calendario Económico MQL5

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

Introducción

En este artículo, exploramos las potentes funciones del calendario económico de MetaQuotes Language 5 (MQL5) y cómo se pueden integrar en el trading algorítmico. El Calendario económico, incorporado en la terminal de operaciones MetaTrader 5, es una herramienta fundamental para los operadores, ya que proporciona noticias y datos esenciales que pueden influir significativamente en los movimientos del mercado. Al comprender cómo recuperar e interpretar esta información, podemos obtener una ventaja a la hora de pronosticar las reacciones del mercado ante los acontecimientos económicos y ajustar nuestras estrategias comerciales en consecuencia.

Comenzaremos con una descripción general del Calendario Económico MQL5, cubriendo sus componentes clave y cómo funciona. A continuación, nos centraremos en la implementación en MQL5, demostrando cómo acceder y mostrar eventos de noticias en el gráfico mediante programación. Finalmente, concluiremos resumiendo los conocimientos adquiridos y los beneficios de incorporar el Calendario Económico a los sistemas de trading. A continuación se muestran los subtemas en los que cubriremos el artículo:

  1. Descripción general del calendario económico MQL5
  2. Implementación en MQL5
  3. Conclusión

Al finalizar este artículo, usted tendrá el conocimiento para desarrollar un Asesor Experto MQL5 que utilice eficazmente el calendario económico MQL5 en sus estrategias comerciales. Empecemos.


Descripción general del calendario económico MQL5

El Calendario Económico MQL5 es una excelente herramienta que proporciona a los traders información actual y coherente sobre los eventos económicos clave capaces de tener un impacto significativo en los mercados financieros. Es una herramienta útil que es aún más accesible porque está integrada en la plataforma MetaTrader 5.

El calendario económico proporciona una buena visión general de los diversos eventos futuros que podrían afectar a los mercados financieros. Muestra todo, desde las fechas de toma de decisiones sobre los tipos de interés, los informes sobre la inflación y las cifras del Producto Interior Bruto (PIB) hasta las estadísticas de empleo y mucho más. Dado que cada uno de estos factores puede influir de manera significativa en los mercados, especialmente en las divisas, las materias primas y las acciones, el calendario es una herramienta imprescindible tanto para los operadores a corto como a largo plazo.

Para abrir el calendario, vaya a la barra de tareas y seleccione «Ver», luego «Caja de herramientas». A continuación se muestra una ilustración.

APERTURA DE LA CAJA DE HERRAMIENTAS

Una vez abierta la ventana de la caja de herramientas, vaya a la pestaña «Calendario» y haga clic en ella. Esto abrirá la ventana del calendario, que debería mostrar la imagen que aparece a continuación.

APERTURA DEL CALENDARIO

Ahora bien, cabe destacar que el Calendario económico MQL5 muestra de forma ordenada los próximos eventos relevantes para los mercados, clasificados según su impacto previsto. Caracteriza a cada uno con una etiqueta clara y sin ambigüedades de «bajo», «medio» o «alto» según su nivel de influencia potencial. Por lo tanto, es muy fácil deducir rápidamente del calendario qué eventos próximos son muy importantes y cuáles no lo son. El calendario también filtra muy bien los eventos según su relevancia monetaria. Aunque los eventos están organizados y codificados por colores según su relevancia, no hay tantos como para que un comerciante pueda sentirse abrumado al intentar tenerlos todos en cuenta. De esta forma, el mecanismo de filtrado garantiza que los traders no se vean abrumados con datos irrelevantes, lo que les permite centrarse en noticias que podrían afectar directamente sus posiciones abiertas o estrategias comerciales.

Una de las principales ventajas del Calendario Económico MQL5 es su integración con MQL5, que permite a los traders acceder programáticamente a datos económicos e incorporarlos a sus Asesores Expertos (EA) o sistemas de trading automatizados. Utilizando sus funciones predefinidas, podemos recuperar datos como el nombre del evento, la hora programada, el país y el valor previsto o real. Esta funcionalidad permite a los traders desarrollar sistemas que reaccionan automáticamente a eventos noticiosos importantes, ya sea cerrar posiciones para evitar la volatilidad, abrir operaciones basadas en pronósticos o ajustar los niveles de stop-loss y take-profit. Este nivel de automatización garantiza que las estrategias comerciales siempre respondan a los últimos desarrollos económicos, sin necesidad de intervención manual. Para resumir las funcionalidades clave del Calendario Económico MQL5, aquí hay una representación visual detallada.

DATOS DEL CALENDARIO

En la imagen, podemos ver que hay 8 columnas de representación de datos. El primero contiene la hora del evento, el segundo contiene el símbolo de la moneda, el tercero contiene el nombre del evento, el cuarto contiene el nivel de prioridad o importancia de los datos de noticias, el quinto contiene el período de datos, mientras que el sexto, séptimo y octavo contienen los datos reales, pronosticados y anteriores o revisados respectivamente.

Por supuesto, no todos los datos son de gran importancia para un comerciante, por lo que se pueden filtrar los datos no necesarios de cuatro maneras. Una es por tiempo, por ejemplo cuando a uno no le interesan los datos ya publicados. La segunda forma es filtrar por moneda y la tercera es por país. Uno podría estar negociando el par "AUDUSD" y, por lo tanto, la noticia que tiene mayor impacto es la que afecta directamente a Australia o a los Estados Unidos. Por lo tanto, las noticias en China no tienen ningún efecto significativo en el par.

Por último, está el filtro de importancia o prioridad el que ayuda a ordenar las noticias en niveles de impacto. Para aplicar cualquiera de los filtros, simplemente haga clic derecho dentro del campo del calendario y aplique el filtro según corresponda. Esto se ilustra nuevamente a continuación.

APLICACIÓN DEL FILTRO

De este modo, al utilizar el Calendario Económico MQL5, los traders pueden formular mejor sus planes comerciales antes de eventos influyentes del mercado. Pueden hacerlo consultando el calendario manualmente en MetaTrader 5 o mediante estrategias de trading automatizadas que actúen sobre los datos del calendario. Esta configuración prepara el camino para comprender claramente el Calendario Económico MQL5 y para descubrir cómo ponerlo a funcionar dentro del sistema de trading MetaTrader 5 con el fin de tener operaciones más claras y una estrategia comercial más clara.


Implementación en MQL5

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

METAEDITOR ABIERTO

Una vez abierto el MetaEditor, en la barra de herramientas, vaya a la pestaña Archivo y marque Nuevo archivo, o simplemente presione CTRL + N, para crear un nuevo documento. Alternativamente, puede hacer clic en el icono Nuevo en la pestaña de herramientas. Esto generará una ventana emergente del Asistente MQL.

CREAR NUEVO EA

En el asistente que aparece, marque Asesor experto (plantilla) y haga clic en Siguiente.

Asistente MQL

En las propiedades generales del Asesor Experto, en la sección de nombre, proporcione el nombre de archivo de su experto. Tenga en cuenta que para especificar o crear una carpeta si no existe, utilice 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 puedes seguir el enlace en la parte inferior del Asistente para saber cómo realizar el proceso con precisión.

NUEVO NOMBRE DE EA

Después de proporcionar el nombre de archivo del Asesor Experto deseado, haga clic en Siguiente, luego en Siguiente y, por último, en Finalizar. Después de hacer todo esto, ahora estamos listos para codificar y programar nuestra estrategia.

Primero, comenzamos definiendo algunos metadatos sobre el Asesor Experto (EA). Esto incluye el nombre del EA, la información de derechos de autor y un enlace al sitio web de MetaQuotes. También especificamos la versión del EA, que se establece en "1.00".

//+------------------------------------------------------------------+
//|                                    MQL5 NEWS CALENDAR PART 1.mq5 |
//|      Copyright 2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader. |
//|                                     https://forexalgo-trader.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader"
#property link      "https://forexalgo-trader.com"
#property description "MQL5 NEWS CALENDAR PART 1"
#property version   "1.00"

En este punto, lo primero que debemos hacer es entender las estructuras para trabajar con el calendario económico. Hay tres: MqlCalendarCountry, que establece las descripciones de los países; MqlCalendarEvent, que establece las descripciones de los eventos, y MqlCalendarValue, que establece los valores de los eventos. Sus métodos de estructura son los siguientes.

Estructura del calendario por países:

struct MqlCalendarCountry 
  { 
   ulong                               id;                    // country ID (ISO 3166-1) 
   string                              name;                  // country text name (in the current terminal encoding) 
   string                              code;                  // country code name (ISO 3166-1 alpha-2) 
   string                              currency;              // country currency code 
   string                              currency_symbol;       // country currency symbol 
   string                              url_name;              // country name used in the mql5.com website URL 
  };

Estructura de eventos del calendario:

struct MqlCalendarEvent 
  { 
   ulong                               id;                    // event ID 
   ENUM_CALENDAR_EVENT_TYPE            type;                  // event type from the ENUM_CALENDAR_EVENT_TYPE enumeration 
   ENUM_CALENDAR_EVENT_SECTOR          sector;                // sector an event is related to 
   ENUM_CALENDAR_EVENT_FREQUENCY       frequency;             // event frequency 
   ENUM_CALENDAR_EVENT_TIMEMODE        time_mode;             // event time mode 
   ulong                               country_id;            // country ID 
   ENUM_CALENDAR_EVENT_UNIT            unit;                  // economic indicator value's unit of measure 
   ENUM_CALENDAR_EVENT_IMPORTANCE      importance;            // event importance 
   ENUM_CALENDAR_EVENT_MULTIPLIER      multiplier;            // economic indicator value multiplier 
   uint                                digits;                // number of decimal places 
   string                              source_url;            // URL of a source where an event is published 
   string                              event_code;            // event code 
   string                              name;                  // event text name in the terminal language (in the current terminal encoding) 
  };

Estructura de valores del calendario:

struct MqlCalendarValue 
  { 
   ulong                               id;                    // value ID 
   ulong                               event_id;              // event ID 
   datetime                            time;                  // event date and time 
   datetime                            period;                // event reporting period 
   int                                 revision;              // revision of the published indicator relative to the reporting period 
   long                                actual_value;          // actual value multiplied by 10^6 or LONG_MIN if the value is not set 
   long                                prev_value;            // previous value multiplied by 10^6 or LONG_MIN if the value is not set 
   long                                revised_prev_value;    // revised previous value multiplied by 10^6 or LONG_MIN if the value is not set 
   long                                forecast_value;        // forecast value multiplied by 10^6 or LONG_MIN if the value is not set 
   ENUM_CALENDAR_EVENT_IMPACT          impact_type;           // potential impact on the currency rate 
  //--- functions checking the values 
   bool                         HasActualValue(void) const;   // returns true if actual_value is set 
   bool                         HasPreviousValue(void) const; // returns true if prev_value is set 
   bool                         HasRevisedValue(void) const;  // returns true if revised_prev_value is set 
   bool                         HasForecastValue(void) const; // returns true if forecast_value is set 
  //--- functions receiving the values 
   double                       GetActualValue(void) const;   // returns actual_value or nan if the value is no set 
   double                       GetPreviousValue(void) const; // returns prev_value or nan if the value is no set 
   double                       GetRevisedValue(void) const;  // returns revised_prev_value or nan if the value is no set 
   double                       GetForecastValue(void) const; // returns forecast_value or nan if the value is no set 
  };

Ahora lo primero que debemos hacer es reunir todos los valores disponibles dentro de un rango de tiempo de nuestra selección y ordenarlos específicamente por los valores que hemos visto, ocho de ellos, así como aplicar los filtros. Para obtener los valores, aplicamos la siguiente lógica.

MqlCalendarValue values[];
datetime startTime = TimeTradeServer() - PeriodSeconds(PERIOD_D1);
datetime endTime = TimeTradeServer() + PeriodSeconds(PERIOD_D1);

int valuesTotal = CalendarValueHistory(values, startTime, endTime, NULL, NULL);

Print("TOTAL VALUES = ", valuesTotal, " || Array size = ", ArraySize(values));

Aquí, declaramos una matriz llamada "values" del tipo de estructura MqlCalendarValue, que contendrá los datos del calendario económico recuperados del Calendario Económico MQL5. A continuación, configuramos dos variables datetime, «startTime» y «endTime», que definen el intervalo de tiempo para la extracción de datos. Calculamos la hora de inicio de los valores como un día antes de la hora actual del servidor, recuperada mediante la función TimeTradeServer y utilizando la función PeriodSeconds para crear un desfase de 24 horas en segundos. La lógica temporal de un día se consigue utilizando la constante «PERIOD_D1». Del mismo modo, «endTime» se establece en un día después de la hora actual del servidor, lo que nos permite capturar los eventos económicos que ocurren en un plazo de dos días alrededor del momento actual.

A continuación, utilizamos la función CalendarValueHistory para rellenar la matriz de valores con los eventos económicos dentro de este intervalo de tiempo especificado. Esta función devuelve el número total de eventos, que almacenamos en la variable «valuesTotal». Los parámetros para CalendarValueHistory incluyen la matriz «values», «startTime» y «endTime», así como dos filtros NULL para el país y el tipo de moneda (los dejamos NULL aquí para recuperar todos los eventos). Por último, utilizamos la función Print para imprimir el recuento total de valores y el tamaño de la matriz utilizando la función ArraySize, confirmando el número total de eventos obtenidos y verificando que la matriz contiene los datos esperados para su uso posterior en nuestra lógica de negociación. Cuando compilamos esto, obtenemos el siguiente resultado.

CONFIRMACIÓN DE VALORES

A continuación, podemos imprimir estos valores en el registro para que podamos confirmar lo que tenemos.

if (valuesTotal >=0 ){
   Print("Calendar values as they are: ");
   ArrayPrint(values);
}

Aquí, primero verificamos si los valores totales son mayores o iguales a cero, lo que indica que la función CalendarValueHistory ha recuperado con éxito algunos eventos del calendario económico o ha devuelto cero sin errores. Si se cumple esta condición, utilizamos la función Print para generar un mensaje, «Calendar values as they are:», como encabezado para informarnos de que ahora se mostrarán los valores. A continuación, llamamos a la función ArrayPrint, que imprime todo el contenido de la matriz «values» en el registro. Al ejecutar, tenemos los siguientes datos.

REGISTRO DE EVENTOS

Desde la imagen, podemos ver que registramos todos los eventos disponibles dentro del período de tiempo seleccionado. Sin embargo, podemos ver que las características del evento están representadas solo por números, que son los identificadores de características que son específicos y no nos brindan mucha información. Para ello debemos seleccionar un valor determinado y a partir de ahí obtener las características específicas de manera estructurada para cada evento. Esto significa que necesitamos recorrer cada valor seleccionado.

for (int i = 0; i < valuesTotal; i++){

//---

}

Aquí, creamos un bucle for que itera sobre cada elemento del array «values», que contiene los datos del calendario económico. El bucle inicializa una variable entera «i» a cero, que representa el índice inicial, y se ejecuta mientras «i» sea menor que el total de valores, que es el número total de eventos recuperados por la función CalendarValueHistory. Con cada iteración, incrementamos «i» en uno, lo que nos permite acceder secuencialmente a cada evento económico de la matriz «values». Ahora, dentro del bucle, podemos procesar o analizar los datos de cada evento, lo que proporciona flexibilidad para tareas como filtrar eventos, aplicar una lógica comercial específica basada en los detalles del evento o imprimir información de eventos individuales. Esta es la lógica que debemos utilizar.

MqlCalendarEvent event;
CalendarEventById(values[i].event_id,event);

Declaramos una variable «event» de tipo MqlCalendarEvent, que almacenará la información detallada de un evento económico específico. A continuación, llamamos a CalendarEventById, pasando dos parámetros. El primer parámetro recupera el ID único del evento económico actual de la matriz «values» (basándose en el índice actual del bucle i), mientras que el segundo, «event», actúa como contenedor para almacenar todos los detalles del evento. El primer parámetro recupera el ID único del evento económico actual de la matriz «values» (basándose en el índice actual del bucle i), mientras que el segundo, «event», actúa como contenedor para almacenar todos los detalles del evento. Para confirmar esto, podemos imprimir el ID del evento de la siguiente manera.

Print("Event ID ",values[i].event_id);

Sin embargo, esto imprimirá demasiados datos en el registro, por lo que reduciremos el intervalo de tiempo de selección a una hora antes y después de la hora actual. Lo único que tenemos que cambiar es la sección del período. Los hemos resaltado en amarillo para facilitar su consulta.

datetime startTime = TimeTradeServer() - PeriodSeconds(PERIOD_H1);
datetime endTime = TimeTradeServer() + PeriodSeconds(PERIOD_H1);

Cuando ejecutamos el programa, obtenemos el siguiente resultado.

ID DE EVENTOS

Ahora podemos proceder a obtener los valores reales del evento específico seleccionado además de los números de los valores del evento. Para lograr esto, solo necesitamos escribir la palabra clave event y usar el "operador de punto" para obtener acceso a todos los métodos y objetos de esa clase o estructura. Esto es lo que deberías obtener.

OPERADOR DE PUNTO

Utilizando el mismo método, podemos recuperar toda la información que hemos rellenado y almacenado en la estructura «event» que hemos creado.

Print("Event ID ",values[i].event_id);
Print("Event Name = ",event.name);
Print("Event Code = ",event.event_code);
Print("Event Type = ",event.type);
Print("Event Sector = ",event.sector);
Print("Event Frequency = ",event.frequency);
Print("Event Release Mode = ",event.time_mode);
Print("Event Importance = ",EnumToString(event.importance));
Print("Event Time = ",values[i].time);
Print("Event URL = ",event.source_url);

Comment("Event ID ",values[i].event_id,
        "\nEvent Name = ",event.name,
        "\nEvent Code = ",event.event_code,
        "\nEvent Type = ",event.type,
        "\nEvent Sector = ",event.sector,
        "\nEvent Frequency = ",event.frequency,
        "\nEvent Release Mode = ",event.time_mode,
        "\nEvent Importance = ",EnumToString(event.importance),
        "\nEvent Time = ",values[i].time,
        "\nEvent URL = ",event.source_url);
}

Aquí, utilizamos las funciones Print para generar los detalles de cada evento económico en la matriz de valores y mostrar esta información en la pestaña Expertos para facilitar su revisión. Comenzamos imprimiendo el ID del evento de values[i], que identifica de forma única el evento. A continuación, recuperamos e imprimimos detalles específicos sobre el evento de la variable «event», incluyendo su nombre, código de evento, tipo, sector, frecuencia, modo de tiempo (que indica el modo de sincronización de publicación), importancia (convertida a una cadena legible mediante la función EnumToString) y la hora programada real. Por último, imprimimos la fuente Uniform Resource Locator (URL), que proporciona un enlace a más información.

Junto con estas instrucciones de impresión, utilizamos la función Comment para mostrar los mismos detalles en el gráfico para su consulta inmediata. La función Comment muestra cada línea dentro del área de comentarios del gráfico, lo que facilita al operador ver las actualizaciones en tiempo real directamente en el gráfico. Después de ejecutar el programa, obtenemos el siguiente resultado.

DATOS DEL EVENTO POR ID

Eso fue un éxito. Para acceder a los datos del país y la moneda, incorporamos otra estructura que maneja los valores del país. Ésta es la lógica que debemos adoptar, que es idéntica a las otras que utilizamos.

MqlCalendarCountry country;
CalendarCountryById(event.country_id,country);

Aquí declaramos una variable «country» de tipo MqlCalendarCountry, en la que pretendemos almacenar la información específica del país relacionada con el evento económico. A continuación, utilizamos la función CalendarCountryById para recuperar los detalles del país pasando dos parámetros.

El primer parámetro proporciona el identificador único del país asociado al evento económico actual, mientras que el parámetro «country» sirve como contenedor de los datos de este país. Al llamar a la función CalendarCountryById, rellenamos nuestra variable «country» con información relevante, como el nombre del país, el código y otras características, lo que nos permite utilizar estos datos para realizar análisis más contextualizados y mostrar detalles específicos de cada país junto con cada evento económico.

Para mostrar esto, volvemos a imprimir la información del país.

Print("Country ID ",country.id);
Print("Country Name ",country.name);
Print("Country Code ",country.code);
Print("Country Currency ",country.currency);
Print("Country Currency Symbol ",country.currency_symbol);
Print("Country URL ",country.url_name);

Esto es lo que obtenemos cuando ejecutamos el programa.

DATOS DEL PAÍS

Eso fue un éxito. Ahora tenemos una introducción completa a las funciones necesarias en MQL5 que nos dan acceso a los datos del calendario. Ahora, podemos proceder a aplicar filtros a nuestro bloque de código para intercambiar típicamente datos específicos de países, datos prioritarios, monedas y noticias específicas en un momento dado. Para lograr esto dinámicamente, podemos trasladar nuestra lógica a una función que podamos utilizar para el propósito mencionado anteriormente.

//+------------------------------------------------------------------+
//|       FUNCTION TO GET NEWS EVENTS                                |
//+------------------------------------------------------------------+
bool isNewsEvent(){
   int totalNews = 0;
   bool isNews = false;
   
   //---
   
   return (isNews);
}

Definimos una función booleana llamada «isNewsEvent» que determinará si hay alguna noticia económica disponible. La función devuelve un valor booleano para indicar si existe un evento de noticias (verdadero) o no (falso). La función devuelve un valor booleano para indicar si existe un evento de noticias (verdadero) o no (falso). Tenemos la intención de utilizar la variable para almacenar el número total de noticias relevantes, que recuperaremos más adelante en la función. También declaramos una variable bool, "isNews", y la establecemos como falsa. Esta variable actuará como un indicador, cambiando a verdadero si detectamos alguna noticia relevante durante la ejecución de la función.

Actualmente, la función simplemente devuelve el valor de «isNews», que es falso por defecto, ya que aún no se están procesando eventos de noticias dentro de la función. Esta estructura de funciones proporciona una base para implementar una lógica que posteriormente pueda recuperar y comprobar si hay noticias, estableciendo «isNews» en verdadero si se detectan eventos. Es a esta función a la que añadimos nuestra lógica previamente definida desde el controlador de eventos OnInit. Sin embargo, llamamos a la función en el controlador de eventos para afectar la lógica de nuestra función.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(){
//---   
   if (isNewsEvent()){
      Print("______ ALERT: WE HAVE NEWS EVENT ___");
   }
   else if (isNewsEvent()==false){
      Print("______ ALERT: WE DON'T ANY HAVE NEWS EVENT ___");
   }
//---
   return(INIT_SUCCEEDED);
}

Aquí, dentro del controlador de eventos OnInit, comenzamos llamando a la función «isNewsEvent». Si la función devuelve verdadero, lo que indica que hay un evento de noticias disponible, se activa el bloque if y se imprime el mensaje «______ ALERT: WE HAVE NEWS EVENT ___». Este mensaje nos avisa de que se ha detectado una noticia económica, lo que nos permite ajustar nuestras estrategias de trading si lo deseamos.

Si devuelve falso, lo que significa que no hay eventos de noticias presentes, se activa el bloque else if e imprimimos "______ ALERT: WE DON'T HAVE ANY NEWS EVENT ___". Este mensaje nos avisa de que no se han identificado noticias de actualidad, lo que puede indicar que las operaciones bursátiles podrían desarrollarse sin las interrupciones que suelen provocar las noticias. Por último, la función devuelve INIT_SUCCEEDED, una constante que indica que la inicialización del EA se ha realizado correctamente. Ahora, tras esta llamada al controlador de eventos, podemos seguir aplicando filtros al tipo de noticias que nos interesan. Actualmente, tenemos el programa vinculado al símbolo «AUDUSD». Desarrollemos una lógica para garantizar que solo se tengan en cuenta las noticias de Estados Unidos.

string currency_filter = "USD";
string currency_base = SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE);
string currency_quote = StringSubstr(_Symbol,3,3);
if (currency_base != currency_filter && currency_quote != currency_filter){
   Print("Currency (",currency_base," | ",currency_quote,
         ") is not equal equal to ",currency_filter);
   return false;
}

Comenzamos definiendo dos variables de cadena, «currency_filter» y «currency_base», para facilitar la comprobación de si el símbolo actual es relevante para el filtro de divisas especificado, «USD». La variable «currency_filter» se inicializa con el valor «USD», que representa la divisa objetivo que nos interesa supervisar. A continuación, recuperamos la divisa base del símbolo actual (por ejemplo, AUD en el par AUDUSD) utilizando la función SymbolInfoString y la almacenamos en «currency_base».

A continuación, definimos «currency_quote», extrayendo la moneda de cotización del símbolo actual tomando los tres últimos caracteres mediante la función StringSubstr, ya que no hay una forma directa de acceder a la moneda de cotización. Por ejemplo, en el par AUDUSD, la función StringSubstr recuperará «USD», la moneda cotizada.

A continuación, comprobamos si tanto la moneda base como la moneda de cotización son diferentes de la moneda del filtro. Si no coinciden con el filtro de moneda de destino (USD en este caso), imprimimos un mensaje indicando que las monedas del símbolo no coinciden con el filtro de moneda. La función luego devuelve falso, finalizando así el procesamiento posterior si el símbolo es irrelevante para la moneda especificada. Si ejecutamos esto en diferentes símbolos, obtenemos el siguiente resultado.

FILTRO DE MONEDA

Desde la visualización, podemos ver que cuando cargamos el programa en los gráficos "AUDUSD" y "USDJPY", no obtenemos ningún error, pero cuando lo cargamos en el gráfico "EURJPY", obtenemos un error, indicando que ninguno de los dígitos de la moneda coincide con nuestra moneda de filtro predefinida. Ahora podemos continuar aplicando varios filtros dinámicamente según la importancia y el tiempo del evento.

if (StringFind(_Symbol,country.currency) >= 0){
   if (event.importance == CALENDAR_IMPORTANCE_MODERATE){
      if (values[i].time <= TimeTradeServer() && values[i].time >= timeBefore){
         Print(event.name," > ", country.currency," > ", EnumToString(event.importance)," Time= ",values[i].time," (ALREADY RELEASED)");
         totalNews++;
      }
            
      if (values[i].time >= TimeTradeServer() && values[i].time <= timeAfter){
         Print(event.name," > ", country.currency," > ", EnumToString(event.importance)," Time= ",values[i].time," (NOT YET RELEASED)");
         totalNews++;
      }
   }
}

Implementamos una serie de condiciones anidadas para identificar eventos noticiosos relevantes para una moneda específica, centrándonos en eventos categorizados como de "importancia moderada" y que caen dentro de un cierto rango de tiempo. En primer lugar, verificamos si el nombre del símbolo comercial actual (representado por_Symbol) contiene la moneda asociada con el evento. A continuación, comprobamos si tanto la moneda base como la moneda de cotización son diferentes de la moneda del filtro.

Esto es similar a la otra lógica que utilizamos, solo que es dinámica, ya que comprueba automáticamente la disponibilidad de la divisa en el símbolo seleccionado. Si se cumple esta condición, pasamos a la siguiente para confirmar que el nivel de importancia del evento coincide con CALENDAR_IMPORTANCE_MODERATE, lo que significa que solo nos interesan los eventos con un impacto moderado, excluyendo aquellos de importancia baja o alta.

Una vez que hemos identificado un evento de importancia moderada, evaluamos su momento en relación con la hora actual del servidor (TimeTradeServer) mediante dos comprobaciones independientes. En la primera comprobación, determinamos si la hora del evento es anterior o igual a la hora actual, pero posterior a «timeBefore». Si es así, esto significa que el evento ya se ha publicado dentro del plazo pasado especificado. A continuación, utilizamos la función Print para registrar los detalles del evento, que incluyen su nombre, la moneda asociada, la importancia y la hora, y lo marcamos como «(ALREADY RELEASED)». También incrementamos la variable «totalNews» para llevar un registro de los eventos que coinciden con nuestros criterios. En la segunda comprobación, determinamos si la hora del evento es posterior o igual a la hora actual, pero anterior o igual a «timeAfter», lo que indica que el evento está por llegar, pero aún dentro del plazo futuro especificado.

Una vez más, registramos detalles similares del evento utilizando la función Print, marcándolo como «(NOT YET RELEASED)» para indicar su estado pendiente, e incrementamos la variable «totalNews» para este evento relevante adicional. Quizás hayas notado que usamos algunas variables de tiempo diferentes en la lógica. Estos sirven simplemente para asegurarse de que el evento esté dentro del rango de tiempo para su acción, y aquí está su lógica.

datetime timeRange = PeriodSeconds(PERIOD_D1);
datetime timeBefore = TimeTradeServer() - timeRange;
datetime timeAfter = TimeTradeServer() + timeRange;
   
Print("FURTHEST TIME LOOK BACK = ",timeBefore," >>> CURRENT = ",TimeTradeServer());

Declaramos estas lógicas justo antes del bucle for para establecer un intervalo de tiempo alrededor de la hora actual del servidor y definir hasta qué punto queremos considerar los eventos de noticias pasados y futuros. Primero declaramos una variable de fecha y hora, «timeRange», y le asignamos la duración de un día utilizando la función PeriodSeconds. Primero declaramos una variable de fecha y hora, «timeRange», y le asignamos la duración de un día utilizando la función PeriodSeconds. A continuación, definimos dos variables de fecha y hora adicionales: «timeBefore» y «timeAfter».

A continuación, definimos dos variables de fecha y hora adicionales: «timeBefore» y «timeAfter». Del mismo modo, «timeAfter» se determina añadiendo «timeRange» a la hora actual del servidor, lo que proporciona el último punto temporal que queremos tener en cuenta en el futuro. Juntos, «timeBefore» y «timeAfter» crean una ventana de 24 horas centrada en la hora actual, lo que nos ayuda a capturar eventos que acaban de ocurrir o que se esperan en breve. Aquí hay un ejemplo.

MIRANDO HACIA ATRÁS Y HACIA EL FUTURO

En la imagen podemos ver que, cuando la hora actual (o más bien la fecha, ya que estamos considerando un escaneo de un día) es 25, tenemos la retrospectiva en la fecha 24 y la prospectiva en la 26, es decir, justo un día antes y un día después de la fecha actual. Los hemos resaltado en azul para mayor claridad. Por último, podemos analizar el número de noticias registradas desde el bucle y devolver los indicadores booleanos respectivos. Adoptamos la siguiente lógica para lograrlo.

if (totalNews > 0){
   isNews = true;
   Print(">>>>>>> (FOUND NEWS) TOTAL NEWS = ",totalNews,"/",ArraySize(values));
}
else if (totalNews <= 0){
   isNews = false;
   Print(">>>>>>> (NOT FOUND NEWS) TOTAL NEWS = ",totalNews,"/",ArraySize(values));
}

Aquí, evaluamos si se han identificado eventos noticiosos relevantes en función del total de noticias registradas. Si el total de noticias es mayor que cero, indica que se encontró al menos un evento noticioso que coincide con nuestros criterios. En este caso, establecemos la variable «isNews» en verdadero e imprimimos un mensaje, mostrando el número total de eventos de noticias coincidentes y el tamaño de la matriz «values». El mensaje, etiquetado como «(FOUND NEWS)», también incluye el total de noticias identificadas y todas las noticias consideradas inicialmente, indicando el número de noticias relevantes encontradas del total de eventos recuperados.

Por el contrario, si el total de noticias es igual a cero o menos, implica que no se encontraron eventos noticiosos relevantes. En este escenario, establecemos «isNews» en falso e imprimimos un mensaje con la etiqueta «(NOT FOUND NEWS)», que muestra que el total de noticias es cero junto con el tamaño de la matriz «values». Esta estructura nos ayuda a rastrear si se han encontrado noticias que coincidan con nuestros criterios y proporciona un registro de resultados, útil para verificar el resultado del proceso de verificación de noticias. Tras la compilación, obtenemos el siguiente resultado.

0 NOTICIAS

De la imagen podemos observar que no hay novedades relevantes por el momento. De esta forma podremos ampliar nuestra búsqueda ampliando el rango temporal o de búsqueda de eventos en este caso a un día.

datetime startTime = TimeTradeServer() - PeriodSeconds(PERIOD_D1);
datetime endTime = TimeTradeServer() + PeriodSeconds(PERIOD_D1);

Si retrocedemos el rango de noticias a un día, obtenemos el siguiente resultado.

5 NOTICIAS

Desde la imagen, podemos ver que tenemos 5 noticias relevantes de 81 e imprimimos que hay eventos de noticias relevantes, que podemos usar para tomar decisiones comerciales, es decir, entrar al mercado o salir del mercado. Eso es todo por esta parte y la función completa responsable de la identificación y filtrado de noticias del calendario MQL5 es como en el siguiente fragmento de código:

//+------------------------------------------------------------------+
//|       FUNCTION TO GET NEWS EVENTS                                |
//+------------------------------------------------------------------+
bool isNewsEvent(){
   int totalNews = 0;
   bool isNews = false;
   
   MqlCalendarValue values[];
   
   datetime startTime = TimeTradeServer() - PeriodSeconds(PERIOD_D1);
   datetime endTime = TimeTradeServer() + PeriodSeconds(PERIOD_D1);
   
   //string currency_filter = "USD";
   //string currency_base = SymbolInfoString(_Symbol,SYMBOL_CURRENCY_BASE);
   //string currency_quote = StringSubstr(_Symbol,3,3);
   //if (currency_base != currency_filter && currency_quote != currency_filter){
   //   Print("Currency (",currency_base," | ",currency_quote,
   //         ") is not equal equal to ",currency_filter);
   //   return false;
   //}
   
   int valuesTotal = CalendarValueHistory(values,startTime,endTime,NULL,NULL);
   
   Print("TOTAL VALUES = ",valuesTotal," || Array size = ",ArraySize(values));
   
   //if (valuesTotal >=0 ){
   //   Print("Calendar values as they are: ");
   //   ArrayPrint(values);
   //}
   
   datetime timeRange = PeriodSeconds(PERIOD_D1);
   datetime timeBefore = TimeTradeServer() - timeRange;
   datetime timeAfter = TimeTradeServer() + timeRange;
   
   Print("Current time = ",TimeTradeServer());
   Print("FURTHEST TIME LOOK BACK = ",timeBefore," >>> LOOK FORE = ",timeAfter);
   
   for (int i = 0; i < valuesTotal; i++){
      MqlCalendarEvent event;
      CalendarEventById(values[i].event_id,event);
      
      
      MqlCalendarCountry country;
      CalendarCountryById(event.country_id,country);
      
      if (StringFind(_Symbol,country.currency) >= 0){
         if (event.importance == CALENDAR_IMPORTANCE_MODERATE){
            if (values[i].time <= TimeTradeServer() && values[i].time >= timeBefore){
               Print(event.name," > ", country.currency," > ", EnumToString(event.importance)," Time= ",values[i].time," (ALREADY RELEASED)");
               totalNews++;
            }
            
            if (values[i].time >= TimeTradeServer() && values[i].time <= timeAfter){
               Print(event.name," > ", country.currency," > ", EnumToString(event.importance)," Time= ",values[i].time," (NOT YET RELEASED)");
               totalNews++;
            }
         }
      }
      
   }
   
   if (totalNews > 0){
      isNews = true;
      Print(">>>>>>> (FOUND NEWS) TOTAL NEWS = ",totalNews,"/",ArraySize(values));
   }
   else if (totalNews <= 0){
      isNews = false;
      Print(">>>>>>> (NOT FOUND NEWS) TOTAL NEWS = ",totalNews,"/",ArraySize(values));
   }
   
   return (isNews);
}


Conclusión

En resumen, hemos dado los primeros pasos necesarios para explorar el calendario económico MQL5. Se trata de extraer información y luego evaluarla según la importancia de las divisas y la relevancia de los acontecimientos. Hemos desarrollado un proceso estructurado que nos permite extraer datos del Calendario Económico, filtrarlos según criterios importantes, como la divisa y la relevancia del acontecimiento, e identificar si los acontecimientos son inminentes o ya han ocurrido. Este enfoque es esencial para automatizar los sistemas de negociación que pueden responder a acontecimientos económicos de gran impacto, lo que nos proporciona una ventaja a la hora de navegar por las fluctuaciones del mercado.

En la siguiente parte de esta serie, ampliaremos nuestra funcionalidad para mostrar los datos económicos filtrados directamente en la ventana del gráfico, aumentando su visibilidad para tomar decisiones de trading en tiempo real. También mejoraremos nuestro Asesor Experto para que utilice esta información con el fin de abrir posiciones de trading basadas en los principales acontecimientos económicos. Con estas funciones integradas, pasaremos del análisis de las noticias económicas al aprovechamiento real de esas noticias para las operaciones bursátiles. Haremos que nuestros sistemas sean más receptivos diseñándolos en torno a un marco en tiempo real y utilizando la información obtenida de los eventos del calendario económico para activar operaciones a raíz de dichos eventos. Manténgase atento.

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

Archivos adjuntos |
Optimización de portafolios en Fórex: Síntesis de VaR y la teoría de Markowitz Optimización de portafolios en Fórex: Síntesis de VaR y la teoría de Markowitz
¿Cómo funciona la negociación de portafolios en Fórex? ¿Cómo pueden sintetizarse la teoría de portafolios de Markowitz para optimizar las proporciones de los portafolios y el modelo VaR para optimizar el riesgo de los portafolios? Hoy crearemos un código de teoría de portafolios en el que, por un lado, obtendremos un riesgo bajo y, por otro, una rentabilidad aceptable a largo plazo.
Trading algorítmico basado en patrones de reversión 3D Trading algorítmico basado en patrones de reversión 3D
Hoy descubriremos al lector el nuevo mundo del trading automatizado con barras 3D. ¿Qué aspecto tiene un robot comercial basado en barras de precios multidimensionales, y pueden los clústeres "amarillos" de barras tridimensionales predecir los cambios de tendencia? ¿Cómo es el trading en múltiples dimensiones?
Explorando la criptografía en MQL5: Un enfoque paso a paso Explorando la criptografía en MQL5: Un enfoque paso a paso
Este artículo analiza la integración de la criptografía en MQL5, mejorando la seguridad y la funcionalidad de los algoritmos de trading. Cubriremos los métodos criptográficos clave y su aplicación práctica en el comercio automatizado.
Indicador de perfil de mercado — Market Profile (Parte 2): Optimización y dibujado en canvas Indicador de perfil de mercado — Market Profile (Parte 2): Optimización y dibujado en canvas
En este artículo analizaremos una versión optimizada del indicador de Perfil de mercado Market Profile, donde el dibujado por parte de un conjunto de objetos gráficos se sustituye por el dibujado en un lienzo: un objeto de la clase CCanvas.