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

 
Alexey Viktorov #:
Не придирайтесь к словам. Смена порядка индексации это и есть переворачивание массива
Нет
 
Maxim Kuznetsov #:

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

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

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

Максим, я взял то, что было предложено из учебника. И прекрасно понимаю, что в учебнике не самые оптимальные решения…

Мой посыл был направлен ТС для того, чтобы он обратил внимание на скорость копирования всей истории. И обратите внимание на то, что замер был в микросекундах. А в миллисекундах был 0…


ps; И пока не удалил код добавил в строку изменения размера массива

    ArrayResize(p, n + 1, 10000);

Время сократилось почти в 3 раза

2024.01.21 13:59:32.374 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 13:59:32.624 !!00 (USDJPY,M15)       Второй замер 5480 254566
2024.01.21 13:59:41.336 !!00 (USDJPY,M15)       Первый замер 5480 35
2024.01.21 13:59:41.586 !!00 (USDJPY,M15)       Второй замер 5480 253171
2024.01.21 14:00:18.995 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 14:00:19.245 !!00 (USDJPY,M15)       Второй замер 5480 252724
2024.01.21 14:00:25.393 !!00 (USDJPY,M15)       Первый замер 5480 35
2024.01.21 14:00:25.643 !!00 (USDJPY,M15)       Второй замер 5480 254811
2024.01.21 14:00:28.996 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 14:00:29.246 !!00 (USDJPY,M15)       Второй замер 5480 254185

но ни в какое сравнение не идёт с копированием всей истории. 

 
Alexey Viktorov #:

Максим, я взял то, что было предложено из учебника. И прекрасно понимаю, что в учебнике не самые оптимальные решения…

Мой посыл был направлен ТС для того, чтобы он обратил внимание на скорость копирования всей истории. И обратите внимание на то, что замер был в микросекундах. А в миллисекундах был 0…


ps; И пока не удалил код добавил в строку изменения размера массива

Время сократилось почти в 3 раза

но ни в какое сравнение не идёт с копированием всей истории. 

вывод неверный.

если вынести ArrayResize из второго цикла наружу - будут примерно похожие показания. 

Вы измерили ArrayResize (это функция катастрофа), а результат интерпретируете к CopyRates

PS когда важна скорость, то заранее делать все массивы, чтобы как можно меньше обращаться к ArrayResize. Тогда можно обойтись без микрооптимизаций в стиле fxsaber (не натягивать наносекунды жертвуя читабельностью) ;-) 

 
Maxim Kuznetsov #:

вывод неверный.

если вынести ArrayResize из второго цикла наружу - будут примерно похожие показания. 

Вы измерили ArrayResize (это функция катастрофа), а результат интерпретируете к CopyRates

PS когда важна скорость, то заранее делать все массивы, чтобы как можно меньше обращаться к ArrayResize. Тогда можно обойтись без микрооптимизаций в стиле fxsaber (не натягивать наносекунды жертвуя читабельностью) ;-) 

Согласен. Не сильно вникал и напрягал мозги.

  i = 0;
  MqlRates p[], r[];
  start = GetMicrosecondCount();
    int n = ArrayResize(p, Bars(_Symbol, PERIOD_CURRENT), 10000);
  do
   {
    ArraySetAsSeries(p, true);
    CopyRates(_Symbol, PERIOD_CURRENT, i, 1, r);
    p[i] = r[0];
    ArraySetAsSeries(p, false);
    i++;
   }
  while(i < rates_total && !IsStopped());
  Print("Второй замер ", rates_total, " ", GetMicrosecondCount()-start);

Но результат неутешительный

2024.01.21 15:33:16.262 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 15:33:16.262 !!00 (USDJPY,M15)       Второй замер 5480 727
2024.01.21 15:33:19.983 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 15:33:19.984 !!00 (USDJPY,M15)       Второй замер 5480 734
2024.01.21 15:33:23.449 !!00 (USDJPY,M15)       Первый замер 5480 35
2024.01.21 15:33:23.449 !!00 (USDJPY,M15)       Второй замер 5480 727
2024.01.21 15:33:27.759 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 15:33:27.759 !!00 (USDJPY,M15)       Второй замер 5480 716
2024.01.21 15:33:30.125 !!00 (USDJPY,M15)       Первый замер 5480 36
2024.01.21 15:33:30.125 !!00 (USDJPY,M15)       Второй замер 5480 703
 
Alexey Viktorov #:

Согласен. Не сильно вникал и напрягал мозги.

Но результат неутешительный

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

Напомню, что Было предложено вместо копирования всего массива котировок брать только свежие, как правило, один свежий бар (без всякого цикла).

Поэтому в замерах скорости нужно из второй части теста делить время на количество баров (будет ведь делаться только один запрос). Итого 716/5480 = 0.13, существенно лучше, чем ваши 36.

 
Stanislav Korotky #:

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

Напомню, что Было предложено вместо копирования всего массива котировок брать только свежие, как правило, один свежий бар (без всякого цикла).

Поэтому в замерах скорости нужно из второй части теста делить время на количество баров (будет ведь делаться только один запрос). Итого 716/5480 = 0.13, существенно лучше, чем ваши 36.

Совершенно верно. Возьмите одну итерацию цикла и полу́чите то, о чём вы говорите. Я сделал такие циклы, чтобы можно было сделать замер скорости выполнения не одной итерации, а многих…

В первом цикле было выполнено 5480 раз копирование всей истории, а во втором цикле 5480 раз по одному бару. И обратите внимание, на вопрос ТС и даже название темы

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

Поэтому если 36/5480 будет гораздо меньше чем 0,13… Почти в 20 раз.

Может вы не видели на первой странице весь код? Так мне не сложно повторить

/****************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[];
  int n = ArrayResize(p, Bars(_Symbol, PERIOD_CURRENT), 10000);
  start = GetMicrosecondCount();
  do
   {
    ArraySetAsSeries(p, true);
    CopyRates(_Symbol, PERIOD_CURRENT, i, 1, r);
    p[i] = r[0];
    ArraySetAsSeries(p, false);
    i++;
   }
  while(i < rates_total && !IsStopped());
  Print("Второй замер ", rates_total, " ", GetMicrosecondCount()-start);
  return(rates_total);
 }/*******************************************************************/
 
Alexey Viktorov #:

Совершенно верно. Возьмите одну итерацию цикла и полу́чите то, о чём вы говорите. Я сделал такие циклы, чтобы можно было сделать замер скорости выполнения не одной итерации, а многих…

В первом цикле было выполнено 5480 раз копирование всей истории, а во втором цикле 5480 раз по одному бару. И обратите внимание, на вопрос ТС и даже название темы

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

Поэтому если 36/5480 будет гораздо меньше чем 0,13… Почти в 20 раз.

Может вы не видели на первой странице весь код? Так мне не сложно повторить

У вас оптимизация компиляции включена наверно? Тогда ваш первый цикл и вызов функции выполняется только 1 раз.

И красным и жирным шрифтом вы что хотели выделить? Я ответил именно на этот вопрос автора темы.
 
Stanislav Korotky #:

У вас оптимизация компиляции включена наверно? Тогда ваш первый цикл и вызов функции выполняется только 1 раз.

И красным и жирным шрифтом вы что хотели выделить? Я ответил именно на этот вопрос автора темы.


Не сильно изменилось.

2024.01.21 17:57:37.051 !!00 (USDJPY,M15)       Первый замер 5480 74
2024.01.21 17:57:37.051 !!00 (USDJPY,M15)       Второй замер 5480 764
2024.01.21 17:57:53.619 !!00 (USDJPY,M15)       Первый замер 5480 82
2024.01.21 17:57:53.619 !!00 (USDJPY,M15)       Второй замер 5480 1035
2024.01.21 18:00:33.448 !!00 (USDJPY,M15)       Первый замер 5480 89
2024.01.21 18:00:33.448 !!00 (USDJPY,M15)       Второй замер 5480 1310
2024.01.21 18:00:38.762 !!00 (USDJPY,M15)       Первый замер 5480 84
2024.01.21 18:00:38.762 !!00 (USDJPY,M15)       Второй замер 5480 904


Что касается выделенного красным: ТС хочет иметь всю историю для пересчёта на каждом баре. По этому ему нужен не только последний бар, а вся история. Или как минимум не один десяток баров. Вот и получается, либо на каждом баре копировать всю историю, либо копировать один бар и дописывать его в другой массив.

 
Alexey Viktorov #:

У вас массивы p и r в локальной области.

С каждым событием Calculate, вы заново физически выделяете память. Более того, терминал ее физически освобождает потом (с каждым Calculate).

Резервирование памяти (с помощью третьего параметра ArrayResize) не работает в вашем коде совсем. У вас один вызов ArrayResize, который с каждым Calculate заново выделяет память.


Alexey Viktorov #:
 do
   {
    ArraySetAsSeries(p, true);
    CopyRates(_Symbol, PERIOD_CURRENT, i, 1, r);
    p[i] = r[0];
    ArraySetAsSeries(p, false);
    i++;
   }
  while(i < rates_total && !IsStopped());

Весь этот do while можно заменить одним вызовом CopyRates, избежав копирования всех баров, а скопировав только те, которые были добавлены.

Вы ведь вызываете Bars() внутри ArrayResize. То есть, вам уже известно актуальное количество баров на графике. А количество баров, которые вы уже скопировали в глобальный массив на предыдущем OnCalculate будет равняться размеру этого глобального массива.

 
Vladislav Boyko #:

У вас массивы p и r в локальной области.

С каждым событием Calculate, вы заново физически выделяете память. Более того, терминал ее физически освобождает потом (с каждым Calculate).

Резервирование памяти (с помощью третьего параметра ArrayResize) не работает в вашем коде совсем. У вас один вызов ArrayResize, который с каждым Calculate заново выделяет память.


Весь этот do while можно заменить одним вызовом CopyRates, избежав копирования всех баров, а скопировав только те, которые были добавлены.

Вы ведь вызываете Bars() внутри ArrayResize. То есть, вам уже известно актуальное количество баров на графике. А количество баров, которые вы уже скопировали в глобальный массив на предыдущем OnCalculate будет равняться размеру этого глобального массива.

Изучите сначала тему с первого сообщения.

О каком выделении и освобождении памяти вы говорите, если в этом ПРИМЕРЕ выполнение цикла происходит только ОДИН раз. ТОЛЬКО ОДИН!!!