//+------------------------------------------------------------------+
//|                                      sm3BarFractalBreak-BoJack vX
//+------------------------------------------------------------------+
#property copyright "Copyright 01.04.2020, SwingMan"
#property strict

#property description "Idea: bojack34"
#property description "https://www.forexfactory.com/showthread.php?p=12850124#post12850124"

/*--------------------------------------------------------------------
Source: sm3BarFractalBreak v2.0
01.04.2020  - v1.0   -  first version

--------------------------------------------------------------------*/

#property indicator_chart_window

#property indicator_buffers 4

#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrRed
#property indicator_color3 clrDodgerBlue
#property indicator_color4 clrRed

#property indicator_width1 0
#property indicator_width2 0

#property indicator_width3 1
#property indicator_width4 1

//------- external parameters ---------------------------------------+
input bool Draw_Fractal_Arrows=false;
input int  Line_Width   =3;
input bool Show_Comment =true;
//+------------------------------------------------------------------+

//---- constants
string CR="\n";
string sObj="3BarBJ_";

//---- buffers
double arrowUP[],arrowDN[];
double arrowFractalUP[],arrowFractalDN[];

//---- variables
datetime thisTime,oldTime;
bool newBar;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorDigits(Digits);
   int iArrowSignal=164;
   int iArrowFractal=159;

   int iBuff=-1;
//--- indicator buffers mapping
   iBuff++; //0
   SetIndexBuffer(iBuff,arrowUP);
   SetIndexStyle(iBuff,DRAW_ARROW);
   SetIndexArrow(iBuff,iArrowSignal);
   SetIndexLabel(iBuff,"high UP");

   iBuff++;  //1
   SetIndexBuffer(iBuff,arrowDN);
   SetIndexStyle(iBuff,DRAW_ARROW);
   SetIndexArrow(iBuff,iArrowSignal);
   SetIndexLabel(iBuff,"low DOWN");

   iBuff++; //2
   SetIndexBuffer(iBuff,arrowFractalUP);
   SetIndexStyle(iBuff,DRAW_ARROW);
   SetIndexArrow(iBuff,iArrowFractal);
   SetIndexLabel(iBuff,"fractal UP");

   iBuff++;  //3
   SetIndexBuffer(iBuff,arrowFractalDN);
   SetIndexStyle(iBuff,DRAW_ARROW);
   SetIndexArrow(iBuff,iArrowFractal);
   SetIndexLabel(iBuff,"fractal DOWN");

//---
   ChartSetInteger(0,CHART_SHOW_OBJECT_DESCR,false);
   ChartSetInteger(0,CHART_SHOW_GRID,false);

   ObjectsDeleteAll(0,sObj);
//---
   if(Show_Comment==true)
      Comment(WindowExpertName(),CR,
              "====================");
//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(Show_Comment==true)
      Comment("");
   ObjectsDeleteAll(0,sObj);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],const double &open[],const double &high[],
                const double &low[],const double &close[],const long &tick_volume[],const long &volume[],const int &spread[])
  {
//---
   int limit=rates_total-prev_calculated;
//---
   if(rates_total<=10)
      return(0);
   if(prev_calculated==0)
      limit=limit-20;

   if(prev_calculated>0)
      limit++;
   if(limit<5)
      limit=5;

//=========================================================
   int      period=Period();

   double close1;
   double low1,low2,low3;
   double high1,high2,high3;
   bool isFractalUP,isFractalDN;
   bool buyCondition,sellCondition;

   for(int i=limit; i>=0; i--)
     {
      //---- new bar    -----------------------------------------
      thisTime=Time[i];
      if(thisTime!=oldTime)
        {
         oldTime=thisTime;
         newBar=true;
        }
      else
         newBar=false;

      //--- prices ----------------------------------------
      close1=NormalizeDouble(iClose(Symbol(),period,i+1),Digits);
      low1=NormalizeDouble(iLow(Symbol(),period,i+1),Digits);
      low2=NormalizeDouble(iLow(Symbol(),period,i+2),Digits);
      low3=NormalizeDouble(iLow(Symbol(),period,i+3),Digits);

      high1=NormalizeDouble(iHigh(Symbol(),period,i+1),Digits);
      high2=NormalizeDouble(iHigh(Symbol(),period,i+2),Digits);
      high3=NormalizeDouble(iHigh(Symbol(),period,i+3),Digits);

      //===================================================
      //--- fractals 1-1 ----------------------------------
      isFractalUP=false;
      isFractalDN=false;


      if(high3<high2 && high1<high2)
        {
         isFractalUP=true;
         if(Draw_Fractal_Arrows==true)
            arrowFractalUP[i+2]=High[i+2];
        }
      if(low3>low2 && low1>low2)
        {
         isFractalDN=true;
         if(Draw_Fractal_Arrows==true)
            arrowFractalDN[i+2]=Low[i+2];
        }


      //===================================================
      //--- signal bars -----------------------------------
      buyCondition =(isFractalDN==true && close1>high2 && close1>high3);
      sellCondition=(isFractalUP==true && close1<low2 && close1<low3);

      if(buyCondition==true)
        {
         arrowUP[i+1]=High[i+1];
         Draw_ShortTrendLine(i,high1,indicator_color1,Line_Width);
        }
      else
         if(sellCondition==true)
           {
            arrowDN[i+1]=Low[i+1];
            Draw_ShortTrendLine(i,low1,indicator_color2,Line_Width);
           }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//                **********************************
//                         FUNCTIONS
//                **********************************
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Draw_ShortTrendLine(int iBar,double value,color dColor,int iWidth)
  {
   string objName=sObj+TimeToString(Time[iBar+1]);
   ObjectDelete(objName);

   ObjectCreate(0,objName,OBJ_TREND,0,Time[iBar+1],value,Time[iBar-1],value);
   ObjectSetInteger(0,objName,OBJPROP_COLOR,dColor);
   ObjectSetInteger(0,objName,OBJPROP_WIDTH,iWidth);
   ObjectSetInteger(0,objName,OBJPROP_RAY,false);
   ObjectSetInteger(0,objName,OBJPROP_HIDDEN,true);
  }
//+------------------------------------------------------------------+
