Особенности языка mql5, тонкости и приёмы работы - страница 88

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Ошибки, баги, вопросы

fxsaber, 2016.07.19 12:41

Какой смысл в наличии  ENUM_DEAL_PROPERTY_INTEGER::DEAL_TICKET, если единственное место, где его можно применить, это HistoryDealGetInteger(TicketDeal, DEAL_TICKET)?

На примере ORDER_TICKET должна быть понятна идея

Forum on trading, automated trading systems and testing trading strategies

OrderCloseTime () in MQL5?

fxsaber, 2018.07.18 03:51

datetime OrderCloseTime( const ulong Ticket )
{
  return((HistoryOrderGetInteger(Ticket, ORDER_TICKET) == Ticket) || HistoryOrderSelect(Ticket) ? (datetime)HistoryOrderGetInteger(Ticket, ORDER_TIME_DONE) : 0);
}

Таким образом можно проверить, содержится ли в текущей исторической таблице, сформированной ранее через HistorySelect-функции, нужная нам запись. Это же касается и DEAL_TICKET.

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Сохранить уровень цены позиции через клиринг (можно?)

fxsaber, 2018.07.17 20:45

// Возвращает цену открытия выбранной позиции без учета клиринга
double GetSummaryPositionPrice()
{
  double TotalVolume = 0;
  double TotalDealPrice = 0;
  
  if (HistorySelectByPosition(PositionGetInteger(POSITION_IDENTIFIER)))
  {
    const int DealsTotal = HistoryDealsTotal();
    
    for (int i = 0; i < DealsTotal; i++)
    {
      const ulong DealTicket = HistoryDealGetTicket(i);
      
      if (HistoryDealGetInteger(DealTicket, DEAL_ORDER))
      {
        const double DealVolume = (HistoryDealGetInteger(DealTicket, DEAL_TYPE) ? -1 : 1) * HistoryDealGetDouble(DealTicket, DEAL_VOLUME);
        const double DealPrice = HistoryDealGetDouble(DealTicket, DEAL_PRICE);
  
        if (TotalVolume * DealVolume >= 0)
          TotalDealPrice = (TotalDealPrice * TotalVolume + DealPrice * DealVolume) / (TotalVolume + DealVolume);
        else if (MathAbs(DealVolume) - MathAbs(TotalVolume) > 0.005)
          TotalDealPrice = DealPrice;
          
        TotalVolume += DealVolume;
      }      
    }
  }
  
  return(TotalDealPrice);
}
 

Возможно не все знают, что функция GetMicrosecondCount, в отличие от GetTickCount, привязана к локальному времени компьютера.  Т.е. при изменении этого времени (например в результате синхронизации с интернет-временем) значения GetMicrosecondCount тоже изменятся на соответствующую величину.  Это надо иметь ввиду, если данная функция используется для замеров интервалов времени.  По сути, применять её для этих целей не следует.  А вот GetTickCount лишена этих проблем. 

В качестве демонстрации можно запустить такой код и в процессе выполнения поменять время компьютера.

  datetime time= TimeLocal();
  ulong    microsec= GetMicrosecondCount();
  uint     ticks= GetTickCount();
  
  while(!IsStopped())
  {
    Comment(int(TimeLocal()-time),"   ",(GetMicrosecondCount()-microsec)/1000000,"   ",(GetTickCount()-ticks)/1000);
    Sleep(10);
  }
 
Alexey Navoykov:

Возможно не все знают, что функция GetMicrosecondCount, в отличие от GetTickCount, привязана к локальному времени компьютера.

Не знал, спасибо!

 

Вариант функции GetTickCount, исключающий переполнение (при условии, что интервал между вызовами функции не превышает 50 дней)

ulong GetTickCountLong()
{
  static ulong sum=0;
  static uint  lasttickcount=0;
  uint tickcount= GetTickCount();
  if (tickcount<lasttickcount) sum+=0x100000000;
  lasttickcount= tickcount;
  return sum + tickcount;
}
 
Alexey Navoykov:

Возможно не все знают, что функция GetMicrosecondCount, в отличие от GetTickCount, привязана к локальному времени компьютера.  Т.е. при изменении этого времени (например в результате синхронизации с интернет-временем) значения GetMicrosecondCount тоже изменятся на соответствующую величину.  Это надо иметь ввиду, если данная функция используется для замеров интервалов времени.  По сути, применять её для этих целей не следует.  А вот GetTickCount лишена этих проблем. 

В качестве демонстрации можно запустить такой код и в процессе выполнения поменять время компьютера.

Ну тогда это баг, который разработчикам неплохо бы исправить. Т.к. тогда функция не соответствует описанию:

Функция GetMicrosecondCount() возвращает количество микросекунд, прошедших с момента начала работы MQL5-программы.
Ценность этой функции в сравнении с GetTickCount - это микросекунды, а не миллисекунды(точность в 1000 раз выше). А также непереполняемость.
Поэтому о ее заменяемости говорить не совсем корректно.
 
Alexey Navoykov:

Возможно не все знают, что функция GetMicrosecondCount, в отличие от GetTickCount, привязана к локальному времени компьютера.  Т.е. при изменении этого времени (например в результате синхронизации с интернет-временем) значения GetMicrosecondCount тоже изменятся на соответствующую величину.  Это надо иметь ввиду, если данная функция используется для замеров интервалов времени.  По сути, применять её для этих целей не следует.  А вот GetTickCount лишена этих проблем. 

В качестве демонстрации можно запустить такой код и в процессе выполнения поменять время компьютера.

И еще одно важное наблюдение, из которого следует что использовать функцию  GetTickCount вместо GetMicrosecondCount совсем неуместно.
Думаю, для многих это будет сюрпризом. 

Исследуя работу простого скрипта:

void OnStart()
  {
   uint i=GetTickCount();
   uint i0=GetTickCount();
   while(i==i0) i0=GetTickCount(); 
   
   int N1=1;
   ulong t1=GetMicrosecondCount();
   uint i1=GetTickCount();
   uint i2=GetTickCount();
   while(i1==i2) { i2=GetTickCount(); N1++;}
   t1=GetMicrosecondCount()-t1;
   
   ulong t=GetMicrosecondCount();
   ulong t0=GetMicrosecondCount();
   while(t==t0) t0=GetMicrosecondCount(); 
   int N2=1;
   ulong t2=GetMicrosecondCount();
   ulong t3=GetMicrosecondCount();
   while(t2==t3) { t3=GetMicrosecondCount(); N2++;}
   ulong t4=t3-t2;

   Print("1 значение в милисекундах:  " +(string)i1+", следующее значение   "+ (string)i2 + ", разница - " +(string)t1 + 
   " микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = " +DoubleToString((double)t1*1000.0/N1,3)+ " наносекунды");
   
   Print("1 значение в микросекундах: " +(string)t2+", следующее значение   "+ (string)t3 + ", разница - " +(string)t4 + 
   " микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = " +DoubleToString((double)t4*1000.0/N2,3)+ " наносекунды");
  }

Результат работы:

2018.07.27 00:23:02.261 TestTimeCount   1 значение в милисекундах:  25225093, следующее значение   25225109, разница - 15663 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.323 наносекунды
2018.07.27 00:23:02.261 TestTimeCount   1 значение в микросекундах: 20247, следующее значение   20248, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 33.333 наносекунды
2018.07.27 00:23:03.590 TestTimeCount   1 значение в милисекундах:  25226421, следующее значение   25226437, разница - 15586 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.324 наносекунды
2018.07.27 00:23:03.590 TestTimeCount   1 значение в микросекундах: 22835, следующее значение   22836, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 30.303 наносекунды
2018.07.27 00:23:04.920 TestTimeCount   1 значение в милисекундах:  25227750, следующее значение   25227765, разница - 15657 микросекунд, время выполнения функции GetTickCount (одного прохода цикла) = 2.309 наносекунды
2018.07.27 00:23:04.920 TestTimeCount   1 значение в микросекундах: 23701, следующее значение   23702, разница - 1 микросекунд, время выполнения функции GetMicrosecondCount (одного прохода цикла) = 27.027 наносекунды

можно сделать следующие выводы:

  • значение функции GetTickCount() меняется не каждую миллисекунду, а каждые 15.625 миллисекунд (1/64 секунды, 64=2^6) , тогда как значение функции GetMicrosecondCount () меняется каждую микросекунду. Т.е. точность GetMicrosecondCount  выше чем у GetTickCount в 15625 раз, а не в 1000. 
  • но зато функция  GetTickCount()  быстрее функции GetMicrosecondCount() приблизительно в 12-15 раз.
 
Nikolai Semko:

Ну тогда это баг, который разработчикам неплохо бы исправить. Т.к. тогда функция не соответствует описанию:

Ценность этой функции в сравнении с GetTickCount - это микросекунды, а не миллисекунды(точность в 1000 раз выше). А также непереполняемость.
Поэтому о ее заменяемости говорить не совсем корректно.

Я вот пока не увидел для себя какой-либо практической пользы от микросекунд.  Если замерять время выполнения каких-то участков программы, то колебания производительности системы нивелируют всю эту точность, и погрешность там идёт на миллисекунды, а то и на десятки миллисекунд.      Если же замерять очень малые отрезки длительностью менее 1 миллисекунды, то какой в этом смысл.  Доля погрешности измерений будет очень высока.

 
Alexey Navoykov:

Я вот пока не увидел для себя какой-либо практической пользы от микросекунд.  Если замерять время выполнения каких-то участков программы, то колебания производительности системы нивелируют всю эту точность, и погрешность там идёт на миллисекунды, а то и на десятки миллисекунд.      Если же замерять очень малые отрезки длительностью менее 1 миллисекунды, то какой в этом смысл.  Доля погрешности измерений будет очень высока.

  1. см. мое предыдущее сообщение
  2. У меня масса примеров с практической пользой от микросекунд.

 
Nikolai Semko:

И еще одно важное наблюдение, из которого следует что использовать функцию  GetTickCount вместо GetMicrosecondCount совсем неуместно.
Думаю, для многих это будет сюрпризом. 

Исследуя работу простого скрипта:

можно сделать следующие выводы:

  • значение функции GetTickCount() меняется не каждую миллисекунду, а каждые 15.6 миллисекунд, тогда как значение функции GetMicrosecondCount () меняется каждую микросекунду. Т.е. точность GetMicrosecondCount  выше чем у GetTickCount в 15600 раз, а не в 1000. 
  • но зато функция  GetTickCount()  быстрее функции GetMicrosecondCount() приблизительно в 12-15 раз.

Существенный аргумент

Причина обращения: