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