Features of the mql4 language, subtleties and techniques - page 34

 
I've noticed the following problem: if you run a script and it crashes (closes the platform), then the log file does not save records while the script is running, which makes it quite difficult to detect an error in the code. I haven't noticed this problem before. Has it always been like this (no records saved) ?
 

There seems to be no way of knowing in MT4 (without re-connecting) if the leverage on the account has changed.

 
fxsaber #:

There seems to be no way in MT4 to know (without re-connecting) if the leverage in the account has changed.

I did it about five years ago. A client's leverage was reduced at certain hours, and it didn't change in the variable AccountInfoInteger(ACCOUNT_LEVERAGE) in any way. And he needed to know about it.

I don't know about the science, but I've decided that there's an account leverage that changes rarely, and there's a symbol leverage that may change several times a day.
I checked it this way:

//+------------------------------------------------------------------------------------------------------------------+
//| Проверяет изменение плеча и сообщает если это было
//+------------------------------------------------------------------------------------------------------------------+
void leverageCheck()
{
  if(MarketInfo(Symbol(), MODE_MARGINREQUIRED) == 0) return;

   // --- получаем текущее плечо из маржинальных требований, стоимости пункта, тек.котировки
  double leverageSymb = MarketInfo(Symbol(),MODE_TICKVALUE) * Bid / MarketInfo(Symbol(),MODE_MARGINREQUIRED) / Point;
  leverageSymb = int(MathRound(leverageSymb));
  
   // --- если плечо по символу стало меньше на 10% плеча по счету отметим это
  if(leverageSymb < percVar(AccountInfoInteger(ACCOUNT_LEVERAGE), -10))
  {
    string txt = TimeToString(TimeCurrent()) + " Leverage is reduced 1:" + (string)leverageSymb;
    Print(txt, " but account leverage = " + (string)AccountInfoInteger(ACCOUNT_LEVERAGE));

    // --- вывод информации на график
  }
}

//+-------------------------------------------------------------------------------------------------------------------+
//| Получает переменную, увеличивает или уменьшает его на переданный процент и возвращает новое значение
//| Чтобы уменьшить, нужно передать percent с минусом
//+-------------------------------------------------------------------------------------------------------------------+
double percVar(double var, double percent)
{
  return var*(1 + percent/100);
}


Sometimes the current calculated leverage by leverageSymb symbol might give 199, 198 instead of 200 (when the leverage is 1:200). Therefore, I had to subtract a certain % from the standard leverage and compare it with this value. The solution above was helpful at the time, it may come in handy.

 
Vasiliy Pushkaryov #:

I did this about five years ago. A client had their leverage reduced at certain hours, and it did not change in any way in the AccountInfoInteger(ACCOUNT_LEVERAGE) variable. And he needed to know about it.

I don't know about the science, but I've decided that there's an account leverage that changes rarely, and there's a symbol leverage that may change several times a day.
I checked it this way:


Sometimes the current calculated leverage by leverageSymb symbol might give 199, 198 instead of 200 (when the leverage is 1:200). Therefore, I had to subtract a certain % from the standard leverage and compare it with this value. The solution above helped then, might come in handy.

Yes, there is no problem with tracking the margin requirements of the symbol. ACCOUNT_LEVERAGE - only reconnect.

 

It is very common practice to filter the trading history by remembering the required orders in a ticket list. And then SELECT_BY_TICKET on that list.

I've never seen a variant where not a ticket but a position is memorized. Below is a comparison of performance.

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006
#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279

int Filter( TICKET_TYPE &Tickets[], int &Pos[] )
{
  const int Total = OrdersHistoryTotal();            

  ArrayResize(Tickets, Total);
  ArrayResize(Pos, Total);
  
  int Amount = 0;

  for (int i = 0; i < Total; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (OrderProfit() > 0))
    {
      Tickets[Amount] = OrderTicket();
      Pos[Amount] = i;
      
      Amount++;
    }
    
  ArrayResize(Tickets, Amount);
  ArrayResize(Pos, Amount);
  
  return(Amount);
}

template <typename T>
double Func1( int TypeSelect, const T &Array[] )
{
  double Res = 0;
  const int Total = ArraySize(Array);
  
  for (int i = 0; i < Total; i++)
    if (OrderSelect(Array[i], TypeSelect, MODE_HISTORY))
      Res += OrderProfit();
      
  return(Res);
}

void OnStart()
{   
  TICKET_TYPE Tickets[];
  int Pos[];

  Print(Filter(Tickets, Pos));
  
  const double Res1 = _B(Func1(SELECT_BY_TICKET, Tickets), 1); // Так делают почти все.
  const double Res2 = _B(Func1(SELECT_BY_POS, Pos), 1);        // Не встречал.
  
  Print(Res1);
  Print(Res2);
}


2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: 561002.61
2021.10.11 01:37:08.254 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 49 in OnStart: Func1(SELECT_BY_POS,Pos)] = 2827 mcs.
2021.10.11 01:37:08.251 Test19 EURUSD.rann,M1: Alert: Bench_Stack = 0, 1 <= Time[Test19.mq4 48 in OnStart: Func1(SELECT_BY_TICKET,Tickets)] = 7460 mcs.
2021.10.11 01:37:08.244 Test19 EURUSD.rann,M1: 35936

We see that the ticket variant loses almost three times in performance.

 
fxsaber #:

It can be seen that the ticket variant loses almost three times in performance.

if a position is closed/open, the logic with the ticket will not break, the logic with the position might.

 
TheXpert #:

if a position is closed/open, the logic with the ticket will not break, the logic with the position may.

It is only about MODE_HISTORY mode.

 

Is it theoretically possible that this code will miss some order that existed BEFORE and AFTER the function was called? Or will it count twice.

double GetLots()
{
  double Lots = 0;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS))
      Lots += OrderLots();
      
  return(Lots);
}

I.e. what happens to the indexing when an order is deleted or appears during the enumeration?

 
fxsaber #:

Or it will count twice.

If we assume default sorting by time or ticket, new orders appear at the end of the list, and logically all are shifted when the oldest ones are deleted.

It turns out when deleting an order from the beginning of the list one of the list can be taken into account twice. It seems easy to work around - just remember the ticket from the previous pass and compare (but still no guarantee).

How to get a pass on the return pass - not figured out

 
Andrei Trukhanovich #:

If we assume default sorting by time or ticket, new orders appear at the end of the list, and logically all are shifted when the oldest ones are deleted.

It turns out when deleting an order from the beginning of the list one of the list can be taken into account twice. It seems easy to work around - just remember the ticket from the previous pass and compare (but still no guarantee).

How to get a pass on the return pass - haven't worked it out

Thanks for the detailed reply! So now I'm wondering how to go through ALL the orders at ONE time.

Reason: