Leer fuentes de noticias RSS a través de MQL4

vgs | 12 abril, 2016


Introducción

Este artículo trata un ejemplo de lectura de márgenes RSS a través de MQL4 utilizando las funciones del artículo Un recorrido por HTML utilizando MQL. Se presupone que el lector ha leído el artículo, o al menos tiene un conocimiento general de las ideas que se describen aquí.



¿Qué es RSS y por qué se necesita en MQL4?

RSS es un formato XML para transferir varios datos de una fuente a otra.

Se utiliza mucho en agencias de noticias, empresas, así como varias páginas web de noticias.

Se puede agregar (o leer) a través de una variedad de aplicaciones especiales (lectores) y entregar a los usuarios de forma conveniente. En este artículo, intentaremos hacer un trabajo que se pueda transformar en un indicador de noticias o en un lector RSS en lenguaje MQL4. ¿Qué tipo de información nos interesa en RSS? Las noticias, por supuesto.

Como se ha mencionado anteriormente, RSS es un documento XML. Entonces, ¿qué es XML?

Xml (del inglés, eXtensible Markup Language [lenguaje de marcas extensibles]), es un formato de texto para almacenar datos estructurados. La estructura se puede representar visualmente como tres elementos. Los elementos XML se describen a través de etiquetas.

A continuación hay un ejemplo de un documento XML simple:

<!--?xml version="1.0" encoding="windows-1252"?-->
<weeklyevents>
        <event>
                <title>Rightmove HPI m/m</title>
                <country>GBP</country>
                <date><!--[CDATA[05-15-2011]]--></date>
                <time><!--[CDATA[23:01]]--></time>
                <impact><!--[CDATA[Medium]]--></impact>
                <forecast>
                <previous><!--[CDATA[1.7%]]--></previous>
        </forecast></event>
</weeklyevents>


Implementación

Como se puede ver en el ejemplo anterior, XML es parecido a HTML. Además, para no "reinventar la rueda", utilizaremos el código del artículo Un recorrido por HTML utilizando MQL4.

Lo primero que hay que hacer es conectar las funciones de recorrido HTML en nuestro proyecto (indicador). Para ello, descargue el archivo ReportHTMLtoCSV-2.mq4 y colóquelo en la carpeta experts/include. Como el archivo se va a utilizar como una librería de función, se debe comentar a función start().

Recomendaría también cambiar el nombre del archivo (por ejemplo, a HTMLTagsLib.mq4) para más claridad.

El archivo está listo. Ahora, conéctelo al indicador (el archivo de trabajo del indicador está adjunto abajo).

#include <htmltagslib.mq4>

Ahora hay que incluir la librería estándar de Windows wininet.dll para trabajar con los enlaces:

#include <winuser32.mqh>
#import "wininet.dll"
  int InternetAttemptConnect(int x);
  int InternetOpenA(string sAgent, int lAccessType, 
                    string sProxyName = "", string sProxyBypass = "", 
                    int lFlags = 0);
  int InternetOpenUrlA(int hInternetSession, string sUrl, 
                       string sHeaders = "", int lHeadersLength = 0,
                       int lFlags = 0, int lContext = 0);
  int InternetReadFile(int hFile, int& sBuffer[], int lNumBytesToRead, 
                       int& lNumberOfBytesRead[]);
  int InternetCloseHandle(int hInet);
#import

Utilizaremos la función ReadWebResource(string url) para la lectura de la URL. El funcionamiento de la función no es el tema de este artículo. Por lo que no profundaremos en ello.

Sólo interesan los argumentos de entrada y salida. La función recibe un link para leer y devuelve el contenido del recurso como una fila.

Para analizar las etiquetas, se utilizarán dos funciones de HTMLTagsLib.mq4 file: FillTagStructure() and GetContent(). Estas funciones se describen con detalle en el artículo Un recorrido por HTML utilizando MQL4. Hay que tener en cuenta que los datos de entrada para el análisis se pasan como una gama. Por lo tanto, cuando se reciban los datos, se deberían convertir en una gama utilizando la función ReadWebResource(string url).

La función ArrayFromString() ayudará a ello:

//+------------------------------------------------------------------+
int ArrayFromString(string & webResData[], string inputStr, string divider) 
{   
   if (inputStr == "") 
   {
     Print ("Input string is not set"); 
     return(0);
   }
   if (divider == "") 
   {
      Print ("Separator is not set"); 
      return(0);
   }
   int i, stringCounter = 0;
   
   string tmpChar, tmpString, tmpArr[64000];   
   int inputStringLen = StringLen(inputStr);
   for (i = 0; i < inputStringLen; i++ ) 
   {
      tmpChar = StringSubstr(inputStr, i, 1);
      tmpString = tmpString + tmpChar;
      tmpArr[stringCounter] = tmpString; 
      if (tmpChar == divider) 
      {          
          stringCounter++;
          tmpString = "";
      }               
   }
   if (stringCounter > 0) 
   {
      ArrayResize(webResData, stringCounter);   
      for (i = 0; i < stringCounter; i++) webResData[i] = tmpArr[i];
   }
   return (stringCounter);
}

Hay tres argumentos pasados a la entrada de la función. El primero es el enlace a la gama en la que se almacena el resultado del funcionamiento de la función, el segundo es una fila que debe convertirse en una gama, y el tercero es un separador que divide la fila. La función devuelve el número de filas en la gama resultante.

Ahora los datos están listos para el análisis.

En el siguiente fragmento, se analizan los datos y se muestran los valores del título y etiquetas de país en la consola de la terminal:

   string webRss = ReadWebResource(rssUrl);
   int i, stringsCount = ArrayFromString(webResData, webRss, ">");      
            
   string tags[];    // array for storing the tags
   int startPos[][2];// tag start coordinates
   int endPos[][2];  // tag end coordinates
   
   FillTagStructure(tags, startPos, endPos, webResData);
   int tagsNumber = ArraySize(tags);
   
   string text = "";
   string currTag;
   int start[1][2];
   int end[1][2];
  
   for (i = 0; i < tagsNumber; i++)
      {
      currTag = tags[i];     

      if (currTag == "<weeklyevents>")
         {
            Print("News block start;");
         }

      if (currTag == "<event>")
         {
            text = "";
            start[0][0] = -1;
            start[0][1] = -1;
         }

      if (currTag == "<title>")
         {// coordinates of the initial position for selecting the content between the tags
            start[0][0] = endPos[i][0];
            start[0][1] = endPos[i][1];
         }
                 
      if (currTag == "</title>")
         {// coordinates of the end position for selecting the contents between the tags
            end[0][0] = startPos[i][0];
            end[0][1] = startPos[i][1];
            text = text + GetContent(webResData, start, end) + ";";
         }

      if (currTag == "<country>")
         {// coordinates of the initial position for selecting the content between the tags
            start[0][0] = endPos[i][0];
            start[0][1] = endPos[i][1];
         }
                       
      if (currTag == "</country>")
         {// coordinates of the end position for selecting the contents between the tags
            end[0][0] = startPos[i][0];
            end[0][1] = startPos[i][1];
            text = text + GetContent(webResData, start, end) + " ;";
         }

      if (currTag == "</event>")
         {
            Print(text);
         }

      if (currTag == "</weeklyevents>")
         {
            Print("end of the news;");
         }

      }

Utilizando la función FillTagStructure(), se recibe el número y la estructura de los datos, mientras que la función GetContent() proporciona su valor.

Resultados del funcionamiento del script:

Resultados del funcionamiento del script:

Fig. 1. Resultados del funcionamiento del script NewsRss:

En los resultados se puede ver el título de las noticias y el símbolo de la divisa del país con el que están relacionadas las noticias.



Conclusiones

Se ha examinado una manera de leer RSS a través de MQL4 utilizando las funciones para el análisis de etiquetas HTML. Los inconvenientes de este método están descritos detalladamente en el artículo Un recorrido por HTML utilizando MQL4. También me gustaría añadir que uno de los inconvenientes del método es un "inconveniente" de uso de las funciones en el código en contraste con otras librerías estándar para leer XML.

Ahora que se han completado el artículo y el script, voy a considerar la conexión de una librería externa para trabajar con XML. En cuanto a las ventajas, diría que una de ellas es la velocidad de implementación.