//+------------------------------------------------------------------+
//|                                        smLazyHedging TrendOsc_vX
//+------------------------------------------------------------------+
#property copyright "Copyright 29.10.2020 SwingMan"
//#property link      "https://www.forexfactory.com/thread/1019505-dave-landrys-swing-trading"
#property strict
#property indicator_separate_window

#property indicator_buffers 5

#property indicator_width1 3
#property indicator_width2 3
#property indicator_width3 3
#property indicator_width4 3
#property indicator_width5 3

#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrOrange
#property indicator_color3 clrSilver
#property indicator_color4 clrDodgerBlue
#property indicator_color5 clrOrange

#property  indicator_level1 0
#property  indicator_levelcolor clrSilver
#property  indicator_levelstyle STYLE_DOT

//-- inputs
//+------------------------------------------------------------------+
enum enTimeFrames
{
   tf_cu  = PERIOD_CURRENT, // Current time frame
   tf_m1  = PERIOD_M1,      // 1 minute
   tf_m5  = PERIOD_M5,      // 5 minutes
   tf_m15 = PERIOD_M15,     // 15 minutes
   tf_m30 = PERIOD_M30,     // 30 minutes
   tf_h1  = PERIOD_H1,      // 1 hour
   tf_h4  = PERIOD_H4,      // 4 hours
   tf_d1  = PERIOD_D1,      // Daily
   tf_w1  = PERIOD_W1,      // Weekly
   tf_mn1 = PERIOD_MN1,     // Monthly
   tf_n1  = -1,             // First higher time frame
   tf_n2  = -2,             // Second higher time frame
   tf_n3  = -3              // Third higher time frame
};

extern enTimeFrames      TimeFrame         = tf_cu; 
sinput string ____Averages="---------------------------------------";
input int Average_Highs_Period   =10;
input int Average_Lows_Period    =8;
input int Average_Shift          =0;
input ENUM_MA_METHOD Average_Method  = MODE_SMA;
input bool           ArrowOnFirst    = true;      // Arrow/Dot on first mtf bar


//sinput string ____Periods="---------------------------------------";
//input int Period_Average_Fast              =10;
//input int Period_Average_Middle            =20;
//input int Period_Average_Slowly            =30;
//sinput string ____Methods="---------------------------------------";
//input ENUM_MA_METHOD Method_Average_Fast   =MODE_SMA;
//input ENUM_MA_METHOD Method_Average_Middle =MODE_EMA;
//input ENUM_MA_METHOD Method_Average_Slowly =MODE_EMA;
//sinput string ____Applied_Price="---------------------------------------";
//input ENUM_APPLIED_PRICE MovingAverage_Price=PRICE_MEDIAN;
//input bool Show_Comment =true;

//input string ____Drawing_Parameters="---------------------------------------";
//input bool Draw_Areas       =true;
//input color Color_UP_Trend  =clrAliceBlue;
//input color Color_DOWN_Trend=clrMistyRose;
//+------------------------------------------------------------------+

//---- constants
string CR="\n";
//string sObj="arProper_";


//---- buffers
double avgHighs[],avgLows[],trendUP[],trendDN[],circleUP[],circleDN[],count[];

//---- variables
int limit;
int firstBarUP,lastBarUP;
int firstBarDN,lastBarDN;
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,tf_cu,"",Average_Highs_Period,Average_Lows_Period,Average_Shift,Average_Shift,_buff,_ind)

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//IndicatorBuffers(8);
//---
   SetIndexBuffer(0,trendUP);
   SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexLabel(0,"UP-Trend");

   SetIndexBuffer(1,trendDN);
   SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexLabel(1,"DOWN-Trend");

//SetIndexBuffer(2,trendNO);
//SetIndexStyle(2,DRAW_HISTOGRAM);
//SetIndexLabel(2,"NULL-Trend");

   SetIndexBuffer(3,circleUP);
   SetIndexStyle(3,DRAW_ARROW);
   SetIndexArrow(3,159);
   SetIndexLabel(3,NULL);

   SetIndexBuffer(4,circleDN);
   SetIndexStyle(4,DRAW_ARROW);
   SetIndexArrow(4,159);
   SetIndexLabel(4,NULL);


//--- more buffers
   IndicatorBuffers(8);
   SetIndexBuffer(5,avgHighs);
   SetIndexBuffer(6,avgLows);
   SetIndexBuffer(7,count);
//---

   int firstBar=Average_Highs_Period;
   SetIndexDrawBegin(0,firstBar);
   SetIndexDrawBegin(1,firstBar);
   SetIndexDrawBegin(2,firstBar);

   SetIndexEmptyValue(0,EMPTY_VALUE);
   SetIndexEmptyValue(1,EMPTY_VALUE);
   SetIndexEmptyValue(2,EMPTY_VALUE);
//---

   
//---
   IndicatorDigits(0);
   indicatorFileName = WindowExpertName();
   TimeFrame         = (enTimeFrames)timeFrameValue(TimeFrame);
   
   string sName=WindowExpertName()+ "  "+timeFrameToString(TimeFrame)+" ("+
                (string)Average_Highs_Period+","+(string)Average_Lows_Period+","+(string)Average_Shift+") ";
   IndicatorShortName(sName);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){}
//+------------------------------------------------------------------+
//| 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 counted_bars=IndicatorCounted();
   if(counted_bars < 0)
      return(-1);
   if(counted_bars>0)
      counted_bars--;
   limit=Bars-counted_bars;
   if(counted_bars==0)
      limit-=Average_Highs_Period+1; count[0] = limit;
         
         //
         //
         //
         
         if (TimeFrame != _Period)
         {
            limit = (int)MathMax(limit,MathMin(Bars-1,_mtfCall(7,0)*TimeFrame/_Period));
            for(int i=limit; i>=0 && !_StopFlag; i--)
            {
               int y = iBarShift(NULL,TimeFrame,Time[i]);
               int x = y;
               if (ArrowOnFirst)
                     {  if (i<Bars-1) x = iBarShift(NULL,TimeFrame,Time[i+1]);               }
               else  {  if (i>0)      x = iBarShift(NULL,TimeFrame,Time[i-1]); else x = -1;  }
                  trendUP[i]  = _mtfCall(0,y);
                  trendDN[i]  = _mtfCall(1,y);
                  circleUP[i] = circleDN[i] = EMPTY_VALUE;
                  if (x!=y)
                  {
                     circleUP[i] = _mtfCall(3,y);
                     circleDN[i] = _mtfCall(4,y);
                  }       
         }
   return(rates_total);
   }  

//if(limit<Average_Highs_Period)
//   limit=Average_Highs_Period;
//---
//--- Moving Averages -------------------------------------
   for(int i=limit; i>=0; i--)
     {
      avgHighs[i]=iMA(Symbol(),Period(),Average_Highs_Period,Average_Shift,Average_Method,PRICE_HIGH,i);
      avgLows[i] =iMA(Symbol(),Period(),Average_Lows_Period,Average_Shift,Average_Method,PRICE_LOW,i);
     }

   Get_TrendChannel();

//--- Histograms ------------------------------------------
   for(int i=limit; i>=0; i--)
     {
      //--- UP-Trend
      if(trendUP[i]==1)
        {
         circleUP[i]=0;
         circleDN[i]=EMPTY_VALUE;
        }
      else
         if(trendDN[i]==-1)
           {
            circleUP[i]=EMPTY_VALUE;
            circleDN[i]=0;
           }
         else
           {
            circleUP[i]=EMPTY_VALUE;
            circleDN[i]=EMPTY_VALUE;
           }
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Get_TrendChannel()
  {
   bool bodyAbove=false;
   bool bodyBelow=false;

   for(int i=limit; i>=0; i--)
     {
      trendUP[i]=EMPTY_VALUE;
      trendDN[i]=EMPTY_VALUE;

      bodyAbove=(Open[i]>avgHighs[i] && Close[i]>avgHighs[i]);
      bodyBelow=(Open[i]<avgLows[i] && Close[i]<avgLows[i]);

      //=============================================================
      //--- UP-Trend ------------------------------------------------
      if(bodyAbove==true && trendUP[i+1]==EMPTY_VALUE)
        {
         trendUP[i]=1;
         trendDN[i]=EMPTY_VALUE;
        }
      else
         if(bodyAbove==true && trendUP[i+1]!=EMPTY_VALUE)
           {
            trendUP[i]=trendUP[i+1]+1;
            trendDN[i]=EMPTY_VALUE;
           }

      //=============================================================
      //--- DOWN-Trend ----------------------------------------------
      if(bodyBelow==true && trendDN[i+1]==EMPTY_VALUE)
        {
         trendDN[i]=-1;
         trendUP[i]=EMPTY_VALUE;
        }
      else
         if(bodyBelow==true && trendDN[i+1]!=EMPTY_VALUE)
           {
            trendDN[i]=trendDN[i+1]-1;
            trendUP[i]=EMPTY_VALUE;
           }

      //=============================================================
      //--- CONTINUATION-Trend --------------------------------------
      if(bodyAbove==false && bodyBelow==false)
        {
         if(trendUP[i+1]!=EMPTY_VALUE && trendDN[i+1]==EMPTY_VALUE)
            trendUP[i]=trendUP[i+1]+1;
         else
            if(trendUP[i+1]==EMPTY_VALUE && trendDN[i+1]!=EMPTY_VALUE)
               trendDN[i]=trendDN[i+1]-1;
        }

     }
  }
//+------------------------------------------------------------------+
//-------------------------------------------------------------------
//
//-------------------------------------------------------------------

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}
int timeFrameValue(int _tf)
{
   int add  = (_tf>=0) ? 0 : fabs(_tf);
   if (add != 0) _tf = _Period;
   int size = ArraySize(iTfTable); 
      int i =0; for (;i<size; i++) if (iTfTable[i]==_tf) break;
                                   if (i==size) return(_Period);
                                                return(iTfTable[(int)fmin(i+add,size-1)]);
}



