问题
Based on ticks per second (ticksLastSecond
), I would now like to calculate the average ticks per second over the last minute. For this, I would need a rolling array with size = 60 I assume, each second pushing the array elements forward by the newest ticksLastSecond
value (preferrably at the beginning (0) of the array) and the oldest one out. How could this be achieved?
Many thanks in advance!
回答1:
you can use arrays, keeping in mind the following: if you need average of 60 (x) values, your array could be of size 60(which is very impractical: you will need to copy elements 1 to 59 into 0 to 58 each second) or 120(copying once per minute) more. So, 120 is preferred I think, more is of no need.
input int size = 60;
int array[];
ArraySize(array,2*size);
int cursor=0; //- shows position of the last element
void add(const int element){
if(cursor>=2*size-1)resize();
array[cursor++]=element;
}
void resize(){
ArrayCopy(array,array,0,size);
cursor=size;
}
//for array average: iMAOnArray() or manually:
double getAvg(){
if(cursor+1<size)return 0;
double sum=0;
for(int i=0;i<size;i++){
sum+=array[cursor-1-i];
}
return(sum/cursor);
}
also possible to keep computed value of average and then add last, subtract first-this will speed up even more, think in case of backtesting. This all might be better to put in a structure.
Same but easier is use of CArrayInt
or CArrayObj
- in such case you do not worry about size, use methods Add()
and DeleteRange(0,size-1)
, for looping :
Total() and
At(i);
Another approach is to use a linked list in mql5, with easy access to first and last element. It is already implemented so try CLinkedList<T> : public ICollection
here
回答2:
I think that using lists is more efficient.
MQL5 provides a series of mechanisms to work with lists. For instance, what I would do is to declare a CList and create a class for the items of the list with the necessary attributes. In your case the time of the tick.
#include <Arrays\List.mqh>
#include <Object.mqh>
int storedItems = 60;
CList *listTicks = new CList;
class listItem : public CObject {
public:
listItem(double n){value=n;};
double getValue(){return value;};
private:
double value;
};
Then, in the OnTick
function, I'd check if the list is full to delete the head item. Finally, I'd insert the new item at the end of the list:
if(listTicks.Total() == storedTicks)
listTicks.Delete(0);
listTicks.Add(new listItem(tick_time));
Instead of copying, deleting, inserting... items in an array, a list only modifies the pointer to the previous and the next item. So it's much more computationally efficient.
来源:https://stackoverflow.com/questions/48608058/rolling-static-array