forked from rosh/MQL5Book
300 lines
7.2 KiB
MQL5
300 lines
7.2 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| IndBufArray.mqh |
| |||
//| Copyright (c) 2016-2021, Marketeer |
| |||
//| https://www.mql5.com/en/users/marketeer |
| |||
//+------------------------------------------------------------------+
| |||
| |||
// helper defines which allows to not use read-accessors
| |||
// by selecting proper operator[] overloads via SETTER/GETTER type
| |||
#define SETTER int
| |||
#define GETTER uint
| |||
| |||
class BufferGetter; // forward declaration, helper class
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Indicator buffer holder |
| |||
//+------------------------------------------------------------------+
| |||
class Buffer // main indicator buffer class
| |||
{
| |||
protected:
| |||
double buffer[]; // indicator buffer
| |||
| |||
int cursor; // position in the buffer
| |||
| |||
BufferGetter *instance; // helper object for reading values (optional)
| |||
| |||
public:
| |||
Buffer(int i,
| |||
const double empty = EMPTY_VALUE,
| |||
const ENUM_INDEXBUFFER_TYPE type = INDICATOR_DATA,
| |||
const bool asSeries = false)
| |||
{
| |||
SetIndexBuffer(i, buffer, type);
| |||
ArraySetAsSeries(buffer, asSeries);
| |||
ArrayInitialize(buffer, empty);
| |||
instance = NULL;
| |||
}
| |||
| |||
virtual ~Buffer()
| |||
{
| |||
if(CheckPointer(instance) == POINTER_DYNAMIC) delete instance;
| |||
}
| |||
| |||
void series(const bool s)
| |||
{
| |||
ArraySetAsSeries(buffer, s);
| |||
}
| |||
| |||
void empty(const double empty = EMPTY_VALUE, const int offset = 0, const int count = 0)
| |||
{
| |||
if(offset == 0 && count == 0)
| |||
{
| |||
ArrayInitialize(buffer, empty);
| |||
}
| |||
else
| |||
{
| |||
ArrayFill(buffer, offset, count, empty);
| |||
}
| |||
}
| |||
| |||
double operator[](GETTER b)
| |||
{
| |||
return buffer[b];
| |||
}
| |||
| |||
Buffer *operator[](SETTER b)
| |||
{
| |||
cursor = (int)b;
| |||
return &this;
| |||
}
| |||
| |||
// writes data from the 'source' into this buffer
| |||
int write(const double &source[], const int from = 0, const int to = 0, const int count = WHOLE_ARRAY)
| |||
{
| |||
ResetLastError();
| |||
return ArrayCopy(buffer, source, to, from, count);
| |||
}
| |||
| |||
// reads data from this buffer to the given 'target'
| |||
int read(double &target[], const int from = 0, const int to = 0, const int count = WHOLE_ARRAY)
| |||
{
| |||
ResetLastError();
| |||
return ArrayCopy(target, buffer, to, from, count);
| |||
}
| |||
| |||
int copy(const int handle, const int bus, const int from, const int count)
| |||
{
| |||
ResetLastError();
| |||
return CopyBuffer(handle, bus, from, count, buffer);
| |||
}
| |||
| |||
double operator=(double x)
| |||
{
| |||
buffer[cursor] = x;
| |||
return x;
| |||
}
| |||
| |||
void set(const int b, const double v)
| |||
{
| |||
buffer[b] = v;
| |||
}
| |||
| |||
void set(const int b, const double &array[])
| |||
{
| |||
for(int i = 0; i < ArraySize(array); i++)
| |||
{
| |||
buffer[b + i] = array[i];
| |||
}
| |||
}
| |||
| |||
BufferGetter *edit()
| |||
{
| |||
if(instance == NULL) instance = new BufferGetter(this);
| |||
return instance;
| |||
}
| |||
| |||
double operator+(double x) const
| |||
{
| |||
return buffer[cursor] + x;
| |||
}
| |||
| |||
double operator-(double x) const
| |||
{
| |||
return buffer[cursor] - x;
| |||
}
| |||
| |||
double operator*(double x) const
| |||
{
| |||
return buffer[cursor] * x;
| |||
}
| |||
| |||
double operator/(double x) const
| |||
{
| |||
return buffer[cursor] / x;
| |||
}
| |||
| |||
double operator+=(double x)
| |||
{
| |||
buffer[cursor] += x;
| |||
return buffer[cursor];
| |||
}
| |||
| |||
double operator-=(double x)
| |||
{
| |||
buffer[cursor] -= x;
| |||
return buffer[cursor];
| |||
}
| |||
| |||
double operator*=(double x)
| |||
{
| |||
buffer[cursor] *= x;
| |||
return buffer[cursor];
| |||
}
| |||
| |||
double operator/=(double x)
| |||
{
| |||
buffer[cursor] /= x;
| |||
return buffer[cursor];
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Indicator buffer read-accessor via operator[](int) overload |
| |||
//+------------------------------------------------------------------+
| |||
class BufferGetter // helper class to access buffer values 'directly'
| |||
{
| |||
private:
| |||
Buffer *owner;
| |||
int cursor;
| |||
| |||
public:
| |||
BufferGetter(Buffer &o)
| |||
{
| |||
owner = &o;
| |||
}
| |||
| |||
double operator[](int b)
| |||
{
| |||
return owner[(GETTER)b];
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Manager class for array of indicator buffer holders |
| |||
//+------------------------------------------------------------------+
| |||
class BufferArray
| |||
{
| |||
protected:
| |||
Buffer *array[];
| |||
| |||
public:
| |||
BufferArray() { }
| |||
| |||
void add(const int m = 1,
| |||
const ENUM_INDEXBUFFER_TYPE type = INDICATOR_DATA,
| |||
const double empty = EMPTY_VALUE,
| |||
const bool asSeries = false)
| |||
{
| |||
const int n = ArraySize(array);
| |||
ArrayResize(array, n + m);
| |||
for(int i = 0; i < m; ++i)
| |||
{
| |||
array[n + i] = new Buffer(n + i, empty, type, asSeries);
| |||
}
| |||
}
| |||
| |||
BufferArray(const int n, const bool asSeries = false, const double empty = EMPTY_VALUE)
| |||
{
| |||
ArrayResize(array, n);
| |||
for(int i = 0; i < n; ++i)
| |||
{
| |||
array[i] = new Buffer(i, empty, INDICATOR_DATA, asSeries);
| |||
}
| |||
}
| |||
| |||
BufferArray(const int n,
| |||
const ENUM_INDEXBUFFER_TYPE &types[],
| |||
const double empty = EMPTY_VALUE,
| |||
const bool asSeries = false)
| |||
{
| |||
ArrayResize(array, n);
| |||
for(int i = 0; i < n; ++i)
| |||
{
| |||
array[i] = new Buffer(i, empty, types[i], asSeries);
| |||
}
| |||
}
| |||
| |||
virtual ~BufferArray()
| |||
{
| |||
const int n = ArraySize(array);
| |||
for(int i = 0; i < n; ++i)
| |||
{
| |||
if(CheckPointer(array[i]) == POINTER_DYNAMIC)
| |||
{
| |||
delete array[i];
| |||
}
| |||
}
| |||
ArrayResize(array, 0);
| |||
}
| |||
| |||
Buffer *operator[](int n) const
| |||
{
| |||
if(n >= ArraySize(array))
| |||
{
| |||
Print("OOB:", n , " >= ", ArraySize(array));
| |||
}
| |||
return array[n];
| |||
}
| |||
| |||
int size() const
| |||
{
| |||
return ArraySize(array);
| |||
}
| |||
| |||
void empty(const double empty = EMPTY_VALUE)
| |||
{
| |||
const int n = ArraySize(array);
| |||
for(int i = 0; i < n; ++i)
| |||
{
| |||
array[i].empty(empty);
| |||
}
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Read-accessor for array of indicator buffer holders/accessors |
| |||
//+------------------------------------------------------------------+
| |||
class BufferArrayGetter
| |||
{
| |||
private:
| |||
BufferGetter *array[];
| |||
| |||
public:
| |||
BufferArrayGetter(){};
| |||
| |||
BufferArrayGetter(const BufferArray &a)
| |||
{
| |||
bind(a);
| |||
}
| |||
| |||
void bind(const BufferArray &a)
| |||
{
| |||
int n = a.size();
| |||
ArrayResize(array, n);
| |||
for(int i = 0; i < n; ++i)
| |||
{
| |||
array[i] = a[i].edit();
| |||
}
| |||
}
| |||
| |||
BufferGetter *operator[](int n) const
| |||
{
| |||
return array[n];
| |||
}
| |||
| |||
virtual ~BufferArrayGetter()
| |||
{
| |||
ArrayResize(array, 0);
| |||
}
| |||
};
| |||
//+------------------------------------------------------------------+
|