Альтернативные реализации стандартных функций/подходов - страница 4

 
fxsaber:

Вариант CopyTicks, который быстрее оригинала иногда на несколько порядков (from > 0)

Билд 1432 - альтернатива CopyTicks не актуальна больше.
 
fxsaber:
Билд 1432 - альтернатива CopyTicks не актуальна больше.

Откуда взялся 1432? У меня на MetaQuotes-Demo последний 1430

 
Alexey Volchanskiy:

Откуда взялся 1432? У меня на MetaQuotes-Demo последний 1430

Ему по блату дали...
 
prostotrader:
Ему по блату дали...

Зря смеёшься. Мне однажды давали.

 
Alexey Viktorov:

Зря смеёшься. Мне однажды давали.

С чего взяли, что смеюсь?
 
prostotrader:
С чего взяли, что смеюсь?
Так показалось.
 

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

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

fxsaber, 2018.04.16 13:23

Гораздо быстрее этот вариант (Release, не Debug)

double StringToDouble2( const string Str, const uint StartPos = 0 )
{
  const uint Size = StringLen(Str);
  
  bool Sign = false;  
  uint i = StartPos;
  
  while (i < Size)
  {
    const int Digit = Str[i];

    if ((Digit != ' ') && (Digit != '\t') && (Digit != '\n') && (Digit != '\r'))
    {
      if ((Sign = (Digit == '-')) || (Digit == '+'))
        i++;
      
      break;
    }
      
    i++;
  }

  long Res = 0;
  int point = 0;
  
  while (i < Size)
  {
    const int Digit = Str[i];
    
    if (!point && (Digit == '.'))
      point = 1;
    else if (((Digit >= '0') && (Digit <= '9')))
    {
      Res = Res * 10 + Digit - '0';
      
      if (point)
        point *= 10;
    }
    else
      break;
      
    i++;
  }
  
  if (Sign)
    Res = -Res;
  
  return((point > 1) ? Res / (double)point : Res); // Возможна потеря точности при делении
}

При парсинге объемных данных получается значительное ускорение.

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

Это касается функций типа NormalizeDouble, строковых операций и тд.

Будет доступно в следующих бетах после релиза на следующей неделе.
 
Renat Fatkhullin:
Мы вернулись к идее встраивания массы простых системных функций нативно в результирующий MQL5 код, что позволило кратно их ускорить за счет использования в глобальной оптимизации результирующего кода.

OK.

 
fxsaber:

OK.

С возвращением!

Аналог ChartXYToTimePrice 

Не полный аналог( по параметрам) ,  но такой вариант, как мне кажется, даже удобнее и практичней. Также быстрее( на пару порядков).
По функциональности полный аналог, и даже более, т.к. возвращает (в отличии от оригинальной функции) номер подокна, в котором находиться Х, Y ( курсор), если -1, то вне окна (подокна).

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



// Fast Analog ChartXYToTimePrice function (https://www.mql5.com/ru/docs/chart_operations/chartxytotimeprice)
int XYToTimePrice(int x,int y,datetime &time,double &price,int id=0) // возвращает номер подокна в котором находится X,Y (курсор), если -1 - то вне окна
  {
   static int left_bar; // номер самого левого бара на экране
   static int Wid;
   static int Hei[10];
   static double y_min[10];
   static double y_max[10];
   static int PerSec=PeriodSeconds();
   static bool ChartChange=true;
   static int windowsTotal=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);
   static int Cur_wind=-1;
   static int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));
   if(id==CHARTEVENT_CHART_CHANGE) if(!ChartChange) {ChartChange=true; return(Cur_wind);}
   if(ChartChange) // если было изменение чатра после последнего вычисления
     {
      windowsTotal=(int)ChartGetInteger(0,CHART_WINDOWS_TOTAL);
      if(windowsTotal>10) {Print("Too many subwindows"); return(-1);}
      for(int i=0;i<windowsTotal;i++) if(i>0) Hei[i]=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,i)+Hei[i-1]+2;
      else Hei[0]=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,0);
      left_bar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR, 0);        // номер самого левого бара на экране
      Wid=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS, 0);               // ширина экрана в пикселях
      WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));                    // растояние между барами в пикселях
                                                                          
      for(int i=0;i<windowsTotal;i++)
        {
         y_min[i]=ChartGetDouble(0,CHART_PRICE_MIN, i);                         // макс. цена на экране
         y_max[i]=ChartGetDouble(0,CHART_PRICE_MAX, i);                         // мин. цена на экране
        }
     }
   if(x>(Wid+1) || x<0 || y<0 || y>=(Hei[windowsTotal-1]+1)) return(-1);  // выходим если точка (x,y) за пределами экрана
   Cur_wind=-1;
   if(y>=0 && y<=Hei[0]) Cur_wind=0;
   else if(windowsTotal>1) for(int i=1;i<windowsTotal;i++) if(y>(Hei[i-1]+1) && y<=Hei[i]) { Cur_wind=i; break; }
   if(Cur_wind>=0)
     {
      if(Cur_wind>0) y=y-Hei[Cur_wind-1]-2;
      int hh=Hei[Cur_wind];
      if(Cur_wind>0) hh-=Hei[Cur_wind-1]+2;
      price=y_min[Cur_wind]+(hh-y)*(y_max[Cur_wind]-y_min[Cur_wind])/hh;

      double NrBar=left_bar-(double)x/(double)WidthBar;
      datetime TT[2];
      if(NrBar>0) { CopyTime(NULL,0,(int)NrBar,2,TT); time=TT[0]+(datetime)((TT[1]-TT[0])*(1.0-NrBar+(int)NrBar)); }
      else        { CopyTime(NULL,0,0,1,TT);          time=TT[0]+(datetime)(fabs(NrBar)*PerSec); }
     }
   ChartChange=false;

   return(Cur_wind);
  }


Эту функцию запускать можно откуда угодно без параметра id, но в OnChartEvent она должна стоять обязательно (с параметром id) для выяснения необходимости произвести обновление внутренних переменных этой функции.

Например, если функция используется не из OnChartEvent, то для нормальной работы в теле OnChartEvent  нужно добавить строчку:

if (id==CHARTEVENT_CHART_CHANGE) { double p=0; datetime t=0; XYToTimePrice(0,0,t,p,id);}
Данный аналог дает заметный выигрыш, когда эта функция используется достаточно часто.
Для разовых обращений смысла нет использовать этот аналог.  
Файлы:
TestSpeedXY.mq5  15 kb