Adding extra lines to a custom MA

 

I'd like the ability to add lines a certain number of pips from the MA line, like the below image, but I don't know how.

Extra MA lines


I've written the code (below) for the colour-changing MA, but I'm hoping someone would help me add the extra lines 200 pips from the MA in either direction.

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_plots 1

//---- plot ColorLine
#property indicator_label1  "MALine"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrBlack,clrOrange,clrCornflowerBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  4

#define PLOT_MAXIMUM_BARS_BACK 5000
#define OMIT_OLDEST_BARS 50

//--- FOR EXPLANATIONS OF THESE INPUTS, SEE COMMENTS IN FOOTER -------
input int MovingAverage = 60;
input ENUM_MA_METHOD MA_Method=MODE_SMA;
input ENUM_APPLIED_PRICE MA_Price=PRICE_CLOSE;

//--- indicator buffers
double MALineBuffer[];
double ColourBuffer[];
double myPoint; //initialized in OnInit
double Close[];
int MA_handle;
double MA[];
double Open[];
double Low[];
int ATR_handle;
double ATR[];
double High[];

//--- Custom functions -----------------------------------------------

double Point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

//--- End of custom functions ----------------------------------------

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | PBItest @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   SetIndexBuffer(0,MALineBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ColourBuffer,INDICATOR_COLOR_INDEX);

   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
     }
   MA_handle = iMA(NULL, PERIOD_CURRENT, MovingAverage, 0, MODE_SMA, PRICE_CLOSE);
   if(MA_handle < 0)
     {
      Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   ATR_handle = iATR(NULL, PERIOD_CURRENT, 16);
   if(ATR_handle < 0)
     {
      Print("The creation of iATR has failed: ATR_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   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 limit = rates_total - prev_calculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(MALineBuffer, true);
   ArraySetAsSeries(ColourBuffer, true);
   //--- initial zero
   if(prev_calculated < 1)
     {
      ArrayInitialize(MALineBuffer, EMPTY_VALUE);
      ArrayInitialize(ColourBuffer, EMPTY_VALUE);
     }
   else
      limit++;
   
   if(CopyClose(Symbol(), PERIOD_CURRENT, 0, rates_total, Close) <= 0) return(rates_total);
   ArraySetAsSeries(Close, true);
   if(BarsCalculated(MA_handle) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
   ArraySetAsSeries(MA, true);
   if(CopyOpen(Symbol(), PERIOD_CURRENT, 0, rates_total, Open) <= 0) return(rates_total);
   ArraySetAsSeries(Open, true);
   if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
   ArraySetAsSeries(Low, true);
   if(BarsCalculated(ATR_handle) <= 0) 
      return(0);
   if(CopyBuffer(ATR_handle, 0, 0, rates_total, ATR) <= 0) return(rates_total);
   ArraySetAsSeries(ATR, true);
   if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
   ArraySetAsSeries(High, true);
   
   //--- copy values of MA into indicator buffer MALineBuffer
   int copied=CopyBuffer(MA_handle,0,0,rates_total,MALineBuffer);
   if(copied<=0) return(0);// copying failed - throw away
   
   //Print ("rates total ",rates_total," prev_calc ",prev_calculated," limit ",limit," copied ", copied);

   //--- main loop
   for(int i = limit-1; i >= 0; i--)
     {
      if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
      
      //--- now set line color for every bar
         if (MALineBuffer [i-1] == MALineBuffer [i])
            ColourBuffer[i] = 0;
            else
            if (MALineBuffer [i-1] < MALineBuffer [i])
               ColourBuffer[i] = 1;
               else
               ColourBuffer[i] = 2;

     }
   return(rates_total);
  }

 
You need to create 2 new buffers and assign their values into the "main loop" you have in your code.

One buffer will have value of MABufferLine + x pips
Other one will have MABufferLine - x pips 
 
Fabio Cavalloni #:
You need to create 2 new buffers and assign their values into the "main loop" you have in your code.

One buffer will have value of MABufferLine + x pips
Other one will have MABufferLine - x pips 

Thank you. I thought I'd start by just adding the upper grey line. I've added what I thought it needed, but the line isn't drawing. I'm not getting any compile errors either.

Please let me know what I'm missing.

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 2

//---- plot ColorLine
#property indicator_label1  "MALine"
#property indicator_type1   DRAW_COLOR_LINE
#property indicator_color1  clrBlack,clrOrange,clrCornflowerBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  4

//---- plot GreyLines
#property indicator_label2  "UpperLine"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrGray
#property indicator_style2  STYLE_DASH
#property indicator_width2  1

#define PLOT_MAXIMUM_BARS_BACK 5000
#define OMIT_OLDEST_BARS 50

//--- INPUTS
input int MovingAverage = 60;
input double ExtraPips = 200;
input ENUM_MA_METHOD MA_Method = MODE_SMA;
input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE;
input bool Draw_Extra_Lines = true;

//--- indicator buffers
double MALineBuffer[];
double ColourBuffer[];
double MA_UpperBuffer[];
double myPoint; //initialized in OnInit
double Close[];
int MA_handle;
double MA[];
double Open[];
double Low[];
int ATR_handle;
double ATR[];
double High[];

//--- Custom functions -----------------------------------------------

double Point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

//--- End of custom functions ----------------------------------------

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | PBItest @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {   
   SetIndexBuffer(0,MALineBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,ColourBuffer,INDICATOR_COLOR_INDEX);
   SetIndexBuffer(2,MA_UpperBuffer,INDICATOR_DATA);

   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
     }
   MA_handle = iMA(NULL, PERIOD_CURRENT, MovingAverage, 0, MODE_SMA, PRICE_CLOSE);
   if(MA_handle < 0)
     {
      Print("The creation of iMA has failed: MA_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   ATR_handle = iATR(NULL, PERIOD_CURRENT, 16);
   if(ATR_handle < 0)
     {
      Print("The creation of iATR has failed: ATR_handle=", INVALID_HANDLE);
      Print("Runtime error = ", GetLastError());
      return(INIT_FAILED);
     }
   
   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 limit = rates_total - prev_calculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(MALineBuffer, true);
   ArraySetAsSeries(ColourBuffer, true);
   ArraySetAsSeries(MA_UpperBuffer, true);
   //--- initial zero
   if(prev_calculated < 1)
     {
      ArrayInitialize(MALineBuffer, EMPTY_VALUE);
      ArrayInitialize(ColourBuffer, EMPTY_VALUE);
      ArrayInitialize(MA_UpperBuffer, EMPTY_VALUE);
     }
   else
      limit++;
   
   if(CopyClose(Symbol(), PERIOD_CURRENT, 0, rates_total, Close) <= 0) return(rates_total);
   ArraySetAsSeries(Close, true);
   if(BarsCalculated(MA_handle) <= 0) 
      return(0);
   if(CopyBuffer(MA_handle, 0, 0, rates_total, MA) <= 0) return(rates_total);
   ArraySetAsSeries(MA, true);
   if(CopyOpen(Symbol(), PERIOD_CURRENT, 0, rates_total, Open) <= 0) return(rates_total);
   ArraySetAsSeries(Open, true);
   if(CopyLow(Symbol(), PERIOD_CURRENT, 0, rates_total, Low) <= 0) return(rates_total);
   ArraySetAsSeries(Low, true);
   if(BarsCalculated(ATR_handle) <= 0) 
      return(0);
   if(CopyBuffer(ATR_handle, 0, 0, rates_total, ATR) <= 0) return(rates_total);
   ArraySetAsSeries(ATR, true);
   if(CopyHigh(Symbol(), PERIOD_CURRENT, 0, rates_total, High) <= 0) return(rates_total);
   ArraySetAsSeries(High, true);
   
   //--- copy values of MA into indicator buffer MALineBuffer
   int copied=CopyBuffer(MA_handle,0,0,rates_total,MALineBuffer);
   if(copied<=0) return(0);// copying failed - throw away
   
   //Print ("rates total ",rates_total," prev_calc ",prev_calculated," limit ",limit," copied ", copied);

   //--- main loop
   for(int i = limit-1; i >= 0; i--)
     {
      if (i >= MathMin(PLOT_MAXIMUM_BARS_BACK-1, rates_total-1-OMIT_OLDEST_BARS)) continue; //omit some old rates to prevent "Array out of range" or slow calculation   
      
      //--- now set line color for every bar
         if (MALineBuffer [i-1] == MALineBuffer [i])
            ColourBuffer[i] = 0;
            else
            if (MALineBuffer [i-1] < MALineBuffer [i])
               ColourBuffer[i] = 1;
               else
               ColourBuffer[i] = 2;
      //--- now set upper line for every bar
         if (Draw_Extra_Lines == true)
            MA_UpperBuffer[i] = MALineBuffer[i] + ExtraPips;
            else
            if (Draw_Extra_Lines == false)
               continue;

     }
   return(rates_total);
  }

 

Hi

You did well, but you haven’t multiplied the distance by point value. Simply change the line with UpperBuffer calculation to this:

MA_UpperBuffer[i] = MALineBuffer[i] + ExtraPips*_Point;

Have a nice day👍📊

 
Marzena Maria Szmit #:

Hi

You did well, but you haven’t multiplied the distance by point value. Simply change the line with UpperBuffer calculation to this:

Have a nice day👍📊

Thank you so much, Marzena. That's done the trick. I'm extremely grateful.