Данные с тф М5 появляются только реалтайм на М1. При запуске история не рисуется...
Решалось костылями, какими именно - сейчас буду искать.
У пользователя был индикатор измеряющий "силу" рынка.
Индикатор работал по текущему ТФ и валютной паре.
Задача была - показать результаты из 8 популярных валют на одном чарте с возможностью выбора независимого TФ для отображения.
На каком бы пользователь ТФ не был - должно показывать результат с установленного в параметры.
Проблему по прогрузке трафика с других валют по нужному ТФ решал следующим костылем:
for (int i = ArraySize(symbols_load) - 1; i >= 0; --i){ int counter = 0; int max_count = 10; while(counter < max_count){ RefreshRates(); double tmp_arr[]; int res = CopyClose(symbols_load[i] + Suffix, int(TF), 0, 3, tmp_arr); if (res == 3) break; RefreshRates(); ++counter; } }
где:
symbols_load - список валют необходимых прогрузить
Suffix - возможная приставка к названию валютных пар
TF - необходимый таймфрейм
Данные с тф М5 появляются только реалтайм на М1. При запуске история не рисуется...
Для того, чтобы результаты из старших таймсерий вытащить в оффлайне или при закрытом рынке, нужно организовать периодический вызов показаний через таймер. При этом в таймере необходимо вызывать OnCalculate.
Как-то так:
#property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_label1 "AO" #property indicator_type1 DRAW_SECTION #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //+------------------------------------------------------------------+ //| inputs //+------------------------------------------------------------------+ input ENUM_TIMEFRAMES TimeFrame_ = PERIOD_D1; //+------------------------------------------------------------------+ //| defines //+------------------------------------------------------------------+ #define _PrintLastError_(info,r) { Print((info != "" ? info+" " : ""),__FUNCTION__,":",__LINE__,":Error#",_LastError); r; } //+------------------------------------------------------------------+ //| global vars //+------------------------------------------------------------------+ ENUM_TIMEFRAMES _MTF; datetime _MTF_TimeBuf[]; int _AO_Handle = INVALID_HANDLE; double _AO_Buf[]; int _LastRatesTotal; int _LastPrevCalculated; double _PriceBuf[]; datetime _Time[]; //+------------------------------------------------------------------+ //| ind buf's //+------------------------------------------------------------------+ double _Main_VBuf[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { _MTF = TimeFrame_; if (PeriodSeconds(_MTF) < PeriodSeconds(_Period)) _MTF = _Period; if ((_AO_Handle = iAO(_Symbol, _MTF)) == INVALID_HANDLE) _PrintLastError_("", return INIT_FAILED) GetTimes(_MTF_TimeBuf, _MTF); EventSetTimer(1); //--- SetIndexBuffer(0, _Main_VBuf); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(_AO_Handle); EventKillTimer(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { if (_LastPrevCalculated <= 0) { OnCalculate (_LastRatesTotal, _LastPrevCalculated, 0, _PriceBuf); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnCalculate (const int rates_total, // размер массива price[] const int prev_calculated, // обработано баров на предыдущем вызове const int begin, // откуда начинаются значимые данные const double& price[]) // массив для расчета { ResetLastError(); //--- if (prev_calculated <= 0) { ArrayInitialize(_Main_VBuf, 0); } //--- if (ArrayCopy(_PriceBuf, price, 0, 0, rates_total) != rates_total) _PrintLastError_("ArrayCopy", return _LastPrevCalculated = 0) _LastRatesTotal = rates_total; //--- if (rates_total != prev_calculated) { if (!GetTimes(_Time, _Period)) _PrintLastError_("", return _LastPrevCalculated = 0) if (!GetTimes(_MTF_TimeBuf, _MTF)) _PrintLastError_("", return _LastPrevCalculated = 0) } if (!GetAO()) { if (_LastError == ERR_INDICATOR_DATA_NOT_FOUND) return _LastPrevCalculated = 0; _PrintLastError_("", return _LastPrevCalculated = 0) } //--- const int MTF_BarsCount = ArraySize(_MTF_TimeBuf); const int Limit = fmax(prev_calculated, (int)ceil((double)PeriodSeconds(_MTF)/(double)PeriodSeconds(_Period))); for (int i=rates_total-1, tf_time_i=MTF_BarsCount-1; i>=Limit; --i) { if (_Time[i] >= _MTF_TimeBuf[tf_time_i]) { _Main_VBuf[i] = _AO_Buf[tf_time_i]; } else { --tf_time_i; if (tf_time_i < 0) return _LastPrevCalculated = 0; } } //--- return _LastPrevCalculated = rates_total; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool GetTimes(datetime & buf[],ENUM_TIMEFRAMES tf) { int BarsCount = Bars(_Symbol, tf); if (CopyTime(_Symbol, tf, 0, BarsCount, buf) != BarsCount) _PrintLastError_("CopyTime", return false) return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool GetAO() { int BarsCount = Bars(_Symbol, _MTF); if (CopyBuffer(_AO_Handle, 0, 0, BarsCount, _AO_Buf) != BarsCount) { if (_LastError == ERR_INDICATOR_DATA_NOT_FOUND) _PrintLastError_("AO is not built yet. Wait...", return false) _PrintLastError_("CopyBuffer", return false) } return true; }
Встречался с такой проблемой при написании мультитаймфреймовых индикаторов года 2 назад - не погруженная история для валютной пары по другим TF.
Решалось костылями, какими именно - сейчас буду искать.
Неоднократно уже обсуждалось.
1. В OnInit запросить все символы-периоды, которые предполагается использовать
2. Запустить 1-минутный таймер
3. В OnTimer запрашивать все нужные символы-периоды. Без дальнейшего использования, типа CopyRates(symbol,period,0,1,rates_array). Только спрашивать (на всякий случай), синхронизировано или нет
4. В OnCalculate спокойно запрашивать и использовать через минуту-полторы после первого запуска.
Добавил модификацию:
#property version "1.1" //+-------------------------------- Versions History --------------------------------+ //| //| //| v.1.1 //| - добавлена проверка на синхронизированность данных по старшему ТФ. //| //| //+-------------------------------- Versions History --------------------------------+ #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_label1 "AO" #property indicator_type1 DRAW_SECTION #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //+------------------------------------------------------------------+ //| inputs //+------------------------------------------------------------------+ input ENUM_TIMEFRAMES TimeFrame_ = PERIOD_D1; //+------------------------------------------------------------------+ //| defines //+------------------------------------------------------------------+ #define _PrintLastError_(info,r) { Print((info != "" ? info+" " : ""),__FUNCTION__,":",__LINE__,":Error#",_LastError); r; } //+------------------------------------------------------------------+ //| global vars //+------------------------------------------------------------------+ bool _IsMTF; ENUM_TIMEFRAMES _MTF; datetime _MTF_TimeBuf[]; datetime _MTF_FirstDate; int _AO_Handle = INVALID_HANDLE; double _AO_Buf[]; int _LastRatesTotal; int _LastPrevCalculated; double _PriceBuf[]; datetime _Time[]; //+------------------------------------------------------------------+ //| ind buf's //+------------------------------------------------------------------+ double _Main_VBuf[]; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnInit() { _MTF = TimeFrame_; if (PeriodSeconds(_MTF) < PeriodSeconds(_Period)) _MTF = _Period; if (PeriodSeconds(_MTF) > PeriodSeconds(_Period)) _IsMTF = true; if ((_AO_Handle = iAO(_Symbol, _MTF)) == INVALID_HANDLE) _PrintLastError_("", return INIT_FAILED) GetTimes(_MTF_TimeBuf, _MTF); EventSetTimer(1); //--- SetIndexBuffer(0, _Main_VBuf); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(_AO_Handle); EventKillTimer(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void OnTimer() { //---MTF control if (_LastPrevCalculated > 0) { if (SymbolIsSynchronized(_Symbol)) { datetime MTF_FirstDate = (datetime)SeriesInfoInteger(_Symbol, _MTF, SERIES_FIRSTDATE); if (_MTF_FirstDate != MTF_FirstDate) { _MTF_FirstDate = MTF_FirstDate; _LastPrevCalculated = 0; } } else _LastPrevCalculated = 0; } if (_LastPrevCalculated <= 0) { OnCalculate (_LastRatesTotal, _LastPrevCalculated, 0, _PriceBuf); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int OnCalculate (const int rates_total, // размер массива price[] const int prev_calculated, // обработано баров на предыдущем вызове const int begin, // откуда начинаются значимые данные const double& price[]) // массив для расчета { ResetLastError(); //--- if (prev_calculated <= 0) { ArrayInitialize(_Main_VBuf, 0); } //--- if (ArrayCopy(_PriceBuf, price, 0, 0, rates_total) != rates_total) _PrintLastError_("ArrayCopy", return _LastPrevCalculated = 0) _LastRatesTotal = rates_total; //--- if (rates_total != prev_calculated) { if (!GetTimes(_Time, _Period)) _PrintLastError_("", return _LastPrevCalculated = 0) if (!GetTimes(_MTF_TimeBuf, _MTF)) _PrintLastError_("", return _LastPrevCalculated = 0) } if (!GetAO()) { if (_LastError == ERR_INDICATOR_DATA_NOT_FOUND) return _LastPrevCalculated = 0; _PrintLastError_("", return _LastPrevCalculated = 0) } //--- const int MTF_BarsCount = ArraySize(_MTF_TimeBuf); const int Limit = fmax(prev_calculated, (int)ceil((double)PeriodSeconds(_MTF)/(double)PeriodSeconds(_Period))); for (int i=rates_total-1, tf_time_i=MTF_BarsCount-1; i>=Limit; --i) { if (_Time[i] >= _MTF_TimeBuf[tf_time_i]) { _Main_VBuf[i] = _AO_Buf[tf_time_i]; } else { --tf_time_i; if (tf_time_i < 0) return _LastPrevCalculated = 0; } } //--- return _LastPrevCalculated = rates_total; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool GetTimes(datetime & buf[],ENUM_TIMEFRAMES tf) { int BarsCount = Bars(_Symbol, tf); if (CopyTime(_Symbol, tf, 0, BarsCount, buf) != BarsCount) _PrintLastError_("CopyTime", return false) return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool GetAO() { int BarsCount = Bars(_Symbol, _MTF); if (CopyBuffer(_AO_Handle, 0, 0, BarsCount, _AO_Buf) != BarsCount) { if (_LastError == ERR_INDICATOR_DATA_NOT_FOUND) _PrintLastError_("AO is not built yet. Wait...", return false) _PrintLastError_("CopyBuffer", return false) } return true; }
Неоднократно уже обсуждалось.
1. В OnInit запросить все символы-периоды, которые предполагается использовать
2. Запустить 1-минутный таймер
3. В OnTimer запрашивать все нужные символы-периоды. Без дальнейшего использования, типа CopyRates(symbol,period,0,1,rates_array). Только спрашивать (на всякий случай), синхронизировано или нет
4. В OnCalculate спокойно запрашивать и использовать через минуту-полторы после первого запуска.
Секунду-полторы?
Официальный костыль!
Секунду-полторы?
Официальный костыль!
нее... периоды строятся долго минуту точно моргать может...
Уже четвёртый день в индикаторе пытаюсь получить данные стандартного индикатора АО со старшего таймфрейма, и всё никак...
я вам писал в другой ветке, используйте BarsCalculated - пока не будет больше нуля не запускаем основной цикл расчета (OnCalculate)
https://www.mql5.com/ru/forum/170952/page32#comment_4864720- www.mql5.com
Неоднократно уже обсуждалось.
1. В OnInit запросить все символы-периоды, которые предполагается использовать
2. Запустить 1-минутный таймер
3. В OnTimer запрашивать все нужные символы-периоды. Без дальнейшего использования, типа CopyRates(symbol,period,0,1,rates_array). Только спрашивать (на всякий случай), синхронизировано или нет
4. В OnCalculate спокойно запрашивать и использовать через минуту-полторы после первого запуска.
Предположим мы на М5.
На М5 приходит новый бар, идет обработка OnCalculate (используется iCustom по другим валютам и с другим TF - M1).
Только затем срабатывает наш минутный таймер.
Вопрос: для МТ4 в OnCalculate будет ли обработка iCustom видить приход нового бара для М1 по всем используемым валютным парам?
Ведь наш таймер отрабатывает уже после OnCalculate.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Уже четвёртый день в индикаторе пытаюсь получить данные стандартного индикатора АО со старшего таймфрейма, и всё никак...
В цикле считываю данные АО, но именно в цикле исторических данных нет. На текущем баре данные есть. В чём подвох? Что делаю не так?