Обновление массива Rates с каждым новым баров. Или как добавить в массив только последний бар.

 

Доброго времени суток. Подскажите, я при начале работы заполняю массив котировками следующим образом:

copied=CopyRates(_Symbol,0,0,Bars(_Symbol,PERIOD_CURRENT),rates);

при этом, при появлении нового бара мне нужно его занести в этот массив как элемент с индексом 0. Я работаю на виртуальном сервере, и порой пока советник запустит повторное заполнение массива уже может появиться 2 или 3 новых бара. Поэтому при добавлении 1 нового элемента в начале массива и добавлении нового бара бывает такое, что некоторые бары просто не заполняются в массив и следовательно все вычисления идут неправильно. Как можно решить эту проблему? Мне нужно оптимизировать этот процесс, т.к. при заполнении каждый раз массива с 0 всеми элементами тратится слишком много времени

 
Anton Novokhatskii:

Доброго времени суток. Подскажите, я при начале работы заполняю массив котировками следующим образом:

при этом, при появлении нового бара мне нужно его занести в этот массив как элемент с индексом 0. Я работаю на виртуальном сервере, и порой пока советник запустит повторное заполнение массива уже может появиться 2 или 3 новых бара. Поэтому при добавлении 1 нового элемента в начале массива и добавлении нового бара бывает такое, что некоторые бары просто не заполняются в массив и следовательно все вычисления идут неправильно. Как можно решить эту проблему? Мне нужно оптимизировать этот процесс, т.к. при заполнении каждый раз массива с 0 всеми элементами тратится слишком много времени

А почему бы не добавить бар последним?

 
Странное заявление, самые мелкие бары обновляются раз в минуту. 60 секунд для операций это не просто много, за это время можно миллион баров в массиве подвигать и еще останется время, пока новый бар придет. Плюс вы не написали, как именно вы добавляете новые бары, в какой момент и каким образом.
 

При работе с Copy-функциями можно учитывать "серийный" признак приёмного массива. Из книги:

Важно отметить, что в приемном массиве полученные данные всегда физически размещаются в хронологическом порядке, от прошлого к будущему. Таким образом, если для приемного массива используется стандартная индексация (то есть к нему не применялась функция ArraySetAsSeries), то элемент с 0-м индексом будет самым старым, а последний элемент — самым новым. Если же для массива была выполнена инструкция ArraySetAsSeries(result, true), то нумерация будет вестись в обратном порядке, как в таймсерии: 0-й элемент окажется самым новым в диапазоне, а последний — самым старым.

Однако копировать все бары каждый раз не имеет смысла, можно копировать лишь те, что появились позже последнего запроса. Этот маленький массив можно дописывать в большой массив котировок с помощью ArrayCopy, задав индекс to равным длине приемного массива - массив будет автоматически расширен под новые элементы. Опять же, чтобы дописывать в начало, а не конец, включите признак серийности.

В частности, легко расширять динамический массив спереди, а не сзади.

// наращиваем массив p спереди
ArraySetAsSeries(p, true);
const int n = ArraySize(p);
ArrayResize(p, n + 1);
p[n] = ...;
ArraySetAsSeries(p, false);

Под индексом 0 оказывается бывший только что последним новый элемент.
Учебник по MQL5: Создание прикладных программ / Временные ряды (таймсерии) / Обзор Copy-функций для получения массивов котировок
Учебник по MQL5: Создание прикладных программ / Временные ряды (таймсерии) / Обзор Copy-функций для получения массивов котировок
  • www.mql5.com
Создание прикладных программ - Программирование на MQL5 для трейдеров - Учебник по языку алгоритмического/автоматического трейдинга для MetaTrader 5
 
Большое спасибо за помощь) Перебрать можно хоть миллион баров, но не на виртуальном сервере если нужно перебрать бары на нескольких символах) Последний комментарий очень помог)
 
Stanislav Korotky #:

При работе с Copy-функциями можно учитывать "серийный" признак приёмного массива. Из книги:

Однако копировать все бары каждый раз не имеет смысла, можно копировать лишь те, что появились позже последнего запроса. Этот маленький массив можно дописывать в большой массив котировок с помощью ArrayCopy, задав индекс to равным длине приемного массива - массив будет автоматически расширен под новые элементы. Опять же, чтобы дописывать в начало, а не конец, включите признак серийности.

В частности, легко расширять динамический массив спереди, а не сзади.

Под индексом 0 оказывается бывший только что последним новый элемент.

Вы думаете два раза перевернуть массив, изменить размер массива и скопировать данные в массив, а это не единичное значение, а структура, будет быстрей чем скопировать повторно все данные? У меня нет желания и времени на замеры, но сомнение есть. Вы не замеряли?


ps; Всё-же я не удержался от замера…

/****************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(prev_calculated > 0 && rates_total-prev_calculated > 1)
    return 0; // Если во время работы индикатора подгрузились новые бары, запустим пересчёт индикатора с нуля…
//--- Основной цикл
  int i = 0;
  MqlRates rates[];
  ulong start = GetMicrosecondCount();
  do
   {
    CopyRates(_Symbol, PERIOD_CURRENT, rates_total, 0, rates);
    i++;
   }
  while(i < rates_total && !IsStopped());
  Print("Первый замер ", rates_total, " ", GetMicrosecondCount()-start);
//---
  i = 0;
  MqlRates p[], r[];
  start = GetMicrosecondCount();
  do
   {
    ArraySetAsSeries(p, true);
    const int n = ArraySize(p);
    ArrayResize(p, n + 1);
    CopyRates(_Symbol, PERIOD_CURRENT, i, 1, r);
    p[n] = r[0];
    ArraySetAsSeries(p, false);
    //BufferClose[i]=close[i];
    i++;
   }
  while(i < rates_total && !IsStopped());
  Print("Второй замер ", rates_total, " ", GetMicrosecondCount()-start);
  return(rates_total);
 }/*******************************************************************/

И вот такой результат

2024.01.21 10:57:52.362 !!00 (USDJPY,M15)       Первый замер 5480 35
2024.01.21 10:57:53.162 !!00 (USDJPY,M15)       Второй замер 5480 803058
2024.01.21 10:58:10.962 !!00 (USDJPY,M15)       Первый замер 5480 40
2024.01.21 10:58:11.752 !!00 (USDJPY,M15)       Второй замер 5480 793128
2024.01.21 10:58:38.514 !!00 (USDJPY,M15)       Первый замер 5480 41
2024.01.21 10:58:39.294 !!00 (USDJPY,M15)       Второй замер 5480 784119
2024.01.21 11:00:03.608 !!00 (USDJPY,M15)       Первый замер 5480 35
2024.01.21 11:00:04.368 !!00 (USDJPY,M15)       Второй замер 5480 762086
2024.01.21 11:00:14.598 !!00 (USDJPY,M15)       Первый замер 5480 41
2024.01.21 11:00:15.358 !!00 (USDJPY,M15)       Второй замер 5480 767572
2024.01.21 11:04:09.801 !!00 (USDJPY,M15)       Первый замер 5480 40
2024.01.21 11:04:10.571 !!00 (USDJPY,M15)       Второй замер 5480 774958
 
Alexey Viktorov #:
Вы думаете два раза перевернуть массив
А в каком месте он переворачивается?
 
Sergey Gridnev #:
А в каком месте он переворачивается?

Тут

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Обновление массива Rates с каждым новым баров. Или как добавить в массив только последний бар.

Stanislav Korotky, 2024.01.20 15:26

При работе с Copy-функциями можно учитывать "серийный" признак приёмного массива. Из книги:

Однако копировать все бары каждый раз не имеет смысла, можно копировать лишь те, что появились позже последнего запроса. Этот маленький массив можно дописывать в большой массив котировок с помощью ArrayCopy, задав индекс to равным длине приемного массива - массив будет автоматически расширен под новые элементы. Опять же, чтобы дописывать в начало, а не конец, включите признак серийности.

В частности, легко расширять динамический массив спереди, а не сзади.

// наращиваем массив p спереди
ArraySetAsSeries(p, true);
const int n = ArraySize(p);
ArrayResize(p, n + 1);
p[n] = ...;
ArraySetAsSeries(p, false);

Под индексом 0 оказывается бывший только что последним новый элемент.

 
Alexey Viktorov #:

Тут


Тут нет переворачивания. Тут лишь смена порядка индексации.
 
Sergey Gridnev #:
Тут нет переворачивания. Тут лишь смена порядка индексации.

Не придирайтесь к словам. Смена порядка индексации это и есть переворачивание массива.

И посмотрите дополнение в моём сообщении. Я не удержался и сделал замер скорости…

 
Alexey Viktorov #:

Не придирайтесь к словам. Смена порядка индексации это и есть переворачивание массива.

И посмотрите дополнение в моём сообщении. Я не удержался и сделал замер скорости…

ArrayResize(), тем более на 1 элемент, крайне длительная операция, вы в основном его замеряли :-) Чтобы было шустро надо резервировать память, то есть использовать 3-й параметр

И смена порядка индексации - это всё-тами просто инверсия флага. 

да ещё никто отчего-то не проверил корректность полученных данных :-) но это традиция

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