Colour change sma with a lookback period

 
Hello, I am still looking for a solution to the below if anyone can help? The indicator is a colour change moving average so if the ma is higher than it was on the last candle then it will change colour to lime and down to red. I would like to introduce a "lookback" period to this so that it looks back 30 candles to decide whether it is higher or lower. This smooths out a lot of the brief colour changes. I think I can see the part of the code where it compares the last two candles but nothing I do to it will work, the ma's just disappear off the chart. I'm guessing that when I add the 30 lookback it is trying to look for data at the extreme left that doesn't exist. If that's the case then I need to start the indicator reference from something like rates_total - 30 but I'm struggling with it to be honest. Any help would be gratefully appreciated.
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots   1

#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrLimeGreen,clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

enum enMATypes
{
   _sma,    // Simple 
   _ema,    // Exponential 
   _smma,   // Smoothed 
   _lwma    // Linear weighted 
};

input int                  MaPeriod    = 100;           // Period    
input enMATypes            MaMethod    = _sma;      // Method   
input ENUM_APPLIED_PRICE   Price       = PRICE_CLOSE;    // Price
input int lookback = 30;

double MaBuffer[];
double ColorBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
    SetIndexBuffer(0,MaBuffer,INDICATOR_DATA);
    SetIndexBuffer(1,ColorBuffer,INDICATOR_COLOR_INDEX);
    IndicatorSetString(INDICATOR_SHORTNAME,shortName(MaMethod));
//---
   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 &TickVolume[],
                const long &Volume[],
                const int &Spread[])
  {
      int i=(int)MathMax(prev_calculated-1,0);for (; i<rates_total && !IsStopped(); i++)
      {
         double price = getPrice(Price,open,close,high,low,i,rates_total,0);
         MaBuffer[i] = iCustomMa(MaMethod,price,MaPeriod,rates_total,i);
         
          if (i>0)
         {
            ColorBuffer[i] = ColorBuffer[i-1];
               if (MaBuffer[i]>MaBuffer[i-1]) {ColorBuffer[i]=0;}
               if (MaBuffer[i]<MaBuffer[i-1]) {ColorBuffer[i]=1; }
         } else ColorBuffer[i]=0;
      }
   
   return(rates_total);
  }
//+------------------------------------------------------------------+
string shortName(int mode)
{
      switch(mode)
     {
      case _sma   : return "Simple MA ("+(string)MaPeriod+")";
      case _ema   : return "Exponential MA ("+(string)MaPeriod+")";
      case _smma  : return "Smoothed MA ("+(string)MaPeriod+")";
      case _lwma  : return "Linear weighted  MA ("+(string)MaPeriod+")";
      default       : return "Moving Average ("+(string)MaPeriod+")";
     }
}
double iCustomMa(int mode,double price,int period,int bars,int r)
  {
   switch(mode)
     {
      case _sma   : return(iSMA(price,period,bars,r));
      case _ema   : return(iEMA(price,period,bars,r));
      case _smma  : return(iSMMA(price,period,bars,r));
      case _lwma  : return(iLWMA(price,period,bars,r));
      default       : return(price);
     }
  }
  
  
double  maArray[];
double iSMA(double price, int period, int bars, int r)
{
   if (ArraySize(maArray)!=bars) ArrayResize(maArray,bars); 
   
   maArray[r] = price;

   double avg = price; 
    int k=1;
   for(; k<period && (r-k)>=0; k++) 
      avg += maArray[r-k];
   
   return(avg/(double)k);
}

double iEMA(double price,double period,int bars, int r)
  {
   if (ArraySize(maArray)!=bars) ArrayResize(maArray,bars); 
   maArray[r]=price;
   if(r>0 && period>1)
      maArray[r]=maArray[r-1]+(2.0/(1.0+period))*(price-maArray[r-1]);
      
   return(maArray[r]);
  }
  
  double iSMMA(double price,double period,int bars, int r)
  {
   if (ArraySize(maArray)!=bars) ArrayResize(maArray,bars); 

   maArray[r]=price;
   if(r>1 && period>1)
      maArray[r]=maArray[r-1]+(price-maArray[r-1])/period;
      
   return(maArray[r]);
  }
  
double iLWMA(double price,double period,int bars, int r)
  {
   if (ArraySize(maArray)!=bars) ArrayResize(maArray,bars); 


   maArray[r] = 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*maArray[r-k];
     }
   return(sum/sumw);
  }  

//
double getPrice(ENUM_APPLIED_PRICE  tprice,const double &open[],const double &close[],const double &high[],const double &low[],int i,int _bars,int instanceNo=0)
  {
   switch(tprice)
   {
         case PRICE_CLOSE:     return(close[i]);
         case PRICE_OPEN:      return(open[i]);
         case PRICE_HIGH:      return(high[i]);
         case PRICE_LOW:       return(low[i]);
         case PRICE_MEDIAN:    return((high[i]+low[i])/2.0);
         case PRICE_TYPICAL:   return((high[i]+low[i]+close[i])/3.0);
         case PRICE_WEIGHTED:  return((high[i]+low[i]+close[i]+close[i])/4.0);
   }
   return(0);
  }
 
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   const int toCopy=(rates_total==prev_calculated)?1:rates_total-prev_calculated;
   if(CopyBuffer(handle,0,0,toCopy,MABuffer)!=toCopy)
      return(0);
//---
   const int limit=(rates_total==prev_calculated)?prev_calculated-1:(!prev_calculated)?Period+Lookback:prev_calculated;
   for(int i=limit;i<rates_total;i++)
      MAColors[i]=(MABuffer[i]>MABuffer[i-Lookback])?0:(MABuffer[i]<MABuffer[i-Lookback])?1:2;
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
Files:
MA_Color.mq5  3 kb
 
Ernst Van Der Merwe:
Thank you, I can sort of see what you did there, I will attempt to implent it into the code.
 
@Ernst Van Der Merwe That's absolutely perfect! Thank you very much.
 

Forum on trading, automated trading systems and testing trading strategies

Showing color iMA using iCustom, is this the solution?

Vladimir Karputov, 2020.08.17 15:28

MA Color N Bars


Indicator idea

The iMA (Moving Average, MA) indicator on the ' MA: trend N Bars ' segment will define the trend. DRAW_COLOR_LINE paints the indicator in three colors using the graphical plotting style. The first color - the trend is not defined, the second - the uptrend and the third - the downward trend.

MA Color N Bars

Figure: 1. MA Color N Bars

The indicator allows you to more visually highlight trend areas.


 
Vladimir Karputov:

Thank you, I've seen that one but I didn't like it as much.

Reason: