English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Cómo copiar el trading desde MetaTrader 5 a MetaTrader 4

Cómo copiar el trading desde MetaTrader 5 a MetaTrader 4

MetaTrader 5Trading | 19 marzo 2014, 09:10
3 166 0
Mykola Demko
Mykola Demko

Introducción

No hace mucho tiempo, muchos traders consideraban MetaTrader 5 una plataforma cruda, inútil para el trading real. Pero ahora, pasado un corto plazo, la opinión publica se hace la pregunta: ¿Cuándo estará disponible el trading real? Mucha gente ha apreciado las ventajas implementadas en MetaTrader 5. Además, el Campeonato organizado por MetaQuotes Software Corp. ha avivado el interés de los desarrolladores por el lenguaje MQL5. Y ahora este interés desea realizarse en forma de obtención de beneficios del trading real. La pregunta "¿Cuándo estará disponible el trading real?" se equivoca de puerta. Es que la decisión depende de cada broker en concreto. Precisamente ellos toman la decisión definitiva respecto a los plazos de traspaso a una plataforma nueva.

¿Entonces, qué es lo que puede hacer un trader solitario en esta situación? La respuesta es obvia: hay que utilizar las posibilidades del trading real disponibles en MetaTrader 4 como de tránsito para MetaTrader 5. Es decir escribir un copiador. La vinculación entre dos plataformas MetaTrader 4 no es algo nuevo en la red. Pues ahora ha llegado la hora de implementar esta vinculación con MetaTrader 5.


Prólogo

Para implementar la idea declarada en el tema, hay que aclarar las siguientes preguntas: ¿De dónde aparece el beneficio? y ¿De qué manera el trader puede controlar el crecimiento de beneficios?". A primera vista, las respuestas son evidentes. Compra más barato, vende más caro. Pero vamos a descomponer el beneficio en sus integrantes. El beneficio es la diferencia entre la compra y la venta multiplicada por la cuota. Es decir, el beneficio tiene dos componentes: las cotizaciones y el volumen de la posición comercial.

¿Qué es lo que puede controlar el trader? ¿Cuál de estos dos componentes del trading es el volante en su trading? Pues, desde luego, el volumen de la posición comercial. Porque el trader recibe las cotizaciones del broker, y su cambio no depende de él de ninguna manera. De aquí se desprende la primera conclusión: para hacer una copia del trading, hay que mantener sincrónicamente los volúmenes de las posiciones comerciales.


1. Comparación de dos plataformas

1.1 Diferencias en el sistema de registro

Las plataformas que estamos comparando tienen los sistemas de registro del trading diferentes, y eso tiene que complicar las cuestiones del copiado. Pero no hay que olvidar que el elemento principal en este enlace es MetaTrader 5. Eso quiere decir que en MetaTrader 4 hay que repetir virtualmente el mismo sistema de registro.

En MetaTrader 5 una posición comercial es el resultado de las órdenes individuales, lo que no contradice al registro de las órdenes adoptado en MetaTrader 4. Los Stop Loss y Take Profit comunes para una posición se puede implementar mediante la colocación del mismo Stop Loss y Take Profit para cada orden abierta. Las diferencias importantes entre las plataformas aparecen sólo en la siguiente cuestión: ¿qué orden hay que cerrar en MetaTrader 4? Ya que en MetaTrader 5 no se lleva a cabo el registro separado de las órdenes en una posición comercial, esta cuestión puede llegar a ser "piedra de tropiezo".

1.2 Volúmenes de posiciones comerciales

Vamos a considerar en detalles, ¿hay alguna diferencia cuál de las órdenes se cierra? ¿Causará eso algún efecto en beneficio? Por ejemplo, tenemos dos órdenes abiertas en diferentes momentos y cerradas también en diferentes momentos, pero que han existido juntas durante un plazo de tiempo. Es decir, vamos a intentar emular la posición comercial en el sistema de registro de las órdenes.

Vamos a calcular diferentes opciones y veremos qué pasará con el beneficio si alternamos los niveles de cierre de las órdenes.

tipo 
volumen
nivel de apertura
 nivel de cierre
sell 0.1 1.39388 1.38438
sell 0.1 1.38868
1.38149

Para el cálculo vamos a escribir el código de la calculadora:

void OnStart()
  {
   double open1=1.39388,close1=1.38438,
         open2=1.38868,close2=1.38149;
   Print("total  ",n1(profit((open1-close1),0.1)+profit((open2-close2),0.1)));
   Print("orden2  pp=",ns(open2-close2),"  profit=",n1(profit((open2-close2),0.1)));
   Print("orden1  pp=",ns(open1-close1),"  profit=",n1(profit((open1-close1),0.1)));
  }
string ns(double v){return(DoubleToString(v,_Digits));}
string n1(double v){return(DoubleToString(v,1));}
double profit(double v,double lot){return(v/_Point*lot);}
Aquí está el cálculo:
orden1  pp=0.00950  profit=95.0
orden2  pp=0.00719  profit=71.9
total  166.9

Ahora alternamos los valores close1 y close2.

orden1  pp=0.01239  profit=123.9
orden2  pp=0.00430  profit=43.0
total  166.9

Fig. 1 Variantes del cierre de la orden

Fig. 1 Variantes del cierre de la orden

La Figura 1 nos muestra que las secciones AB y CD tienen en ambos casos el volumen 0,1, la sección BC tiene el volumen 0,2, y eso no depende del hecho el volumen de qué orden ha sido cerrado.

En los beneficios de las órdenes individuales tenemos la diferencia. Sin embargo, los beneficios finales de las posiciones realizadas son iguales. Pero pido que el lector se fije en que este ejemplo ha sido calculado con los volúmenes iguales de las órdenes. Es decir, en los mismos niveles ha sido realizado el cierre del mismo volumen, y no de la orden. Si seguimos estrictamente el principio del cierre de los volúmenes, no importa qué volumen tiene la orden. Si el volumen del cierre supera el volumen de la orden, el cierre va a ser parcial.

De aquí se desprende la principal conclusión: para la posición total, no importa cuál de las órdenes ha sido cerrada, lo importante es que los volúmenes cerrados en los niveles establecidos sean iguales.

1.3 Particularidades del copiado de transacciones

De los ejemplos de arriba se puede ver que para obtener el mismo beneficio, no es necesario transmitir las señales producidas por el Asesor Experto escrito en el lenguaje MQL5. Será suficiente sólo repetir los volúmenes de posiciones comerciales. Aunque, por una serie de razones de las que hablaremos más abajo, esto no será el trading completamente idéntico. Sin embargo, estas razones no podrán ser un obstáculo para obtener el beneficio real usando un Asesor Experto rentable escrito en MQL5.

La primera razón que reduce el beneficio es la diferencia en las cotizaciones. Con diferentes brokers esta diferencia puede superar un spread. El caso es que, la transmisión se realiza en tiempo real. Y si en MetaTrader 5 el Asesor Experto ha decidido abrir la posición en un nivel determinado, el broker al que está conectado MetaTrader 4 simplemente puede tener otro precio. Además, en este caso la diferencia puede ser tanto a favor, como en contra.

La segunda razón que puede reducir el beneficio es el factor de tiempo. La posición se copia cuando ya ha aparecido en MetaTrader 5, y eso significa que el retraso es inevitable.

Estas dos razones inutilizan todas las estrategias de scalping. Por eso hasta que en MetaTrader 5 esté disponible el trading real, no se podrá aplicar dichas estrategias. 

Los sistemas, que suponen obtener beneficio (desde el trade) y que superan bastante el spead y no son sensibles a las cotizaciones de un determinado broker, sí que pueden ser iniciados para obtener el beneficio real utilizando el copiador de posiciones.


2. Planteamiento del problema

  1. Vinculación para transmitir las señales entre MetaTrader 5 y MetaTrader 4
  2. Transmisión de posiciones desde MetaTrader 5
  3. Recepción de señales en MetaTrader 4
  4. Repetición de posiciones comerciales en MetaTrader 4

2.1. Vinculación para transmitir las señales entre MetaTrader 5 y MetaTrader 4

Lo primero que llega a la mente es la transmisión de señales a través de un archivo compartido. La pregunta es la siguiente: ¿si podrán las entradas frecuentes dañar el hardware? Si los nuevos datos se escriben sólo cuando se haya producido el cambio de la posición, estas entradas no serán muy frecuentes. No con más frecuencia que los desarrolladores de Windows realizan los cambios en el archivo de paginación. Eso, en su lugar, es una operación ya comprobada que no provoca el daño del hardware. La escritura en un archivo compartido es una implementación aceptable para las solicitudes no muy frecuentes. Es una limitación más para las estrategias de scalping, aunque no tan significante en comparación con las limitaciones anteriores.

Para la vinculación podemos usar el recurso de MetaTrader 5 para escribir las subcarpetas para cualquier profundidad. No he comprobado lo de este "cualquier", pero hasta 10 subdirectorios, eso es cierto. Es que, tampoco necesitamos más. Claro que se puede utilizar DLL para organizar el acceso. Pero mi posición de principio consiste en no utilizar DLL si se puede solucionar el problema sin acudir a ellas. Para solucionar el problema sin DLL, bastará con instalar MetaTrader 4 en la carpeta \Files\ del terminal MetaTrader 5 (véase operaciones con archivos).

Entonces, la ruta hacia el archivo compartido será la siguiente:

C:\Program Files\MetaTrader 5\MQL5\Files\MetaTrader 4\experts\files\xxx      //donde xxx-nombre del archivo compartido.

Con esta ubicación el archivo estará disponible tanto en MetaTrader 4, como en MetaTrader 5. La posibilidad del uso compartido del archivo está prevista en las prestaciones funcionales del MQL5.

2.2. Transmisión de posiciones desde MetaTrader 5

Para la transmisión de posiciones y el consumo económico de recursos, hace falta una función que va a monitorear la situación de aparición/cambio/cierre de la posición comercial para todos los instrumentos. Como hemos dicho antes, para la transmisión del trading, hace falta sólo saber el volumen de la posición comercial. Añadiremos al volumen el símbolo del instrumento y los niveles SL y TP.

Para monitorear los cambios, necesitaremos saber el estado anterior de la posición. Y si el estado anterior y el actual no son iguales (significa que la posición ha cambiado), eso hay que reflejar en el archivo. Además, vamos a necesitar una función que escriba esta información en el archivo. Este archivo hay que abrir de tal manera que esté disponible para el uso simultaneo por varios programas.

Para no perder el momento del cambio de la posición, el sistema de monitoreo tiene que ser implementada en la función OnTimer(), porque habrá que monitorear todos los instrumentos simultáneamente, y los ticks llegan a la hora diferente para los símbolos diferentes. Además, hay que enviar la señal sobre el cambio del contenido del archivo.

2.3. Recepción de señales en MetaTrader 4

Hay que rastrear la señal de actualización del archivo. Eso se puede organizar a través de la variable cuyo estado se monitorea para la entrada en la zona del cambio de las posiciones. Necesitamos una función que lea el archivo con el estado de las posiciones. Es una función estándar, que son muchas. Con eso no habrá ningún problema.

Transmisión del contenido del archivo a los arrays para los cálculos. Aquí necesitaremos un analizador sintáctico (parser). Ya que se transmiten no sólo los números, sino también los símbolos, sería mejor codificar todo en el tipo string a la hora de transmitir desde MetaTrader 5. Además, si escribimos todos los datos para cada símbolo en una cadena de texto, evitamos la posibilidad de confundir los datos.

2.4. Repetición de posiciones comerciales en MetaTrader 4

Es el mayor conjunto de funciones. Habrá que dividirlo en varias subclases.

  1. Comparación de posiciones virtuales;
  2. Función de selección de órdenes;
  3. Función de apertura de órdenes;
  4. Función de cierre de órdenes;
  5. Función de modificación de órdenes.

2.4.1. Comparación de posiciones virtuales

La comparación de las posiciones virtuales se requiere para garantizar que las posiciones se encuentren en conformidad. La función debe calcular la posición para cada instrumento en concreto, también ser capaz de filtrar las posiciones para los que el trading está prohibido (si existen).

En la práctica puede surgir situación cuando el broker no tenga instrumento para el que ha sido transferida la señal desde MetaTrader 5. Pero eso no tiene que bloquear el trading en general, aunque hay que prever un aviso. El usuario tiene derecho a ser informado sobre dicha situación.

2.4.2. Función de selección de órdenes

Esta función tiene que escoger las órdenes dependiendo del símbolo para trabajar con ellas en futuro. Y en este caso, ya que estamos transmitiendo sólo las posiciones abiertas, las órdenes también tienen que ser filtradas para que no se metan las órdenes pendientes.

2.4.3. Función de apertura de órdenes

Tiene que contener el máximo número de los cálculos. De esta manera, será suficiente pasar el volumen y el tipo.

2.4.4. Función de cierre de órdenes

Igual que la función anterior tiene que calcular todo antes de dar el comando para el cierre.

2.4.5. Función de modificación de órdenes

La función tiene que contener la comprobación a propósito de la proximidad al mercado. Además, sería deseable colocar la orden y sus niveles Stop en momentos diferentes, porque no todos los brokers permiten la colocación simultánea de los niveles Stop a la hora de la apertura. Es más, la apertura de la orden y de los niveles Stop en el mismo momento aumenta la probabilidad de las recuotas.

Así, la posición será repetida máximamente rápido. Y la colocación de los niveles Stop es una cuestión secundaria, aunque también no deja de ser importante.


3. Implementación

Los códigos están comentados muy detalladamente, casi cada línea. Por eso voy a explicar sólo los momentos más difíciles.

Vinculación para transmitir las señales entre MetaTrader 5 y MetaTrader 4

La vinculación ha sido implementada en MetaTrader 5 a través de la función:

void WriteFile(string folder="Translator positions") // por defecto se pone el nombre del archivo compartido

Las banderas de apertura significan:

FILE_WRITE|FILE_SHARE_READ|FILE_ANSI

archivo se abre para la escritura | para diferentes programas se permite el uso compartido para la lectura | en codificación ansi

En MetaTrader 4 la vinculación ha sido implementada a través de la función:

int READS(string files,string &s[],bool resize)

El parámetro resize prohíbe la redistribución de la memoria del array de los datos recibidos. En el código la asignación de la memoria para este array se realiza durante cada iteración, ya que el desarrollador no puede predecir cuántas líneas van a haber. Eso depende del número de instrumentos elegidos en MetaTrader 5. Por eso no es posible calcularlo de antemano en MetaTrader 4.

Entonces, hay que aumentar el array por un uno en cada paso. Pero habrá que bloquear esta operación en la segunda llamada a la función, porque la longitud del array ya está determinada y no va a cambiarse. Para eso tenemos la variable bool resize.

Transmisión de posiciones desde MetaTrader 5

Para organizar la transmisión en la función OnTimer con la frecuencia de 1 segundo, los datos sobre todas las posiciones se reciben en la función:

void get_positions()

Con la siguiente comparación del valor anterior de la posición con el valor actual en la función:

bool compare_positions()

La salida por return(true) ocurre en el caso si al menos una célula no coincide. La salida por return(true) significa que las posiciones no son iguales y el archivo tiene que ser reescrito. Al reescribir el archivo , el contador de reescritura cnt_command se aumenta a un uno.

Recepción de señales en MetaTrader 4

Después de que la función READS() haya leído el archivo, tenemos el array de cadenas llenado s[].

Para que estas cadenas se conviertan en una información útil, hace falta un analizador sintáctico (parser).

La función:

int parser(int Size)

es sólo un envoltorio (wrapper) para la llamada a la función de identificación de la cadena:

void parser_string(int x)

La función reconoce todas las células, excepto los símbolos.

El reconocimiento de los símbolos se realiza en ciclo (sólo una vez, al principio del algoritmo) a través de la función:

void parser_string_Symbols(int x)

Luego no vamos a referirnos al código en mql5, y sólo discutiremos el código mql4, si eso no se especifica aparte.

Comparación de posiciones virtuales

La comparación de las posiciones se divide en dos partes. La comparación del volumen y el tipo de la posición está implementado en la función:

bool compare_positions()

en este envoltorio está implementada la llamada para obtener el estado real de la posición en la función:

void real_pos_volum()

y el ciclo de comparación según el principio ya mencionado "todo o nada". Es decir, si al menos una célula no coincide, todas las posiciones se consideran diferentes. En real_pos_volum() está implementada una serie de filtros descritos detalladamente en el mismo código, y que van a utilizarse repetidamente en otras funciones.

En particular, será usada a la hora de sumar todas las órdenes del mismo símbolo en una posición virtual. Para que las posiciones de bloqueo (si existen) se procesen correctamente, las órdenes buy tendrán el volumen con un menos, y las órdenes sell con un más.

La segunda parte de la comparación es la comparación de los niveles stop (con los niveles stop se sobreentiende no sólo Stop Loss, sino también Take Profit), está implementada en la función similar a la anterior:

bool compare_sl_tp_levels()
Igual que en el caso con los volúmenes, dentro del envoltorio se realiza la llamada para obtener la información sobre el estado real de los niveles stop en la función:
void real_pos_sl_tp_levels()

Función de selección de órdenes

Las órdenes se seleccionan sólo para el cierre del volumen, por eso la función de la selección compleja y especializada está implementada exclusivamente para el cierre:

void close_market_order(string symbol,double lot)

Tiene los parámetros del símbolo y el volumen que hay que cerrar. Para fraccionar la orden lo menos posible, en el primer ciclo de la función se realiza la búsqueda de la orden que por su volumen sea igual al volumen de cierre pasado en el parámetro.

Si esta orden no existe (de lo que dice el estado true de la bandera de cierre FlagLot), entonces se cierra el volumen (especificado en el parámetro) de la primera orden del ciclo (la comprobación del exceso del volumen de la orden está implementada en la función de cierre Closes()).

La selección de la órdenes para la modificación de los niveles stop está implementada en la función:

void modification_sl_tp_levels()

Las órdenes se filtran sólo por el símbolo, porque todos los niveles stop dentro de un instrumento son iguales.

Función de apertura de órdenes

Está implementada en la función:

int open_market_order(string symbol,int cmd,double volume,
                     int stoploss=0,int takeprofit=0,int magic=0)

contiene todas las verificaciones necesarias para una cómoda apertura de la orden usando los datos especificados.

Función de cierre de órdenes

Está implementada en la función:

bool Closes(string symbol,int ticket,double lot)

El código contiene una verificación para el caso cuando el parámetro lot supere el volumen real de la orden seleccionada anteriormente.

Función de modificación de órdenes

Está implementada en la función:

bool OrderTradeModif(int ticket,string symbol,int cmd,double price,
                    double stoploss=0,double takeprofit=0,int magic=0)

El código contiene verificaciones: si los niveles stop no corresponden al tipo de la orden, se realiza el intercambio de los valores. Además, se comprueba si los niveles ya tienen el valor solicitado.

4. Funciones de lógica

El plan formado anteriormente ya está terminado pero en el código quedan algunas funciones no aclaradas. Se trata de las funciones de lógica. Se puede decir que son las funciones básicas que mueven todo el proceso.

void processing_signals()
void processing_sl_tp_levels()

Ambas funciones son ciclos infinitos con la salida a través de break condicional. Cabe mencionar que el script está implementado como bucle infinito. Para que el usuario pueda eliminar fácilmente el programa, en la condición principal del ciclo ha sido insertada la función IsStopped().

El código se transfiere desde el Asesor Experto en el script cíclico de la siguiente manera:

 // Init()
 while(!IsStopped())
    {
     // Start()
     Sleep(1000);
    }
 // Deinit()

Toda la lógica del script está descrita en el mismo bucle infinito en la función estándar start().

El código del ciclo ubicado en start() será el siguiente:

     Si el flujo comercial no está ocupado
          Leer el archivo y guardar los datos en el array (sin cambiar el tamaño del array);
          Si dentro del array ha habido cambios,
               escribimos nuevos comentarios;
               recordamos la hora del inicio de los ciclos de comprobación de la conformidad (ubicados más abajo);
               si las posiciones cuyos volúmenes se comparan no son iguales,
                    procesamos las posiciones por volúmenes;
               si las posiciones cuyos stops se comparan no son iguales,
                    procesamos las posiciones por stops;
               calculamos la hora de terminación de las comprobaciones;
          Si el tiempo no ha sido superado,
               hacemos la pausa para el resto del tiempo;

Las construcciones lógicas más complicadas se encuentran en las funciones processing_signals() y processing_sl_tp_levels().

Vamos a empezar las descripción de las funciones "de simple a complejo". Aunque dentro del código la llamada va al revés.

//+------------------------------------------------------------------+
//| procesamiento de los niveles stop                                |
//+------------------------------------------------------------------+
void processing_sl_tp_levels()
  {
//--- recordamos la hora de entrada en el ciclo   
   int start=GetTickCount();
   while(!IsStopped())
     {
      //--- si el flujo comercial no está ocupado
      if(Busy_and_Connected())
        {
         //--- selección de la orden y modificación de los niveles stop           
         modification_sl_tp_levels();
        }
      //--- si el tiempo de retraso se ha expirado, actualizaremos la información desde el archivo  
      if(GetTickCount()-start>delay_time)READS("Translator positions",s,false);
      //--- si en el archivo se ha cambiado el contador de actualizaciones, salimos del ciclo      
      if(cnt_command!=StrToInteger(s[0]))break;
      //--- micro pausa      
      Sleep(50);
      //--- si los niveles stop reales y los del archivo son iguales, salimos del ciclo     
      if(!compare_sl_tp_levels())break;
     }
   return;
  }

Como ya hemos mencionado antes, la función es un bucle infinito con la salida por dos condiciones:

La primera condición de la salida del ciclo ocurre cuando el valor cnt_command no es igual al mismo valor en el archivo. Antes de eso se realiza la recepción de la última información sobre el archivo con la condición de que el tiempo de trabajo del ciclo haya superado el retraso establecido en la variable global delay_time.

El tiempo puede ser superado, ya que todas las modificaciones están protegidas con el filtro Busy_and_Connected(). Es decir, entrar sólo si el flujo comercial está libre.

Es necesario explicar que en MetaTrader 4 (a diferencia de MetaTrader 5) resulta imposible enviar una serie de comandos al servidor sin obtener la recotización (requote). El servidor puede aceptar sólo la primera solicitud, las demás serán perdidas. Por eso antes de enviar el comando al servidor, hay que comprobar si el flujo comercial está libre.

La segunda comprobación para la salida del ciclo es la función descrita anteriormente de comprobación de la posición por niveles stop compare_sl_tp_levels(): si las posiciones son iguales, salimos del ciclo.

Ahora vamos a lo complicado: la función processing_signals() está organizada de forma similar, pero la parte lógica se diferencia mucho en su funcionalidad.

Pues, vamos a analizar detalladamente está parte:

//--- convertimos la dirección de las posición guardada en el archivo en la forma -1,+1            
int TF=SymPosType[i]*2-1;
//--- convertimos la dirección de la posición real en la forma -1,+1
int TR=realSymPosType[i]*2-1;
//--- guardamos el volumen de la posición almacenada en el archivo                     
double VF=SymPosVol[i];
//--- guardamos el volumen de la posición real 
double VR=realSymPosVol[i];
double lot;
//--- si las posiciones para el símbolo actual no son iguales
if(NormalizeDouble(VF*TF,8)!=NormalizeDouble(VR*TR,8))
  {
//--- si el volumen real no es igual a cero y las direcciones no son iguales, o
//--- si las direcciones son iguales y el volumen real supera el volumen en el archivo                              
   if((VR!=0 && TF!=TR) || (TF==TR && VF<VR))
     {
      //--- si las direcciones son iguales y el volumen real supera el volumen en el archivo 
      if(TF==TR && VF<VR)lot=realSymPosVol[i]-SymPosVol[i];
      //--- si el volumen real no es igual a cero y las direcciones no son iguales
      else lot=realSymPosVol[i];
      //--- cerramos para el volumen calculado y salimos del ciclo                  
      close_market_order(Symbols[i],lot);
      break;
     }
   else
     {
      //--- si las direcciones son iguales y el volumen real es menor que el volumen en el archivo 
      if(TF==TR && VF>VR)lot=SymPosVol[i]-realSymPosVol[i];
      //--- si las direcciones no son iguales y el volumen real es igual a cero                  
      else lot=SymPosVol[i];
      //--- abrimos para el volumen calculado y salimos del ciclo 
      open_market_order(Symbols[i],SymPosType[i],lot);
      break;
     }
  }

Las variables TF,TR guardan el valor del tipo de la posición como buy=-1,sell=1. Correspondientemente, TF es el valor guardado en el archivo, TR es el valor real de la posición virtual. Lo mismo pasa con los volúmenes VF,VR.

De esta manera, la desigualdad:
if(VF*TF!=VR*TR)

será true si los volúmenes o tipos de las posiciones no son iguales.

Luego va el conjuntivo lógico:

if((VR!=0 && TF!=TR) || (TF==TR && VF<VR))

que significa que si el valor real no es igual a cero y los tipos no son iguales, hay que cerrar la posición entera.

Esto incluye las opciones cuando el volumen en el archivo es igual a cero, y la opción cuando la posición está invertida por dirección. En la variante cuando la posición está invertida por dirección, primero hay que preparar la posición para la apertura, es decir cerrar el volumen anterior. Entonces, durante la siguiente iteración la lógica irá por otro ramo, para la apertura.

La segunda condición complicada del conjuntivo lógico significa que si el tipo es correcto pero el valor real es mayor que el que se guarda en el archivo, entonces hay que reducir el volumen real. Para eso primero se calcula el tamaño del lote que es necesario para reducir el volumen.

Si ninguna condición del cierre conviene a esta situación, y las posiciones (como hemos aclarado en el primer filtro) no son iguales, entonces hay que abrir nueva orden. Aquí también hay dos opciones: abrir la orden para el tamaño entero de la posición en el archivo o añadir hasta las órdenes existentes. Ahora me gustaría subrayar que la comprobación del exceso del volumen límite se encuentra en la misma función de apertura, por eso el volumen que falta (si la comprobación no lo ha permitido) será abierto durante la siguiente iteración del algoritmo. Debido a que primero se procesan las situaciones de cierre y sólo luego de apertura, la situación de bloqueo es prácticamente imposible.

Al final del análisis de los códigos me gustaría mencionar un lugar delicado que ha requerido bastantes esfuerzos durante el desarrollo del algoritmo. La situación de reapertura de una orden que acaba de cerrarse en MetaTrader 4 por accionamiento de stops. Ya he mencionado antes que la discrepancia de las cotizaciones suele mantenerse en torno de 2-3 puntos de cinco dígitos. Con un spread de 15 la diferencia no es importante. Pero con esta diferencia, si Stop Loss o Take Profit se activaba en MetaTrader 4 antes que en MetaTrader 5, surgía la situación cuando el algoritmo intentaba recrear la posición recién cerrada, con su posterior eliminación cuando se activaban los stops en MetaTrader 5.

Eso no suponía grandes pérdidas, pero un spread se perdía en vano. Por esta razón el algoritmo fue rediseñado de tal manera que después de la eliminación de la posición MetaTrader 4 no la restauraba, sino esperaba el cambio del estado del archivo. Y sólo después, volverá a actuar. En esta situación, el trader puede eliminar la posición manualmente si la considera incorrecta. Y ella no será restaurada hasta que MetaTrader 5 haga los cambios en el archivo.

El único punto débil es la rara situación cuando los stops de MetaTrader 4 eliminarán la posición, y en MetaTrader 5 la posición no será cerrada. En este caso puedo aconsejar reiniciar el script Copyist positions. Y lo último, el código no verifica el trabajo los fines de semana. Eso no importa, excepto que el log estará lleno de las recotizaciones absolutamente inútiles.


5. Comprobando la implementación en la práctica

Instalamos MetaTrader 4 en la carpeta C:\Program Files\MetaTrader 5\MQL5\Files\

Iniciamos el Asesor Experto compilado Translator positions en cualquier gráfico en MetaTrader 5  (el trabajo del Asesor Experto no depende del gráfico en el que ha sido iniciado).

Fig. 2. Translator positions en MetaTrader 5 

Fig. 2. Translator positions en MetaTrader 5

En la pantalla aparece el comentario de varias líneas que muestra el estado del contador en la primera línea y el log de todas las posiciones en cada siguiente línea.

Iniciamos el script compilado Copyist positions en cualquier gráfico en MetaTrader 4  (el trabajo del script ciclado no depende del gráfico en el que ha sido iniciado). En la pantalla aparece el comentario de varias líneas que muestra el estado del contador en la primera línea y el log de todas las posiciones en cada siguiente línea.

Fig. 3. Copyist positions en MetaTrader 4

Fig. 3. Copyist positions en MetaTrader 4

A continuación podemos iniciar cualquier Asesor Experto en MetaTrader 5. Los resultados de su trabajo serán copiados en MetaTrader 4 con la máxima rapidez.

Fig. 4. Posiciones y órdenes en los terminales MetaTrader 4 (arriba) y MetaTrader 5 (abajo)

Fig. 4. Posiciones y órdenes en los terminales MetaTrader 4 (arriba) y MetaTrader 5 (abajo)

Por cierto, la administración de la cuenta en MetaTrader 5 se puede realizar manualmente, o la cuenta puede ser logueada usando la contraseña de inversor.

Así, por ejemplo, Usted puede iniciar el copiador en cualquier cuenta del Campeonato.


Conclusión

Este artículo sirve para acelerar la transición de los traders a nueva plataforma y estimular el aprendizaje de MQL5.

En conclusión me gustaría decir que el presente código no puede sustituir completamente el trading directo en una cuenta real en MetaTrader5. Está escrito como un código universal para cualquier sistema de trading sin tomar en consideración la lógica. Por tanto, como todo lo que es universal, no es ideal. Basándose en él, Usted puede escribir el transmisor de señales para una estrategia concreta. Para muchos traders que no dominan la programación, este código  puede servir de fase transitoria a la espera del lanzamiento.

A los que dominan bien la programación les recomiendo mejorar el código en cuanto al reconocimiento de las órdenes por el número mágico, e implementar la transmisión y colocación de las órdenes pendientes. La colocación de las órdenes pendientes no influye en la obtención del beneficio si la conexión con el servidor es estable. Pero si las pérdidas de conexión ocurren a menudo, hay que copiar toda la parte del servidor, inclusive las órdenes pendientes también.

Aprendan el nuevo lenguaje, utilícenlo para escribir los sistemas de trading automatizados. ¡Qué tengan suerte en el trading!

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/189

Archivos adjuntos |
Cómo reducir el gasto de memoria en los indicadores auxiliares Cómo reducir el gasto de memoria en los indicadores auxiliares
Si el indicador implica en sus cálculos los valores de muchos otros indicadores, este tipo de sistema gastará mucha memoria. En el artículo veremos varias maneras de reducir el gasto de memoria al usar los indicadores auxiliares. La memoria ahorrada le permitirá aumentar el número de parejas de divisas, de indicadores y estrategias usadas de manera simultánea en el terminal, incrementando así la fiabilidad de su portfolio comercial. De este modo, esta pequeña gestión de los recursos de su computadora es capaz de convertirse en recursos materiales para su propio uso.
Los miembros más activos de la comunidad MQL5 ¡han sido premiados con iPhones! Los miembros más activos de la comunidad MQL5 ¡han sido premiados con iPhones!
Después de que decidiéramos premiar a los participantes más destacados de MQL5.com, hemos seleccionado el criterio clave para determinar la contribución de cada participante al desarrollo de la Comunidad. Como resultado, tenemos los siguientes campeones que publicaron la mayor cantidad de artículos en la website - investeo (11 artículos) y victorg (10 artículos) y quien envió sus programas a la Base de Código - GODZILLA (340 programas), Integer (61 programas) y abolk (21 programas).
Cómo deshacerse del lastre de las DLL caseras Cómo deshacerse del lastre de las DLL caseras
Si a un programador de MQL5 no le basta con la funcional del lenguaje, entonces deberá recurrir a instrumentos adicionales. Para ello debrá usar otro lenguaje de programación y crear un DLL intermedio. En MQL5 existe un mecanismo de representación de diversos tipos de datos, con ayuda de estructuras y su transmisión a API, pero por desgracia, el MQL5 no responde a la cuestión de cómo extraer los datos del índice adoptado. En este artículo vamos a poner punto final a esta cuestión, mostrando mecanismos sencillos de intercambio de tipos complejos de datos y cómo trabajar con ellos.
Programación basada en autómatas como nuevo enfoque en la creación de sistemas de trading automatizados Programación basada en autómatas como nuevo enfoque en la creación de sistemas de trading automatizados
Este artículo nos lleva en una nueva dirección a la hora de desarrollar Asesores Expertos, indicadores y scripts en MQL4 y MQL5. En el futuro, este modelo de programación se convertirá en un estándar para todos los operadores en la implementación de Asesores Expertos. Utilizando el modelo de programación basado en autómatas, los desarrolladores de MQL5 y Meta Trader 5 estarán cerca de poder crear un nuevo lenguaje, MQL6, y una nueva plataforma, Meta Trader 6.