Библиотеки: Fast iBarShift and Bars for MT5 - страница 2

 
Alexey Navoykov:

Ну да, немало.  Я как-раз и ориентируюсь на портфельный анализ и портфельную торговлю.   Впрочем, когда речь идёт о больших расчётах, то там вообще iBarShift неуместна, т.к. работа идёт с массивами.   По сути, iBarShift и прочие аналогичные функции предназначены для редких вызовов.  В цикле их гонять нерационально.  Просто получаем массив в CopyTime и быстренько всё находим.  Поэтому тестовый пример по сути малоприменим в реальной практике.  Если конечно кодер не чайник )   А ради чайников утруждаться не стоит, я думаю )

Мне кажется, вашу функцию логичней обернуть в класс.  Тогда и проверку символа/периода не придётся проводить на каждом вызове.  Для каждой таймсерии будет свой объект.

Я не спорю. Просто эти функции создавались тогда, когда не было еще встроеной iBarShift и Bars был глючный.

Лично мне эти функции нужны для управления программы и графиками с помощью мыши. Так же я создаю синтетические ТФ с логарифмическим масштабом и эти функции там очень пригождаются. Они необходимы в решении задачи распознания образов и значительно убыстряют вычисления. Такой синтетический ТФ содержит всю историю символа и при этом содержит всего 3000 баров.

 

Разочаровался я окончательно в функциях Bars и iBarShift. MQ никак не могут их до ума довести. Одно лечат - другое калечат.

Осознал я, что это рудиментарные функции и лучше про них забыть как страшный сон. 

Пусть остаются для студентов и консерваторов. 

Разумно считаю использовать поиск номера бара по времени через обычный поиск в массиве time[].

Например, это можно осуществлять с помощью такой функции:

int wBarShift(datetime t,datetime &arr[],ENUM_TIMEFRAMES tf)
  {
   int size=ArraySize(arr);
   int PerSec=PeriodSeconds(tf);
   int cur,start=0;
   int fin=size-1;
   if(t<arr[0] || t>=arr[fin]) return(0);
   if(t>=arr[fin] && t<(arr[fin]+PerSec)) return(fin);
   while(true)
     {
      cur=(start+fin)/2;
      if(t<arr[cur]) {if(t>=arr[cur-1]) return(size-cur);    fin=cur;}
      else           {if(t< arr[cur+1]) return(size-cur-1);start=cur;}
      if((arr[fin]-arr[start])==((fin-start)*PerSec) && tf!=PERIOD_MN1)
         return(size-1-start-int(int(t-arr[start])/PerSec));
     }
  }

Да, нужен массив. Но лично у меня он всегда под рукой и обновляется с каждым тиком. Поэтому мне его даже формировать не нужно.

А по быстродействию данная функция в десятки раз превосходит оригинальную iBarShift.

Пример поиска номера бара по времени в массиве размерностью 100 000 элементов методом половинного деления:

2018.06.22 03:29:35.533 wBarShift (EURUSD,M1)   Время выполнения wBarShift = 26   наносекунд, контрольная сумма = 5407361
2018.06.22 03:29:35.536 wBarShift (EURUSD,M1)   Время выполнения iBarShift = 3368 наносекунд, контрольная сумма = 5407361
2018.06.22 03:29:36.283 wBarShift (EURUSD,M1)   Время выполнения wBarShift = 26   наносекунд, контрольная сумма = 5305162
2018.06.22 03:29:36.286 wBarShift (EURUSD,M1)   Время выполнения iBarShift = 3318 наносекунд, контрольная сумма = 5305162
2018.06.22 03:29:37.033 wBarShift (EURUSD,M1)   Время выполнения wBarShift = 28   наносекунд, контрольная сумма = 5341596
2018.06.22 03:29:37.036 wBarShift (EURUSD,M1)   Время выполнения iBarShift = 3323 наносекунд, контрольная сумма = 5341596
2018.06.22 03:29:37.667 wBarShift (EURUSD,M1)   Время выполнения wBarShift = 30   наносекунд, контрольная сумма = 5367340
2018.06.22 03:29:37.671 wBarShift (EURUSD,M1)   Время выполнения iBarShift = 3819 наносекунд, контрольная сумма = 5367340
Файлы:
wBarShift.mq5  5 kb
 
Мда уж, видимо переход на встроенные функции действительно дает просадку по времени работы советника в тестере...
 

Исправьте. Пр выходе за пределы имеющейся истории возвращает неправильную позицию:

void OnStart()
  {
   datetime tm=StringToTime("2000.01.01");
   int pos=fBarShift(Symbol(),Period(),tm);
   double open[];
   Print(CopyOpen(Symbol(),Period(),pos,1,open));
   ArrayPrint(open);
  }

Результат: 

2020.03.13 13:35:50.729 test2 (EURUSD,M1)       -1
Функция fBarShift() в данном случае возвращает общее количество баров, что не является корректной позицией.
 
Судя по коду, как такового поиска нужного бара нету, происходит расчёт его. А если история будет битой?
 
Aliaksandr Hryshyn:

Исправьте. Пр выходе за пределы имеющейся истории возвращает неправильную позицию:

Результат: 

2020.03.13 13:35:50.729 test2 (EURUSD,M1)       -1
Функция fBarShift() в данном случае возвращает общее количество баров, что не является корректной позицией.


не понял возвращает -1, как и должно быть.

 
Aliaksandr Hryshyn:
Судя по коду, как такового поиска нужного бара нету, происходит расчёт его. А если история будет битой?

Какой Вы смысл вкладываете в слова "Судя по коду"?

Вам показалось или Вы его досконально изучили?

Это было давно, но как я помню, там был расчёт лишь в том случае когда это было уместно, т.е. когда история 100% не битая и нет дырок. Это легко проверяется проверкой разницы во времени между барами. За счет этого и происходит выигрыш в скорости. Проверьте, если не верите.

Сейчас данный код хоть и быстрее штатной iBarShift, но не значительно (20-50%, раньше было в 10 раз). Уже MQ исправили код. Так что можно сказать, что этот код уже не так актуален.

 
Nikolai Semko:


не понял возвращает -1, как и должно быть.

Это код возврата функции CopyOpen()

Print(CopyOpen(Symbol(),Period(),pos,1,open));

И тут отсутствует четвёртый параметр:

int pos=fBarShift(Symbol(),Period(),tm);
 
Nikolai Semko:

Какой Вы смысл вкладываете в слова "Судя по коду"?

Вам показалось или Вы его досконально изучили?

Это было давно, но как я помню, там был расчёт лишь в том случае когда это было уместно, т.е. когда история 100% не битая и нет дырок. Это легко проверяется проверкой разницы во времени между барами. За счет этого и происходит выигрыш в скорости. Проверьте, если не верите.

Сейчас данный код хоть и быстрее штатной iBarShift, но не значительно (20-50%, раньше было в 10 раз). Уже MQ исправили код. Так что можно сказать, что этот код уже не так актуален.

Я использовал код с первой страницы. Циклов нету, значит только расчёт(исключая глупые варианты). Я не говорю что неправильно, всё верно у вас кроме одного исключения.

 
Aliaksandr Hryshyn:

Я использовал код с первой страницы. Циклов нету, значит только расчёт(исключая глупые варианты). Я не говорю что неправильно, всё верно у вас кроме одного исключения.

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

Я исправил одну ошибку (поменял - на + в функции fBarShift). У меня она оказывается была исправлена, а выложить видимо забыл. Обновил. Версия 1.04.

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