Спасибо, но это тоже не работает: смотрите, прилагаю простейший код - индикатор - он делает 2 вещи:
1. Записывает время первого тика time0 (в момент инициализации индикатора на любом таймфрейме)
2. Вычисляет и отображает комментарием сдвиг найденного времени TheShift=iBarShift(NULL,0,time0,false); опция false означает, насколько я понимаю, что будет найден бар, время начала которого наиболее близко к time0.
В норме, при переключении на новый таймфрейм должно быть TheShift=0 или 1 и только спустя много времени TheShift=2,3 и т.д. когда начнут приходить новые бары. Но я вижу, что TheShift может скакнуть и на 25 и на 88, и т.д.
Такая вот .. вещь.
//+------------------------------------------------------------------+ //| TimeFrameSwitchTest.mq4 | //| qomment | //| https://www.mql5.com/ru/users/qomment | //+------------------------------------------------------------------+ #property copyright "qomment" #property link "https://www.mql5.com/ru/users/qomment" #property version "1.00" #property strict #property indicator_chart_window int OnCalculateCounter=0; // считаем тики datetime time0; // время первого тика bool time0switch=0; // переключатель //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if(!time0switch) { ResetLastError(); time0=iTime(NULL,0,0); if(!GetLastError()) time0switch=1; } if(time0switch) { int TheShift=iBarShift(NULL,0,time0,false); if(TheShift!=-1) Comment("TimeFrame=",Period()," OnCalculateCounter=",OnCalculateCounter," TheShift=",TheShift); } OnCalculateCounter++; //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+
TheShift всегда будет 0, потому что в time0 будет всегда (в момент вычисления TheShift) время текущего бара
iBarShift будет возвращать 0, т.к. бар со временем time0 всегда будет находиться и это 0-й бар
Нет. В том то и дело. Попробуйте код и убедитесь. Только проблема будет возникать не всегда, скажем в 5% случаев, так что надо активно попереключать фреймы и т.д.
Нужно брать не любой таймфрейм, а один конкретный, т. е. в iTime должен быть не 0 на месте таймфрейма, а константное значение, используемое при работе индикатора на любом таймфрейме.
А что, при вызове iBarShift(NULL,0,time0,false) он не в конкретном таймфрейме считает??? посмотрите код.
А что, при вызове iBarShift(NULL,0,time0,false) он не в конкретном таймфрейме считает??? посмотрите код.
В своем сообщении я не упоминал iBarShift. Речь шла о функции iTime. В приведенном коде этой функции передается 0 - текущий таймфрейм. Именно в этом и проблема - нужно использовать заранее определенный таймфрейм. Причем получить значение нужно именно после подкачки данных. Проверяется это так:
input ENUM_TIMEFRAMES i_tf = PERIOD_H1; datetime time; int error = ERR_HISTORY_WILL_UPDATED; while (error == ERR_HISTORY_WILL_UPDATED) { time = iTime(NULL, i_tf, 0); error = GetLastError(); Sleep(1000); }
В своем сообщении я не упоминал iBarShift. Речь шла о функции iTime. В приведенном коде этой функции передается 0 - текущий таймфрейм. Именно в этом и проблема - нужно использовать заранее определенный таймфрейм. Причем получить значение нужно именно после подкачки данных. Проверяется это так:
Большое спасибо. Насчёт iBarShift - моя неточность в ответе, я имел ввиду iTime конечно. Посмотрю Ваш вариант проверки подкачки. Правда Sleep в индикаторах не работает - надо как-то по-другому будет проверять. Кроме того, кажется, Вы согласны, что во время подкачки могут быть ошибки, то есть даже iTime(NULL, i_tf,0) может скакать? Именно в этом был мой вопрос. Получается, в любой кастомный индикатор имеет смысл вставлять такую процедуру - проверку подкачки данных при переключении таймфрейма.
Большое спасибо. Насчёт iBarShift - моя неточность в ответе, я имел ввиду iTime конечно. Посмотрю Ваш вариант проверки подкачки. Правда Sleep в индикаторах не работает - надо как-то по-другому будет проверять. Кроме того, кажется, Вы согласны, что во время подкачки могут быть ошибки, то есть даже iTime(NULL, i_tf,0) может скакать? Именно в этом был мой вопрос. Получается, в любой кастомный индикатор имеет смысл вставлять такую процедуру - проверку подкачки данных при переключении таймфрейма.
Факт подкачки данных никем не оспаривался - в МТ4 история по таймфреймам закачивается асинхронно. Это в МТ5 все строится на минутных данных. Было предложено несколько вариантов решения проблемы.
В индикаторе функция Sleep, да, не поможет. Там приходится разделять приведенную функцию на две части:
int OnInit() { ... iTime(NULL, i_tf, 0); // Запуск процесса обновления нужного таймфрейма ... } int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { datetime time = iTime(NULL, i_tf, 0); if (GetLastError() == ERR_HISTORY_WILL_UPDATED) // Расчет значений индикатора не запускает до тех пор, пока не будет окончен процесс подкачки истории return prev_calculated; ... return rates_total; }
Факт подкачки данных никем не оспаривался - в МТ4 история по таймфреймам закачивается асинхронно. Это в МТ5 все строится на минутных данных. Было предложено несколько вариантов решения проблемы.
В индикаторе функция Sleep, да, не поможет. Там приходится разделять приведенную функцию на две части:
Насколько я понял, асинхронно - в данном случае значит "беспорядочно". То есть порядок загрузки баров может не соответствовать упорядочению их времен открытия. И "все про это знают", только в официальном хелпе про это - ни слова (вроде бы).
Ещё раз спасибо, ERR_HISTORY_WILL_UPDATED - полезна. При этом с помощью этого кода ошибки проверяется загрузка всей истории - несмотря на то , что для индикатора нужны например самые поздние 100 баров. Приходится ждать несколько секунд, вместо того, чтобы сразу начать оперировать со 100 барами. Но нет, они могут еще измениться в процессе подгрузки. Правильно?
Еще вопрос и заранее еще большее спасибо - в чём разница между iTime(NULL,0,0) и iTime(NULL, i_tf,0) если i_tf соответствует текущему таймфрейму? По идее никакой (если верить официальному хелпу). Кроме того, если определять i_tf руками, то пропадает смысл переключения таймфремов в терминале - программа просто будет работать на текущем таймфрейме и всё.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Я вижу, что иногда, в короткое время после смены таймфрейма, Time[0] меняется. Причём 100% до появления нового нулевого бара (например, переключаем на 15-минутки. до наступления нового 15-минутного бара еще далеко). То есть, при смене таймфрейма, история, соответствующая новому периоду, подгружается или пересчитывается, причем таким образом, что Time[0] не является временем открытия текущего бара, а просто является первым элементом массива. И только спустя непродолжительное время Time[0] "стабилизируется" и становится настоящим временем открытия текущего бара. Это очень неудобно, например, если программа хочет засечь бар, на котором она начала работать на новом таймфрейме - как его засекать-то, если начальные значения времени неадекватны? Кто-нибудь сталкивался с подобным? Код не выкладываю, т.к., во-первых, он элементарен, а во-вторых, проблема возникает спорадически, видимо, в зависимости от подгрузки истории при переключении таймфрейма.
Если описанная проблема полностью исключена по построению mt4, буду признателен, если это подтвердит кто-то из модераторов.