Descargar MetaTrader 5

Programación basada en autómatas como nuevo enfoque en la creación de sistemas de trading automatizados

14 marzo 2014, 10:33
GOURO
0
989

ἓν οἶδα ὅτι οὐδὲν οἶδα ( ο φιλόσοφος Σωκράτης )

Solo sé que no sé nada (el filósofo Sócrates)


Introducción

Para empezar, esta materia es completamente nueva para los operadores que desarrollan Asesores Expertos mediante el lenguaje de MetaQuotes 4/5 (MQL4/5). Pude verlo por mí mismo cuando intenté hacer la respectiva investigación en la web de MetaQuotes. No hay nada sobre este asunto.

Cada operador crea su propio Asesor Experto que requiere un serio enfoque para afrontar todos los problemas asociados a la programación y la complicada lógica del programa. Al final del día se supone que el programa se ejecuta POR SÍ MISMO como un mecanismo de relojería en cualquier situación normal o de fuerza mayor.

Pero ¿cómo puede uno abarcarlo todo? Esto es extremadamente difícil y por esta razón que los sistemas de control requieren una programación adecuada, siendo la mejor forma de conseguirlo el uso de las técnicas de programación más apropiadas basadas en autómatas. En los últimos años, se ha prestado gran atención al desarrollo de tecnologías de programación para sistemas adheridos y en tiempo real que establecen altos requisitos de calidad del software.

En 1991, el autor ruso A.A. Shalyto (conferenciante, Doctor en Ingeniería, Jefe del Departamento de "Tecnologías de Programación en SPbSU ITMO) desarrolló una tecnología de programación que llamó "programación basada en autómatas". Creo que a los lectores les puede interesar ver lo simple que es la programación basada en autómatas o tecnología SWITCH. Permite realizar desarrollos de MTS usando el lenguaje de MetaQuotes tan correctamente que no se podría hacer mejor. Y se integra bien en el sistema de toma de decisiones complejas.


1. Preparando el terreno para el problema

El sueño de todo creador y programador de software debe ser disponer de una solución al problema (algoritmo) y de una implementación del algoritmo que sea coherente con él. Pero no parece que sea así para los creadores y desarrolladores. Los algoritmos tienden a omitir lo que es importante para la implementación por parte de los desarrolladores, al tiempo que el texto del programa en sí se parece poco al algoritmo.

Por ello, existen dos algoritmos, uno es el que está sobre el papel (para guardar y documentar las soluciones de diseño) que normalmente representa un cierto diseño en vez de los métodos empleados para obtener un determinado resultado, mientras que el segundo algoritmo está en la mente del programador (que está también guardado textualmente).

La versión final del texto del programa va seguida a menudo por intentos de modificar la documentación donde, de nuevo, muchas cosas no se tienen en cuenta. En esta caso, la lógica del programa puede ser igualmente diferente de la lógica del algoritmo, demostrando una falta de correspondencia. Digo "igualmente" porque nadie va a comprobar nunca el texto del programa de nadie.

Si el programa es extenso, es imposible comprobar si se corresponde con el algoritmo solo a partir del texto. La exactitud de la implementación puede comprobarse usando un procedimiento llamado "prueba". Básicamente comprueba cómo el programador captó el algoritmo (que estaba sobre el papel), lo transformó en otro algoritmo en su mente y generó el programa. Con el tiempo, el desarrollador es el único poseedor de la información valiosa sobre la lógica y todo lo realizado antes de la implementación es absolutamente irrelevante.

No es que el desarrollador pueda caer enfermo (o renunciar). La cuestión es que la lógica del programa subyacente sería distinta con cada programador dependiendo de su inteligencia y conocimiento del lenguaje de programación. En cualquier caso, el programador introduce y utiliza muchas variables intermedias según cree conveniente. Y si el programa es extenso y complejo, se requieren los servicios de un especialista más cualificado para encontrar los fallos (y no me refiero a fallos del sistema operativo o del uso incorrecto de de las funciones del programa, sino a la implementación incorrecta en términos de lógica) y resolverlos en el mismo texto del programa.

A la mayoría de los programadores no les gusta escribir algoritmos antes de programar (ni siquiera esbozarlos en un papel), lo que se debe probablemente al hecho de que no necesitan inventar nada durante el proceso. De hecho, para qué perder tiempo en dibujar unos rectángulos, diamantes y flechas cuando es mejor programar directamente y luego diseñar algo parecido o un algoritmo muy general de que ya esté en la documentación.

Todo el mundo se ha acostumbrado a hacerlo así, los desarrolladores lo hacen porque es más fácil de esta forma, mientras que los creadores no siempre tienen las habilidades de programación necesarias e incluso si las tienen, no son capaces de hacer un cambio a tiempo respecto a lo que los desarrolladores puedan proponer. Los entornos de programación adecuados también contribuyen a la validez de la orden especificada de desarrollo. Las herramientas avanzadas de depuración y monitorización de los valores de las variables nos permiten esperar la detección de cualquier error en la lógica.

A medida que transcurre el tiempo y se aproxima la fecha de entrega del proyecto, el desarrollador se encuentra esbozando en una "servilleta" las soluciones a los problemas lógicos que, por cierto, todavía deben ser implementados, por no mencionar los errores pasados por alto durante las pruebas que siguen un escenario (caótico) muy parecido... Esta es la situación actual. ¿Hay alguna solución o puede al menos mejorarse? Creo que se ha perdido algo importante en la transición de un algoritmo diseñado según la forma estándar y el código del programa.


2. La parte lógica del programa

El autor de la "programación basada en autómatas" propuso el siguiente concepto de la parte lógica ideal de un programa. Toda la lógica del programa se basa en el interruptor. En pocas palabras, cualquier algoritmo de control (autómata) puede ser implementado como se muestra a continuación (no le de muchas vueltas al significado de los comentarios en este momento, tan solo observe la estructura).

switch(int STATUS ) // Мulti-valued global state variable of the automaton.
{
  case 0:  // start

  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met. 0

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;
  
  case 1:
  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met. 

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;
  
*********
*********
*********

 case N-1:
  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met. 

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;

 case N:
  // Checking arc and loop conditions (in order of priority),
  // transition (change of the value of the variable STATUS)
  // and execution of arc and loop actions (output function execution);
  // logging transitions and actions if the condition is met.

  // Calling nested automata.
  // Execution of output functions in the state.
  break ;
}


3. Programación basa en autómatas explicada por el autor A.A. Shalyto

Con independencia de las técnicas de desarrollo, cualquier programa posee estados que vienen determinados por todos los valores de sus datos en un momento determinado. Puede haber cientos en incluso miles de variables y algunos flujos de control en un programa de una gran aplicación. El estado de la aplicación en un momento concreto viene descrito por un conjunto de variables.

El estado del programa puede ser tratado de forma simple como una colección de valores de todas las variables de control, las que participan en todas las condiciones de la transición. Un cambio en una de las variables de control implicará un cambio en el estado del programa, y el número de estados posibles del programa vendrá determinado por el número máximo posible de combinaciones de los valores de las variables de control que surjan durante la operación del programa. Supongamos que solo se usan variables de control binarias (flags) en un programa. El número de estados del programa que contienen n variables de control binarias quedará comprendido, en este caso, en un rango entre n a 2n.

Puede ser que el desarrollador haya previsto las reacciones de todas las combinaciones de los valores de las variables de control (2n combinaciones en nuestro caso). Sin embargo, es más probable que algunas combinaciones de los valores de las variables de control (hasta 2n-n) no estén especificadas. Luego si surge una combinación inesperada de las acciones de entrada, el programa puede realizar una transición hacia un estado no especificado.

Tiene el mismo efecto que una inactividad de un Asesor Experto para un operador en los siguientes eventos:

  • lagunas,
  • pérdida del depósito,
  • tener un saldo negativo con la consiguiente Margin Call,
  • no tener un buen beneficio y dirigiéndose a cero y luego en el rojo,
  • apertura y cierre incorrectos de largas y cortas,
  • otras situaciones adversas.

Dichos estados se llaman "no visualizados". La complejidad provoca una dificultad a la hora de hacer una enumeración, mucho menos comprensible, todos los posibles estados del programa que llevan a su falta de fiabilidad... La complejidad de la estructura es la fuente de estados no visualizados que constituyen puertas traseras en materia de seguridad. L comportamiento del programa en un estado no especificado puede variar desde fallos en la protección de la memoria a ampliar las funciones del programa y crear efectos colaterales de distinta naturaleza.

Muchas usuarios de PC y probablemente todos los desarrolladores de software se han encontrado con situaciones donde el programa en uso o bajo desarrollo se sitúa en un estado no determinado.

Para eliminar la posibilidad de estados no especificados en el programa, todos los estados requeridos deben ser explícitamente especificados en la etapa de diseño y solo debe usarse una variable de control de valores múltiples para poderlos distinguir entre sí. Es necesario identificar todas las posibles transacciones entre los estados y desarrollar un programa para que no vaya "por mal camino".

Estos son los tres componentes necesarios para conseguir cierto rigor en el desarrollo del comportamiento del programa:

  • Un modelo matemático que permita identificar sin ambigüedad los estados del programa y las posibles transiciones entre estos;
  • Notación gráfica para ese modelo;
  • Método universal para la implementación de algoritmos expresado en esta notación.

Una automatización finita basada en el concepto de "estado" se propone para su uso como modelo matemático. La programación basada en autómatas soporta dichas etapas de desarrollo del software como el diseño, la implementación, la depuración y la documentación.

En vista de que el término "evento" se está haciendo más habitual en la programación en los últimos años, el enfoque propuesto se basa en el concepto de "estado". Después de asociarlo con el término "acción de entrada" que puede ser una variable de entrada o un evento, puede presentarse el término "automatización sin salida". Este último es seguido del término "acción de salida" y se introduce además el concepto de automatización (finita determinista). El área de programación basada en este concepto se llama programación basada en autómatas y al correspondiente proceso de desarrollo se hace referencia con el nombre de diseño de programa basado en autómatas.

El enfoque señalado es peculiar en el sentido de que es aplicado, el autómata es representado mediante gráficos de transición. Para distinguir entre sus nodos, se presenta el término "asignación de estado". Al elegir una "asignación de estado con valores múltiples", los estados cuyos números coinciden con el número de valores que puede tomar la variable elegida, pueden distinguirse usando solo una variable. Este hecho permitió introducir en la programación el término "observación del programa".

La programación bajo el enfoque propuesto se realiza a través de "estados" en lugar de "variables" (flags) que ayudan a comprender y especificar mejor el problema y sus componentes. La depuración se realiza en este caso registrando los términos del autómata.

Como el enfoque anterior propone ir desde el gráfico de la transición al código del programa usando un método formal e isomórfico, parece que es más razonable hacer esto aplicando estructuras de interruptor (switch) cuando se usan lenguajes de programación del alto nivel. Por eso se decidió usar el término "tecnología SWITCH" para hacer referencia al modelo de programación basada en autómatas.


4. Programación explícita basada en el estado

La aplicación del enfoque basado en autómatas se extendió posteriormente a los sistemas guiados por eventos que también se llaman "reactivos". Los sistemas reactivos interaccionan con el entorno usando mensajes a la velocidad establecida por el entorno (puede incluirse un Asesor Experto en la misma clase).

El desarrollo de los sistemas guiados por evento que usan autómatas se hizo posible gracias al empleo del enfoque basado en el procedimiento, del que derivó el nombre de programación explícita basada en el estado. Las acciones de salida se asignan en este método a los arcos, lazos o nodos de los gráficos de transición (se utilizan los autómatas mixtos de Moore y Mealy). Esto permite tener una representación compacta de la serie de acciones que son reacciones a las acciones de entrada correspondientes.

El enfoque propuesto de programación de esta clase de sistemas dispone de una mayor centralización de la lógica debido a que ha sido eliminada de los controladores de eventos y a la generación de un sistema de autómatas interconectados que son llamados desde los controladores. La interacción entre autómatas en dicho sistema puede conseguirse anidando, llamando e intercambiando una serie de estados.

El sistema de autómatas interconectados constituye una parte del programa independiente del sistema, mientras que se forma una parte dependiente a partir de funciones de acciones de entrada y salida, controladores, etc.

Otra característica fundamental de dicho enfoque es que cuando este se aplica, los autómatas son usados de tres formas:

  • para la especificación;
  • para la implementación (permanecen en el código del programa);
  • para registrar términos del autómata (según se indicó anteriormente).

El último permite controlar la precisión de la operación del sistema autómata. El registro se realiza automáticamente en base al programa desarrollado y puede usarse para problemas de grandes dimensiones con lógica de programas complejos. Cada registro puede, en este caso, ser considerado un script.

Los registros permiten monitorizar el programa durante la operación e ilustran el hecho de que los autómatas no son "imágenes" sino entidades activas reales. El enfoque basado en autómatas se ha propuesto para su uso no solo a la hora de crear un sistema de control, sino también para modelar objetos de control.


5. Conceptos básicos de la programación basada en autómatas

El concepto básico de programación basada en autómatas es ESTADO. La principal propiedad del estado del sistema en un momento específico t0 es "separar" el futuro (t > t0) del pasado (t < t0) en el sentido de que el estado contiene toda la información sobre el pasado del sistema que es necesaria para determinar sus reacciones frente a cualquier acción generada en cualquier momento t0.

Al usar el término ESTADO, no es necesario el conocimiento de los datos históricos. El estado puede considerarse como una característica especial que combina implícitamente todas las acciones de entrada del pasado que afectan a la reacción de la entidad en el momento presente. La reacción no solo depende de la acción de entrada y del estado actual.

El concepto de "acción de entrada" es también uno de los conceptos de la programación basada en autómatas. Una acción de entrada es casi siempre un vector. Sus componentes se dividen en eventos y variables de entrada, dependiendo del significado y el mecanismo de generación.

La combinación del conjunto finito de estados y el conjunto finito de acciones de entrada constituye un autómata (finito) sin salida. Dicho autómata reacciona a las acciones de entrada cambiando su estado actual de una forma determinada. Las reglas por las que pueden cambiar los estados se llaman funciones de transición automatizadas.

Lo que se conoce como automatización (finita) en la programación basada en autómatas es básicamente la combinación de "autómatas sin salida" y "acciones de entrada". Dicho autómata reacciona a la acción de entrada no solo cambiando su estado sino generando también ciertos valores en las salidas. Las reglas para generar acciones de salida se llaman funciones de salida del autómata.

Al diseñar un sistema con un comportamiento complejo es necesario tomar como punto de partida los objetos de control existentes con un determinado conjunto de operaciones y un grupo dado de eventos que pueden surgir en el entorno externo (mercado).

En la práctica, el diseño se basa normalmente en los objetos de control y eventos:

  1. El dato inicial del problema no es solo una descripción verbal del comportamiento objetivo del sistema sino también una especificación exacta (más o menos) del conjunto de eventos de llegada al sistema procedentes del entorno externo y un gran número de solicitudes y comandos de todos los objetos de control.

  2. Se construye un conjunto de estados de control.

  3. A cada solicitud de objetos de control se le asigna la correspondiente variable de entrada del autómata, mientras que a cada comando se le asigna la respectiva variable de salida. El autómata que no va a garantizar un comportamiento del sistema tal y como se requiere se construye en base a los estados de control, eventos y variables de entrada y salida.


6. Características y ventajas del programa

La primera característica de un programa basado en autómatas es que es esencial la presencia de un lazo exterior. Aquí no parece haber nada nuevo. Lo principal aquí es que este lazo será ¡el único en la parte lógica de todo el programa! (es decir, nuevo tick de llegada)

La segunda característica se deriva de la primera. Cualquier autómata contiene una estructura de interruptor (de hecho, está virtualmente compuesto de ella) que comprende todas las operaciones lógicas. Cuando se llama a un autómata el control se transfiere a una de las etiquetas de la "instancia" y a continuación de las acciones correspondientes se completa hasta el nuevo inicio la operación del autómata (subprograma). Estas acciones consisten en comprobar las condiciones de la transición y si se cumple una cierta condición se llama a la respectiva función de salida y se cambia el estado del autómata.

La principal consecuencia de todo lo dicho anteriormente es que la implementación de un autómata no solo es simple sino que, más importante aún, el programa puede funcionar sin muchas variables locales intermedias (flags) cuya funcionalidad en cada autómata es proporcionada por una variable de estado de valores múltiples.

La última afirmación es difícil de creer ya que estamos acostumbrados a usar un montón de variables locales y globales (flags) sin pensar demasiado. ¿Cómo podemos trabajar sin ellas? Son flags muy habituales que señalan al programa que se ha cumplido una condición. El flag se establece (a VERDADERO) cuando el programador lo considera necesario pero es entonces (normalmente solo después de que el flag empieza a producir los efectos deseados estando siempre en modo VERDADERO) cuando fastidiosamente pasa a adoptar el valor FALSO en algún lugar del programa.

Suena familiar ¿verdad? Ahora observemos el ejemplo y veamos: no se usan aquí ninguna variable adicional y el cambio afecta solo al valor del número de estado y solo cuando se cumple una condición lógica. ¿No es una sustitución de los flags respetable?

El algoritmo juega un papel principal en la creación de la parte lógica de un programa. La frase clave a recordar aquí es "parte lógica". El estado subyace a todo en este caso. Otra palabra que debe añadirse aquí es "esperar". Y, en mi opinión, tenemos una definición bastante adecuada de "estado de espera". Cuando hay un estado, esperamos a la aparición de las acciones de entrada (atributos, valores o eventos). La espera puede ser corta o larga. O, en otras palabras, hay estados que pueden ser estables y otros que pueden ser inestables.

La primera propiedad del estado es el hecho de que en el estado se espera a un conjunto limitado de acciones de entrada. Cualquier algoritmo (y obviamente cualquier programa) tiene información de entrada y salida. Las acciones de salida pueden dividirse en dos tipos: variables (p.ej. operaciones sobre propiedades de objetos) y funciones (p.ej. llamada de una función de inicio de una aplicación, función de informe, etc.).

La segunda propiedad del estado es la provisión de un conjunto de valores precisos de las variables de salida. Esto revela una circunstancia muy simple y extremadamente importante: todos los valores de la variable de salida pueden determinarse en cualquier momento, ya que el algoritmo (programa) se encuentra en un cierto estado en cada momento.

El número de estados es limitado, ya que es el número de valores de la variables de salida. La función para registrar las transiciones se integra adecuadamente en la función del autómata y la secuencia de transiciones entre estados y, por tanto, la entrega de acciones de salida puede siempre determinarse.

La lista completa de características se encuentra en la sección 2. Características de la tecnología propuesta, y la lista completa de las ventajas se encuentra en la sección 3. Ventajas de la tecnología propuesta. Este artículo simplemente ¡no puede cubrir la gran cantidad de información sobre este tema! Después de un estudio en profundidad de toda la bibliografía de investigación escrita por Anatoly Shalyto, todas las cuestiones teóricas deben dirigirse a él personalmente a shalyto@mail.ifmo.ru.

Y al ser usuario de sus ideas científicas mientras tengo en mente nuestros objetivos y problemas, a continuación daré tres ejemplos de mi implementación de la tecnología de programación basada en autómatas.


7. Ejemplos de programación basada en autómatas

7.1. Ejemplo para la comprensión

El estado es un modo en el que existe el sistema. Por ejemplo, el agua existe en tres estados: sólida, líquida y gaseosa. Este cambia de un estado a otro cuando se ve afectado por una variable: la temperatura (a presión constante).

Supongamos que tenemos un gráfico que representa la temperatura (t) a lo largo del tiempo (en nuestro caso el valor del precio):

int STATUS=0; // a global integer is by all means always a variable !!! STATUS is a multi-valued flag
//----------------------------------------------------------------------------------------------//
int start() // outer loop is a must
  {
   switch(STATUS)
     {
      case 0:  //--- start state of the program
         if(T>0 && T<100) STATUS=1;
         if(T>=100)       STATUS=2;
         if(T<=0)         STATUS=3;
         break;

      case 1:  //---  liquid
         // set of calculations or actions in this situation (repeating the 1st status -- a loop in automata-based programming) //
         // and calls of other nested automata A4, A5;
         if(T>=100 )      { STATUS=2; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         if(T<0)          { STATUS=3; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         // logging transitions and actions when the condition is met.
         break;

      case 2:  //--- gas
         // set of calculations or actions in this situation (repeating the 2nd status -- a loop in automata-based programming) //
         // and calls of other nested automata A4, A5;
         if(T>0 && T<100) { STATUS=1; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         if(T<=0)         { STATUS=3; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         // logging transitions and actions when the condition is met.
         break;

      case 3:  //--- solid
         // set of calculations or actions in this situation (repeating the 3rd status -- a loop in automata-based programming) //
         // and calls of other nested automata A4, A5;
         if(T>0 && T<100) {STATUS=1; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         if(T>=100)       {STATUS=2; /* set of actions when transitioning, calls of other nested automata A2, A3;*/}
         // logging transitions and actions when the condition is met.
         break;
     }
   return(0);
  }

El programa puede hacerse más sofisticado añadiendo el parámetro de la presión P y nuevos estados introduciendo una compleja dependencia mostrada en el gráfico:


Este autómata tiene 32 = 9 condiciones de cambio, por lo que no puede dejarse atrás ni obviarse nada. Este estilo puede ser también muy adecuado ¡al escribir instrucciones y leyes! Aquí no se permiten escapatorias ni excepciones al cumplimiento de las reglas: todas las combinaciones de variantes de sucesión de eventos deben ser cubiertas y todos los casos deben ser descritos.

La programación basada en autómatas requiere que tengamos todo en cuenta, incluso en el caso de aquellas variantes de sucesión que en otros casos no se hubiesen tenido en cuenta, y por esta razón es la principal herramienta al comprobar la consistencia e integridad de las leyes, instrucciones y sistemas de control. También hay una ley matemática:

Si hay N estados (excepto para el inicio 0) en el sistema, el número total de condiciones de transición es N2.

Diagrama de la transición: N = 3 estados, el número de transiciones y lazos es N2 = 9 (igual al número de flechas).


Si el número de variables en el ejemplo fuera diferente, entonces:


Esto muestra que todos los valores calculados en la tabla aumentan exponencialmente, es decir, el diseño es un proceso complejo que requiere minuciosidad al seleccionar las variables sistémicas principales.

Incluso si solo hay dos parámetros, ¡es muy difícil describirlo todo! Sin embargo, en la práctica, ¡todo es mucho más fácil! Dependiendo de la lógica y del significado, el 50-95% de las transiciones no pueden existir físicamente y el número de estados es también un 60-95% menor. Este análisis de la lógica y el significado disminuye la dificultad de describir todas las transiciones y estados.

En casos más complejos, se requiere calcular el máximo número de estados para todos los datos de entrada y salida conocidos en un Asesor Experto. La solución a este problema se encuentra aplicando la combinatoria y fórmulas de combinaciones, permutaciones, distribuciones y combinatoria enumerativa.

7.2. Regulador con histéresis

La programación de reguladores, gatillos, registros, contadores, decodificadores, comparadores y otros elementos del sistema no lineales digitales y analógicos pueden ser muy adecuados en un Asesor Experto.

  • xmax = 100 - the maximum pick-up value;
  • xmin = -100 - the minimum pick-up value;
  • x = x(t) - signal at the input;
  • Y = Y(t) - signal at the output.
int   status=0;  // at the beginning of the program we globally assign
//------------------------------------------------------------------//
switch(status)
  {
   case 0: //  start  
      Y=x;
      if(x>xmax)  {status=1;}
      if(x<xmin)  {status=2;}
      break;

   case 1: //++++++++++++++++++++
      if(x>xmax)  Y=x;
      if(x<xmax)  Y=xmin;
      if(x<=xmin) {status=2; Y=xmin;}
      break;

   case 2: //--------------------
      if(x<xmin)  Y=x;
      if(x>xmin)  Y=xmax;
      if(x>=xmax) {status=1; Y=xmax;}
      break;
  }

La característica de un regulador:

7.3. Plantilla para 9 estados y 81 variantes de sucesión de eventos

Y es el estado de entrada actual del autómata desde 1 a 9. El valor de Y se genera en el Asesor Experto fuera del subprograma. El estado anterior de Y es MEGASTATUS.

int MEGASTATUS=0; // at the beginning of the program we globally assign
//---------------------------------------------------------------------//
void A0(int Y) // automaton template
  {
   switch(MEGASTATUS)
     {
      case 0:  // start
          MEGASTATUS=Y;
          break;

      case 1: // it was the past
          // it became current, repeating
          if(Y=1) { /*set of actions in this situation, calls of other nested automata A2, A3, ... */ } // Loop//
          // new current
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 2: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ } //Loop//
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          // e.g. if the transition from 2 to 6 is in essence impossible or does not exist, do not write anything
          if(Y=6) { /* set of actions in this situation */ }
          // the automaton will then be reduced but the automaton template shall be complete to count in everything
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 3: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ } //Loop//
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 4: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ } //Loop//
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 5: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ } //Loop//
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 6: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ } //Loop//
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 7: // it was the past  
          //it has become current  
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ } //Loop//
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 8: // it was the past
          // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ } //Loop//
          if(Y=9) { /* set of actions in this situation */ }
          // logging transitions and actions when the condition is met.
          break;

      case 9: // it was the past
         // it has become current
          if(Y=1) { /* set of actions in this situation */ }
          if(Y=2) { /* set of actions in this situation */ }
          if(Y=3) { /* set of actions in this situation */ }
          if(Y=4) { /* set of actions in this situation */ }
          if(Y=5) { /* set of actions in this situation */ }
          if(Y=6) { /* set of actions in this situation */ }
          if(Y=7) { /* set of actions in this situation */ }
          if(Y=8) { /* set of actions in this situation */ }
          if(Y=9) { /* set of actions in this situation */ } //Loop//
          // logging transitions and actions when the condition is met.
          break;
     }
   MEGASTATUS=Y;
  }

7.4. Autómata de reproducción de audio

Vamos a examinar un reproductor de audio simple.

Este dispositivo puede adoptar 6 estados:

  1. Listo;
  2. Sin pistas de audio;
  3. Reproduciendo;
  4. Avance rápido;
  5. Rebobinar;
  6. Pausa.

El sistema de control del reproductor de audio está representado por un autómata. Los botones que se pulsan se consideran eventos con efecto sobre el autómata. Las transiciones entre pistas, reproducción, control de visualización, etc., son acciones de salida.

switch(STATUS)
  {
   case 0: //--- "Ready"
      if(Event == 3) { STATUS = 3; } //«>>» button pressed
      if(Event == 6) { STATUS = 1; } //Audio file not found 
      if(Event == 1) { STATUS = 2; } //«PLAY» button pressed
   
      z1();  // Set the indicator to the initial state
      break;

   case 1: //--- "No Track"
      z6();  // Give the «No Track» message
      break;

   case 2: //--- "Playing"
      if(Event == 4) { STATUS = 4; } //«<<» button pressed
      if(Event == 5) { STATUS = 5; } //«PAUSE»( | | ) button pressed
      if(Event == 3) { STATUS = 3; } //«>>» button pressed
      if(Event == 2) { STATUS = 0; } //«STOP» button pressed
      z2(); // Playing
      break;

   case 3: //--- "Fast-Forward"
      z3();  // Next track
      { STATUS=2; }
      break;

   case 4: //--- "Rewind"
      z4(); // Previous track
      { STATUS=2; }
      break;

   case 5: //--- "Pause"
      if(Event == 5) { STATUS = 2; } //«PAUSE» button pressed
      if(Event == 1) { STATUS = 2; } //«PLAY» button pressed
      if(Event == 2) { STATUS = 0; } //«STOP» button pressed
      if(Event == 3) { STATUS = 3; } //«>>» button pressed
      if(Event == 4) { STATUS = 4; } //«<<» button pressed
      z5(); //Pause
      break;
  }

En teoría, este autómata podría contener 36 variantes de transición, pero solo 15 existen realmente y toda la información se encuentra disponible en la descripción proporcionada por el autor.


8. А.А. Recomendaciones de Shalyto en relación a la ejecución del proyecto

Puede consultarse la información completa sobre cómo preparar y escribir documentación del proyecto aquí http://project.ifmo.ru/books/3, aunque en este artículo solo voy a daros un breve extracto:

  1. El libro de A.A. Shalyto "Control lógico. Métodos de implementación de algoritmos de hardware y software. SPb.: Nauka, 2000", disponible en la web señalada en la sección "Libros" puede tomarse como prototipo. Recoge una adecuada representación de la información tal y como fue publicada por la más antigua y prestigiosa empresa editorial de Rusia.
  2. La introducción debe sentar las bases de la importancia de la temática elegida, plantear brevemente el problema a considerar y especificar el lenguaje de programación y el sistema operativo utilizado en el proyecto.
  3. En la sección "Descripción del problema" debe incluirse una descripción verbal detallada del problema junto con las figuras, diagramas y capturas de pantalla que clarifican el problema descrito.
  4. Al usar la programación orientada a objeto, la sección "Diseño" debe incluir un diagrama de clases. Las principales clases deben describirse con detalle. Es aconsejable que se prepare un "Diagrama de bloque de la clase" para cada una de ellas y de esta forma presentar su interfaz u los métodos utilizados junto con la indicación de los métodos basados en autómatas.
  5. Deben incluirse tres documentos para cada autómata en la sección "Autómata": una descripción verbal, un diagrama de enlaces del autómata y un gráfico de transición.
  6. La descripción debe ser muy detallada, aunque dado que el comportamiento de una autómata complejo es difícil de describir de forma clara, normalmente representa una "declaración de intento".
  7. El diagrama de enlaces del autómata proporciona una descripción detallada de su interfaz. La parte izquierda del diagrama debe tener:
    • las fuentes de datos;
    • el nombre completo de cada variable de entrada;
    • el nombre completo de cada evento;
    • los enunciados con los números de estado de otros autómatas usados en el autómata en cuestión como acciones de entrada. Por ejemplo, puede usarse el enunciado Y8 == 6 que toma el valor igual a uno una vez que tienen lugar las ocho transiciones hasta el sexto estado;
    • variables de entrada designadas como x con los índices respectivos;
    • eventos designados como e con los índices respectivos;
    • variables para guardar los estados del autómata con el número N, designadas como YN.

    La parte derecha del diagrama debe tener:
    • variables de salida designadas como z con los índices respectivos;
    • el nombre completo de cada variable de salida;
    • los eventos generados por el autómata en cuestión (si los hay);
    • el nombre completo de cada evento generado;
    • los receptores de datos;
  8. Si se usan algoritmos complejos en nodos o transiciones, la sección "Algoritmos de cómputo" explica la elección de algoritmos y proporciona su descripción (incluyendo la descripción matemática). Estos algoritmos se designan por las variables x y z, dependiendo de si los cálculos se realizan a la entrada o a la salida.
  9. Las peculiaridades de la implementación del programa deben incluirse en la sección "Implementación". Debe mostrar una plantilla para realizar una implementación formal e isomórfica del autómata. Aquí deben incluirse también las implementaciones del autómata.
  10. La "Conclusión" incluye las ventajas y desventajas del proyecto completo. También puede ofrecer formas de mejorar el proyecto.


9. Conclusión

Os animo a todos a:

  • explorar este nuevo enfoque sobre la programación.
  • implementar enfoque totalmente nuevo e interesante para programar con vuestras ideas y estrategias de trading.

Espero que la programación basada en autómatas:

  • con el tiempo se convierta en un estándar en la programación y diseño para todos los operadores e incluso para los desarrolladores del lenguaje de MetaQuotes.
  • sea la base de la toma de decisiones complejas al diseñar un Asesor Experto.
  • de lugar en el futuro a un nuevo lenguaje, el lenguaje MetaQuotes 6, con soporte para el enfoque de la programación basada en autómatas y una nueva plataforma, Meta Trader 6.

Si todos los programadores siguieran este enfoque de programación, podría alcanzarse el objetivo de crear un Asesor Experto ganador. Este primer artículo es mi intento de mostraros toda una nueva fuente de productividad e investigación en el campo del diseño y programación basado en autómatas, como un nuevo impulso a los inventos y descubrimientos.

Y una cosa más: estoy completamente de acuerdo con el artículo del autor y creo que es importante hacéroslo llegar de forma concisa (texto completo aquí http://is.ifmo.ru/works/open_doc/):

Por qué los códigos fuente no son una solución para comprender los programas

La cuestión central en la programación práctica es comprender los códigos de los programas. Siempre es conveniente tener los códigos fuente a mano pero el problema es que estos a menudo no es suficiente. Normalmente se necesita información adicional para conseguir entender un programa algo complejo. Este necesidad crece exponencialmente a medida que el código se hace más extenso.

El análisis del código de los programas destinado a la obtención de las decisiones originarias realizadas por los desarrolladores y la comprensión de los programas son dos ramas importantes de la tecnología de programación cuya existencia va de la mano con la insuficiencia de los códigos fuente para comprender los programas.

Todo el que ha estado alguna vez involucrado en un proyecto grande de reconstrucción de software recordará para siempre la sensación de indefensión y perplejidad que se siente cuando se ve por primera vez un montón de códigos fuente sin documentar (aunque no siempre mal escritos). La disponibilidad de códigos fuente no es realmente de mucha ayuda cuando no hay acceso a los desarrolladores principales. Si el programa está escrito en un lenguaje de bajo nivel y está además mal documentado, todas las decisiones de diseño principales se dedican a los detalles de programación y requiere reconstrucción. En casos como estos, el valor de la documentación de alto nivel, como la especificación de la interfaz y la descripción de la arquitectura, puede tener más peso que el propio código fuente.

El hecho de que los códigos fuente son inadecuados para comprender los programas ha dado pie a intentos de combinar el código y una documentación de alto nivel.

Si pasamos por alto las primeras etapas del proyecto, la complejidad y la cantidad de trabajo virtualmente "bloqueará" nuestro acceso al código fuente, siempre que no haya una documentación de alto nivel. La comprensión del código "prehistórico" en ausencia de los desarrolladores que trabajaron originariamente en el proyecto o la adecuada documentación que permita clasificar las decisiones arquitectónicas correspondientes, es probablemente uno de los retos más difíciles con los que puede encontrarse un programador.


Por qué a los programas les falta diseño

Mientras que la ausencia de código fuente puede ser malo, su disponibilidad puede ser igualmente poco beneficiosa. ¿Por qué todavía se omite "por siempre jamás"? La respuesta es simple, una documentación de diseño detallada y precisa que incluye documentación sobre el programa como uno de sus componentes.

Los puentes, carreteras, y rascacielos no pueden construirse normalmente sin documentación a mano, lo que no es cierto en el caso de los programas.

Esta situación que ocurre en la programación puede definirse de la siguiente forma: "Si los constructores construyeran edificios de la forma en que los programadores escriben los programas, el primer pájaro carpintero que llegara destruiría toda la civilización."

¿Por qué se suministra una gran cantidad de información detallada y clara sobre el diseño para el hardware que puede ser relativamente fácil de comprender y modificar por una especialista incluso años después de publicarse, pero dicha documentación es inexistente para el software o está escrita de modo puramente formal y solo los especialistas altamente cualificados pueden modificarla (si no se encuentra al desarrollador?

Aparentemente, esta situación puede explicarse de la siguiente forma. Primero, el desarrollo y la fabricación de hardware son dos procesos distintos realizados por organizaciones distintas. Por tanto, si la calidad de la documentación es pobre, el ingeniero de desarrollo pasará el resto de su vida trabajando en la "planta" que obviamente no es lo que este desearía. Cuando se trata de desarrollo de software, la situación cambia ya que en este caso tanto el desarrollador del software como el fabricante son normalmente la misma empresa y por tanto, con independencia de la lista de documentos, sus contenidos serán, por lo general, muy superficiales.

Segundo, el hardware es "hard" (duro) mientras que el software es "soft (suave)". Esto hace que sea sencillo modificar programas pero no quiere decir que no deba suministrarse documentación al respecto. Se sabe que la mayoría de programadores son patológicamente reacios a leer, y aún más, a escribir documentación.

La experiencia sugiere que prácticamente ninguno de los nuevos programadores cualificados, ni siquiera los más listos, pueden elaborar documentación de diseño. Y a pesar del hecho de que muchos de ellos estudiaron largos y complejos cursos de matemáticas, esto apenas tiene efecto en su lógica y rigor al escribir documentación. Pueden utilizar diferentes anotaciones para una misma cosa a lo largo de toda la documentación (con independencia de su tamaño), llamando a los objetos, p. ej., la bombilla, la bombilla de luz, la lámpara, escribiéndolo en minúsculas o mayúsculas según les parezca. ¡Imagine qué ocurrirá cuando den rienda suelta a toda su imaginación!

Aparentemente ocurre debido al hecho de que al programar, el compilador muestra las inconsistencias mientras que la documentación de diseño se escribe sin ningún mensaje de ningún tipo.

La cuestión de la calidad de la documentación del software se está convirtiendo en una cuestión de gran importancia social. El desarrollo de software se está haciendo cada vez más parecido al negocio del espectáculo con su fuerte orientación al beneficio. Todo se realiza con una alocada rapidez sin pensar en qué será del producto en el futuro. Como en el negocio del espectáculo, la programación mide todo en términos de "beneficio y pérdidas", en lugar de "bueno o malo". En la mayoría de casis, una buena tecnología no es aquella que es realmente buena sino aquella otra que da beneficios.

La falta de disponibilidad para escribir documentación de diseño está probablemente también asociada con el hecho de que cuanto más restringido (indocumentado) sea el proyecto, más indispensable será el autor.

Dicho comportamiento se extiende por desgracia al desarrollo de software para sistemas altamente críticos. Ello se debe al hecho de que los programas son escritos, en la mayoría de casos, y no diseñados. "Al diseñar, cualquier técnica más complicada que las tarjetas CRC o el uso de diagramas de caso se considera algo demasiado complejo y por tanto no se utiliza. Un programador puede siempre negarse a aplicar una determinada tecnología simplemente informando al jefe que no podrá cumplir con el plazo de entrega".

Esto lleva a situaciones donde incluso los "usuarios no consideran que los errores del software sean algo extraordinario".

Hoy día es una idea muy extendida el que el diseño y la documentación adecuada se encuentren disponibles en el ámbito de la edificación, pero no en el campo del software.

En definitiva, debe señalarse que dicha situación no solía existir en la programación en el pasado, cuando se usaban los primeros ordenadores de gran escala, los programas se diseñaban o desarrollaban con mucho cuidado y en caso de error el siguiente intento ocurría tan pronto como al siguiente día. De esta forma, el progreso técnico nos ha llevado a una programación más descuidada.


Por desgracia, nuestros problemas y preocupaciones no pueden trasladarse al departamento del instituto donde trabaja A.A. Shalyto. Ellos tienen sus propios problemas y objetivos y son totalmente ajenos a nuestros conceptos y definiciones, y por tanto no son un ejemplo a seguir por nosotros.


Los principales libros y textos de A.A. Shalyto:

  1. Programación basada en autómatas. http://is.ifmo.ru/books/_book.pdf
  2. Usando gráficos de flujo y gráficos de transición en la implementación de algoritmos de control lógicos. http://is.ifmo.ru/download/gsgp.pdf
  3. Programación basada en autómatas. http://is.ifmo.ru/works/_2010_09_08_automata_progr.pdf
  4. Transformación de algoritmos iterativos en algoritmos basados en autómatas. http://is.ifmo.ru/download/iter.pdf
  5. Tecnología de interruptor (switch): Enfoque basado en autómatas para desarrollar software para sistemas reactivos. http://is.ifmo.ru/download/switch.pdf
  6. Diseño de programas basado en autómatas. Algoritmos y programación de problemas de control lógico. http://is.ifmo.ru/download/app-aplu.pdf
  7. Uso de algoritmos genéticos para diseñar autopilotos para un modelo de helicóptero simplificado. http://is.ifmo.ru/works/2008/Vestnik/53/05-genetic-helicopter.pdf
  8. Programación explícita basada en el estado. http://is.ifmo.ru/download/mirpk1.pdf
  9. Algoritmos y programación de sistemas de control lógico y reactivos. http://is.ifmo.ru/download/arew.pdf
  10. Enfoque orientado a objetos para programación basada en autómatas. http://is.ifmo.ru/works/ooaut.pdf
  11. Notación gráfica para la herencia de clases basadas en autómatas. http://is.ifmo.ru/works/_12_12_2007_shopyrin.pdf
  12. Programando en... 1 (un) minuto. http://is.ifmo.ru/progeny/1minute/?i0=progeny&i1=1minute

Proyectos:

  1. Operación de modelado de ATM. http://is.ifmo.ru/unimod-projects/bankomat/
  2. Modelado de procesos de control de reactores nucleares. http://is.ifmo.ru/projects/reactor/
  3. Sistema de control de un ascensor. http://is.ifmo.ru/projects/elevator/
  4. Desarrollo basado en autómatas del sistema de control de una máquina de café. http://is.ifmo.ru/projects/coffee2/
  5. Diseño e investigación de autómatas para conducción. http://is.ifmo.ru/projects/novohatko/
  6. Modelado de una cámara digital usando la programación basada en autómatas. http://project.ifmo.ru/shared/files/200906/5_80.pdf
  7. Usando la programación basada en autómatas para modelar un sistema de agentes múltiples para vehículos no tripulados. http://project.ifmo.ru/shared/files/200906/5_41.pdf
  8. Sistema de solución visual del cubo de Rubik. http://is.ifmo.ru/projects/rubik/

y otros interesantes artículos y proyectos: http://project.ifmo.ru/projects/http://is.ifmo.ru/projects_en/ and http://is.ifmo.ru/articles_en/.


P.D.

El número de eventos posibles distintos de un cubo de Rubik es (8! × 38−1) × (12! × 212−1)/2 = 43 252 003 274 489 856 000. Pero este número no tiene en cuenta que los cuadrados centrales pueden tener diferentes orientaciones.

Por tanto, teniendo en cuenta las orientaciones de las caras centrales, el número de evento es 2048 veces más grande, es decir, 88 580 102 706 155 225 088 000.

El mercado Forex y el de acciones no tienen tantas variantes de sucesión de eventos, pero los problemas asociados a ellos pueden ser fácilmente resueltos en 100-200 pasos usando este modelo de programación. ¡Es cierto! El mercado y los Asesores Expertos están en constante competición. Es como jugar al ajedrez, donde nadie conoce la siguiente jugada del oponente (como nosotros). Sin embargo, hay programas impresionantes como Rybka (una máquina de ajedrez muy potente) diseñado en base a los algoritmos de poda alfa-beta.

¡Muchos de estos éxitos de otros en otras áreas de la programación nos dan la energía y el compromiso necesario para nuestro trabajo! Aunque la verdad es que todos sabemos que no sabemos nada.


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

OpenCL: De una programación simple a una más intuitiva OpenCL: De una programación simple a una más intuitiva

Este artículo se centra en algunas capacidades de optimización que surgen cuando se tiene en cuenta el hardware subyacente en el que se ejecuta el kernel de OpenCL. Las cifras obtenidas están lejos de ser un límite pero aún así sugieren que al tener disponibles los recursos existentes aquí y ahora (la API de OpenCL como se implementó por los desarrolladores del terminal no permite el control de algunos parámetros importantes para la optimización, particularmente el tamaño del grupo) la ganancia de rendimiento sobre la ejecución del programa anfitrión es muy sustancial.

OpenCL: El puente hacia mundos paralelos OpenCL: El puente hacia mundos paralelos

A finales de enero de 2012 la empresa de desarrollo de software que está detrás de Meta Trader 5 anunció el soporte nativo de OpenCL en MQL5. Utilizando un ejemplo ilustrativo, el artículo plantea los fundamentos de programación en OpenCL en el entorno MQL5 y proporciona algunos ejemplos de la optimización simple del programa para incrementar la velocidad de operación.

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 copiar el trading desde MetaTrader 5 a MetaTrader 4 Cómo copiar el trading desde MetaTrader 5 a MetaTrader 4

¿Se puede tradear hoy en día en una cuenta real utilizando MetaTrader 5? ¿Cómo organizar este trading? Se aporta la base teórica de estas preguntas, así como los códigos con la ayuda de los cuales se realiza el copiado de las transacciones del terminal MetaTrader 5 a MetaTrader 4. Este artículo será útil tanto para los desarrolladores de los Asesores Expertos, como para los traders que operan en el mercado.