Puga/PugaFiles/RangerNew.mqh
super.admin cb1aa93a0a convert
2025-05-30 16:18:30 +02:00

310 lines
23 KiB
MQL5

//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include <Arrays\ArrayDouble.mqh>
class Ranger
{
private:
int counter;
datetime start, vWapStart;
string symbol;
ENUM_TIMEFRAMES tf;
CArrayDouble pr, md, rs;
double vWap, stopLoss, takeProfit, close[];
//Определение диапазонов используя макд
int RangeCheck()
{
//Хэндлы и подготовка
int macd_handle = iMACD(symbol,tf,12,26,9,PRICE_CLOSE);
double macd[], sig[];
ArraySetAsSeries(macd, true);
ArraySetAsSeries(sig, true);
//UPD 3 значения в буфере необходимы что бы избежать перерисовки, путем сдвига на 2-1 индекс вместо 1-0
CopyBuffer(macd_handle,0,0,3,macd);
CopyBuffer(macd_handle,1,0,3,sig);
if((macd[2] > 0 && macd[1] < 0) || (macd[2] < 0 && macd[1] > 0))
{
start = TimeCurrent();
}
else
if
(start != TimeCurrent() && ((macd[1] > 0 && sig[2] < macd[2] && sig[1] > macd[1]) || (macd[1] < 0 && sig[2] > macd[2] && sig[1] < macd[1])))
{
counter = Bars(symbol,tf,start,TimeCurrent());
start = TimeCurrent();
}
return ((counter > 2 && macd[1] < 0) ? counter+1 : (counter > 2 && macd[1] > 0) ? -counter-1 : NULL);
};
//Заполнение массивов экстремумами
//Разобраться с заполнением данными, косяки со сдвигами присутствуют//done for now??
void Arranger()//Сбор и упорядочивание данных для последующих процедур
{
int range = MathAbs(RangeCheck());
if(range-2 > 0 && range < 10000)
{
//Volume tests
MqlRates candle[];
MqlRates daily[];
long volArray[];
vector volume;
ArraySetAsSeries(volArray, true);
ArraySetAsSeries(candle, true);
ArraySetAsSeries(daily,true);
CopyRates(symbol,tf,1,range,candle);
CopyRates(symbol,PERIOD_D1,0,1,daily);
int totalBars = Bars(symbol,tf,daily[0].time,TimeCurrent());
double avgVol = (double)daily[0].tick_volume/totalBars;
//Print("Daily Avg Vol: ", avgVol);
//CopyTickVolume(symbol,tf,candle[range-1].time,candle[1].time,volArray);
ArrayResize(volArray,range);
for(int i=0; i<ArraySize(candle); i++)
{
volArray[i] = candle[i].tick_volume;
}
//ArrayReverse(volArray,0,WHOLE_ARRAY);//что бы объемы соответствовали свече, тики которой скопированы
volume.Assign(volArray);
if((volume.Sum()/volume.Size())/avgVol < 1.5)
{
pr.Shutdown();
md.Shutdown();
rs.Shutdown();
vWapStart = NULL;
return;
}
//Print("Volume Test OK: ", (volume.Sum()/volume.Size())/avgVol);
//If tests OK -> Хэндлы и подготовка
int macd_handle = iMACD(symbol,tf,12,26,9,PRICE_CLOSE);
int rsi_handle = iRSI(symbol,tf,14,PRICE_CLOSE);
double price[], macd[], rsi[];
ArraySetAsSeries(price, true);
ArraySetAsSeries(macd, true);
ArraySetAsSeries(rsi, true);
//Получение последней клозины
CopyClose(symbol,tf,0,1,close);
//Заполнение массивов индикаторов
CopyBuffer(macd_handle,0,0,range,macd);
CopyBuffer(rsi_handle,0,0,range,rsi);
//Проверка какой из экстремумов использовать, заполнение массива price
if(macd[0] < 0)
{
ArrayResize(price,range);
for(int i=0; i<ArraySize(candle); i++)
{
price[i] = candle[i].low;
}
vWapStart = vWapStart == NULL ? candle[ArraySize(candle)-1].time : vWapStart;
pr.Add(price[ArrayMinimum(price,0,WHOLE_ARRAY)]);
md.Add(macd[ArrayMinimum(macd,0,WHOLE_ARRAY)]);
rs.Add(rsi[ArrayMinimum(rsi,0,WHOLE_ARRAY)]);
counter = 0;
start = TimeCurrent();
}
else
{
ArrayResize(price,range);
for(int i=0; i<ArraySize(candle); i++)
{
price[i] = candle[i].high;
}
vWapStart = vWapStart == NULL ? candle[ArraySize(candle)-1].time : vWapStart;
pr.Add(price[ArrayMaximum(price,0,WHOLE_ARRAY)]);
md.Add(macd[ArrayMaximum(macd,0,WHOLE_ARRAY)]);
rs.Add(rsi[ArrayMaximum(rsi,0,WHOLE_ARRAY)]);
counter = 0;
start = TimeCurrent();
}
//Фильтр последовательности добавлений значений(- за -, + за +)
if(md.Total() > 0 && ((md.At(0) > 0 && md.At(md.Total()-1) < 0) || (md.At(0) < 0 && md.At(md.Total()-1) > 0)))
{
pr.Shutdown();
md.Shutdown();
rs.Shutdown();
vWapStart = NULL;
return;
}
}
};
public:
double Rrange(string currentSymbol, ENUM_TIMEFRAMES currentTF, int rangesToSignal)
{
//Конструктор для дальнейшей передачи в Arranger
//Доработать проверку на спред. При большом среднем(?) спреде(?) игнорить вход целиком
symbol = currentSymbol;
tf = currentTF;
double signal = 0;
Arranger();
//Формирование векторов при условии достаточного количества значений, иначе выход
if(pr.Total() == rangesToSignal && md.Total() == rangesToSignal && rs.Total() == rangesToSignal)
{
if((md.At(rangesToSignal-2) > 0 && md.At(rangesToSignal-1) > 0) || (md.At(rangesToSignal-2) < 0 && md.At(rangesToSignal-1) < 0))
{
int bb_handle = iBands(symbol,PERIOD_M30,20,0,2,PRICE_CLOSE);
double upper[], mid[], lower[];
ArraySetAsSeries(upper,true);
ArraySetAsSeries(mid,true);
ArraySetAsSeries(lower,true);
CopyBuffer(bb_handle,1,0,3,upper);
CopyBuffer(bb_handle,0,0,3,mid);
CopyBuffer(bb_handle,2,0,3,lower);
if(md.At(rangesToSignal-1) > 0 && (close[0] > upper[0] || close[0] < mid[0]))
{
pr.Shutdown();
md.Shutdown();
rs.Shutdown();
vWapStart = NULL;
//Print("BB range check false");
return 0;
}
else
if(md.At(rangesToSignal-1) < 0 && (close[0] < lower[0] || close[0] > mid[0]))
{
pr.Shutdown();
md.Shutdown();
rs.Shutdown();
vWapStart = NULL;
//Print("BB range check false");
return 0;
}
vector priceRange, mdRange, rsRange;
priceRange.Init(rangesToSignal);
mdRange.Init(rangesToSignal);
rsRange.Init(rangesToSignal);
//Заполнение векторов для определения кореляции
for(int i=0; i<rangesToSignal; i++)
{
priceRange[i] = pr.At(i);
mdRange[i] = md.At(i);
rsRange[i] = rs.At(i);
}
double mdCorr = priceRange.CorrCoef(mdRange);
double rsCorr = priceRange.CorrCoef(rsRange);
signal = (MathAbs(mdCorr)+MathAbs(rsCorr))/2;
//Очистка не нужных уже листов, с этого момента начинается работа с векторами
pr.Shutdown();
md.Shutdown();
rs.Shutdown();
//Блок работы с данными
if(mdRange[rangesToSignal-1] < 0 && (mdCorr < 0 || rsCorr < 0))
{
// //Подключаем VWAP ***
// int vWapBars = Bars(symbol,tf,vWapStart,TimeCurrent());
// MqlRates candle[];
// double price[];
// long volumeArray[];
// vector wap, volume;
//
// ArraySetAsSeries(candle, true);
// ArraySetAsSeries(price, true);
// ArraySetAsSeries(volumeArray, true);
// ArrayResize(volumeArray,vWapBars);
// ArrayResize(price,vWapBars);
//
// CopyRates(symbol,tf,0,vWapBars,candle);
// for(int i=0; i<ArraySize(candle); i++)
// {
// volumeArray[i] = candle[i].tick_volume;
// }
// for(int i=0; i<ArraySize(candle); i++)
// {
// price[i] = candle[i].low;
// }
//
// wap.Assign(price);
// volume.Assign(volumeArray);
//
// //VWAP formula
// for(ulong i=0; i<wap.Size(); i++)
// {
// wap[i] = wap[i]*volume[i];
// }
// vWap = wap.Sum()/volume.Sum();
// //Print(vWap);
stopLoss = priceRange.Min()*0.9985;
// //Print("StopLoss: ", stopLoss);
// takeProfit = close[0]*1.002;// + (close[0] - stopLoss)*1.5;
// //Print("TakeProfit: ", takeProfit);
// //***
return signal;
}
else
if(mdRange[rangesToSignal-1] > 0 && (mdCorr < 0 || rsCorr < 0))
{
// //Подключаем VWAP ***
// int vWapBars = Bars(symbol,tf,vWapStart,TimeCurrent());
// MqlRates candle[];
// double price[];
// long volumeArray[];
// vector wap, volume;
//
// ArraySetAsSeries(candle, true);
// ArraySetAsSeries(price, true);
// ArraySetAsSeries(volumeArray, true);
// ArrayResize(volumeArray,vWapBars);
// ArrayResize(price,vWapBars);
//
// CopyRates(symbol,tf,0,vWapBars,candle);
// for(int i=0; i<ArraySize(candle); i++)
// {
// volumeArray[i] = candle[i].tick_volume;
// }
// for(int i=0; i<ArraySize(candle); i++)
// {
// price[i] = candle[i].high;
// }
//
// wap.Assign(price);
// volume.Assign(volumeArray);
//
// //VWAP formula
// for(ulong i=0; i<wap.Size(); i++)
// {
// wap[i] = wap[i]*volume[i];
// }
// vWap = wap.Sum()/volume.Sum();
// //Print(vWap);
stopLoss = priceRange.Max()*1.0015;
// //Print("StopLoss: ", stopLoss);
// takeProfit = close[0]*0.998;// - (stopLoss - close[0])*1.5;
// //Print("TakeProfit: ", takeProfit);
// //***
return -signal;
}
}
else
{
pr.Shutdown();
md.Shutdown();
rs.Shutdown();
vWapStart = NULL;
return 0;
}
}
return 0;
};
double getSL() {return stopLoss;}
double getTP() {return takeProfit;}
double getVWAP() {return vWap;}
};
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+