Array out of range для Low [ i ] и прочих функций

 
Часто сталкиваюсь с такой проблемой. Пишу скрипт или индикатор, график на маленьких таймфреймах на экране отображается за несколько лет. Но при попытке вызвать функцию, например, Low [ 3000 ] или Time [ 3000 ] (что для пятиминутного графика всего лишь 10 дней) я получаю ошибку Array out of range. Скачивание котировок из архива ни к чему не приводит. Обычно появляется сообщение - нет новых данных для символа. Для некоторых символов мне приходится запускать платформу одного из известных брокеров, у которого нет ошибки до Low [ 60000 ]. Но во первых это не удобно, каждый раз переключаться. А во-вторых у него далеко не все символы имеются для работы. Существует какое-то решение данной проблемы?

Забыл упомянуть, что работаю в МТ4
 

Какое количество поставлено тут?


После изменения обязательно перезапустить МТ.

 
Макс баров в истории 1000000
Макс баров в окне 65000

По факту на 3000 уже дает ошибку
 
В документации есть пример индикатора который показывает номер бара под крыской. Попробуйте посмотреть номер крайнего левого бара.
ArraySetAsSeries - Операции с массивами - Справочник MQL4
ArraySetAsSeries - Операции с массивами - Справочник MQL4
  • docs.mql4.com
ArraySetAsSeries - Операции с массивами - Справочник MQL4
 
Номер крайнего левого бара выдает не очень большим. На разных символах по разному, но в среднем 3000-5000. При этом если запустить вот такое...

Print("Количество баров по символу-периоду на данный момент = ",
         SeriesInfoInteger(Symbol(),0,SERIES_BARS_COUNT), " ", Bars, " ", iBars ( Symbol(), PERIOD_CURRENT ) );
 
   Print("Самая первая дата по символу-периоду на данный момент = ",
         (datetime)SeriesInfoInteger(Symbol(),0,SERIES_FIRSTDATE));
 
   Print("Самая первая дата в истории по символу на сервере = ",

         (datetime)SeriesInfoInteger(Symbol(),0,SERIES_SERVER_FIRSTDATE));


То результат получается

2022.05.13 11:07:53.292 instatfin_digit DowJones30,M5: Самая первая дата в истории по символу на сервере = 2021.05.28 09:50:00

2022.05.13 11:07:53.292 instatfin_digit DowJones30,M5: Самая первая дата по символу-периоду на данный момент = 2022.04.13 20:20:00

2022.05.13 11:07:53.292 instatfin_digit DowJones30,M5: Количество баров по символу-периоду на данный момент = 5563 5563 5563

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


 
Reactor555 #:
Номер крайнего левого бара выдает не очень большим. На разных символах по разному, но в среднем 3000-5000. При этом если запустить вот такое...

Print("Количество баров по символу-периоду на данный момент = ",
         SeriesInfoInteger(Symbol(),0,SERIES_BARS_COUNT), " ", Bars, " ", iBars ( Symbol(), PERIOD_CURRENT ) );
 
   Print("Самая первая дата по символу-периоду на данный момент = ",
         (datetime)SeriesInfoInteger(Symbol(),0,SERIES_FIRSTDATE));
 
   Print("Самая первая дата в истории по символу на сервере = ",

         (datetime)SeriesInfoInteger(Symbol(),0,SERIES_SERVER_FIRSTDATE));


То результат получается

2022.05.13 11:07:53.292 instatfin_digit DowJones30,M5: Самая первая дата в истории по символу на сервере = 2021.05.28 09:50:00

2022.05.13 11:07:53.292 instatfin_digit DowJones30,M5: Самая первая дата по символу-периоду на данный момент = 2022.04.13 20:20:00

2022.05.13 11:07:53.292 instatfin_digit DowJones30,M5: Количество баров по символу-периоду на данный момент = 5563 5563 5563

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

Возможно на сервере брокера это максимальное количество баров по инструменту.

 
Alexey Viktorov #:

Возможно на сервере брокера это максимальное количество баров по инструменту.

И это никак не обойти?

 
Reactor555 #:

И это никак не обойти?

Не знаю.

 

Чем плох вариант с проверкой доступного количества баров? Тогда можно обращаться только к тем барам, которые будут реально доступны.

Также еще стоит уйти от прямого доступа к котировкам (как раз вот эти Low, Open и т. д.) к вызову соответствующих функций: iLow, iOpen. Во-первых, сразу уйдет ошибка выхода за пределы массива. Во-вторых, получится кроссплатформенный код. В-третьих, код получит универсальность в плане доступа к любому ТФ, а не только к текущему.

 
    // если терминал не найдет у себя требуемых баров
    // то автоматический будет сделан запрос на сервер
    int rcode = ERR_SUCCESS; // код ошибки
    int numBars = -1; // кол-во скопированных баров
    int numRequest = 3; // макс.кол-во запросов
    for (int j = 0; j < numRequest && numBars < 0; j++) {
        ResetLastError();
        numBars = CopyRates(symbol, period, time0Bar, count, rates);
        if (numBars == -1) Sleep(1000); // ждем 1 сек для подкачки баров
        rcode = GetLastError();
    }
 
Malik Arykov #:

Для скрипта может и подойдёт, а для индикатора - точно нет. 

Дело в том, что главным требованием к индикатору является скорость его исполнения. Индикатор не умеет ничего ждать, от слова совсем. Получив команду на выполнение, он немедленно начинает ее исполнять на тех данных, которые уже есть в терминале строго на этот момент времени и ни миллисекундой позже. Новые, более свежие данные могут быть получены индикатором только из его окружения (терминала) и только в момент начала очередного цикла его выполнения (Start, OnCalculate). Никаких других данных индикатор не видит и не способен их получить нативными способами. 

Думаю, со скриптами ситуация похожая, только они умеют ждать и использовать внешние данные. В остальном - слепок данных на момент подачи команды и все немедленно бегут эту команду исполнять. 

Причина обращения: