C билда 1847 MT5 был исправлен баг зависания в функции Bars. Также была добавлена штатная функция iBarShift.
Поэтому для увеличения быстродействия этих функций (где-то в раз 10) лучше теперь использовать такой вариант кода :
int fBars(string symbol_name,ENUM_TIMEFRAMES timeframe,datetime start_time,datetime stop_time) { static string LastSymb=NULL; static ENUM_TIMEFRAMES LastTimeFrame=0; static datetime LastTime=0; static datetime LastTime0=0; static int PerSec=0; static int PreBars=0; static datetime LastBAR=0; static datetime LastTimeCur=0; static bool flag=true; static int max_bars=TerminalInfoInteger(TERMINAL_MAXBARS); datetime TimeCur; if(timeframe==0) timeframe=_Period; const bool changeTF=LastTimeFrame!=timeframe; const bool changeSymb=LastSymb!=symbol_name; const bool change=changeTF || changeSymb || flag; LastTimeFrame=timeframe; LastSymb=symbol_name; if(changeTF) PerSec=::PeriodSeconds(timeframe); if(PerSec==0) { flag=true; return(0);} if(stop_time<start_time) { TimeCur=stop_time; stop_time=start_time; start_time=TimeCur; } if(changeSymb) { if(!SymbolInfoInteger(symbol_name,SYMBOL_SELECT)) { SymbolSelect(symbol_name,true); ChartRedraw(); } } TimeCur=TimeCurrent(); if(timeframe==PERIOD_W1) TimeCur-=(TimeCur+345600)%PerSec; // 01.01.1970 - Thursday. Minus 4 days. if(timeframe<PERIOD_W1) TimeCur-=TimeCur%PerSec; if(start_time>TimeCur) { flag=true; return(0);} if(timeframe==PERIOD_MN1) { MqlDateTime dt; TimeToStruct(TimeCur,dt); TimeCur=dt.year*12+dt.mon; } if(changeTF || changeSymb || TimeCur!=LastTimeCur) LastBAR=(datetime)SeriesInfoInteger(symbol_name,timeframe,SERIES_LASTBAR_DATE); LastTimeCur=TimeCur; if(start_time>LastBAR) { flag=true; return(0);} datetime tS,tF=0; if(timeframe==PERIOD_W1) tS=start_time-(start_time+345599)%PerSec-1; else if(timeframe<PERIOD_MN1) tS=start_time-(start_time-1)%PerSec-1; else // PERIOD_MN1 { MqlDateTime dt; TimeToStruct(start_time-1,dt); tS=dt.year*12+dt.mon; } if(stop_time<=LastBAR) { if(timeframe<PERIOD_W1) tF=stop_time-(stop_time)%PerSec; else if(timeframe==PERIOD_W1) tF=stop_time-(stop_time+345600)%PerSec; else // PERIOD_MN1 { MqlDateTime dt0; TimeToStruct(stop_time-1,dt0); tF=dt0.year*12+dt0.mon; } } if(change || tS!=LastTime || tF!=LastTime0) { PreBars=Bars(symbol_name,timeframe,start_time,stop_time); LastTime=tS; LastTime0=tF; } flag=false; return(PreBars); } int fBarShift(string symb,ENUM_TIMEFRAMES TimeFrame,datetime time,bool exact=false) { int Res=fBars(symb,TimeFrame,time+1,UINT_MAX); if(exact) if((TimeFrame!=PERIOD_MN1 || time>TimeCurrent()) && Res==fBars(symb,TimeFrame,time-PeriodSeconds(TimeFrame)+1,UINT_MAX)) return(-1); return(Res); }
C билда 1847 MT5 была исправлен баг зависания в функции Bars. Также была добавлена штатная функция iBarShift.
Поэтому для увеличения быстродействия этих функций (где-то в раз 10) лучше теперь использовать такой вариант кода :
Отправьте код в сервисдеск, пусть его внедрят штатно в платформу
Отправьте код в сервисдеск, пусть его внедрят штатно в платформу
Да кто я такой, чтобы им указывать.
Этот код кроссплатформенный. И самое интересное, что на MT4 выигрыша нет, так что в MT4 функция Bars написана оптимально.
Да кто я такой, чтобы им указывать.
Этот код кроссплатформенный. И самое интересное, что на MT4 выигрыша нет, так что в MT4 функция Bars написана оптимально.
За этой веткой следят. Вставьте через карман свой пост.
- 2016.09.01
- www.mql5.com
Ок. Только почему-то не получилось через карман. Не фурычит. Через ссылку сбросил.
Поэтому для увеличения быстродействия этих функций (где-то в раз 10) лучше теперь использовать такой вариант кода :
Вы не погорячились насчёт быстродействия? Особенно учитывая огромное количество всевозможных проверок в вашем коде. Лень вникать в суть этого, но с трудом верится, что такая портянка работает быстро.
Вы не погорячились насчёт быстродействия? Особенно учитывая огромное количество всевозможных проверок в вашем коде. Лень вникать в суть этого, но с трудом верится, что такая портянка работает быстро.
Лучше бы Вам лень было писать это сообщение. ))
Я специально к этим функциям приложил индикатор для теста скорости.
Функция Bars выполняется за микросекунды, а проверки, арифметические операции(даже вычисление квадратного корня из двоичного числа) меньше наносекунды:
void OnStart() { ulong t; double sum=0; t=GetMicrosecondCount(); for (double i=1; i<2;i+=0.000001 ) sum+=sqrt(i); t=GetMicrosecondCount()-t; Print("Сумма 1 000 000 корней = " + DoubleToString(sum,18)+ " за " + IntegerToString((int)t) + " микросекунд"); } 2018.06.14 19:23:31.188 SpeedSQRT (EURUSD,M4) Сумма 1 000 000 корней = 1218952.6235881459433586 за 1990 микросекунд 2018.06.14 19:26:30.814 SpeedSQRT (EURUSD,M4) Сумма 1 000 000 корней = 1218952.6235881459433586 за 1946 микросекунд 2018.06.14 19:26:34.188 SpeedSQRT (EURUSD,M4) Сумма 1 000 000 корней = 1218952.6235881459433586 за 1946 микросекунд 2018.06.14 19:26:36.344 SpeedSQRT (EURUSD,M4) Сумма 1 000 000 корней = 1218952.6235881459433586 за 1973 микросекунд
Из этого теста скорости видно, что 1 миллион циклов по расчету сумм корней двоичных чисел выполняется за 2000 микросекунд.
Значит один цикл выполняется за 2 наносекунды. Один цикл - это 1 проверка, две суммы двоичных чисел, одно вычисление квадратного корня из двоичного числа.
Лучше бы Вам лень было писать это сообщение. ))
Я специально к этим функциям приложил индикатор для теста скорости.
Функция Bars выполняется за микросекунды, а проверки, арифметические операции(даже вычисление квадратного корня из двоичного числа) меньше наносекунды:
Из этого теста скорости видно, что 1 миллион циклов по расчету сумм корней двоичных чисел выполняется за 2000 микросекунд.
Значит один цикл выполняется за 2 наносекунды. Один цикл - это 1 проверка, две суммы двоичных чисел, одно вычисление квадратного корня из двоичного числа.
Я новые билды пока не ставил, поэтому воспроизвести не могу. Но я вам верю. Просто как я понял, ваша функция оптимизирована для частного случая, который и представлен в вашем индикаторе. Символ не меняется, таймфрейм тоже, и т.д. Поэтому, полагаю, функция Bars там вызывается однократно. Причём и символ, и таймфрейм тупо заданы константами. Поэтому вполне даже вероятно, что компилятор заоптимизировал всю вашу функцию, выбросив всё лишнее.
Короче, тесты проведены некорректно. Там должен быть массив символов и массив периодов. И по всем ним пройтись вашей функцией. Тогда уже можно будет о чём-то говорить.
Я новые билды пока не ставил, поэтому воспроизвести не могу. Но я вам верю. Просто как я понял, ваша функция оптимизирована для частного случая, который и представлен в вашем индикаторе. Символ не меняется, таймфрейм тоже, и т.д. Поэтому, полагаю, функция Bars там вызывается однократно. Причём и символ, и таймфрейм тупо заданы константами. Поэтому вполне даже вероятно, что компилятор заоптимизировал всю вашу функцию, выбросив всё лишнее.
Короче тесты проведены некорректно. Там должен быть массив символов и массив периодов. И по всем ним пройтись вашей функцией. Тогда уже можно будет о чём то говорить.
Ничего сего - частный случай: "Символ не меняется, таймфрейм тоже"!
А что - у Вас много таких индикаторов или советников, в которых постоянно идет смена ТФ и символов?
Конечно, Вы правы. Если каждое обращение Bars будет сопровождаться сменой ТФ или символа, тогда штатная будет работать быстрее. Хотя и в этом случае просто необходимо заменить статические переменные массивом статических переменных размерностью равным количеством ТФ. Но это как раз я считаю частным случаем. Но такое решение этого частного случая имеет право на жизнь, если это необходимо. Возможно имеет смысл внести поправки в код для таких случаев. А ... Вы об этом наверное и говорили.
А на счет констант - спасибо, что заметили. Я исправил, т.к. в оригинальной функции параметры не константные. По скорости ничего не изменилось.
А что - у Вас много таких индикаторов или советников, в которых постоянно идет смена ТФ и символов?
Ну да, немало. Я как-раз и ориентируюсь на портфельный анализ и портфельную торговлю. Впрочем, когда речь идёт о больших расчётах, то там вообще iBarShift неуместна, т.к. работа идёт с массивами. По сути, iBarShift и прочие аналогичные функции предназначены для редких вызовов. В цикле их гонять нерационально. Просто получаем массив в CopyTime и быстренько всё находим. Поэтому тестовый пример по сути малоприменим в реальной практике. Если конечно кодер не чайник ) А ради чайников утруждаться не стоит, я думаю )
Мне кажется, вашу функцию логичней обернуть в класс. Тогда и проверку символа/периода не придётся проводить на каждом вызове. Для каждой таймсерии будет свой объект.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Fast iBarShift and Bars for MT5:
Существует множество вариантов функции iBarShift для MetaTrader 5. Но этот вариант отличается простотой, быстротой и правильностью.
На момент опубликования этого кода встроенная функция Bars, которая используется в данной функции iBarShift, содержит в себе баг, который проявляется как подвисание программы на более чем 10 секунд. В основном это происходит, когда функции Bars необходимо возвращать ноль.
Например, при выполнении кода:
"2" напечатается после "1" более чем через 10 секунд.
Рекомендую всем в своих программах заменить штатную функцию Bars на данную функцию iBars, особенно, если вы замечаете странные подвисания на более чем 10 секунд.
Автор: Nikolai Semko