136 lines
3.7 KiB
MQL5
136 lines
3.7 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| TickFilter.mqh |
|
|
//| Copyright 2022, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Several methods of prunning ticks for faster optimization and |
|
|
//| lower resource consumption |
|
|
//+------------------------------------------------------------------+
|
|
class TickFilter
|
|
{
|
|
public:
|
|
enum FILTER_MODE
|
|
{
|
|
NONE,
|
|
SEQUENCE,
|
|
FLUTTER,
|
|
FRACTALS,
|
|
};
|
|
|
|
static int filter(FILTER_MODE mode, MqlTick &data[])
|
|
{
|
|
switch(mode)
|
|
{
|
|
case SEQUENCE: return filterBySequences(data);
|
|
case FLUTTER: return filterBySpreadFlutter(data);
|
|
case FRACTALS: return filterByFractals(data);
|
|
}
|
|
return ArraySize(data);
|
|
}
|
|
|
|
static int filterBySequences(MqlTick &data[])
|
|
{
|
|
const int size = ArraySize(data);
|
|
if(size < 3) return size;
|
|
|
|
int index = 2;
|
|
bool dirUp = data[1].bid - data[0].bid + data[1].ask - data[0].ask > 0;
|
|
|
|
for(int i = 2; i < size; i++)
|
|
{
|
|
if(dirUp)
|
|
{
|
|
if(data[i].bid - data[i - 1].bid + data[i].ask - data[i - 1].ask < 0)
|
|
{
|
|
dirUp = false;
|
|
data[index++] = data[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(data[i].bid - data[i - 1].bid + data[i].ask - data[i - 1].ask > 0)
|
|
{
|
|
dirUp = true;
|
|
data[index++] = data[i];
|
|
}
|
|
}
|
|
}
|
|
return ArrayResize(data, index);
|
|
}
|
|
|
|
static int filterBySpreadFlutter(MqlTick &data[])
|
|
{
|
|
const int size = ArraySize(data);
|
|
if(size < 3) return size;
|
|
|
|
bool dirUp = true;
|
|
int index = 0;
|
|
double priceMinMax = -DBL_MAX;
|
|
|
|
for(int i = 0; i < size; i++)
|
|
{
|
|
const double bid = data[i].bid;
|
|
const double ask = data[i].ask;
|
|
|
|
if(dirUp)
|
|
{
|
|
if(bid > priceMinMax)
|
|
{
|
|
priceMinMax = bid;
|
|
data[index++] = data[i];
|
|
}
|
|
else if(ask <= priceMinMax)
|
|
{
|
|
priceMinMax = ask;
|
|
dirUp = false;
|
|
data[index++] = data[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(ask < priceMinMax)
|
|
{
|
|
priceMinMax = ask;
|
|
data[index++] = data[i];
|
|
}
|
|
else if(bid >= priceMinMax)
|
|
{
|
|
priceMinMax = bid;
|
|
dirUp = true;
|
|
data[index++] = data[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
return ArrayResize(data, index);
|
|
}
|
|
|
|
static int filterByFractals(MqlTick &data[])
|
|
{
|
|
int index = 1;
|
|
const int size = ArraySize(data);
|
|
if(size < 3) return size;
|
|
|
|
for(int i = 1; i < size - 2; i++)
|
|
{
|
|
if((data[i].bid < data[i - 1].bid && data[i].bid < data[i + 1].bid)
|
|
|| (data[i].ask > data[i - 1].ask && data[i].ask > data[i + 1].ask))
|
|
{
|
|
data[index++] = data[i];
|
|
}
|
|
}
|
|
|
|
return ArrayResize(data, index);
|
|
}
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
/*
|
|
Example outputs:
|
|
|
|
Create new custom symbol 'EURUSD.TckFltr-SEQUENCE'?
|
|
Done ticks - read: 37682157, written: 19896830, ratio: 52.8%
|
|
|
|
*/
|
|
//+------------------------------------------------------------------+
|