OnTradeTransaction - page 8

 
Igor Zakharov:

On "normal" robots, the case I described, I didn't notice at all; but in one case I was asked to make a security system: the condition was that positions are always locked (either with real positions or a pending order), i.e. the number of buy lots equals the number of sell lots. This is the case that introduced me to the nuances of order/position/trade counting in a fiver.

The difference, as I explained it to myself :) is that the four, when getting an answer from the broker, first synchronizes its "tables" with open orders and history, and then informs the user about the broker's answer. The five immediately broadcasts this answer to us, and at the same time corrects its "tables" (and all mql programs read data from these "tables"). This is the moment we catch on the millisecond timer. But then, why don't we catch it in the tester?

In general, I've made my peace of mind...

No, things are worse.

The order at the moment of transformation from a pending (or market) into a historical order (executed or cancelled), it disappears from the terminal altogether for some time. It does not appear either among pending (or "started" market), or among historical ones.

So it's not a matter of execution, but of synchronization of these two tables. The answer from the server came ("Order executed, generated transaction so-and-so"), it is removed from one table, but it is not entered into the other.

 
Andrey Khatimlianskii:

No, things are worse.

When an order changes from a pending (or market) to a historical order (executed or cancelled), it disappears from the terminal altogether for some time. It does not appear either among pending (or "started" market), or among historical ones.

So it's not a matter of execution, but of synchronization of these two tables. The answer came from the server ("Order executed, triggered the deal so-and-so") and it is deleted from one table but not entered into the other.

It is interesting to check it.Igor Makanu intrigued me with the taskhttps://www.mql5.com/ru/forum/6343/page1097#comment_12518742

I made the first approximation on my knee. Then I will make somestatistics about OnOrder and OnOrderTransaction operation and trading environment state and if I'm not too lazy I may put it for demo test to see what is going on in different accounts/brokers.

then it will be possible to analyse. Assumptions made so far: 1. no partial execution is checked and the peculiarities of the account are not checked; I sent a market order, opened position is remembered, I wait for the appearance of the closing of this position in the journal and open again in the opposite direction. 2. Ideally, a certain transaction should be caught in OnOrderTransaction but so far I have done it this way - in both events I check everything in the same way.

Of course, the code is not optimal. I can already see where the order-positions will be lost if everything is as bad as described in the post above.

//+------------------------------------------------------------------+
//|                                                 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:

This is interesting to check out.Igor Makanu intrigues me with the task https://www.mql5.com/ru/forum/6343/page1097#comment_12518742

there was a solution in the discussionhttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819, part of the discussion, however, has been deleted (((
 
There is a solution in the MT4Orders thread. But you have to feel every rake yourself ;)
 
Aleksey Mavrin:

Made a first approximation on the knee.

This demo is better to look at.ForexTimeFXTM-Demo01

 
Igor Zakharov:

I did not notice the case I described on "normal" trading robots at all.

Any trading library can and should be checked for lousiness using stress tests on various demo accounts. It should pass everything without a hitch.

Well, to make it happen, the author has to get acquainted with MT5-jokes personally. In my practice it turned out that even this is not enough.

There are some very specific things that were not detected by the terrible spamming of orders to the trade servers. Thanks to feedback it was possible to find quite strange behaviour that even the developers themselves don't seem to realise.

 
Igor Makanu:
there was a solution in the discussionhttps://www.mql5.com/ru/forum/6343/page1098#comment_12519819, part of the discussion has been deleted (((
Andrey Khatimlianskii:
There is a solution in the branch of MT4Orders. But you have to feel every rake yourself ;)

That's right, the rake is always interesting, and then see how the pros did it. Thefxsaber solution is brilliant in its conciseness, but I see a catch in that solution in one thing - the manuals say that the position ticket is EXACTLY the ticket of the order opened, but NOT EVERYTHING.

In my solution I was proceeding from that.

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

Any trading library can and should be checked for lousiness through stress tests on various demo accounts. It should pass everything without a hitch.

I used 200ms for the tests and when I gave it back, the man set it to 5ms. At five it worked almost every time on any account.

I don't know if it's important, but the timeBeginPeriod(1) was used, i.e. everything went below the standard 20ms

 
Aleksey Mavrin:

position ticket OVERALLY the opening order ticket, but NOT ALWAYS.

I don't remember it very well, but it seems to be always.

 
fxsaber:

I don't remember it very well, but I think it's always been there.

Yes, you're right, as in this case it's a position identifier, constant throughout its life. I confused it with the position ticker, which changes during rollovers and netting.

But I do not understand - when a position is partially closed, the ticket does not change to the ticket of the last order affecting the position?

I will review my codes, thanks. I have visited the forum not for nothing)

Concerning the "lost order" which is not in the list of current or historical orders: It seems to me this is not a bug, I just need to carefully look at the features of

I think this is not a bug, just need to carefully look at peculiarities of terminal-server MT-market (in the case of instant execution the market does not work). I think so, look - the terminal sends a market order, in the case of synchronous function - it waits and gets a reply from the server,

If there is no error, the reply may only be TRADE_RETCODE_DONE (in the case of instant execution it is still requotes, but so far it is the market type), which essentially means that the server has sent the order to the market and it

It actually means that the server has sent the order and waits for its reply. The state of the order at this moment isORDER_STATE_STARTED if I am not mistaken and its ticket is known. If the order is executed, the server sends OnTradeTransaction to the terminal and the order status changes to ORDER_STATE_FILLED and the trade is known

and position becomes known. It is only at this point that the terminal records the order into the history. It does not do this beforehand since we are not sure what has happened to it and it has already given the initial reply from the server.

This is the time until the order is executed in the ECN network or somewhere else, they are not in either of the two lists. I.e. in the case of market order, it only appears in the history (I am not sure about the case of requotes during instant execution),

it will never appear in the list of open ones. And when a pending order triggers, it is removed from the list of the open ones because it has already become a market order and we wait for the market-server to respond, and then it is sent to history.

Am I right?

Reason: