OrderCloseTime Expert Advisor MQL5 12

Hi, Im looking for a way to retrieve the last closed order/deal/position close time, possibly in datetime. Ive searched for various solutions, but none seem to work, Anyone with Ideas ?

Thanks

Did you read this: https://www.mql5.com/en/docs/trading/historydealgetinteger

Do you mean by using DEAL_ENTRY_OUT, I 've tried this, but some problem occurred

Look at the example:

Note

Do not confuse orders, deals and positions. Each deal is the result of the execution of an order, each position is the summary result of one or more deals.

Example:

//+------------------------------------------------------------------+ 
//| Trade function                                                   | 
//+------------------------------------------------------------------+ 
void OnTrade() 
  { 
//--- receive the last deal's ticket from week's trading history 
   ulong last_deal=GetLastDealTicket(); 
   if(HistoryDealSelect(last_deal)) 
     { 
      //--- time of deal execution in milliseconds since 01.01.1970 
      long deal_time_msc=HistoryDealGetInteger(last_deal,DEAL_TIME_MSC); 
      PrintFormat("Deal #%d DEAL_TIME_MSC=%i64 => %s", 
                  last_deal,deal_time_msc,TimeToString(deal_time_msc/1000)); 
     } 
   else 
      PrintFormat("HistoryDealSelect() failed for #%d. Eror code=%d", 
                  last_deal,GetLastError()); 
//--- 
  } 
//+------------------------------------------------------------------+ 
//| Returns the last deal ticket in history or -1                    | 
//+------------------------------------------------------------------+ 
ulong GetLastDealTicket() 
  { 
//--- request history for the last 7 days 
   if(!GetTradeHistory(7)) 
     { 
      //--- notify on unsuccessful call and return -1 
      Print(__FUNCTION__," HistorySelect() returned false"); 
      return -1; 
     } 
//---  
   ulong first_deal,last_deal,deals=HistoryOrdersTotal(); 
//--- work with orders if there are any 
   if(deals>0) 
     { 
      Print("Deals = ",deals); 
      first_deal=HistoryDealGetTicket(0); 
      PrintFormat("first_deal = %d",first_deal); 
      if(deals>1) 
        { 
         last_deal=HistoryDealGetTicket((int)deals-1); 
         PrintFormat("last_deal = %d",last_deal); 
         return last_deal; 
        } 
      return first_deal; 
     } 
//--- no deal found, return -1 
   return -1; 
  } 
//+--------------------------------------------------------------------------+ 
//| Requests history for the last days and returns false in case of failure  | 
//+--------------------------------------------------------------------------+ 
bool GetTradeHistory(int days) 
  { 
//--- set a week period to request trade history 
   datetime to=TimeCurrent(); 
   datetime from=to-days*PeriodSeconds(PERIOD_D1); 
   ResetLastError(); 
//--- make a request and check the result 
   if(!HistorySelect(from,to)) 
     { 
      Print(__FUNCTION__," HistorySelect=false. Error code=",GetLastError()); 
      return false; 
     } 
//--- history received successfully 
   return true; 
  }

See also

HistoryDealsTotal(), HistorySelect(), HistoryDealGetTicket(), Deal Properties
#include <MT4Orders.mqh> // https://www.mql5.com/en/code/16006

void OnStart()
{
  if (OrderSelect(OrdersHistoryTotal() - 1, SELECT_BY_POS, MODE_HISTORY))
  {
    Print(OrderCloseTime());
    
    OrderPrint();
  }
}

Library are useful, but are often slow :

2018.07.06 00:07:18.336 262536 (EURUSD,H1) 2018.06.27 16:40:21
2018.07.06 00:07:18.336 262536 (EURUSD,H1) #2019953 2018.06.25 15:56:14 sell 1.00 M6AU8 0.7406 0.0000 0.7360 2018.06.27 16:40:21 0.7363 0.00 0.00 43.00 [tp 0.7360] 1600
2018.07.06 00:07:18.336 262536 (EURUSD,H1) MQL4 style: Duration: 25001 µs
2018.07.06 00:07:18.341 262536 (EURUSD,H1) #1735257 Open time:2018.06.25 15:56:14 Close time:2018.06.27 16:40:21
2018.07.06 00:07:18.341 262536 (EURUSD,H1) MQL5 style: Duration: 4752 µs

 begin=GetMicrosecondCount();

   if(HistorySelect(0,INT_MAX))
     {
      int total=HistoryDealsTotal();

      for(int i=total-1;i>=0;i--)
        {
         ulong ticket=HistoryDealGetTicket(i);

         long entry=HistoryDealGetInteger(ticket,DEAL_ENTRY);
         if(entry==DEAL_ENTRY_OUT)
           {
            datetime oct=(datetime)HistoryDealGetInteger(ticket,DEAL_TIME);
            long positionTicket=HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
            if(HistorySelectByPosition(positionTicket))
              {
               ticket=HistoryDealGetTicket(0);
               printf("#%lli Open time:%s Close time:%s",
                      positionTicket,
                      TimeToString((datetime)HistoryDealGetInteger(ticket,DEAL_TIME),TIME_DATE|TIME_SECONDS),
                      TimeToString(oct,TIME_DATE|TIME_SECONDS));
               break;
              }
           }
        }
     }
   printf("MQL5: Duration: %llu µs",GetMicrosecondCount()-begin);

Code incomplete just to check execution time. Don’t copy and paste it without understanding.

#include <MT4Orders.mqh> // https://www.mql5.com/en/code/16006

void LastTimeMQL4( datetime &OpenTime, datetime &CloseTime )
{
  if (OrderSelect(OrdersHistoryTotal() - 1, SELECT_BY_POS, MODE_HISTORY))
  {
    OpenTime = OrderOpenTime();
    CloseTime = OrderCloseTime();
  }
}

void LastTimeMQL5( datetime &OpenTime, datetime &CloseTime )
{
  if (HistorySelect(0, INT_MAX))
  {
    for (int i = HistoryDealsTotal() - 1; i >= 0; i--)
    {
      const ulong Ticket = HistoryDealGetTicket(i);
  
      if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
      {
        CloseTime = (datetime)HistoryDealGetInteger(Ticket, DEAL_TIME);

        if (HistorySelectByPosition(HistoryDealGetInteger(Ticket, DEAL_POSITION_ID)))
          OpenTime = (datetime)HistoryDealGetInteger(HistoryDealGetTicket(0), DEAL_TIME);
          
        break;
      }
    }
  }
}

typedef void (*GetLastTime)( datetime&, datetime& );

void Bench( GetLastTime LastTime, const int Amount = 10000 )
{
  datetime OpenTime, CloseTime;
  datetime Tmp = 0;

  for (int i = 0; i < Amount; i++)
  {
    LastTime(OpenTime, CloseTime);
    
    Tmp += CloseTime - OpenTime;        
  }
  
  Print(Tmp);
}

#define BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

#define PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{  
  if (HistorySelect(0, INT_MAX))
    PRINT(HistoryDealsTotal());

  BENCH(Bench(LastTimeMQL4))
  BENCH(Bench(LastTimeMQL5))  
}

Result:

HistoryDealsTotal() = 343
1970.01.01 00:00:00
Time[Bench(LastTimeMQL4)] = 88705
1970.01.01 00:00:00
Time[Bench(LastTimeMQL5)] = 749410

Ok you are right, the print statement should be outside the bench, but let’s be fair. My code is not optimized to be run in a loop.

void Bench( GetLastTime LastTime, const int Amount = 1 )
HistoryDealsTotal() = 4580
1970.01.03 00:44:07
Time[Bench(LastTimeMQL4)] = 3534
1970.01.03 00:44:07
Time[Bench(LastTimeMQL5)] = 2467

And I had to tweak your code because the last deal in my history is not a trade.

void LastTimeMQL4(datetime &OpenTime,datetime &CloseTime)
  {
   int total=OrdersHistoryTotal();

   for(int i=total-1;i>=0;i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)
         && OrderType()<2)
        {
         OpenTime=OrderOpenTime();
         CloseTime=OrderCloseTime();
         break;
        }
     }
  }

Native code is always more efficient than a wrapper library.

Imagine that you call a function on each event NewTick.

And I had to tweak your code because the last deal in my history is not a trade

You solve a somewhat different task from the one that the author of the topic asked.

Native code is always more efficient than a wrapper library.

Unfortunately, it is not.

To understand the convenience of the MQL5-native, try writing a function not for the last deal, but for the penultimate one.

PS With

void LastTimeMQL4( datetime &OpenTime, datetime &CloseTime )
{
  for (int i = OrdersHistoryTotal() - 1; i >= 0; i--)  
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderType() <= OP_SELL))
    {
      OpenTime = OrderOpenTime();
      CloseTime = OrderCloseTime();
      
      break;
    }
}
Result
HistoryDealsTotal() = 345
1970.01.01 01:56:40
Time[Bench(LastTimeMQL4)] = 21528
1970.01.01 01:56:40
Time[Bench(LastTimeMQL5)] = 153839

It was not a specification, obviously I will not select all history on each tick.

You solve a somewhat different task from the one that the author of the topic asked.
No it’s exactly what was asked. Why are you thinking it’s different ?

Unfortunately, it is not.

I demonstrated above it is. Why are you saying it’s not ?

To understand the convenience of the MQL5-native, try writing a function not for the last deal, but for the penultimate one.
What’s the problem ?

P.S: You can’t run my code in a loop, doesn’t make sense. The results you posted are flawed.

So write a function that you can call on each event NewTick!

No it’s exactly what was asked. Why are you thinking it’s different ?

It does not matter. Look at the result above.

Measuring the performance of the code is done on a multiple call.

If you want a scientific benchmark yes. It was not my goal. I executed the script a dozen of time (Amount=1) and mql5 style was ALWAYS faster, obviously. Everyone can check by himself and should better learn mql5.

Refer to @Renat Fatkhullin for clarification.

void LastTimeMQL5( datetime &OpenTime, datetime &CloseTime )
{
  static datetime PrevTime = 0;
  
  if (HistorySelect(PrevTime, INT_MAX)) // HistorySelect(0, INT_MAX) - slow.
  {
    for (int i = HistoryDealsTotal() - 1; i >= 0; i--)
    {
      const ulong Ticket = HistoryDealGetTicket(i);
  
      if (HistoryDealGetInteger(Ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
      {
        CloseTime = (datetime)HistoryDealGetInteger(Ticket, DEAL_TIME);

        if (HistorySelectByPosition(HistoryDealGetInteger(Ticket, DEAL_POSITION_ID)))
          OpenTime = (datetime)HistoryDealGetInteger(HistoryDealGetTicket(0), DEAL_TIME);
          
        break;
      }
    }
  }
  
  PrevTime = CloseTime;
}

Result

HistoryDealsTotal() = 345
1970.01.01 19:26:40
Time[Bench(LastTimeMQL4)] = 186586
1970.01.01 19:26:40
Time[Bench(LastTimeMQL5)] = 151659

The larger the size of the history of trading, the stronger the MQL5-native loses.

HistoryDealsTotal() = 3721
HistoryOrdersTotal() = 6303
1970.01.03 02:00:00
Time[Bench(LastTimeMQL4)] = 1111305
1970.01.03 02:00:00
Time[Bench(LastTimeMQL5)] = 1799255

Your library is using the MQL5-native and is keeping data in memory. Of course the mql5 above could be optimized to keep data in memory too, and you know it.

If someone want to use your library or an other, there is no problem. However, I am still suggesting people to learn the mql5 way.

It’s not in my library. It’s not at all clear **how to write simple functions in MQL5-native, so that they are still fast?

Interestingly, the history is not cached there, but only tickets are stored.

#include <Generic\HashMap.mqh>

class MT4HISTORY
{
private:
  CHashMap<ulong, ulong> DealsIn;
  CHashMap<ulong, ulong> DealsOut;

  long Tickets[];