Draw line from last higher/lower Fractal until it is broken

 

Good evening everyone,

I have written a function which draws a line from the last 3 fractal highs/lows until it is broken by the price. This works in 90% of the cases, but there are always situations where the line goes further than it should ;)

Maybe someone can have a look at the code and see if he notices anything, because I can't find the error ;(

Many thanks in advance

Here is an example of the bug. It is the 5 minute Chart.


And there is the Code:

//#################################################################################################################################
//# H1 Liquidity Levels                                                                                                           #
//#################################################################################################################################

#include "ICT-Fractals.mqh"


input int                     InpMaxBarCount                = 5000;              // Liquidity Levels - Max Candles Counted
input int                     InpMaxFractalCount            = 1500;               // Liquidity Levels - Max Fractals Counted   
input color                   InpColorBUYsideLiquidity      = clrGreenYellow;    // Color BUY Side Liquidity
input color                   InpColorSELLsideLiquidity     = clrOrangeRed;      // Color SELL Side Liquidity
enum ENUM_FRACTAL_JOICE{ICT_FRACTALS,WILLIAMS_FRACTALS};
input ENUM_FRACTAL_JOICE      InpFractalJoice               = WILLIAMS_FRACTALS; // Williams or ICTs Fractals

double arrUpperFractals[];
double arrLastUpperFractals[];
double arrLowerFractals[];
datetime arrUpperFractalsTime[];
datetime arrLowerFractalsTime[];

double lastUpperLiquidityLevel = 0.0;
datetime lastUpperLiquidityTime;
double lastLowerLiquidityLevel = 0.0;
datetime lastLowerLiquidityTime;
      
bool liqBroken = false;
bool LowerLiquidityBreakSet_h1 = false;
bool UpperLiquidityBreakSet_h1 = false;

int maxBarCount = InpMaxBarCount;
int maxLiquidityLevels = 3;
int fractalCountUpper = 0;
int maxfractalCountUpper = InpMaxFractalCount;
int fractalCountLower = 0;
int maxfractalCountLower = InpMaxFractalCount;
   
double arrLiquidityLevelsUpper[];
double arrLiquidityLevelsLower[];
datetime arrLiquidityTimeUpper[];
datetime arrLiquidityTimeLower[];

string LiquiditySignalUpper = "";
string LiquiditySignalLower = "";
string LiquiditySignal = "";
   
void LiquidityLevels(){
   
   ArrayResize(arrUpperFractals,maxfractalCountUpper);
   ArrayResize(arrLastUpperFractals,maxfractalCountUpper);
   ArrayResize(arrLowerFractals,maxfractalCountUpper);
   ArrayResize(arrUpperFractalsTime,maxfractalCountUpper);
   ArrayResize(arrLowerFractalsTime,maxfractalCountUpper);
   
   ArrayResize(arrLiquidityLevelsUpper,maxLiquidityLevels);
   ArrayResize(arrLiquidityLevelsLower,maxLiquidityLevels);
   ArrayResize(arrLiquidityTimeUpper,maxLiquidityLevels);
   ArrayResize(arrLiquidityTimeLower,maxLiquidityLevels);
   
   
//#############################
//# Find UPPER Fractals in H1 #
//#############################

   lastUpperLiquidityLevel = arrLiquidityLevelsUpper[0];
   lastLowerLiquidityLevel = arrLiquidityLevelsLower[0];
   
   for(int i=0;i<= maxBarCount;i++){
      double upperFractal;
      if(InpFractalJoice == WILLIAMS_FRACTALS){
         upperFractal = iFractals(Symbol(),PERIOD_H1,MODE_UPPER,i);
      }else if(InpFractalJoice == ICT_FRACTALS){
         upperFractal = ICT_Fractals(MODE_UPPER,PERIOD_H1,false, i-2);
      }else{
         upperFractal = iFractals(Symbol(),PERIOD_H1,MODE_UPPER,i);
      }
      
      if(upperFractal != 0 && upperFractal != EMPTY_VALUE){
         arrUpperFractals[fractalCountUpper] = upperFractal;
         arrUpperFractalsTime[fractalCountUpper] = iTime(Symbol(),PERIOD_H1,i);
         //Print("Upper Fractal Array[",fractalCountUpper,"] = ",upperFractal," Fractal Time: ",arrUpperFractalsTime[fractalCountUpper]);
         fractalCountUpper += 1;
      }
      
      if(fractalCountUpper == maxfractalCountUpper){
         fractalCountUpper = 0;
         break;
      }

   }
   
//##############################   
// Find Upper Liquidity Levels #
//##############################

   int lastUpperFractalCount = 0;
   
   // Fill first Liquidity Level
   for(int o = 0;o<maxfractalCountUpper;o++){
      if(arrUpperFractals[0] != 0 && arrUpperFractals[0] != EMPTY_VALUE && arrUpperFractals[o] > Bid && iHigh(Symbol(),Period(),iHighest(Symbol(), Period(), MODE_HIGH, iBarShift(Symbol(),Period(),arrUpperFractalsTime[o]),0))==arrUpperFractals[o]){
         arrLiquidityLevelsUpper[0] = arrUpperFractals[o];
         arrLiquidityTimeUpper[0] = arrUpperFractalsTime[o];
         break;
      } 
   }
   
   // Fill second Liquidity Level
   for(int j=1;j<maxfractalCountUpper;j++){
      if(arrUpperFractals[j]>arrLiquidityLevelsUpper[0] && arrUpperFractals[0] != 0 && arrUpperFractals[0] != EMPTY_VALUE){
         arrLiquidityLevelsUpper[1] = arrUpperFractals[j];
         arrLiquidityTimeUpper[1] = arrUpperFractalsTime[j];
         lastUpperFractalCount = j;
         break;
      }
   }     
    
   // Fill third Liquidity Level
   for(int k = lastUpperFractalCount;k<maxfractalCountUpper;k++){
      if(arrUpperFractals[k]>arrLiquidityLevelsUpper[1] && arrLiquidityLevelsUpper[1] != 0 && arrLiquidityLevelsUpper[1] != EMPTY_VALUE){
         arrLiquidityLevelsUpper[2] = arrUpperFractals[k];
         arrLiquidityTimeUpper[2] = arrUpperFractalsTime[k];
         break;
      }
   }
   
Fractals - Bill Williams' Indicators - Technical Indicators - Price Charts, Technical and Fundamental Analysis - MetaTrader 5 Help
  • www.metatrader5.com
All markets are characterized by the fact that on the most part the prices do not change too much, and only short periods of time (15–30 percent)...
 
//##############################   
// Find Upper Liquidity Levels #
//##############################   
   
   int lastLowerFractalCount = 0;
   
   // Fill first Liquidity Level
   
   for(int p = 0;p<maxfractalCountLower;p++){
            if(arrLowerFractals[0] != 0 && arrLowerFractals[0] != EMPTY_VALUE && arrLowerFractals[p] < Bid  && iLow(Symbol(),Period(),iLowest(Symbol(), Period(), MODE_LOW, iBarShift(Symbol(),Period(),arrLowerFractalsTime[p]),0))==arrLowerFractals[p]){
         arrLiquidityLevelsLower[0] = arrLowerFractals[p];
         arrLiquidityTimeLower[0] = arrLowerFractalsTime[p];
         break;
      } 
   }
    
   // Fill second Liquidity Level
   for(int m=1;m<maxfractalCountLower;m++){
      if(arrLowerFractals[m]<arrLiquidityLevelsLower[0] && arrLowerFractals[0] != 0 && arrLowerFractals[0] != EMPTY_VALUE){
         arrLiquidityLevelsLower[1] = arrLowerFractals[m];
         arrLiquidityTimeLower[1] = arrLowerFractalsTime[m];
         lastLowerFractalCount = m;
         break;
      }
   }      
   
   // Fill third Liquidity Level
   for(int n = lastLowerFractalCount;n<maxfractalCountLower;n++){
      if(arrLowerFractals[n]<arrLiquidityLevelsLower[1] && arrLiquidityLevelsLower[1] != 0 && arrLiquidityLevelsLower[1] != EMPTY_VALUE){
          arrLiquidityLevelsLower[2] = arrLowerFractals[n];
          arrLiquidityTimeLower[2] = arrLowerFractalsTime[n];
          break;
      }
   }
   
   
   if(lastUpperLiquidityLevel != arrLiquidityLevelsUpper[0]){
      Print("SELLSIDE Liqudity Break H1 " + DoubleToStr(lastUpperLiquidityLevel,2) + "  |  New Liqudity" +DoubleToStr(arrLiquidityLevelsUpper[0],2));
      
      //if(lastUpperLiquidityLevel > arrLiquidityLevelsUpper[0]){
      //   Print("Last Upper bigger Upper");
      //   LiquiditySignalUpper = "";
      //}
      
      if(lastUpperLiquidityLevel < arrLiquidityLevelsUpper[0]){
         Print("Last Upper kleiner Upper");
         LiquiditySignalUpper = "SELLSIDE";
         LiquiditySignalLower = "";
         BreakOutSignal = "";
         H1andM5breakSignal = "";
         MarketStructureBreak_m5 = "";
      }
   
   }
   
   if(lastLowerLiquidityLevel != arrLiquidityLevelsLower[0]){
      Print("BUYSIDE Liqudity Break H1 " + DoubleToStr(lastLowerLiquidityLevel,2) + "  |  New Liqudity" +DoubleToStr(arrLiquidityLevelsLower[0],2));
      
      //if(lastLowerLiquidityLevel < arrLiquidityLevelsLower[0]){
      //   Print("Last Lower bigger Lower");
      //   LiquiditySignalLower = "";   
      //}   
     
      if(lastLowerLiquidityLevel > arrLiquidityLevelsLower[0]){
         Print("Last Lower kleiner Lower");
         LiquiditySignalLower = "BUYSIDE";
         LiquiditySignalUpper = "";
         BreakOutSignal = "";
         H1andM5breakSignal = "";
         MarketStructureBreak_m5 = "";
      }
   }
   
   if(LiquiditySignalUpper == "SELLSIDE"){
      LiquiditySignal = "SELLSIDE";
      
   }else if(LiquiditySignalLower == "BUYSIDE"){
      LiquiditySignal = "BUYSIDE";

   }else if(LiquiditySignalUpper == "" && LiquiditySignalLower == ""){
      LiquiditySignal = "";
   }
   
   

   // Draw Sellside Liquidity 1
   string nameSellSideLiquidityH1_1 = "H1 Sell Side Liquidity " + TimeToStr(arrLiquidityTimeUpper[0]);
   int SSL1inWindow = ObjectFind(0,nameSellSideLiquidityH1_1);
   
   if(SSL1inWindow<0){
      ObjectCreate(0,nameSellSideLiquidityH1_1,OBJ_TREND,0,arrLiquidityTimeUpper[0],arrLiquidityLevelsUpper[0],Time[1],arrLiquidityLevelsUpper[0]);
      ObjectSetInteger(0, nameSellSideLiquidityH1_1, OBJPROP_COLOR, 0, InpColorSELLsideLiquidity);
      ObjectSet(nameSellSideLiquidityH1_1, OBJPROP_RAY, False);  
   }else{
      
         ObjectSetInteger(0, nameSellSideLiquidityH1_1, OBJPROP_TIME, 0, arrLiquidityTimeUpper[0]);
         ObjectSetInteger(0, nameSellSideLiquidityH1_1, OBJPROP_TIME, 1, Time[1]);
         ObjectSetDouble(0, nameSellSideLiquidityH1_1, OBJPROP_PRICE, 0, arrLiquidityLevelsUpper[0]);
         ObjectSetDouble(0, nameSellSideLiquidityH1_1, OBJPROP_PRICE, 1, arrLiquidityLevelsUpper[0]);
         ObjectSet(nameSellSideLiquidityH1_1, OBJPROP_RAY, False); 
      
   }
   
   // Draw Sellside Liquidity 2
   string nameSellSideLiquidityH1_2 = "H1 Sell Side Liquidity ";
   int SSL2inWindow = ObjectFind(0,nameSellSideLiquidityH1_2);
   
   if(SSL2inWindow<0){
      ObjectCreate(0,nameSellSideLiquidityH1_2,OBJ_TREND,0,arrLiquidityTimeUpper[1],arrLiquidityLevelsUpper[1],Time[1],arrLiquidityLevelsUpper[1]);
      ObjectSetInteger(0, nameSellSideLiquidityH1_2, OBJPROP_COLOR, 0, InpColorSELLsideLiquidity);
      ObjectSet(nameSellSideLiquidityH1_2, OBJPROP_RAY, False);  
   }else{
      
         ObjectSetInteger(0, nameSellSideLiquidityH1_2, OBJPROP_TIME, 0, arrLiquidityTimeUpper[1]);
         ObjectSetInteger(0, nameSellSideLiquidityH1_2, OBJPROP_TIME, 1, Time[1]);
         ObjectSetDouble(0, nameSellSideLiquidityH1_2, OBJPROP_PRICE, 0, arrLiquidityLevelsUpper[1]);
         ObjectSetDouble(0, nameSellSideLiquidityH1_2, OBJPROP_PRICE, 1, arrLiquidityLevelsUpper[1]);
         ObjectSet(nameSellSideLiquidityH1_2, OBJPROP_RAY, False); 
      
   }
   
   // Draw Sellside Liquidity 3
   string nameSellSideLiquidityH1_3 = "H1 Sell Side Liquidity ";
   int SSL3inWindow = ObjectFind(0,nameSellSideLiquidityH1_3);
   
   if(SSL3inWindow<0){
      ObjectCreate(0,nameSellSideLiquidityH1_3,OBJ_TREND,0,arrLiquidityTimeUpper[2],arrLiquidityLevelsUpper[2],Time[1],arrLiquidityLevelsUpper[2]);
      ObjectSetInteger(0, nameSellSideLiquidityH1_3, OBJPROP_COLOR, 0, InpColorSELLsideLiquidity);
      ObjectSet(nameSellSideLiquidityH1_3, OBJPROP_RAY, False);  
   }else{
      ObjectSetInteger(0, nameSellSideLiquidityH1_3, OBJPROP_TIME, 0, arrLiquidityTimeUpper[2]);
      ObjectSetInteger(0, nameSellSideLiquidityH1_3, OBJPROP_TIME, 1, Time[1]);
      ObjectSetDouble(0, nameSellSideLiquidityH1_3, OBJPROP_PRICE, 0, arrLiquidityLevelsUpper[2]);
      ObjectSetDouble(0, nameSellSideLiquidityH1_3, OBJPROP_PRICE, 1, arrLiquidityLevelsUpper[2]);
      ObjectSet(nameSellSideLiquidityH1_3, OBJPROP_RAY, False); 
   }
   
   
    // Draw Buyside Liquidity 1
   string nameBuySideLiquidityH1_1 = "H1 Buy Side Liquidity " +TimeToStr(arrLiquidityTimeLower[0]);
   int BSL1inWindow = ObjectFind(0,nameBuySideLiquidityH1_1);
   
   if(BSL1inWindow<0){
      if(iLow(Symbol(),Period(),iLowest(Symbol(), Period(), MODE_LOW, iBarShift(Symbol(),Period(),arrLiquidityTimeLower[0]),0))>=arrLiquidityLevelsLower[0]){
         ObjectCreate(0,nameBuySideLiquidityH1_1,OBJ_TREND,0,arrLiquidityTimeLower[0],arrLiquidityLevelsLower[0],Time[1],arrLiquidityLevelsLower[0]);
         ObjectSetInteger(0, nameBuySideLiquidityH1_1, OBJPROP_COLOR, 0, InpColorBUYsideLiquidity);
         ObjectSet(nameBuySideLiquidityH1_1, OBJPROP_RAY, False);  
      }
   }else{
      if(iLow(Symbol(),Period(),iLowest(Symbol(), Period(), MODE_LOW, iBarShift(Symbol(),Period(),arrLiquidityTimeLower[0]),0))>=arrLiquidityLevelsLower[0]){
         ObjectSetInteger(0, nameBuySideLiquidityH1_1, OBJPROP_TIME, 0, arrLiquidityTimeLower[0]);
         ObjectSetInteger(0, nameBuySideLiquidityH1_1, OBJPROP_TIME, 1, Time[1]);
         ObjectSetDouble(0, nameBuySideLiquidityH1_1, OBJPROP_PRICE, 0, arrLiquidityLevelsLower[0]);
         ObjectSetDouble(0, nameBuySideLiquidityH1_1, OBJPROP_PRICE, 1, arrLiquidityLevelsLower[0]);
         ObjectSet(nameBuySideLiquidityH1_1, OBJPROP_RAY, False); 
      }
   }
   
   // Draw Buyside Liquidity 2
   string nameBuySideLiquidityH1_2 = "H1 Buy Side Liquidity " + TimeToStr(arrLiquidityTimeLower[1]);
   int BSL2inWindow = ObjectFind(0,nameBuySideLiquidityH1_2);
   
   if(BSL2inWindow<0){
      if(iLow(Symbol(),Period(),iLowest(Symbol(), Period(), MODE_LOW, iBarShift(Symbol(),Period(),arrLiquidityTimeLower[0]),0))>=arrLiquidityLevelsLower[0]){
         ObjectCreate(0,nameBuySideLiquidityH1_2,OBJ_TREND,0,arrLiquidityTimeLower[1],arrLiquidityLevelsLower[1],Time[1],arrLiquidityLevelsLower[1]);
         ObjectSetInteger(0, nameBuySideLiquidityH1_2, OBJPROP_COLOR, 0, InpColorBUYsideLiquidity);
         ObjectSet(nameBuySideLiquidityH1_2, OBJPROP_RAY, False);  
      }
   }else{
      if(iLow(Symbol(),Period(),iLowest(Symbol(), Period(), MODE_LOW, iBarShift(Symbol(),Period(),arrLiquidityTimeLower[0]),0))>=arrLiquidityLevelsLower[0]){
         ObjectSetInteger(0, nameBuySideLiquidityH1_2, OBJPROP_TIME, 0, arrLiquidityTimeLower[1]);
         ObjectSetInteger(0, nameBuySideLiquidityH1_2, OBJPROP_TIME, 1, Time[1]);
         ObjectSetDouble(0, nameBuySideLiquidityH1_2, OBJPROP_PRICE, 0, arrLiquidityLevelsLower[1]);
         ObjectSetDouble(0, nameBuySideLiquidityH1_2, OBJPROP_PRICE, 1, arrLiquidityLevelsLower[1]);
         ObjectSet(nameBuySideLiquidityH1_2, OBJPROP_RAY, False); 
      }
   }
   // Draw Buyside Liquidity 3
   string nameBuySideLiquidityH1_3 = "H1 Buy Side Liquidity ";
   int BSL3inWindow = ObjectFind(0,nameBuySideLiquidityH1_3);
   
   if(BSL3inWindow<0){
      ObjectCreate(0,nameBuySideLiquidityH1_3,OBJ_TREND,0,arrLiquidityTimeLower[2],arrLiquidityLevelsLower[2],Time[1],arrLiquidityLevelsLower[2]);
      ObjectSetInteger(0, nameBuySideLiquidityH1_3, OBJPROP_COLOR, 0, InpColorBUYsideLiquidity);
      ObjectSet(nameBuySideLiquidityH1_3, OBJPROP_RAY, False);  
   }else{
      ObjectSetInteger(0, nameBuySideLiquidityH1_3, OBJPROP_TIME, 0, arrLiquidityTimeLower[2]);
      ObjectSetInteger(0, nameBuySideLiquidityH1_3, OBJPROP_TIME, 1, Time[1]);
      ObjectSetDouble(0, nameBuySideLiquidityH1_3, OBJPROP_PRICE, 0, arrLiquidityLevelsLower[2]);
      ObjectSetDouble(0, nameBuySideLiquidityH1_3, OBJPROP_PRICE, 1, arrLiquidityLevelsLower[2]);
      ObjectSet(nameBuySideLiquidityH1_3, OBJPROP_RAY, False); 
   }
   WindowRedraw();
}
//#################################################################################################################################
//# ICT Fractals                                                                                                                  #
//#################################################################################################################################

double ICT_Fractals(ENUM_CHART_MODE Mode, ENUM_TIMEFRAMES TimeFrame,bool print, int Shift){

    int shift = Shift;
    
    if(Mode == MODE_UPPER){
      if(iHigh(Symbol(),TimeFrame,3+shift) < iHigh(Symbol(),TimeFrame,2+shift) && iHigh(Symbol(),TimeFrame,2+shift) > iHigh(Symbol(),TimeFrame,1+shift)){
         if(print == true){
            ObjectCreate(0, "Upper Fractal " + TimeToStr(TimeCurrent()), OBJ_ARROW, 0, iTime(Symbol(),TimeFrame,2+shift), iHigh(Symbol(),TimeFrame,2+shift)+0.75*iATR(Symbol(),Period(),250,shift));
            ObjectSet("Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_ANCHOR,ANCHOR_LOWER);
            ObjectSet("Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_YDISTANCE,1700);
            ObjectSetInteger(0,"Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_YDISTANCE,1700);
            ObjectSet("Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_SCALE,6);
            ObjectSetInteger(0,"Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_YOFFSET,1700);
            ObjectSetInteger(0,"Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_ARROWCODE,115);
            ObjectSetInteger(0,"Upper Fractal " + TimeToStr(TimeCurrent()),OBJPROP_COLOR,clrGreenYellow);
            //ObjectSetInteger(0,"Upper Fractal" + TimeToStr(TimeCurrent()),OBJPROP_TIMEFRAMES,TimeFrame);
         }
         return iHigh(Symbol(),TimeFrame,2+shift); 
      }else{return 0.0;}
      
    }else if(Mode == MODE_LOWER){
      if(iLow(Symbol(),TimeFrame,3+shift) > iLow(Symbol(),TimeFrame,2+shift) && iLow(Symbol(),TimeFrame,2+shift) < iLow(Symbol(),TimeFrame,1+shift)){
         if(print == true){
            ObjectCreate(0, "Lower Fractal " + TimeToStr(TimeCurrent()), OBJ_ARROW, 0, iTime(Symbol(),TimeFrame,2+shift), iLow(Symbol(),TimeFrame,2+shift)-0.25*iATR(Symbol(),Period(),250,0));
            ObjectSet("Lower Fractal " + TimeToStr(TimeCurrent()),OBJPROP_YDISTANCE,10);
            ObjectSetInteger(0,"Lower Fractal " + TimeToStr(TimeCurrent()),OBJPROP_YDISTANCE,300);
            ObjectSet("Lower Fractal " + TimeToStr(TimeCurrent()),OBJPROP_SCALE,6);
            ObjectSet("Lower Fractal " + TimeToStr(TimeCurrent()),OBJPROP_ANCHOR,ANCHOR_UPPER);
            ObjectSetInteger(0,"Lower Fractal " + TimeToStr(TimeCurrent()),OBJPROP_ARROWCODE,115);
            ObjectSetInteger(0,"Lower Fractal " + TimeToStr(TimeCurrent()),OBJPROP_COLOR,clrOrange);
            //ObjectSetInteger(0,"Lower Fractal" + TimeToStr(TimeCurrent()),OBJPROP_TIMEFRAMES,TimeFrame);
         }
         return iLow(Symbol(),TimeFrame,2+shift); 
      }else{return 0.0;}
    }else{
      Print("Please use MODE_UPPER or MODE_LOWER");
      return 0.0;
    }
   
}