В стандартном индикаторе буферные массивы формируются из данных параметров, передаваемых через функцию события OnCalulate( ... ). Но для мультивалютного и/или мультитаймфреймового индика тора вам придется использовать одно из двух решений:
- Использование старого метода вариаций "iFunction", таких как iTime(), iVolume, iOpen, iClose и т.д., но с другим символом, таким как "EURUSD", "JPYUSD" и т.д. вместо стандартного _Symbol или Symbol().
- Используя более новый метод первого варианта функции ArrayCopyRates() вместе с указателями массивов MqlRates, "скопированные" массивы фактически не будут занимать места и будут просто указателями на существующие данные различных символов и тайм-фреймов.
Однако, чтобы это работало, для работы мульти-символа и/или мульти-таймфрейма должно существовать одно из двух условий:
- Либо соответствующие графики для символов и тайм-фреймов уже открыты, так что ошибка не возникает,
- иначе при первом запросе данных вы получите ошибку 4066 (ERR_HISTORY_WILL_UPDATED), и вам придется кодировать цикл sleep & retry, чтобы дождаться загрузки данных и затем снова запросить данные.
Мое личное решение, которое я считаю наиболее эффективным и простым способом обработки ошибки 4066, - это метод ArrayCopyRates() и MqlRates .
Более подробную информацию об этом можно найти в документации и файлах справки по MQL4.
PS! NB! При обращении к встроенным функциям индикаторов, таким как iMA(), iATR() и т.д. для различных символов и тайм-фреймов, не забудьте также реализовать циклы sleep и retry, чтобы не получить ошибку 4066. Вот цитата из документа MQL4:
Помните, что ОП спрашивает об индикаторе. Sleep() игнорируется в индикаторах.
Извините, не знал этого! Я использую этот метод довольно широко в советниках, но не в индикаторах, поэтому не знал о недостатке сна.
В этом случае ему придется построить цикл повтора вокруг последовательных вызовов на каждом тике функции OnCalculate() (где использование ArrayCopyRates() является лучшим решением).
В качестве альтернативы, если он работает в функции OnInit(), это может быть предпочтительным методом подготовки данных для индикатора, с очень длинным количеством повторных попыток (без сна) для этого случая.
...
- или вы получите ошибку 4066 (ERR_HISTORY_WILL_UPDATED) при первом запросе данных, и вам придется закодировать цикл sleep & retry, чтобы дождаться загрузки данных и затем снова запросить данные.
PS! NB! При обращении к встроенным функциям индикаторов, таким как iMA(), iATR() и т.д. для различных символов и тайм-фреймов, не забудьте также реализовать циклы sleep и retry, чтобы не получить ошибку 4066. Вот цитата из документа MQL4:
Если только они не изменили что-то недавно, вы будете получать ошибку 4066 каждый раз с первого вызова функции (и только с этого первого вызова), независимо от условий или хода обновления истории. Это не имеет практического применения.
FMIC: В этом случае ему придется построить цикл повторного вызова вокруг последовательных вызовов на каждом тике функции OnCalculate() (где использование ArrayCopyRates() является лучшим решением). В качестве альтернативы, если это работает в функции OnInit(), это может быть предпочтительным методом подготовки данных для индикатора, с очень длинным счетом повторных попыток (без sleep) для этого случая. |
|
if(pair1[0].time == 0) return;
Это никогда не будет правдой.
Если для символа и таймфрейма загружена история, функция получит самое последнее значение.
Если история не загружена, вы получите ошибку Array out of range.
То же самое с iTime и т.д.
Это никогда не будет правдой.
Если для символа и таймфрейма загружена история, функция получит самое последнее значение.
Если история не загружена, вы получите ошибку Array out of range.
То же самое с iTime и т.д.
Я склонен согласиться!
Лично я просто проверяю возвращаемое значение функции "ArrayCopyRates()" и после этого просто отслеживаю размер массива, прежде чем обращаться к данным массива.
Что касается "iTime()" и других подобных функций, я всегда сначала проверяю "iBars()".
Это никогда не будет правдой.
if(pair1[0].time == 0) return;
Если для символа и таймфрейма загружена история, функция получит самое последнее значение.
Если история не загружена, вы получите ошибку Array out of range.
То же самое с iTime и т.д.
Существует множество исторических (до сборки 600) примеров просмотра ACR. Другого способа сделать это не существует. Последующие вызовы ACR или iTime НЕ возвращают 4066, поэтому как вы можете узнать, были ли загружены данные.
iTime всегда возвращает ноль при ошибке.
Существует множество исторических (до сборки 600) примеров просмотра ACR. Другого способа сделать это не существует. Последующие вызовы ACR или iTime НЕ вернут 4066, так что как вы можете узнать, были ли данные загружены.
iTime всегда возвращал ноль при ошибке.
Что вы имеете в виду под "нет другого способа сделать это"?
Проверка количества возвратов из "ArrayCopyRates" и проверка размера массива кажется более надежным методом проверки, чем "pair1[0].time == 0", который может легко вернутьошибку "Array index is out of range".
EDIT: Удалил некоторые из моих утверждений после более внимательного прочтения вашего сообщения.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Я хочу выбрать от 1 до 10 различных валют и 5 баров для каждой валюты.
Но я не знаю, как это сделать.