forked from rosh/MQL5Book
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%
| |
| |
*/
| |
//+------------------------------------------------------------------+
|