//------------------------------------------------------------------
#property link      "https://howtofxmarkets.web.app/"
#property copyright "https://howtofxmarkets.web.app/ SingleInsideBar by csj179t"
//   - Forex education, mentorship, trading rooms.
//   - Low cost forex broker, high leverage available. With a lot of FREE additional services.
//   - And a Guide-o-FX is a list of FREE useful forex resources.
//------------------------------------------------------------------
#property copyright "www.forex-station.com"
// Many thanks to forex-station.com, to mrtools, mladen
// and other coder helping for free. Special thanks to Jimmy! 
// I got this code template at forex-station:  bars iterator, mtf feature...
// And making my indicators, by editing modifying it.

#property indicator_chart_window
#property indicator_buffers    2




extern ENUM_TIMEFRAMES    TimeFrame       = PERIOD_CURRENT;
input int                 SmoothingPeriod = 14;                    // Smoothing Period
enum  enMaTypes
      {
         ma_sma,                                                 // Simple moving average
         ma_ema,                                                 // Exponential moving average
         ma_smma,                                                // Smoothed MA
         ma_lwma,                                                // Linear weighted MA
      };
input enMaTypes           SmoothingMethod  = ma_ema;               // Smoothing Method
extern color              BullCol          = clrYellow; //clrGreen;
extern color              BearCol          = clrYellow;//clrRed;
extern double             gap              = 0.5;
extern int                upCode           = 164; //241;
extern int                dnCode           = 164; //242
extern bool               Interpolate      = true;

extern string             name = "SingleInsideBar";


double buffer1[];
double buffer2[],linm[],temp[];


string indicatorFileName;
bool   returnBars;

string name2 = name + " " + TimeFrame;



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init()
  {

   IndicatorBuffers(4);
   SetIndexBuffer(0,buffer1); SetIndexStyle(0,DRAW_ARROW,0,0,BullCol); SetIndexArrow(0,upCode);
   SetIndexBuffer(1,buffer2); SetIndexStyle(1,DRAW_ARROW,0,0,BearCol); SetIndexArrow(1,dnCode);
   SetIndexBuffer(2,linm);
   SetIndexBuffer(3,temp);


   indicatorFileName = WindowExpertName();
   returnBars        = TimeFrame==-99;
   TimeFrame         = fmax(TimeFrame,_Period);

   IndicatorShortName(name2);

   return(0);
  }

int deinit(){ return(0); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {



              
              
   int counted_bars=IndicatorCounted();
   int i,limit;


   if(counted_bars < 0)
      return(-1);
   if(counted_bars > 0)
      counted_bars--;
   limit = MathMin(Bars-counted_bars,Bars-1);
   if(returnBars)
     {
      buffer1[0] = limit+1;
      return(0);
     }


   if(TimeFrame == Period())
   {

      for(i=limit; i>=0; i--)
      {
        double atr   = iATR(NULL,0,20,i)* 0.5;  
           temp[i]    = Volume[i]*(Close[i]-Open[i]);
           linm[i]    = iCustomMa(SmoothingMethod,temp[i],SmoothingPeriod,i,Bars); 
           buffer1[i] = linm[i]>0 && Low[i]>Low[i+1] && High[i]<High[i+1] && Close[i]>Open[i] && Close[i+1]<Open[i+1] ?  Low[i] - gap * atr : EMPTY_VALUE;
           buffer2[i] = linm[i]<0 && Low[i]>Low[i+1] && High[i]<High[i+1] && Close[i]<Open[i] && Close[i+1]>Open[i+1] ? High[i] + gap * atr : EMPTY_VALUE;

      }
   return(0);
   }



   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,TimeFrame,indicatorFileName,-99,0,0)*TimeFrame/Period()));
   for(i=limit; i>=0; i--)
    {
      int y = iBarShift(NULL,TimeFrame,Time[i]);

      buffer1[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,SmoothingPeriod,SmoothingMethod,BullCol,BearCol,gap,upCode,dnCode,0,y);
      buffer2[i] = iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,SmoothingPeriod,SmoothingMethod,BullCol,BearCol,gap,upCode,dnCode,1,y);
    
    }
return(0);
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//

string getAvgName(int method)
{
      switch(method)
      {
         case ma_ema:    return("EMA");
         case ma_lwma:   return("LWMA");
         case ma_sma:    return("SMA");
         case ma_smma:   return("SMMA");
      }
return("");      
}

//------------------------------------------------------------------
//                                                                  
//------------------------------------------------------------------
//
//
//
//
//

#define _maInstances 1
#define _maWorkBufferx1 1*_maInstances
#define _maWorkBufferx2 2*_maInstances
#define _maWorkBufferx3 3*_maInstances

double iCustomMa(int mode, double price, double length, int r, int bars, int instanceNo=0)
{
   r = bars-r-1;
   switch (mode)
   {
      case ma_sma   : return(iSma(price,(int)ceil(length),r,bars,instanceNo));
      case ma_ema   : return(iEma(price,length,r,bars,instanceNo));
      case ma_smma  : return(iSmma(price,(int)ceil(length),r,bars,instanceNo));
      case ma_lwma  : return(iLwma(price,(int)ceil(length),r,bars,instanceNo));
      default       : return(price);
   }
}

//
//
//
//
//

double workSma[][_maWorkBufferx1];
double iSma(double price, int period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workSma,0)!= _bars) ArrayResize(workSma,_bars);

   workSma[r][instanceNo+0] = price;
   double avg = price; int k=1;  for(; k<period && (r-k)>=0; k++) avg += workSma[r-k][instanceNo+0];  
   return(avg/(double)k);
}

//
//
//
//
//

double workEma[][_maWorkBufferx1];
double iEma(double price, double period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workEma,0)!= _bars) ArrayResize(workEma,_bars);

   workEma[r][instanceNo] = price;
   if (r>0 && period>1)
          workEma[r][instanceNo] = workEma[r-1][instanceNo]+(2.0/(1.0+period))*(price-workEma[r-1][instanceNo]);
   return(workEma[r][instanceNo]);
}

//
//
//
//
//

double workSmma[][_maWorkBufferx1];
double iSmma(double price, double period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workSmma,0)!= _bars) ArrayResize(workSmma,_bars);

   workSmma[r][instanceNo] = price;
   if (r>1 && period>1)
          workSmma[r][instanceNo] = workSmma[r-1][instanceNo]+(price-workSmma[r-1][instanceNo])/period;
   return(workSmma[r][instanceNo]);
}

//
//
//
//
//

double workLwma[][_maWorkBufferx1];
double iLwma(double price, double period, int r, int _bars, int instanceNo=0)
{
   if (ArrayRange(workLwma,0)!= _bars) ArrayResize(workLwma,_bars);
   
   workLwma[r][instanceNo] = price; if (period<=1) return(price);
      double sumw = period;
      double sum  = period*price;

      for(int k=1; k<period && (r-k)>=0; k++)
      {
         double weight = period-k;
                sumw  += weight;
                sum   += weight*workLwma[r-k][instanceNo];  
      }             
      return(sum/sumw);
}

