Скачать MetaTrader 5

Вопрос: сдвиг индексов в массивах при сдвиге индексов баров

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Где найти программиста? В сервисе Фриланс!
Forex Trader
114257
Forex Trader 2007.02.08 10:53 
Пытаюсь решить следующую проблему.
Есть некий массив (например, 1000 элементов), в который помещаются некие ценовые данные по последним 1000 барам. Порядок баров соответствует порядку элементов в массиве. Т.е. для 0 бара данные в 0 индексе массива, для 1 бара – в 1 индексе и т.д.
Массив объявлен на глобальном уровне. Возникает новый бар, и теперь уже он имеет номер 0, а «старый» нулевой бар имеет номер 1 и т.д. Т.е. имеет место ротация индексов баров. Соответственно необходимо сделать аналогичную ротацию массива БЕЗ пересчета всех его значений (предварительно увеличив его размер).
А теперь сам вопрос. Можно ли это как-то сделать средствами MQL? Желательно максимально оптимально по скорости. Я экспериментировал, пытаясь назначить массив как тайм серию, но эффекта это не дало – новые элементы добавляются в конец индексов (т.е. если массив n, то новый элемент массива становится n+1).
Заранее признателен за помощь.
Forex Trader
114257
Forex Trader 2007.02.08 12:37  
Наверное, надо тупо копировать каждый элемент в следующий (arr[i+1] = arr[i]; i --;). Естественно, с конца в начало.
Хотя, можно попробовать создавать временный массив и копировать через него сразу все данные.
Forex Trader
114257
Forex Trader 2007.02.08 16:25  
Если массив - результат ф-ции ArrayCopyRates, то ничего с ним сделать нельзя. Нужно объявлять собственный, который будет находиться под контролем советника, а не терминала.
Непонятно, что за "ротация", поэтому вопрос неясен. Массив (в часности вышеупомянутый) в MQL нужно подразумевать как какой-то класс-массив в С++, индекс к элементам которого обратный. Например,
class Array
{
DATA data[n];
int count;// <= n
DATA operator[](int i){ return data[count - i - 1]; }
};


Это не значит, что на самом деле там элементы располагаются в обратном порядке. Они только так индексируюстя.

Forex Trader
114257
Forex Trader 2007.02.08 18:27  
Нет, массив содержит произвольные данные. Например, данные стороннего индикатора/ф-ции, которые в свою очередь используются для вычисления текущего значения индикатора. И т.к. в вычислениях текущего значения индикатора участвуют данные за n-баров назад, то при появлении каждого нового бара не хочется пересчитывать весь массив заново.
Соответственно, я надеялся, что может существует способ помимо ручного сдвига.
Однако, Resize добавляет новые элементы в конец, и тогда сдвигать придется "ручками".
Forex Trader
114257
Forex Trader 2007.02.08 19:12  
В таком случае можно объявить буфер со статическим к-вом элементов и при появлении нового смещать их на один назад например с помощью ф-ции ArrayCopy, которая ксорее всего в свою очередь использует одну из ассемблеровских функций, поэтому времени для копирования потребуется гораздо меньше.
Forex Trader
114257
Forex Trader 2007.02.08 19:19  
double buf[MAX];
if(bNewData)
{
    ArrayCopy(buf, buf, 0, 1, MAX - 1);
    buf[MAX-1] = dNewValue;
}
Forex Trader
114257
Forex Trader 2007.02.21 14:02  
Проблему решил. Не знаю, может это и очевидно, но на всякий случай напишу. Мало ли... кому-то может пригодится. ;о) VNN, спасибо за подсказку. На самом деле делается так:
//========процедура сдвига всего 3-x мерного массива buf на 1 индекс========
   ArraySetAsSeries(buf,true); //"переворачиваем" массив
   ArrayCopy(buf, buf, ArrayRange(buf,1)*ArrayRange(buf,2), 0, WHOLE_ARRAY-1);
   ArraySetAsSeries(buf,false);//возвращаем в исходное значение


Замерял по скорости еще два способа (через промежуточный массив и банальный перенос в циклах), так они оказались медленнее, чем указанный.

elibrarius
1758
elibrarius 2016.01.24 12:19  
Forex Trader:
Проблему решил. Не знаю, может это и очевидно, но на всякий случай напишу. Мало ли... кому-то может пригодится. ;о) VNN, спасибо за подсказку. На самом деле делается так:


Замерял по скорости еще два способа (через промежуточный массив и банальный перенос в циклах), так они оказались медленнее, чем указанный.

Здравствуйте,

задался таким же вопросом. Сейчас вижу, что ArraySetAsSeries нельзя применять к многомерным массивам (возможно в 2007г. это было возможно)

Жаль что MQL до сих пор так и не придумал команду для смещения значений массивов.

Как сейчас сдвигать многомерные массивы? Полным перебором и копированием в цикле? Жалко терять процессорное время (а следовательно время на оптимизацию) на такую операцию.

Vasiliy Sokolov
21758
Vasiliy Sokolov 2016.01.24 17:42  
elibrarius:

Здравствуйте,

задался таким же вопросом. Сейчас вижу, что ArraySetAsSeries нельзя применять к многомерным массивам (возможно в 2007г. это было возможно)

Жаль что MQL до сих пор так и не придумал команду для смещения значений массивов.

Как сейчас сдвигать многомерные массивы? Полным перебором и копированием в цикле? Жалко терять процессорное время (а следовательно время на оптимизацию) на такую операцию.

Сдвигать массивы нельзя, на то они и массивы. Для экономного использования процессорного времени, Вы должны научится пользоваться классами, в частности списком CList, где добавление нового элемента происходит практически мгновенно. Если Вам также важен быстрый доступ по индексу, советую присмотреться в сторону CDictionary. В нем в качестве ключа можно указать сам индекс, при этом доступ к элементу будет таким же быстрым, как в массиве, а добавление нового элемента - таким же быстрым как в CList.
Maxim Kuznetsov
9803
Maxim Kuznetsov 2016.01.24 17:50  
Forex Trader:
Пытаюсь решить следующую проблему.
Есть некий массив (например, 1000 элементов), в который помещаются некие ценовые данные по последним 1000 барам. Порядок баров соответствует порядку элементов в массиве. Т.е. для 0 бара данные в 0 индексе массива, для 1 бара – в 1 индексе и т.д.
Массив объявлен на глобальном уровне. Возникает новый бар, и теперь уже он имеет номер 0, а «старый» нулевой бар имеет номер 1 и т.д. Т.е. имеет место ротация индексов баров. Соответственно необходимо сделать аналогичную ротацию массива БЕЗ пересчета всех его значений (предварительно увеличив его размер).
А теперь сам вопрос. Можно ли это как-то сделать средствами MQL? Желательно максимально оптимально по скорости. Я экспериментировал, пытаясь назначить массив как тайм серию, но эффекта это не дало – новые элементы добавляются в конец индексов (т.е. если массив n, то новый элемент массива становится n+1).
Заранее признателен за помощь.

если считать ваш массив кольцевым буфером, то индекс высчитывается через модуль по размеру - и ненадо ничего наместе копировать

Dmitry Fedoseev
42907
Dmitry Fedoseev 2016.01.24 17:58  
Просто вычислять индекс. Новые элементы добавлять в конец, а чтобы обращаться к индексу 0, вычислять - количество минус 1 и минус 0. 
123
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий