English Русский 中文 Português
preview
Simulación de mercado (Parte 07): Sockets (I)

Simulación de mercado (Parte 07): Sockets (I)

MetaTrader 5Ejemplos |
113 0
Daniel Jose
Daniel Jose

Introducción

En el artículo anterior, "Simulación de mercado (Parte 06): Transfiriendo información desde MetaTrader 5 hacia Excel", expliqué cómo puedes transferir datos de cotización de MetaTrader 5 a Excel usando medios simples y únicamente MQL5. Claro que aquello fue solo un ejemplo bastante sencillo, cuya intención era ser lo más didáctico posible. Sin embargo, habrás notado que la actualización de las cotizaciones no se producía en tiempo real. No obstante, el objetivo del conocimiento presentado en el artículo anterior era mostrar algo que realmente necesitaremos hacer.

Pero, como existen diversas maneras de hacer lo mismo, y lo que realmente nos interesa es siempre el resultado, quiero mostrar que sí, existe una forma sencilla de pasar datos desde MetaTrader 5 hacia otros programas, como, por ejemplo, Excel. Sin embargo, la idea principal no es transferir datos de MetaTrader 5 a Excel, sino hacer lo contrario. Es decir, transferir datos desde Excel, o desde cualquier otro programa, hacia MetaTrader 5.

Hay diversas maneras de hacerlo, algunas más simples y otras más elaboradas. Algunas lo harán en tiempo real y otras tendrán un pequeño retraso. Lo que importa es si podemos controlar MetaTrader 5 o alguna aplicación que se ejecute en él mediante datos externos. Esta cuestión puede parecer trivial, pero abre algunos precedentes. Por ejemplo, se podría realizar algún tipo de estudio o análisis con un programa externo diseñado específicamente para este tipo de tareas. Se podrían establecer puntos de interés en términos de precio o cotización y colocar dichos datos en un lugar donde alguna aplicación —ya sea un Asesor Experto, un Servicio, un Script o incluso un Indicador— pueda utilizarlos, lo que nos permitiría obtener señales directamente en el gráfico e, incluso, en el caso del Asesor Experto, ayudarnos en la toma de decisiones.

En este punto, lo que cuenta es tu imaginación y tu interés. Esto será, de hecho, lo que limitará lo que se puede hacer y hasta dónde podemos llegar. Pero antes de pasar a la fase de desarrollo de algo que realmente necesitaremos en el sistema de repetición/simulador, quiero mostrar otra cosa. Para ello, es necesario presentar estos conceptos, ideas y posibilidades, de modo que puedas entender realmente lo que se desarrollará e implementará después y aprovechar al máximo todo este conocimiento.

Lo que mostraré en este artículo es un paso adelante en esa misma cuestión presentada en el artículo anterior. Porque, como dije, aquella forma mostrada no nos permite enviar datos en tiempo real, aunque ya sea suficiente para lo que necesitaremos en el sistema de repetición/simulador. Sin embargo, no se ajusta a lo que necesitamos si queremos información en tiempo real.


Explicación del concepto

Como mencioné en el artículo anterior, el uso de un RTD o un DDE no garantiza una comunicación bidireccional entre MetaTrader 5 y otro programa. Pero, podemos aplicar el mismo concepto utilizado en un RTD o DDE de manera que obtengamos lo que queremos, es decir, una comunicación bidireccional. Para lograrlo, necesitaremos hacer algo diferente a lo que hemos hecho hasta ahora. Durante toda esta fase de desarrollo, he mantenido y realizado absolutamente todo en MQL5 puro. Sin embargo, existen casos en los que MQL5 puro no es suficiente, no por lo que puede hacer, sino por lo que otros programas no pueden hacer sin ayuda. La cuestión se resume en una sola cosa, que tiene un nombre: SOCKET.

El socket está firmemente arraigado en el mundo de la informática. Si no sabes qué es un socket ni para qué sirve, te sugiero que lo investigues, especialmente si deseas realizar ciertas tareas. Al usarlos, pasamos a tener un enorme grado de libertad. No voy a profundizar demasiado en el tema, ya que es bastante extenso y abarca diversas posibilidades y aspectos que necesitarás estudiar con calma si realmente quieres trabajar con sockets. Pero, haré una breve explicación para que no te sientas completamente perdido ni sin entender qué estamos haciendo ni qué está ocurriendo.


Protocolo TCP

Lo primero que necesitas entender es que existen muchos tipos diferentes de sockets. Cada uno sirve para un propósito distinto. Sin embargo, los más comunes son los de los tipos Stream y DataGram. El tipo Stream, o socket de flujo, se utiliza comúnmente en comunicaciones bidireccionales confiables. La palabra «confiable» se refiere al hecho de que siempre se verifica la recepción de la información. Dichos sockets del tipo Stream hacen uso del protocolo de control de transmisión, más conocido como TCP.

Este tipo de socket tiene otro detalle importante: está diseñado para que los paquetes de información siempre lleguen en un orden determinado. Es decir, puedes transferir la información como si fuera una lista enorme que se va desplegando a medida que los paquetes van llegando. Así, puedes notar claramente dónde se utiliza con mayor frecuencia, por ejemplo, en el control de aplicaciones a distancia, donde no se pueden permitir la pérdida de datos en la transmisión y se necesita la garantía de que la información será recibida. Sin embargo, esto hace que el protocolo sea un poco más lento. Típicamente, tiene la siguiente forma, que se muestra en la imagen de abajo:

Imagen 01

Pero, en términos de programación, nos interesa otra cosa. Se trata de cómo se elige e implementa este protocolo en el código que crearemos. Existen algunas pequeñas diferencias estructurales en el código cuando se usa TCP en Windows o en Linux. Aunque existan diferencias en el código, no interfieren en la comunicación. Es decir, se puede hacer que una aplicación de Windows se comunique con otra de Linux usando TCP y ambas aplicaciones podrán entenderse perfectamente. Eso sí, siempre que se sigan las reglas de comunicación. Lo mismo ocurre con el siguiente protocolo, que veremos más adelante.


Protocolo UDP

Dicho esto sobre el tipo Stream, pasemos ahora a entender el tipo DataGram. El tipo DataGram, también conocido como socket de datagrama, es completamente diferente del socket de flujo o TCP. Esto se debe a que este socket de datagrama está orientado a una comunicación unidireccional e inconexa. Pero, ¿cómo es posible? ¿Cómo puede una comunicación ser unidireccional y no fiable? Bien, vayamos con calma.

En primer lugar, debemos entender que este socket hace uso del protocolo UDP, el más conocido. Este protocolo no establece una conexión real, sino que simplemente permite enviar datos. Para que lo comprendas mejor, sería como una carta: la escribes y la envías, pero una vez enviada, no sabes cuándo —ni si— llegará realmente al destinatario.

Pero la cosa es un poco más complicada que eso. Porque después de enviar la carta, te das cuenta de que faltaron algunos detalles por explicar. Entonces, escribes otra carta para aclarar esos detalles. Y esto puede suceder varias veces, por lo que acabas enviando todas las cartas que has escrito.

Ahora viene el punto clave: si el servicio postal funciona correctamente y ninguna carta se extravía, quien las reciba puede recibirlas todas de una vez. Puede recibirlas en el mismo orden en que se enviaron o en un orden aleatorio.

Imagina el trabajo que tendrás que hacer para entender el mensaje enviado. Sin embargo, si tú enviaste la carta y esperas una respuesta, no tendrás ninguna certeza ni garantía de que el destinatario la recibió o entendió los mensajes. Por eso, este protocolo UDP es de tipo unidireccional y no fiable. ¿Entiendes ahora por qué no podemos tomar las cosas al pie de la letra? Aunque creas que no tiene utilidad, no es así.

Existen situaciones, como en el sondeo de datos, en las que no es necesario que los datos estén en una secuencia y, mucho menos, que se reciban todos. Podemos permitirnos perder algunos y los que recibamos serán suficientes para comprender la información.

Un ejemplo típico sería en las videollamadas o las llamadas de voz, donde lo que buscamos y priorizamos la mayor parte del tiempo es la velocidad de transferencia. Otro ejemplo serían las sondas o sensores remotos, em que el objetivo sería únicamente comprobar una condición determinada. En este tipo de situaciones, en la mayoría de los casos no es necesario confirmar la recepción de los datos, siempre que la cantidad de datos recopilados sea suficiente para analizar la información. Este protocolo tiene el siguiente formato típico:

Imagen 02

Creo que esto ya habrá despertado tu curiosidad y te habrás quedado con ganas de profundizar más en el estudio de este tema. De hecho, es muy amplio y sumamente interesante. Aquí solo estoy ofreciendo una ligera visión de todo lo que se puede hacer. Encontrarás a varias personas que comentan sobre el tema en artículos o en el foro de la comunidad MQL5. En cualquier caso, el tema es extremadamente amplio, pero he dado esta breve introducción para que puedas entender lo que haremos a continuación.


Programar un sistema modesto

Aquí debemos hacer un paréntesis aquí, porque para demostrar lo que se va a hacer necesitamos utilizar un código bastante simple. Como MQL5 no nos permite crear un servidor directamente dentro del lenguaje, usaremos MQL5 para producir la parte del cliente. Sí, vamos a crear un modelo cliente-servidor. La parte del servidor se hará mediante programación externa. En este caso, podrás hacerlo con cualquier tipo de código o lenguaje que permita crear un servidor de red. Pero, hay algunos detalles a los que debes prestar atención, como el puerto y el tipo de protocolo que se utilizará. Para simplificar al máximo, utilizaré un código que podrás estudiar directamente desde la fuente. Es decir, usaremos un código público y disponible en Internet. El código del servidor se encuentra en la página de Microsoft. Podrás acceder a él usando este enlace: Servidor WinSock. Servidor WinSock.

Al final del artículo dejaré este mismo enlace como referencia. Así podrás estudiar paso a paso cómo funciona el código, además de otros detalles relacionados con los sockets. Esto no solo se aplica a la parte del servidor, sino también a la del cliente, que también está explicada en ese mismo lugar.

NOTA IMPORTANTE: el servidor que estoy indicando es un modelo muy simple que recibe una conexión, captura lo que se le envía y, a continuación, cierra la conexión sin poder recibir otra, devolviendo al cliente exactamente la información enviada. Es decir, sería un servidor de eco que solo servirá para fines de demostración.

Sin embargo, en la parte del cliente haremos algo un poco diferente. Vamos a crear el cliente directamente en MQL5, prescindiendo así del código en lenguaje C/C++ que se puede encontrar en el sitio mencionado. De esta manera, podrás entender cómo se produce realmente la comunicación. Recuerda que incluso podrías convertir MetaTrader 5 en un servidor, pero eso nos obligaría a utilizar una DLL. Y, por el momento, no quiero utilizar este tipo de recurso. Al menos por ahora.

Así que, ¡manos a la obra! Puedes utilizar el código que indiqué o crear el tuyo propio en cualquier lenguaje o plataforma. La idea es crear un sistema modesto y sencillo que sirva de punto de partida para que entiendas cómo funcionan las cosas. Cuando el servidor esté compilado y funcionando, pasaremos a la parte correspondiente a MQL5. Para ello, abre MetaEditor y crea el cliente en MQL5 puro.


Ejecutar la parte MetaTrader

Antes de establecer una conexión con nuestro servidor local, debemos comprender cómo se realiza una conexión correctamente. Esto se debe a que, por defecto, MetaTrader 5 impide la conexión a cualquier servidor que no sea el de trading. Este tipo de restricción es una medida de seguridad que debes aceptar y comprender. No sería apropiado permitir que una plataforma como MetaTrader se conecte libremente a cualquier dirección. Por esa razón, es necesario realizar un pequeño ajuste para que MetaTrader permita la conexión.

Para que lo entiendas de manera muy sencilla, utilizaremos algo que se encuentra en la propia documentación de MQL5. Por lo tanto, el código que se muestra a continuación no es de mi autoría, sino que forma parte de la documentación, donde puede consultarse buscando SocketCreate. A continuación, se muestra el código fuente tal como aparece en la documentación.

001. //+------------------------------------------------------------------+
002. //|                                                SocketExample.mq5 |
003. //|                        Copyright 2018, MetaQuotes Software Corp. |
004. //|                                             https://www.mql5.com |
005. //+------------------------------------------------------------------+
006. #property copyright   "Copyright 2018, MetaQuotes Software Corp."
007. #property link        "https://www.mql5.com"
008. #property version     "1.00"
009. #property description "Add Address to the list of allowed ones in the terminal settings to let the example work"
010. #property script_show_inputs
011.  
012. input string Address="www.mql5.com";
013. input int    Port   =80;
014. bool         ExtTLS =false;
015. //+------------------------------------------------------------------+
016. //| Send command to the server                                       |
017. //+------------------------------------------------------------------+
018. bool HTTPSend(int socket,string request)
019.   {
020.    char req[];
021.    int  len=StringToCharArray(request,req)-1;
022.    if(len<0)
023.       return(false);
024. //--- if secure TLS connection is used via the port 443
025.    if(ExtTLS)
026.       return(SocketTlsSend(socket,req,len)==len);
027. //--- if standard TCP connection is used
028.    return(SocketSend(socket,req,len)==len);
029.   }
030. //+------------------------------------------------------------------+
031. //| Read server response                                             |
032. //+------------------------------------------------------------------+
033. bool HTTPRecv(int socket,uint timeout)
034.   {
035.    char   rsp[];
036.    string result;
037.    uint   timeout_check=GetTickCount()+timeout;
038. //--- read data from sockets till they are still present but not longer than timeout
039.    do
040.      {
041.       uint len=SocketIsReadable(socket);
042.       if(len)
043.         {
044.          int rsp_len;
045.          //--- various reading commands depending on whether the connection is secure or not
046.          if(ExtTLS)
047.             rsp_len=SocketTlsRead(socket,rsp,len);
048.          else
049.             rsp_len=SocketRead(socket,rsp,len,timeout);
050.          //--- analyze the response
051.          if(rsp_len>0)
052.            {
053.             result+=CharArrayToString(rsp,0,rsp_len);
054.             //--- print only the response header
055.             int header_end=StringFind(result,"\r\n\r\n");
056.             if(header_end>0)
057.               {
058.                Print("HTTP answer header received:");
059.                Print(StringSubstr(result,0,header_end));
060.                return(true);
061.               }
062.            }
063.         }
064.      }
065.    while(GetTickCount()<timeout_check && !IsStopped());
066.    return(false);
067.   }
068. //+------------------------------------------------------------------+
069. //| Script program start function                                    |
070. //+------------------------------------------------------------------+
071. void OnStart()
072.   {
073.    int socket=SocketCreate();
074. //--- check the handle
075.    if(socket!=INVALID_HANDLE)
076.      {
077.       //--- connect if all is well
078.       if(SocketConnect(socket,Address,Port,1000))
079.         {
080.          Print("Established connection to ",Address,":",Port);
081.  
082.          string   subject,issuer,serial,thumbprint;
083.          datetime expiration;
084.          //--- if connection is secured by the certificate, display its data
085.          if(SocketTlsCertificate(socket,subject,issuer,serial,thumbprint,expiration))
086.            {
087.             Print("TLS certificate:");
088.             Print("   Owner:  ",subject);
089.             Print("   Issuer:  ",issuer);
090.             Print("   Number:     ",serial);
091.             Print("   Print: ",thumbprint);
092.             Print("   Expiration: ",expiration);
093.             ExtTLS=true;
094.            }
095.          //--- send GET request to the server
096.          if(HTTPSend(socket,"GET / HTTP/1.1\r\nHost: www.mql5.com\r\nUser-Agent: MT5\r\n\r\n"))
097.            {
098.             Print("GET request sent");
099.             //--- read the response
100.             if(!HTTPRecv(socket,1000))
101.                Print("Failed to get a response, error ",GetLastError());
102.            }
103.          else
104.             Print("Failed to send GET request, error ",GetLastError());
105.         }
106.       else
107.         {
108.          Print("Connection to ",Address,":",Port," failed, error ",GetLastError());
109.         }
110.       //--- close a socket after using
111.       SocketClose(socket);
112.      }
113.    else
114.       Print("Failed to create a socket, error ",GetLastError());
115.   }
116. //+------------------------------------------------------------------+

Código fuente presente en la documentación MQL5

Este código es perfecto para explicar cómo trabajar y ajustar las conexiones en MetaTrader 5, ya que, además de ser muy sencillo, nos permite el acceso remoto. Es decir, accederemos a una página web. Creo que quienes tengan algo de experiencia en programación de redes podrán comprender este código sin dificultad. Pero, para quienes no tengan conocimientos sobre el tema, daré una breve explicación, ya que después necesitaremos entender algunos conceptos que aparecen aquí.

Este código es un script y debe compilarse como tal. No es posible usar sockets en indicadores. Consulta la documentación para obtener más información. Ahora veamos cómo funciona. En la línea 12 indicamos el nombre del sitio al que se va a acceder. En la línea 13, indicamos el puerto que se utilizará. En este caso, se trata de un puerto que responde a solicitudes del tipo HTTP. Es decir, se trata de un servidor web. Consulta la referencia para saber qué esperar de cada tipo de puerto.

Muy bien, cuando el código se inicia (algo que ocurre en la línea 71), lo primero que hacemos es crear un socket, algo que sucede en la línea 73. Hasta aquí todo es muy simple. Sin embargo, necesitamos verificar si el socket creado es válido, lo que se realiza en la línea 75. En la línea 78, intentamos conectarnos al servidor y al puerto indicados en las líneas 12 y 13. Si falla la conexión, se mostrará algo similar a lo que se ve en la imagen de abajo:

Imagen 03

Este mensaje probablemente aparece porque MetaTrader 5 está bloqueando la conexión. Para habilitarla, debes presionar Ctrl + O y añadir una excepción a la regla, tal y como se muestra a continuación:

Imagen 04

Una vez realizada la modificación que puedes ver arriba, podrás volver a ejecutar el script y el resultado será similar al de la siguiente imagen:

Imagen 05

Pero, ¿cómo sucedió esto? ¿Cómo obtuvimos cierta información del servidor web? ¿No era necesario usar una llamada WebRequest para hacerlo? En realidad, no necesariamente. La llamada WebRequest hace prácticamente lo mismo que acabamos de hacer. Sin embargo, ahora estamos en una capa un poco más cercana al hardware. Esto se debe a que la llamada WebRequest crea una abstracción para el socket que está justo debajo. Por eso, el resultado es el mismo en ambos modos de uso. Ya exploramos el uso de la llamada WebRequest en el pasado. Si deseas conocer más detalles, revisa los siguientes artículos:

Lo que se hizo en los tres artículos mencionados anteriormente se puede hacer usando los sockets directamente. No obstante, tendrás que programar un poco más para obtener el mismo resultado. Pero volvamos a nuestro sistema, que estamos analizando en este artículo. Una vez compilado el código del servidor indicado en la sección anterior, deberás dejarlo en ejecución antes de ejecutar el script que mostraré a continuación. Recuerda que puedes crear tu propio servidor en el lenguaje que prefieras. El único requisito, por ahora, es que los datos recibidos por el servidor se reenvíen al cliente para que tengamos el mismo comportamiento que estaré explicando.

Veamos entonces el código en MQL5 que será nuestro cliente. Este puede verse a continuación en su totalidad.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property version   "1.00"
04. #property script_show_inputs 
05. //+------------------------------------------------------------------+ 
06. input string user00 = "127.0.0.1";          //Address
07. input int    user01 = 27015;                //Port
08. //+------------------------------------------------------------------+
09. bool ConnectionWrite(int socket, string szMsg, bool TLS = false)
10. {
11.     char buff[];
12.     int  len = StringToCharArray(szMsg, buff) - 1;
13. 
14.     if (len < 0) return false;
15.     Print("To Server:", szMsg);
16.     return (TLS ? SocketTlsSend(socket, buff, len) : SocketSend(socket, buff, len)) == len;
17. }
18. //+------------------------------------------------------------------+
19. string ConnectionRead(int socket, uint timeout)
20. {
21.     uint len;
22.     int  ret;
23.     char resp[];
24.     string info;
25.     uint timeout_check = GetTickCount() + timeout;
26.     
27.     info = "";
28.     do
29.     {
30.             len = SocketIsReadable(socket);
31.             ret = SocketRead(socket, resp, len, timeout);
32.             if (ret > 0)
33.                     info += CharArrayToString(resp, 0, ret);
34.     }while ((GetTickCount() < timeout_check) && (!_StopFlag));
35.     
36.     return info;
37. }
38. //+------------------------------------------------------------------+
39. void OnStart()
40. {
41.     int socket = SocketCreate();
42.     
43.     if (socket == INVALID_HANDLE)
44.     {
45.             Print("Unable to create socket. Error: ", GetLastError());
46.             return;
47.     }
48.     if (!SocketConnect(socket, user00, user01, 1000))
49.     {
50.             Print("Connection with the address [", user00,"] in port: ",user01, " failed. Error code: ", GetLastError());
51.             SocketClose(socket);
52.             return;
53.     }
54.     
55.     Print("Trying to send ", ConnectionWrite(socket, "Testing Server Echo...") ? "Ok..." : "Failed...");
56.     
57.     Print("From Server:", ConnectionRead(socket, 1000));
58. 
59.     SocketClose(socket);
60. }
61. //+------------------------------------------------------------------+

Código de demostración

Analicemos algunos detalles de este código antes de ver cómo se ejecuta en MetaTrader 5. La primera cosa está en la línea seis. En ella indicamos dónde se encuentra nuestro servidor. En este caso, indicamos que se encuentra en la misma máquina en la que está instalado MetaTrader 5. La línea siete indica cuál es el puerto que utilizaremos en el servidor. Un detalle muy importante: este puerto debe coincidir con el indicado en el código del servidor. Por eso señalé un código público, que está muy bien explicado en el sitio web mencionado En caso de dudas, consulta la documentación disponible en el sitio web, que se indicará al final de este artículo como referencia.

Básicamente, todas las funciones de este script de MQL5 se explican por sí mismas y, en caso de duda, bastará con consultar la documentación para entender qué está ocurriendo. Sin embargo, hay una parte en la que las cosas no están tan claras y que merece una explicación adicional.

Observa que en la línea 28 entramos en un bucle. Su finalidad es leer lo que el servidor publicará en el socket. Pero ¿por qué usar un bucle? ¿No bastaría con leer el socket? Puede parecer algo confuso, pero tiene sus razones. Cuando se envía algo al socket, no sabemos cómo se enviará; solo sabemos que se enviará. La información puede ir en un único paquete, pero también puede transmitirse en varios paquetes pequeños, incluso si el mensaje es relativamente corto.

Esta situación hace que muchas personas que empiezan a experimentar con la programación de sockets tengan ciertas dificultades. Precisamente porque piensan que la información se enviará en un solo bloque, cuando en realidad puede estar dividida en varios bloques o paquetes. Entonces, ¿hay alguna manera de saberlo de antemano? En realidad, no existe una forma sencilla de saberlo. Lo único que podemos esperar es que el paquete enviado sea recibido, y esto ocurre cuando usamos el protocolo TCP, como expliqué al principio del artículo. La cuestión es que la información se envía y se recibe normalmente en forma de paquetes.

Para entenderlo mejor, observa la línea 55. En esa línea realizamos una llamada a la línea nueve, que recibirá la información que deberá ser colocada en el socket. Muy bien, en la línea 15 indicamos cuál será el mensaje, y en la línea 16 lo enviamos. La forma en que el servidor recibirá efectivamente el mensaje, y en cuántos paquetes lo hará, ya no depende de nosotros; el propio sistema se encargará de esa división.

En cuanto se ejecute la línea 57, leeremos efectivamente lo que el servidor publicó. Presta atención a esto: no leeremos lo que enviamos, sino lo que el servidor devolvió. Como el servidor que indiqué es del tipo eco, se nos devolverá el mismo mensaje que enviamos. Esto sería algo parecido a hacer un ping al servidor.

Pero, del mismo modo que no controlamos cómo se transmitirá el mensaje, tampoco sabemos cuántos paquetes utilizará el servidor para devolverlo. Si eliminas el bucle de la línea 28, ejecutas solo la llamada de la línea 31 y usas la línea 33 para convertir en cadena lo que el servidor devolvió, notarás que el mensaje aparece fragmentado, como si le faltara alguna parte. Sin embargo, en algunos momentos se mostrará completo. Esto sucede porque el mensaje es bastante corto. Y es precisamente este tipo de situación la que muchos no logran comprender.

Sé que esto puede parecer bastante confuso y poco eficiente, y que no parece tener ninguna utilidad práctica. Sin embargo, me gustaría destacar algo: si logras entender cómo funcionan estos dos códigos, tanto el que cumple la función de servidor como el que se ejecuta en MetaTrader 5, te darás cuenta de que se pueden hacer muchas cosas.

Pero antes de poner este script en funcionamiento, será necesario informar a MetaTrader 5 que la dirección utilizada debe estar permitida. De este modo, el mismo valor indicado en la línea seis deberá figurar en la lista de direcciones en MetaTrader 5. Entonces deberás ver algo como lo que se muestra en la imagen de abajo.

Imagen 06

Con esta modificación, podremos ejecutar ambos programas. Para que sepas cómo hacerlo, incluyo en el vídeo de abajo una forma de probar localmente cómo funciona el sistema, por si no tienes experiencia en programación en múltiples hilos. Sin embargo, quiero dejar claro que el objetivo del vídeo no es promocionar ninguna herramienta en concreto, sino mostrar a quienes no lo saben cómo ejecutar programas con múltiples hilos de trabajo para poder desarrollar algo sin complicaciones.




Consideraciones finales

En este artículo, di una breve introducción a uno de los conceptos más complejos que se pueden utilizar en MetaTrader 5: el uso de sockets. El objetivo de este artículo es explicar lo más básico sobre cómo utilizar los sockets en MetaTrader 5 para que puedas comprender algunos de los conceptos fundamentales. Aunque el contenido de este artículo sea muy básico, resulta esencial para quienes desean estudiar los sockets y su aplicación.

Sin embargo, como lo único que hicimos aquí fue generar un eco en el servidor, tal vez no haya quedado del todo claro cuánto podemos lograr realmente. Para aclarar este punto, en el próximo artículo haremos algo un poco más elaborado, ya que este concepto sobre sockets puede ayudarte mucho a mejorar la calidad del uso del sistema de repetición/simulador. Aún necesitaremos implementar algunas cosas, como el sistema de órdenes, y estoy considerando seriamente hacerlo de una manera más sofisticada. Pero, para que tú, estimado lector, puedas entender realmente lo que se va a programar, es necesario que comprendas estos pequeños conceptos que estoy mostrando aquí.

Si existe algo que de verdad te hará estudiar mucho en programación, se llama SOCKET.En lo que respecta a los sockets, nunca se sabe lo suficiente. Y, cuando creas que ya lo has explorado todo en lo que respecta a los sockets, te darás cuenta de que aún queda algo por descubrir. Así que no te pierdas el próximo artículo, porque mostraré algo muy interesante y sencillo de implementar relacionado con este tema.


Referencia

Documentación de uso de WinSock de Microsoft

Puertos de red

Archivo Descripción
Experts\Expert Advisor.mq5
Demuestra la interacción entre Chart Trade y el Asesor Experto (Es necesario el Mouse Study para la interacción)
Indicators\Chart Trade.mq5 Crea la ventana para configurar la orden a ser enviada (es necesario el Mouse Study para la interacción)
Indicators\Market Replay.mq5 Crea los controles para la interacción con el servicio de reproducción/simulador (es necesario el Mouse Study para la interacción)
Indicators\Mouse Study.mq5 Permite la interacción entre los controles gráficos y el usuario (Necesario tanto para operar el sistema de repetición como en el mercado real)
Servicios\Market Replay.mq5 Crea y mantiene el servicio de reproducción y simulación de mercado (archivo principal de todo el sistema)
Código VS C++\Server.cpp Crea y mantiene un socket servidor en C++ (versión Mini Chat)
Code in Python\Server.py Crea y mantiene un socket en Python para la comunicación entre MetaTrader 5 y Excel
Scripts\CheckSocket.mq5 Permite realizar una prueba de conexión con un socket externo
Indicators\Mini Chat.mq5 Permite implementar un mini chat mediante un indicador (requiere el uso de un servidor para funcionar)
Experts\Mini Chat.mq5 Permite implementar un mini chat mediante un Asesor Experto (requiere el uso de un servidor para funcionar)

Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/12621

Archivos adjuntos |
Anexo.zip (550.91 KB)
Anexo.zip (560.03 KB)
Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 9): Flujo externo Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 9): Flujo externo
Este artículo explora una nueva dimensión del análisis utilizando librerías externas diseñadas específicamente para análisis avanzados. Estas librerías, como pandas, proporcionan potentes herramientas para procesar e interpretar datos complejos, lo que permite a los operadores obtener una visión más profunda de la dinámica del mercado. Al integrar estas tecnologías, podemos salvar la brecha entre los datos brutos y las estrategias viables. Únase a nosotros para sentar las bases de este enfoque innovador y liberar el potencial de combinar la tecnología con la experiencia en el comercio.
Redes neuronales en el trading: Modelos bidimensionales del espacio de enlaces (Quimera) Redes neuronales en el trading: Modelos bidimensionales del espacio de enlaces (Quimera)
Descubra el innovador framework Chimera, un modelo bidimensional de espacio de estados que utiliza redes neuronales para analizar series temporales multivariantes. Este método ofrece una gran precisión con un bajo coste computacional, superando a los enfoques tradicionales y a las arquitecturas de Transformer.
Simulación de mercado (Parte 08): Sockets (II) Simulación de mercado (Parte 08): Sockets (II)
¿Qué te parece si creamos algo práctico con sockets? Bien, en este artículo empezaremos a crear un minichat. Acompáñanos y descubre cómo se hace, porque será algo bastante interesante. Recuerda que el código que se mostrará aquí tiene un objetivo puramente didáctico. En realidad, no deberías utilizar este código con fines comerciales ni en una aplicación finalizada, ya que no cuenta con ningún tipo de seguridad en la transmisión de datos y es posible ver el contenido que se está transportando a través del socket.
Kit de herramientas de negociación MQL5 (Parte 7): Ampliación de la libreria EX5 de gestión del historial con las funciones de última orden pendiente cancelada Kit de herramientas de negociación MQL5 (Parte 7): Ampliación de la libreria EX5 de gestión del historial con las funciones de última orden pendiente cancelada
Aprenda a completar la creación del módulo final en la librería History Manager EX5, centrándose en las funciones responsables de gestionar la orden pendiente cancelada más recientemente. Esto le proporcionará las herramientas necesarias para recuperar y almacenar de manera eficiente los detalles clave relacionados con las órdenes pendientes canceladas con MQL5.