//+------------------------------------------------------------------+
//|                                       smTMMS Oscillator_vX
//+------------------------------------------------------------------+
#property copyright "Copyright 30.06.2019, SwingMan"
#property strict
#property indicator_separate_window

#property indicator_buffers 8

#property indicator_color1 clrSienna      //lines
#property indicator_color2 clrLime
#property indicator_color3 clrSlateGray 
#property indicator_color4 clrGreen       //histograms
#property indicator_color5 clrRed
#property indicator_color6 clrDarkGray
#property indicator_color7 clrLime        //arrows
#property indicator_color8 clrOrange

#property indicator_width1 1              //lines
#property indicator_width2 1
#property indicator_width3 1
#property indicator_width4 3              //histograms
#property indicator_width5 3
#property indicator_width6 3
#property indicator_width7 1              //arrows
#property indicator_width8 1

#property indicator_level1 20
#property indicator_level2 0
#property indicator_level3 -20
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT
#property indicator_levelwidth 1

#property indicator_maximum 50
#property indicator_minimum -50
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum ENUM_ARROW_TYPE
  {
   Circle,
   Rectangle
  };

//--- inputs
//+------------------------------------------------------------------+
input bool           Draw_Oscillator_Lines=false;
sinput string        sRSI="RSI"; //=================================     
input int            RSI_Period=14;
input ENUM_APPLIED_PRICE      RSI_AppliedPrice=PRICE_CLOSE;
//
sinput string        sStochastic="STOCHASTIC"; //=================================    
input int            Stochastic_1_Period_K  = 8;
input int            Stochastic_1_Period_D  = 3;
input int            Stochastic_1_Slowing   = 3;
input ENUM_STO_PRICE Stochastic_1_PriceField = STO_LOWHIGH;
input ENUM_MA_METHOD Stochastic_1_MAmethod   = MODE_SMMA;
input int            Stochastic_2_Period_K  = 14;
input int            Stochastic_2_Period_D  = 3;
input int            Stochastic_2_Slowing   = 3;
input ENUM_STO_PRICE Stochastic_2_PriceField = STO_LOWHIGH;
input ENUM_MA_METHOD Stochastic_2_MAmethod   = MODE_SMMA;
//
sinput string             sHullAverage="HULL MovingAverage"; //=================================  
input bool                Draw_HullTrend  =true;
input int                 Hull_Period     =12;
input double              Hull_Divisor    =2;
input ENUM_APPLIED_PRICE  Hull_AppliedPrice=PRICE_CLOSE;
input ENUM_ARROW_TYPE     Arrow_Type=Circle;
//+------------------------------------------------------------------+

//---- buffers
double bufRSI[],bufStoch1[],bufStoch2[];
double bufHistUP[],bufHistDN[],bufHistNO[];
double bufHullUP[],bufHullDN[],bufHull[],buffHullAvg[],trend[];
//---

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   int iArrow=108;
//--- indicator buffers mapping
   int iBuff=-1;
//--- lines   
   iBuff++; SetIndexBuffer(iBuff,bufRSI);     SetIndexStyle(iBuff,DRAW_LINE); SetIndexLabel(iBuff,"RSI"); if(Draw_Oscillator_Lines==false) SetIndexStyle(iBuff,DRAW_NONE);
   iBuff++; SetIndexBuffer(iBuff,bufStoch1);  SetIndexStyle(iBuff,DRAW_LINE); SetIndexLabel(iBuff,"Stochastic ("+(string)Stochastic_1_Period_K+")"); if(Draw_Oscillator_Lines==false) SetIndexStyle(iBuff,DRAW_NONE);
   iBuff++; SetIndexBuffer(iBuff,bufStoch2);  SetIndexStyle(iBuff,DRAW_LINE); SetIndexLabel(iBuff,"Stochastic ("+(string)Stochastic_2_Period_K+")");
//--- histograms
   iBuff++; SetIndexBuffer(iBuff,bufHistUP);  SetIndexStyle(iBuff,DRAW_HISTOGRAM);  SetIndexLabel(iBuff,NULL);
   iBuff++; SetIndexBuffer(iBuff,bufHistDN);  SetIndexStyle(iBuff,DRAW_HISTOGRAM);  SetIndexLabel(iBuff,NULL);
   iBuff++; SetIndexBuffer(iBuff,bufHistNO);  SetIndexStyle(iBuff,DRAW_HISTOGRAM);  SetIndexLabel(iBuff,NULL);
//--- arrows - HULL moving average
   if(Arrow_Type==Circle) iArrow=108; else if(Arrow_Type==Rectangle) iArrow=110;
   iBuff++; SetIndexBuffer(iBuff,bufHullUP);  SetIndexStyle(iBuff,DRAW_ARROW); SetIndexArrow(iBuff,iArrow); SetIndexLabel(iBuff,"HMA_Trend UP");   if(Draw_HullTrend==false) SetIndexStyle(iBuff,DRAW_NONE);
   iBuff++; SetIndexBuffer(iBuff,bufHullDN);  SetIndexStyle(iBuff,DRAW_ARROW); SetIndexArrow(iBuff,iArrow); SetIndexLabel(iBuff,"HMA_Trend DOWN"); if(Draw_HullTrend==false) SetIndexStyle(iBuff,DRAW_NONE);

//--- more buffers
   IndicatorBuffers(11);
   iBuff++; SetIndexBuffer(iBuff,bufHull);
   iBuff++; SetIndexBuffer(iBuff,buffHullAvg);
   iBuff++; SetIndexBuffer(iBuff,trend);
//---
   IndicatorDigits(2);
   return(INIT_SUCCEEDED);
  }
//---

//+------------------------------------------------------------------+
//| 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    i,pos;
   double threshold=50,limit=0;

//---
   if(rates_total<=10)
      return(0);

   pos=0;

//--- main loop of calculations
   for(i=pos; i<rates_total; i++)
     {
      //--- oscillators
      bufRSI[i]=iRSI(Symbol(),Period(),RSI_Period,RSI_AppliedPrice,i);
      bufStoch1[i]=iStochastic(Symbol(),Period(),
                               Stochastic_1_Period_K,Stochastic_1_Period_D,Stochastic_1_Slowing,
                               Stochastic_1_MAmethod,Stochastic_1_PriceField,MODE_MAIN,i);
      bufStoch2[i]=iStochastic(Symbol(),Period(),
                               Stochastic_2_Period_K,Stochastic_2_Period_D,Stochastic_2_Slowing,
                               Stochastic_2_MAmethod,Stochastic_2_PriceField,MODE_MAIN,i);
      bufRSI[i]=bufRSI[i]-threshold;
      bufStoch1[i]=bufStoch1[i]-threshold;
      bufStoch2[i]=bufStoch2[i]-threshold;

      //--- histograms
      bufHistUP[i]=EMPTY_VALUE;
      bufHistDN[i]=EMPTY_VALUE;
      bufHistNO[i]=EMPTY_VALUE;
      if(bufRSI[i]>limit && bufStoch1[i]>limit && bufStoch2[i]>limit)
         bufHistUP[i]=bufStoch2[i];
      else
      if(bufRSI[i]<limit && bufStoch1[i]<limit && bufStoch2[i]<limit)
         bufHistDN[i]=bufStoch2[i];
      else
         bufHistNO[i]=bufStoch2[i];
     }

//--- Hull Moving Average   
   if(Draw_HullTrend==true)
      Get_HullMovingAverage(rates_total,bufHullUP,bufHullDN);

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Get_HullMovingAverage(int limitX,double &hullUP[],double &hullDN[])
  {
   double zero=0;
//-- Hull moving average current TF -------------
   int MA_period1=(int)(Hull_Period/Hull_Divisor);
   int pPeriod=(int)MathSqrt(Hull_Period);

   for(int i=0; i<limitX; i++)
      bufHull[i]=2*iMA(Symbol(),Period(),MA_period1,0,MODE_LWMA,Hull_AppliedPrice,i)-
                 iMA(Symbol(),Period(),Hull_Period,0,MODE_LWMA,Hull_AppliedPrice,i);

   for(int i=0; i<limitX-Hull_Period; i++)
      buffHullAvg[i]=iMAOnArray(bufHull,0,pPeriod,0,MODE_LWMA,i);

//-- Arrows Hull moving average trend -----------
   for(int i=limitX-Hull_Period-1; i>=0; i--)
     {
      //trend[i]=trend[i+1];
      if(buffHullAvg[i]>=buffHullAvg[i+1]) trend[i]=1; else trend[i]=-1;

      if(trend[i]>0)
        {
         hullUP[i]=zero;
         hullDN[i]=EMPTY_VALUE;
        }
      else
      if(trend[i]<0)
        {
         hullUP[i]=EMPTY_VALUE;
         hullDN[i]=zero;
        }
     }
  }
//+------------------------------------------------------------------+
