OnTradeTransaction - página 8

 
Igor Zakharov:

En los robots "normales", el caso que he descrito, no lo noté en absoluto; pero en un caso me pidieron que hiciera un sistema de seguridad: la condición era que las posiciones estuvieran siempre bloqueadas (ya sea con posiciones reales o con una orden pendiente), es decir, que el número de lotes de compra fuera igual al número de lotes de venta. Este es el caso que me introdujo en los matices del recuento de orden/posición/comercio en un cinco.

La diferencia, según me expliqué :) es que el cuatro, al obtener una respuesta del broker, primero sincroniza sus "tablas" con las órdenes abiertas y el historial, y luego informa al usuario de la respuesta del broker. El cinco nos transmite inmediatamente esta respuesta, y al mismo tiempo corrige sus "tablas" (y todos los programas mql leen los datos de estas "tablas"). Este es el momento en el que cogemos el temporizador de milisegundos. Pero entonces, ¿por qué no lo detectamos en el probador?

En general, he hecho mi tranquilidad...

No, las cosas son peores.

La orden en el momento de la transformación de una orden pendiente (o de mercado) en una orden histórica (ejecutada o cancelada), desaparece del terminal por completo durante algún tiempo. No aparece ni entre los pendientes (o "iniciados" del mercado), ni entre los históricos.

Así que no es una cuestión de ejecución, sino de sincronización de estas dos tablas. La respuesta del servidor llegó ("Orden ejecutada, transacción generada tal y cual"), se elimina de una tabla, pero no se introduce en la otra.

 
Andrey Khatimlianskii:

No, las cosas son peores.

Cuando una orden pasa de pendiente (o de mercado) a histórica (ejecutada o cancelada), desaparece por completo del terminal durante algún tiempo. No aparece ni entre los pendientes (o "iniciados" del mercado), ni entre los históricos.

Así que no es una cuestión de ejecución, sino de sincronización de estas dos tablas. La respuesta vino del servidor ("Orden ejecutada, desencadenó el acuerdo fulano") y se borra de una tabla pero no se introduce en la otra.

Es interesante comprobarlo.Igor Makanu me intrigó con la tareahttps://www.mql5.com/ru/forum/6343/page1097#comment_12518742

Hice la primera aproximación sobre mi rodilla. Luego haré algunasestadísticas sobre el funcionamiento de OnOrder y OnOrderTransaction y el estado del entorno de trading y si no me da pereza puede que lo ponga a prueba en la demo para ver qué pasa en diferentes cuentas/brokers.

entonces será posible analizar. Supuestos realizados hasta ahora: 1. no se comprueba la ejecución parcial y no se comprueban las peculiaridades de la cuenta; envié una orden de mercado, se recuerda la posición abierta, espero la aparición del cierre de esta posición en el diario y abro de nuevo en sentido contrario. 2. Lo ideal sería atrapar una determinada transacción en OnOrderTransaction, pero hasta ahora lo he hecho así: en ambos eventos compruebo todo de la misma manera.

Por supuesto, el código no es óptimo. Ya veo donde se perderán las posiciones de orden si todo es tan malo como se describe en el post anterior.

//+------------------------------------------------------------------+
//|                                                 Test_Makalu2.mq5 |
//|                                           Copyright 2019, Allex@ |
//|                                                 alex-all@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Allex@"
#property link      "alex-all@mail.ru"
#property version   "1.00"
#include <Expert\Expert.mqh>
//--- input parameters
input int      TP=200;
input int      SL=200;
input double   Lot=0.01;
input string   File;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CExpertTest : public CExpert
  {
public:
   int               type;
   ulong             order;
   ulong             deal;
   ulong             position;
   bool              send;
   bool              placed;
   bool              opened;
   bool              history;
   datetime          last_history;

                     CExpertTest() {order=0;};
                    ~CExpertTest() {};
   bool              Buy(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Buy(volume, price, sl, tp,  comment);};
   bool              Sell(double volume,double price,double sl,double tp,const string comment="") {return m_trade.Sell(volume, price, sl, tp,  comment);};
   bool              CheckOrder(ulong order)
     {
      ulong state;
      if(OrderSelect(order))
        {
         if(OrderGetInteger(ORDER_STATE)==ORDER_STATE_FILLED)
            position=OrderGetInteger(ORDER_POSITION_ID);
        }
      else
         if(HistoryOrderSelect(order))
           {
            if(HistoryOrderGetInteger(order,ORDER_STATE,state)&& state==ORDER_STATE_FILLED)
               position=HistoryOrderGetInteger(order,ORDER_POSITION_ID);
           }
         else
           {
            return false;
           }
      return true;

     }
   virtual bool      Processing(void)
     {
      double price;
      if(order==0)
        {
         last_history=TimeCurrent();
         price=m_symbol.Ask();
         if(Buy(Lot,price,m_symbol.NormalizePrice(price-SL*m_symbol.Point()),m_symbol.NormalizePrice(price+TP*m_symbol.Point())))
            if(m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
              {
               //ulong deal2;
               deal=m_trade.ResultDeal();
               order=m_trade.ResultOrder();
               if(order!=0 && CheckOrder(order))
                  return true;
              }
        }
      return false;
     }
   void              OnTrade()
     {
      if(order==0 || !CheckOrder(order))
         return;
      HistorySelect(last_history,TimeCurrent());
      for(int i=HistoryDealsTotal()-1; i>=0; i--)
        {
         ulong ticket=HistoryDealGetTicket(i);
         ulong ordticket=HistoryDealGetInteger(ticket,DEAL_ORDER);
         ulong pos=HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
         if(pos==position || ordticket==order || ticket==deal)
           {
            int entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
            ulong type=HistoryDealGetInteger(ticket,DEAL_TYPE);
            if(pos==position && entry==DEAL_ENTRY_OUT)
              {
               Refresh();
               double price;
               double sl;
               double tp;
               bool result=false;
               datetime dt=TimeCurrent();
               if(type==DEAL_TYPE_SELL)
                 {
                  price=m_symbol.Bid();
                  sl=m_symbol.NormalizePrice(price+SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price-TP*m_symbol.Point());
                  result=Sell(Lot,price,sl,tp);
                 }
               if(type==DEAL_TYPE_BUY)
                 {
                  price=m_symbol.Ask();
                  sl=m_symbol.NormalizePrice(price-SL*m_symbol.Point());
                  tp=m_symbol.NormalizePrice(price+TP*m_symbol.Point());
                  result=Buy(Lot,price,sl,tp);
                 }
               if(result && m_trade.ResultRetcode()==TRADE_RETCODE_DONE)
                 {
                  deal=m_trade.ResultDeal();
                  order=m_trade.ResultOrder();
                  if(order!=0 && CheckOrder(order))
                     last_history=dt;
                 }
              }
           }
        }
     }
  };
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
CExpertTest Expert;
//---
int OnInit()
  {
   if(!Expert.Init(Symbol(),Period(),Point()))
      return INIT_FAILED;
   Expert.OnTradeProcess(true);
   return(INIT_SUCCEEDED);
  }
//---
void OnTick()
  {
   Expert.OnTick();
  }
//+------------------------------------------------------------------+
void OnTrade()
  {
   Expert.OnTrade();
  }
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
  {
   Expert.OnTrade();
  }
Вопросы от начинающих MQL5 MT5 MetaTrader 5
Вопросы от начинающих MQL5 MT5 MetaTrader 5
  • 2019.07.21
  • www.mql5.com
Подскажите пожалуйста, такой показатель тестера в жизни реален? И хороший это или плохой результат за год с депо 3000...
 
Aleksey Mavrin:

Es interesante comprobarlo.Igor Makanu me intriga con la tarea https://www.mql5.com/ru/forum/6343/page1097#comment_12518742

había una solución en la discusiónhttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819, parte de la discusión, sin embargo, ha sido borrada (((
 
Hay una solución en el hilo de MT4Orders. Pero tienes que sentir cada rastrillo tú mismo ;)
 
Aleksey Mavrin:

Hice una primera aproximación a la rodilla.

Esta demo es mejor para mirar.ForexTimeFXTM-Demo01

 
Igor Zakharov:

No he notado para nada el caso que he descrito en los robots de trading "normales".

Cualquier librería de comercio puede y debe ser comprobada en cuanto a su peligrosidad utilizando pruebas de estrés en varias cuentas demo. Debería pasar todo sin problemas.

Pues bien, para conseguirlo, el autor tiene que conocer personalmente los chistes de MT5. En mi práctica resultó que incluso esto no es suficiente.

Hay cosas muy específicas que no fueron detectadas por el terrible spam de órdenes a los servidores de comercio. Gracias a los comentarios fue posible encontrar comportamientos bastante extraños de los que ni siquiera los propios desarrolladores parecen darse cuenta.

 
Igor Makanu:
había una solución en la discusiónhttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819, parte de la discusión ha sido borrada (((
Andrey Khatimlianskii:
Hay una solución en la rama de MT4Orders. Pero tienes que sentir cada rastrillo tú mismo ;)

Así es, el rastrillo siempre es interesante, y luego ver cómo lo hicieron los profesionales. La solución defxsaber es brillante por su concisión, pero veo una pega en esa solución en una cosa: los manuales dicen que el ticket de posición es EXACTAMENTE el ticket de la orden abierta, pero NO TODO.

En mi solución partía de eso.

fxsaber
fxsaber
  • www.mql5.com
Опубликовал пост "Out-Of-Sample" - где расположить, справа или слева? Когда-то в паблике столкнулся с мнением, что OOS должен располагаться только справа. Т.е. расположение его слева от интервала Оптимизации - ошибка. Я с этим был категорически не согласен, т.к. не видел разницы. Теперь вижу. Ошибался, был не прав... Опубликовал пост...
 
fxsaber:

Cualquier librería de comercio puede y debe ser comprobada para ver si es mala a través de pruebas de estrés en varias cuentas de demostración. Debería pasar todo sin problemas.

Usé 200ms para las pruebas y cuando lo devolví, el hombre lo puso a 5ms. A los cinco funcionó casi siempre en cualquier cuenta.

No sé si es importante, pero usaron winapi timeBeginPeriod(1), es decir, por debajo de los 20ms estándar todo ocurrió

 
Aleksey Mavrin:

billete de posición OVERALLY el billete de orden de apertura, pero NO SIEMPRE.

No lo recuerdo muy bien, pero parece que es siempre.

 
fxsaber:

No lo recuerdo muy bien, pero creo que siempre ha estado ahí.

Sí, tienes razón, ya que en este caso se trata de un identificador de posición, constante durante toda su vida. Lo confundí con el ticker de la posición, que cambia durante las prórrogas y la compensación.

Pero no entiendo - cuando una posición se cierra parcialmente, el ticket no cambia al ticket de la última orden que afecta a la posición?

Revisaré mis códigos, gracias. No he visitado el foro para nada)

En cuanto a la "orden perdida" que no aparece en la lista de órdenes actuales o históricas: Me parece que no es un error, sólo tengo que mirar cuidadosamente las características de

Creo que esto no es un error, sólo hay que mirar cuidadosamente las peculiaridades de la terminal-servidor MT-mercado (en el caso de la ejecución instantánea del mercado no funciona). Creo que sí, mira - el terminal envía una orden de mercado, en el caso de la función sincrónica - espera y obtiene una respuesta del servidor,

Si no hay ningún error, la respuesta sólo puede ser TRADE_RETCODE_DONE (en el caso de la ejecución instantánea es requotes, pero hasta ahora es el tipo de mercado), lo que significa esencialmente que el servidor ha enviado la orden al mercado y ésta

En realidad significa que el servidor ha enviado la orden y espera su respuesta. El estado de la orden en este momento esORDER_STATE_STARTED si no me equivoco y su ticket es conocido. Si la orden se ejecuta, el servidor envía OnTradeTransaction al terminal y el estado de la orden cambia a ORDER_STATE_FILLED y se conoce la operación

y se conoce la posición. Sólo en este momento el terminal registra la orden en el historial. No lo hace de antemano, ya que no estamos seguros de lo que le ha pasado y ya ha dado la respuesta inicial del servidor.

Es el tiempo que transcurre hasta que la orden se ejecuta en la red ECN o en otro lugar, no están en ninguna de las dos listas. Es decir, en el caso de la orden de mercado, sólo aparece en el historial (no estoy seguro del caso de las recotizaciones durante la ejecución instantánea),

nunca aparecerá en la lista de abiertos. Y cuando una orden pendiente se dispara, se elimina de la lista de las abiertas porque ya se ha convertido en una orden de mercado y se espera a que el servidor de mercado responda, y entonces se envía al historial.

¿Estoy en lo cierto?