La gran y terrible MT4 para siempre (o cómo hacer una estrategia de transición) - página 13

 
JRandomTrader:

Esto es de la documentación:

"El orden de llegada de estas transacciones al terminal no está garantizado, por lo que no se puede basar el algoritmo de negociación en la espera de que lleguen unas transacciones comerciales después de que hayan llegado otras. " https://www.mql5.com/ru/docs/event_handlers/ontradetransaction

Y por experiencia, las transacciones TRADE_TRANSACTION_ORDER_DELETE, TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_HISTORY_ADD pueden llegar en cualquier orden.

De ahí que tengamos situaciones en las que todavía no hay acuerdo ni orden en la historia, pero el orden ya existe. O viceversa, la orden sigue ahí, pero la operación ya se ha ejecutado. Pero la situación cuando el orden está presente en el activo, así como en la historia, es difícilmente posible.

No capto los acontecimientos, sino que miro el cuadro completo en una nueva garrapata.


JRandomTrader:

De hecho, por eso me he negado a utilizar la clase CTrade, ya que pisa todos estos escollos.

Tengo una solución: cada EA mantiene una lista de sus órdenes y controla su estado. Esto incluye estados "no estándar": "pedido enviado pero aún no presente en los pedidos activos" (aquí es donde podrían duplicarse), "pedido eliminado pero no presente en el historial". Esto también ayuda a trabajar simultáneamente en el mismo símbolo cuando se hace la red.

Hasta hace poco utilizaba una muleta universal que comprobaba la ausencia de órdenes. Pero en algún momento empezó a fallar.

He añadido una muleta personal más al Asesor Experto que ahora controla sus propias órdenes por separado.

Son muchas muletas...

 
Andrey Khatimlianskii:

Son muchas muletas...

Estudiar el tema. Incluso me encuentro con esto: OrderSend market order true, entonces PositionsTotal= 0, OrdersTotal = 0, tablas históricas sin cambios.

Parece que se ha conseguido escribir IsSynchronized(). El código es un poco pesado. Todavía no he decidido en qué forma publicarlo.

 
// Демонстрация открытия дубля позиции в MT5.

#include <Trade\Trade.mqh>

void OnStart()
{
  CTrade Trade;
  
  while (!IsStopped() && (PositionsTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (PositionsTotal() == 1)
      Trade.PositionClose(PositionGetTicket(0)); // Если есть позиция - закрываем.
    else if (!OrdersTotal())
      Trade.Buy(0.01); // Если нет позиции и ордера - открываем позицию.
}

Ejecute este código en una cuenta demo vacía y vea si se abren dos posiciones después de unos segundos.


La misma lógica en MT4 se ve así.

void OnStart()
{
  while (!IsStopped() && (OrdersTotal() <= 1)) // Закончим, когда появится более одной позиции.
    if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0) // Если есть позиция - закрываем.
    else
      OrderSend(_Symbol, OP_BUY, 0.01, Ask, 0, 0, 0) // Если нет позиции и ордера - открываем позицию.
}

Está claro que este código en MT4 no causará la inversión de la posición. Pero no en MT5.

 
fxsaber:

Ejecute este código en una cuenta demo vacía y vea si se abren dos posiciones después de unos segundos.


La misma lógica en MT4 se ve así.

Está claro que dicho código en MT4 no causará la inversión de la posición. Pero no en MT5.

Por último, ¿acaba de descubrirlo? Este problema es tan antiguo como el propio terminal. Pero finalmente los usuarios de terminales se dieron cuenta... después de una década.

Cuando se realizan acciones de comercio por sí mismo, el problema puede ser resuelto de una manera simple - para insertar Sleep() durante un segundo después de la acción se realiza. Pero cuando el EA utiliza stoploss/stackprofit y el cierre del mercado, existe el peligro de encontrar este problema, y en este caso no hay solución.

 
Dmitry Fedoseev:

¡Por fin! ¿Acabas de descubrir esto? Este problema es tan antiguo como el propio terminal. Pero los usuarios de terminales por fin se han dado cuenta... después de una década.

El problema se ha debatido durante mucho tiempo. Casi todo el mundo se ha encontrado con ella. Es la primera vez que un código estable lo reproduce.

Cuando usted mismo realiza una acción de comercio, puede resolver el problema de una manera sencilla - insertar Sleep() durante un segundo después de que se realice la acción. Pero cuando el Stop Loss/StackProfit y el cierre del mercado se utilizan en un EA, existe el peligro de encontrar el problema, y no hay solución en este caso.

Se ha encontrado la solución.

 
fxsaber:

Ejecute este código en una cuenta demo vacía y vea si se abren dos posiciones después de unos segundos.

Extraño. No se reproduce. Comprobado en la demo de MQ, build 2900, EURUSD, cero spread. Esperé unos cinco minutos.

¿Quizás tenga que utilizar algún servidor específico de un DC/broker real y no el servidor MQ?

 
Ihor Herasko:

Extraño. No se reproduce. Comprobado en la demo de MQ, construir 2900, EURUSD, cero propagación. Esperé unos cinco minutos.

¿Quizás tenga que utilizar algún servidor específico de un DC/broker real y no el servidor MQ?

ForexTimeFXTM-Demo01

 
fxsaber:

ForexTimeFXTM-Demo01

Sí, ahora el guión se detiene. Pero aún queda un puesto. ¿Supongo que el segundo tiene tiempo para cerrar?

 
Ihor Herasko:

Sí, ahora el guión se detiene. Pero aún queda un puesto. ¿El segundo debe tener tiempo para cerrar?

Siempre me quedan dos. Si se queda uno, es aún más un error:

  1. PositionsTotal = 1 - envía una orden de cierre.
  2. Entonces PositionsTotal = 2 y la orden del punto 1 está cerrada.
 
fxsaber:

Siempre me quedan dos. Si queda uno, es un error aún mayor:

  1. PositionsTotal = 1 - envía una orden de cierre.
  2. Entonces PositionsTotal = 2 y la orden del punto 1 está cerrada.

Sí, eso es lo que quiero decir. Resulta que el script consigue cerrar una de las posiciones cuando en realidad son dos, pero PositionsTotal() devuelve 1. Y entonces, tras el cierre, se cumple la condición de finalización del bucle, es decir, PositionsTotal() devuelve 2.