182 lignes
Pas d'EOL
6,1 Kio
MQL5
182 lignes
Pas d'EOL
6,1 Kio
MQL5
//#include<Generic/Queue.mqh>
|
|
|
|
extern MqlRates rates[];
|
|
|
|
|
|
input group "Orderflow configurations"
|
|
input ENUM_TIMEFRAMES inpOrderflowtf=PERIOD_CURRENT;
|
|
|
|
class COrderflow /*:public CCore*/{
|
|
protected:
|
|
int orderflowCurrent; //latest orderflow flag -1 for BEARISH, 1 for BULLISH
|
|
double latestBullishRoot, latestBearishRoot;
|
|
enum CISDOrderblocks{BEARISHORDERBLOCK=-1, ORDERBLOCKNONE=0, BULLISHORDERBLOCK=1};
|
|
//CQueue<CISDOrderblocks> orderblocks;
|
|
//array
|
|
//latest cisd
|
|
bool isCISD;
|
|
|
|
public:
|
|
//getters
|
|
int getOrderflow(){return orderflowCurrent;};
|
|
bool whatWasOrderflow(int index, int &orderflowFlag, double &bearishRoot, double &bullishRoot); //asking for orderflow from the history
|
|
bool whenWasCISD(int &index, int &flag, int bias=0); //asking when was the last CISD
|
|
bool isCISDBySwings(int &flag);
|
|
bool isGap();
|
|
bool wasGap(double &range, double &lowerBand, double &upperBand);
|
|
bool initialize();
|
|
void update();
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
bool COrderflow::initialize(void){
|
|
|
|
if(latestBearishRoot!=0 && latestBullishRoot!=0){ //already initialized
|
|
Print("roots already loaded!");
|
|
return true;
|
|
}
|
|
|
|
int bullishRootIdx=0, bearishRootIdx=0;
|
|
|
|
for(int i=1; i<Bars(_Symbol,PERIOD_CURRENT)-1; i++){
|
|
bool currBullish = rates[i].close > rates[i].open;
|
|
bool currBearish = rates[i].close < rates[i].open;
|
|
bool prevBullish = rates[i+1].close > rates[i+1].open;
|
|
bool prevBearish = rates[i+1].close < rates[i+1].open;
|
|
|
|
// Bullish candle after bearish → start of bullish move → bullish root
|
|
if(currBullish && prevBearish && latestBullishRoot==0){
|
|
rates[i].open < rates[i+1].close ? latestBullishRoot=rates[i].open : latestBullishRoot=rates[i+1].close; //avoiding the gap trap
|
|
bullishRootIdx=i;
|
|
}
|
|
|
|
// Bearish candle after bullish → start of bearish move → bearish root
|
|
if(currBearish && prevBullish && latestBearishRoot==0){
|
|
rates[i].open > rates[i+1].close ? latestBearishRoot=rates[i].open : latestBearishRoot=rates[i+1].close; //avoiding the gap trap
|
|
bearishRootIdx=i;
|
|
}
|
|
|
|
if(latestBullishRoot!=0 && latestBearishRoot!=0){
|
|
Print("roots successfully loaded");
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(latestBullishRoot==0 || latestBearishRoot==0){
|
|
Print("failed to load one of roots");
|
|
return false;
|
|
}
|
|
|
|
if(rates[1].close > latestBearishRoot){
|
|
orderflowCurrent=1;
|
|
}
|
|
else if(rates[1].close < latestBullishRoot){
|
|
orderflowCurrent=-1;
|
|
}
|
|
else{ // closing in between — the most recently formed root decides
|
|
orderflowCurrent = (bullishRootIdx < bearishRootIdx) ? 1 : -1;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool COrderflow::whatWasOrderflow(const int index,int &orderflowFlag, double &bearishRoot, double &bullishRoot){
|
|
if(bearishRoot!=0||bullishRoot!=0)
|
|
{
|
|
Print("Reference provided is already loaded, reset it before proceeding");
|
|
Sleep(200);
|
|
bullishRoot=0;
|
|
bearishRoot=0;
|
|
}
|
|
|
|
int bullishRootIdx=0, bearishRootIdx=0;
|
|
|
|
for(int i=index; i<Bars(_Symbol,PERIOD_CURRENT)-1; i++){
|
|
bool currBullish = rates[i].close > rates[i].open;
|
|
bool currBearish = rates[i].close < rates[i].open;
|
|
bool prevBullish = rates[i+1].close > rates[i+1].open;
|
|
bool prevBearish = rates[i+1].close < rates[i+1].open;
|
|
|
|
// Bullish candle after bearish → start of bullish move → bullish root
|
|
if(currBullish && prevBearish && bullishRoot==0){
|
|
rates[i].open < rates[i+1].close ? bullishRoot=rates[i].open : bullishRoot=rates[i+1].close; //avoiding the gap trap
|
|
bullishRootIdx=i;
|
|
}
|
|
|
|
// Bearish candle after bullish → start of bearish move → bearish root
|
|
if(currBearish && prevBullish && bearishRoot==0){
|
|
rates[i].open > rates[i+1].close ? bearishRoot=rates[i].open : bearishRoot=rates[i+1].close; //avoiding the gap trap
|
|
bearishRootIdx=i;
|
|
}
|
|
|
|
if(bullishRoot!=0 && bearishRoot!=0)
|
|
break;
|
|
}
|
|
|
|
if(bullishRoot==0 || bearishRoot==0)
|
|
return false;
|
|
|
|
if(rates[index].close > bearishRoot){
|
|
orderflowFlag=1;
|
|
}
|
|
else if(rates[index].close < bullishRoot){
|
|
orderflowFlag=-1;
|
|
}
|
|
else{ // closing in between — the most recently formed root decides
|
|
orderflowFlag = (bullishRootIdx < bearishRootIdx) ? 1 : -1;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void COrderflow::update(void){
|
|
if(orderflowCurrent==0){
|
|
Print("There was NULL Orderflow, trying to initialize right now.. ");
|
|
COrderflow::initialize();
|
|
}
|
|
|
|
if(orderflowCurrent==1){ //the current orderflow is bullish
|
|
if(rates[1].close<latestBullishRoot){
|
|
//cisd
|
|
isCISD=true;
|
|
orderflowCurrent=-1;
|
|
}
|
|
|
|
if(rates[1].close<rates[1].open //
|
|
&& rates[2].close>rates[2].open){ //receiving first-time opposing candle
|
|
//
|
|
rates[1].open>rates[2].close ? latestBearishRoot=rates[1].open : latestBearishRoot=rates[2].close;
|
|
}
|
|
|
|
if(rates[1].close>rates[1].open //
|
|
&& rates[2].close<rates[2].open){ //receiving first-time opposing candle
|
|
//
|
|
rates[1].open>rates[2].close ? latestBullishRoot=rates[2].close : latestBullishRoot=rates[1].open;
|
|
}
|
|
|
|
}
|
|
|
|
if(orderflowCurrent==-1){ //the current orderflow is bearish
|
|
if(rates[1].close>latestBearishRoot){
|
|
//cisd
|
|
isCISD=true;
|
|
orderflowCurrent=1;
|
|
}
|
|
|
|
if(rates[1].close>rates[1].open //
|
|
&& rates[2].close<rates[2].open){ //receiving first-time opposing candle
|
|
//
|
|
rates[1].open>rates[2].close ? latestBullishRoot=rates[2].close : latestBullishRoot=rates[1].open;
|
|
}
|
|
|
|
if(rates[1].close<rates[1].open //
|
|
&& rates[2].close>rates[2].open){ //receiving first-time opposing candle
|
|
//
|
|
rates[1].open>rates[2].close ? latestBearishRoot=rates[1].open : latestBearishRoot=rates[2].close;
|
|
}
|
|
}
|
|
|
|
} |