Errores típicos y cómo afrontarlos en el entorno comercial

 
En este hilo hablaremos de los errores más comunes que se cometen al trabajar con el entorno comercial del terminal en algunos algoritmos, los métodos para eliminarlos y evitarlos en el futuro.
 
De acuerdo.
Sólo como introducción:
El Asesor Experto analiza la dirección (o beneficio, ... ) de la última orden cerrada. El último pedido se cerró hace 2 días.
El comerciante estableció la profundidad del historial en 1 día.
OrdersHistoryTotal() no ve ese pedido.
¿La solución?
 
Andrei Fandeev:
Bien.
Sólo como introducción:
El Asesor Experto analiza la dirección (o beneficio, ... ) de la última orden cerrada. El último pedido se cerró hace 2 días.
Y el comerciante establece la profundidad del historial a 1 día.
OrdersHistoryTotal() no ve ese pedido.
¿Solución?

Para MT4 - en mi opinión, sin ambigüedad, dar al usuario una advertencia al lanzar el EA para utilizar la profundidad requerida de la historia.

MT5 permite cargar el historial hasta la profundidad requerida.

 
Artyom Trishkin:

Para MT4 - en mi opinión, sin ambigüedad, dar al usuario una advertencia al lanzar el EA para utilizar la profundidad requerida de la historia.

Confiar en el usuario es una mala idea. Tiene que haber un control.
Artem, en MT4 no he encontrado Get para obtener el valor de la profundidad del historial establecido.
¿Es realmente imposible conseguirlo de forma programada?

 
Andrei Fandeev:

Confiar en el usuario es una mala idea. Necesitas un cheque.
Artem, en MT4 no he podido encontrar cómo obtener el valor de la profundidad del historial establecido.
¿Es realmente imposible conseguirlo de forma programada?

Sí, es cierto.

 

Hay dos paradigmas para trabajar con el entorno comercial y escribir EAs.

  1. Las entradas de eventos (OnTick, OnTimer, etc.) dependen unas de otras. Hay información que DEBE tener entre los eventos (no por velocidad, como el caché, sino por usabilidad). Por ejemplo, necesitamos guardar el resultado de OrderSendAsync y utilizarlo en OnTradeTransaction. Los cachés NO son información obligatoria y sólo se utilizan para agilizar. Por eso no los consideramos de inmediato.
  2. Las entradas de eventos (OnTick, OnTimer, etc.) NO dependen unas de otras. Cada entrada es desde cero. Más o menos como un Script que usted mismo ejecuta en cada evento.
En MT4 probablemente podría resolver todo a través de la segunda opción. La MT5 no está tan clara.


Ventajas de la segunda opción sobre la primera

  • Puede terminar el algoritmo en cualquier punto (normal y anormal).
  • Puede iniciar/continuar el algoritmo en cualquier lugar.
  • Alta fiabilidad.


Desventajas

  • En Tester será inferior a la primera variante en términos de rendimiento.
  • La lógica "desde cero" hace que se escriba un código algo "ilógico", al que hay que acostumbrarse al principio.

 

¿Cómo se comparan las API de los entornos comerciales? Introducir una gran variedad de TS diferentes. E imaginemos nuestra API virtual ideal, que permitiría un esfuerzo mínimo para plasmar la ST en un código fiable.

Si es posible crear esta API virtual tan ideal como una envoltura de una API real, entonces la API original es excelente. Incluso a pesar del esfuerzo y el tiempo que se necesita para crear una envoltura.


MT4 y MT5 son excelentes APIs según este criterio. Sólo las APIs de origen son difíciles, pero permiten (sin restricciones arquitectónicas/técnicas) escribir una gran envoltura, y por lo tanto son buenas.

Así que cuando dicen que MT5 es más compleja que MT4 - quieren decir que aún no han conocido una envoltura de MT5 (tal vez aún no se ha escrito) que sea tan fácil de usar como la envoltura de MT4 que utilizan.


En general, ambas plataformas permiten crear una única API de alto nivel (wrapper) a partir de APIs de bajo nivel. Así que la complejidad de las API de su entorno comercial es igual.

 

MT4 tiene una API de muy alto nivel, por lo que poca gente trata de escribir una envoltura universal más fácil de usar. Pero ese no es el caso de MT5 - la API original de bajo nivel sólo REQUIERE escribir algún tipo de envoltura. Así que no tiene mucho sentido discutir las características de cada envoltorio en este hilo. Más bien, es importante demostrar que seguirá siendo necesaria una envoltura. Qué características de una API de bajo nivel hay que tener en cuenta al escribir una API de alto nivel.

В общем, обе платформы позволяют из низкоуровневых API создать единый высокоуровневый API (обертка). Так что сложности API торговых окружений у них равны!

Basándonos en esta afirmación, tenemos que aprender a escribir código MT5 que no sea inferior al código MT4 en términos de usabilidad. Las envolturas de la API pueden ser diferentes (la sintaxis por lo general), pero arquitectónicamente MT5 no debería ser inferior a MT4, de lo contrario la afirmación destacada se pierde. Por lo tanto, el código de MT5, más engorroso, no debe verse como un motivo de crítica, sino como una ayuda para coserlo en un envoltorio no menos fácil de usar que el de MT4.

 
Tomemos una simple plantilla MT4 TS

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

Organizar un bucle de pedidos

fxsaber, 2018.02.15 23:19

// Шаблон большинства ТС

#property strict // обязательно

// Сигнал на покупку
bool BuySignal( const string Symb ) { return(true); }

// Сигнал на продажу
bool SellSignal( const string Symb ) { return(false); }

// Находит ордер соответствующего типа
bool OrdersScan( const string Symb, const int Type )
{
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type) && (OrderSymbol() == Symb))
      return(true);    
    
  return(false);  
}

// Торговое действие на сигнал
bool Action( const string Symb, const int Type, const double Lots = 1 )
{
  bool Res = true;    
  
  // Закрыли противоположные сигналу позиции
  while ((OrdersScan(Symb, 1 - Type)) && (Res = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100)));

  // Открыли позицию по сигналу
  return(Res && !OrdersScan(Symb, Type) && OrderSend(Symb, Type, Lots, SymbolInfoDouble(Symb, Type ? SYMBOL_BID : SYMBOL_ASK), 100, 0, 0));
}

// Шаблон торговой стратегии
void Strategy( const string Symb )
{
  if (BuySignal(Symb))
    Action(Symb, OP_BUY);
  else if (SellSignal(Symb))
    Action(Symb, OP_SELL);
}

void OnTick()
{
  Strategy(_Symbol);
}

No demuestra la conveniencia de MT4 ni un poco, sólo sirve como punto de comparación. Es ese listón más bajo de usabilidad el que debe sostener un envoltorio de MT5. La plantilla está escrita en base al segundo paradigma.


Parece que escribimos lo mismo en MT5

Foro sobre comercio, sistemas de comercio automatizados y prueba de estrategias de comercio

Organizar un ciclo de desbordamiento de pedidos

fxsaber, 2018.02.15 22:30

// Шаблон большинства ТС

#include <Trade/Trade.mqh>

// Сигнал на покупку
bool BuySignal( const string Symb ) { return(true); }

// Сигнал на продажу
bool SellSignal( const string Symb ) { return(false); }

// Находит позицию соответствующего типа
bool PositionsScan( const string Symb, const ENUM_POSITION_TYPE Type )
{
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if ((PositionGetSymbol(i) == Symb) && (PositionGetInteger(POSITION_TYPE) == Type))
      return(true);    
    
  return(false);  
}

// Торговое действие на сигнал
bool Action( const string Symb, const ENUM_POSITION_TYPE Type, const double Lots = 1 )
{
  static CTrade Trade;    
  bool Res = true;    
  
  // Закрыли противоположные сигналу позиции
  while ((PositionsScan(Symb, (ENUM_POSITION_TYPE)(1 - Type))) && (Res = Trade.PositionClose(PositionGetInteger(POSITION_TICKET))));

  // Открыли позицию по сигналу
  return(Res && !PositionsScan(Symb, Type) && (Type ? Trade.Sell(Lots, Symb) : Trade.Buy(Lots, Symb)));
}

// Шаблон торговой стратегии
void Strategy( const string Symb )
{
  if (BuySignal(Symb))
    Action(Symb, POSITION_TYPE_BUY);
  else if (SellSignal(Symb))
    Action(Symb, POSITION_TYPE_SELL);
}

void OnTick()
{
  Strategy(_Symbol);
}

Por alguna razón, algunas personas escriben más código para la misma TS. Pero en realidad este código lo hace igual de bien. La mayoría de los CTs sólo requieren escribir BuySignal y SellSignal. No se necesita nada más.

La plantilla de ejemplo está escrita específicamente con SB. Así que la pregunta a los expertos de MT5, ¿es el código correcto?


La función que muestra la necesidad de envoltura está marcada en rojo. Su problema se describe aquí. Alguien recordará que este es el antiguo problema de la reapertura de la posición que se solucionaba usando el Sleep en la antigüedad, esperando que la posición se abriera después del OrderSend. Pero en realidad, este problema no tiene nada que ver con OrderSend. Hay que saber leer correctamente el entorno comercial.

 
fxsaber:

Hay que saber leer correctamente el entorno comercial.

Un ejemplo sencillo de cómo hacerlo bien

// Возвращает количество позиций по символу
int GetAmountPositions( const string Symb )
{
  int Res = 0;
  
  for (int i = PositionsTotal() - 1; i >= 0; i--)
    if (PositionGetSymbol(i) == Symb)
      Res++;
      
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderGetTicket(i) && (OrderGetInteger(ORDER_TYPE) <= ORDER_TYPE_SELL) &&
        !OrderGetInteger(ORDER_POSITION_ID) && (OrderGetString(ORDER_SYMBOL) == Symb))
      Res++;  

/*
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
      Res++;
*/      
  return(Res);
}

La cuestión, en pocas palabras, es la siguiente: si hay una orden de mercado, considérela también una "posición". Entre comillas, porque es una posición envuelta. El código resaltado no suele aparecer en ningún sitio. Pero evita reabrir posiciones. Lo más interesante aquí está resaltado en rojo. La necesidad de este chip no es evidente.

El asunto es que existen las llamadas órdenes de cierre de mercado. El mismo SL/TP. Obviamente, no nos gustaría ver esas órdenes de mercado como "posiciones". Y no nos gustaría que se cerraran también esos pedidos que hemos hecho. Así que la condición resaltada es el filtro apropiado.


ZZZ pegar este código aquí y comprobar el resultado en el servidor de demostración.

 
fxsaber:

La opción correcta con un ejemplo sencillo

El punto en resumen es el siguiente: si hay una orden de mercado, considérela también una "posición". Entre comillas, porque es una posición envuelta. El código resaltado no suele aparecer en ningún sitio. Pero evita reabrir posiciones. Lo más interesante aquí está resaltado en rojo. La necesidad de este chip no es evidente.

El asunto es que existen las llamadas órdenes de cierre de mercado. El mismo SL/TP. Obviamente, no nos gustaría ver esas órdenes de mercado como "posiciones". Y no nos gustaría que se cerraran también esos pedidos que hemos hecho. Así que la condición resaltada es el filtro apropiado.


HZ pegar este código aquí y comprobar el resultado en el servidor de demostración.

Pregunta: ¿qué ocurre si después de enviar una orden de mercado hasta el siguiente tick la orden de mercado no es colocada por el servidor?

Razón de la queja: