MQL4 - My program doesn't work when I use '#properties strict'

 

Hello, I am new to MQL4 programming language and I am trying to write the SuperTrend indicator in Tradingview in mql4. My problem is that when I use the #properties strict code, my program does not work, but when I delete this code, the program runs smoothly. What do you think I should change in my code, can you help me ?
Note: The program works without using 'properties #strict', but will it cause a problem in the future if I run this code without using it?

#property copyright "Copyright © 2022, Ahmet Akçay."
#property link      ""
#property version   "1.00"
//#property strict //Why doesn't the program work when I use this code and how can I fix it?

enum ENUM_ATR_MA_TYPE
{
   ATR_MA_TYPE_SMA=0,// SMA
   ATR_MA_TYPE_EMA=1,// EMA
   ATR_MA_TYPE_SMMA=2,// SMMA
   ATR_MA_TYPE_LWMA=3,// LWMA
};

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2

double TrendUpBuffer[], TrendDownBuffer[], ATRValue[];
int trendup = 0,trenddown = 0;
string MA_Name;
extern int Nbr_Periods = 10; 
extern double Multiplier = 3.0; 
input ENUM_ATR_MA_TYPE ATR_MA_Type = ATR_MA_TYPE_SMMA; 
input ENUM_APPLIED_PRICE Source = PRICE_MEDIAN; 

int OnInit()
  {
   if (ATR_MA_Type == 0)
   {
      MA_Name="SMA";
   }
   else if (ATR_MA_Type == 1)
   {
      MA_Name="EMA";
   }
   else if (ATR_MA_Type == 2)
   {
      MA_Name="SMMA";
   }
   else if (ATR_MA_Type == 3)
   {
      MA_Name="LWMA";
   }
   
   IndicatorDigits(Digits);
   IndicatorBuffers(3);
   SetIndexBuffer(0, TrendUpBuffer);
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(0, "ST Up"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexBuffer(1, TrendDownBuffer);
   SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(1, "ST Down"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(2,ATRValue);
   
   return(INIT_SUCCEEDED);
  }

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;
   double up[], down[], SourcePrice, atr, prev_up, prev_down;
   
   int xsize = ArraySize(ATRValue);
   
   ArrayResize(up,xsize);
   ArrayResize(down,xsize);
      
   for(i = rates_total; i >= 0; i--) 
   {
      ATRValue[i] = iATR(NULL, 0, 1, i);
   }
      
   for(i = rates_total; i >= 0; i--)
   {    
      if (ATR_MA_Type == 0)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_SMA,i);
      }
      else if (ATR_MA_Type == 1)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_EMA,i);
      }
      else if (ATR_MA_Type == 2)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_SMMA,i);
      }
      else if (ATR_MA_Type == 3)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_LWMA,i);
      }
      
      if(Source == 0)SourcePrice = Close[i];
      if(Source == 1)SourcePrice = Open[i];
      if(Source == 2)SourcePrice = High[i];
      if(Source == 3)SourcePrice = Low[i];
      if(Source == 4)SourcePrice = (High[i]+Low[i])/2;
      if(Source == 5)SourcePrice = (High[i]+Low[i]+Close[i])/3;
      if(Source == 6)SourcePrice = (High[i]+Low[i]+Close[i]+Close[i])/4;
      
      up[i] = SourcePrice - (Multiplier * atr);
      prev_up = up[i+1];

      if(Close[i] > prev_up){up[i] = MathMax(up[i],prev_up);}
      
      down[i] = SourcePrice + (Multiplier * atr);
      prev_down = down[i+1];

      if(Close[i] < prev_down){down[i] = MathMin(down[i],prev_down);}
      
      if(Close[i] > prev_down && trendup != 1)
      {
         trendup = 1;
         trenddown = 0;
      }
      if(Close[i] < prev_up && trenddown != -1)
      {
         trenddown = -1;
         trendup = 0;
      }
      
      if(trendup == 0) {TrendUpBuffer[i] = EMPTY_VALUE;}   
      if(trendup == 1){TrendUpBuffer[i] = up[i];}
      if(trenddown == 0){TrendDownBuffer[i] = EMPTY_VALUE;}
      if(trenddown == -1){TrendDownBuffer[i] = down[i];}
         
   }
   WindowRedraw();
      
   return(rates_total);
  }
 
  1. Always use strict. Fixing the warnings will save you hours of debugging, but you must understand the differences.


  2.    for(i = rates_total; i >= 0; i--) 
       {
          ATRValue[i] = iATR(NULL, 0, 1, i);

    The buffer has rates_total values. The indexes are then [0 … rates_total-1]. What are you accessing?

 
William Roeder #:
  1. Always use strict. Fixing the warnings will save you hours of debugging, but you must understand the differences.


  2. The buffer has rates_total values. The indexes are then [0 … rates_total-1]. What are you accessing?

Hello, the default moving average method in the ATR indicator in tradingview is RMA (However, it produces the same value as SMMA in MQL4). However, since the moving average method used for ATR in MQL4 is not changed, I assign the 1 period ATR value to an array and then take the moving average of this array. As I said, I am very new to the MQL4 programming language, but I understand that the problem is in the arrays. When I use Strict, the program does not work if there is no data in the previous array. The array I am going to use should not be given a value at the beginning and it should expand as it gets values. I cannot access the previous data of a dynamic array, how can I do this?
 
As William Roeder mentioned above – use strict always.
Here I believe the problem is with array ranges – in the code you didn’t check if there are enough elements in the array to call. So you simply need to change all loops to be going from rates_total-1 (not rates total) :
   for(i = rates_total-1; i >= 0; i--)
and before calling array elements you need to be sure that it’s smaller than their size (so add in line 114:
if(i+1<ArraySize(down))prev_down = down[i+1];
and  119:
if(i+1<ArraySize(down))prev_down = down[i+1];
 
Marzena Maria Szmit #:
As William Roeder mentioned above – use strict always.
Here I believe the problem is with array ranges – in the code you didn’t check if there are enough elements in the array to call. So you simply need to change all loops to be going from rates_total-1 (not rates total) :
   for(i = rates_total-1; i >= 0; i--)
and before calling array elements you need to be sure that it’s smaller than their size (so add in line 114:
if(i+1<ArraySize(down))prev_down = down[i+1];
and  119:
if(i+1<ArraySize(down))prev_down = down[i+1];

Thank you very much, now it works perfectly.
For those who need a SuperTrend indicator like the one in Tradingview in Metatrader, I am republishing the code of the project here;

#property copyright "Copyright © 2022, Ahmet Akçay."
#property link      ""
#property version   "1.00"
#property strict

enum ENUM_ATR_MA_TYPE
{
   ATR_MA_TYPE_SMA=0,// SMA
   ATR_MA_TYPE_EMA=1,// EMA
   ATR_MA_TYPE_SMMA=2,// SMMA
   ATR_MA_TYPE_LWMA=3,// LWMA
};

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2

double TrendUpBuffer[], TrendDownBuffer[], ATRValue[];
int trendup = 0,trenddown = 0;
string MA_Name;
extern int Nbr_Periods = 10; 
extern double Multiplier = 3.0; 
input ENUM_ATR_MA_TYPE ATR_MA_Type = ATR_MA_TYPE_SMMA; 
input ENUM_APPLIED_PRICE Source = PRICE_MEDIAN; 

int OnInit()
  {
   if (ATR_MA_Type == 0)
   {
      MA_Name="SMA";
   }
   else if (ATR_MA_Type == 1)
   {
      MA_Name="EMA";
   }
   else if (ATR_MA_Type == 2)
   {
      MA_Name="SMMA";
   }
   else if (ATR_MA_Type == 3)
   {
      MA_Name="LWMA";
   }
   
   IndicatorDigits(Digits);
   IndicatorBuffers(3);
   SetIndexBuffer(0, TrendUpBuffer);
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(0, "ST Up"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexBuffer(1, TrendDownBuffer);
   SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(1, "ST Down"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(2,ATRValue);
   
   return(INIT_SUCCEEDED);
  }

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;
   double up[], down[], SourcePrice, atr, prev_up, prev_down;
   
   int xsize = ArraySize(ATRValue);
   
   ArrayResize(up,xsize);
   ArrayResize(down,xsize);
      
   for(i = rates_total-1; i >= 0; i--) 
   {
      ATRValue[i] = iATR(NULL, 0, 1, i);
   }
      
   for(i = rates_total-1; i >= 0; i--)
   {    
      if (ATR_MA_Type == 0)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_SMA,i);
      }
      else if (ATR_MA_Type == 1)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_EMA,i);
      }
      else if (ATR_MA_Type == 2)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_SMMA,i);
      }
      else if (ATR_MA_Type == 3)
      {
         atr = iMAOnArray(ATRValue,0,Nbr_Periods,0,MODE_LWMA,i);
      }
      
      if(Source == 0)SourcePrice = Close[i];
      if(Source == 1)SourcePrice = Open[i];
      if(Source == 2)SourcePrice = High[i];
      if(Source == 3)SourcePrice = Low[i];
      if(Source == 4)SourcePrice = (High[i]+Low[i])/2;
      if(Source == 5)SourcePrice = (High[i]+Low[i]+Close[i])/3;
      if(Source == 6)SourcePrice = (High[i]+Low[i]+Close[i]+Close[i])/4;
      
      up[i] = SourcePrice - (Multiplier * atr);
      if(i+1<ArraySize(up))prev_up = up[i+1];

      if(Close[i] > prev_up){up[i] = MathMax(up[i],prev_up);}
      
      down[i] = SourcePrice + (Multiplier * atr);
      if(i+1<ArraySize(down))prev_down = down[i+1];
      
      if(Close[i] < prev_down){down[i] = MathMin(down[i],prev_down);}
      
      if(Close[i] > prev_down && trendup != 1)
      {
         trendup = 1;
         trenddown = 0;
      }
      if(Close[i] < prev_up && trenddown != -1)
      {
         trenddown = -1;
         trendup = 0;
      }
      
      if(trendup == 0) {TrendUpBuffer[i] = EMPTY_VALUE;}   
      if(trendup == 1){TrendUpBuffer[i] = up[i];}
      if(trenddown == 0){TrendDownBuffer[i] = EMPTY_VALUE;}
      if(trenddown == -1){TrendDownBuffer[i] = down[i];}
         
   }
      
   return(rates_total);
  }
Files:
1.png  33 kb
 

@Marzena Maria Szmit beat me to it , but here is a different adaptation . Lets say this has a carbon fiber exterior and is more aerodynamic .

Great work though @Marzena Maria Szmit @Ahmet Akçay   👏 👏 👏

#property copyright "Copyright © 2022, Ahmet Akçay."
#property link      "https://www.mql5.com/en/users/ahmetakcay"
#property version   "1.00"
#property strict 
#property indicator_buffers 10
#property indicator_plots   2
#property indicator_chart_window
#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2

extern int Nbr_Periods = 10; 
extern double Multiplier = 3.0; 
input ENUM_MA_METHOD ATR_MA_Type = MODE_SMMA; 
input ENUM_APPLIED_PRICE Source = PRICE_MEDIAN; 

/*
first we turn up down prev up prev down into buffers , why? 
if a new tick comes it resets your prevs variables 
if new data comes in the past the prevs it has will be from the present , or , it's future 
which is impossible
Also since you are sequencing previous states you will need a hard reset function 
for when new data comes in 
Same for the trendup and trenddown 
*/
double TrendUpBuffer[], TrendDownBuffer[], ATRValue[],up[],down[],prev_up[],prev_down[],trendup[],trenddown[],range[];
string MA_Name;
//here is the reset function
void reset(){
ArrayFill(TrendUpBuffer,0,ArraySize(TrendUpBuffer),0.0);
ArrayFill(TrendDownBuffer,0,ArraySize(TrendDownBuffer),0.0);
ArrayFill(ATRValue,0,ArraySize(ATRValue),0.0);
ArrayFill(up,0,ArraySize(up),0.0);
ArrayFill(down,0,ArraySize(down),0.0);
ArrayFill(prev_up,0,ArraySize(prev_up),0.0);
ArrayFill(prev_down,0,ArraySize(prev_down),0.0);
ArrayFill(trendup,0,ArraySize(trendup),0.0);
ArrayFill(trenddown,0,ArraySize(trenddown),0.0);
ArrayFill(range,0,ArraySize(range),0.0);
/*
one may ask , "aren't there better more efficient ways to reset depending on where the new data landed ?
               i think this code would crash the cpu of a 1976 jumbo jet 747 !"
yes there are better ways.
For now , we'll use this though
*/
}

int OnInit()
  {
   if (ATR_MA_Type == 0)
   {
      MA_Name="SMA";
   }
   else if (ATR_MA_Type == 1)
   {
      MA_Name="EMA";
   }
   else if (ATR_MA_Type == 2)
   {
      MA_Name="SMMA";
   }
   else if (ATR_MA_Type == 3)
   {
      MA_Name="LWMA";
   }
   SetIndexBuffer(0, TrendUpBuffer);
   SetIndexEmptyValue(0,0.0);
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(0, "ST Up"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexBuffer(1, TrendDownBuffer);
   SetIndexEmptyValue(1,0.0);
   SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(1, "ST Down"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(2,ATRValue);
   SetIndexStyle(3,DRAW_NONE);
   SetIndexBuffer(3,up);
   SetIndexStyle(4,DRAW_NONE);
   SetIndexBuffer(4,down);
   SetIndexStyle(5,DRAW_NONE);
   SetIndexBuffer(5,prev_up);
   SetIndexStyle(6,DRAW_NONE);
   SetIndexBuffer(6,prev_down);
   SetIndexStyle(7,DRAW_NONE);
   SetIndexBuffer(7,trendup);
   SetIndexStyle(8,DRAW_NONE);
   SetIndexBuffer(8,trenddown);
   SetIndexStyle(9,DRAW_NONE);
   SetIndexBuffer(9,range);
   return(INIT_SUCCEEDED);
  }

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[])
  {
  /*
  Some basics first 
  when you set index buffers they are automatically sized to this :
  rates_total
  
  The first element in an array is [0]
  So if we have 5 items in an array and the first one is [0] the last one will be [4] [0][1][2][3][4]
  or 
  it will be [items-1]
  or in this case 
  rates_total-1
  
  Secondly , if you have periods in your parameters 
  you will need to start calculations after the max period can be attained 
  For instance 
  Let's say i have 10 items and i want the MA5 
  i cannot take the MA5 on items [0][1][2][3] because there are <5 items
  So , similarly .
  The indicator provides the size of the indexes as rates_total
  and we saw we must start from rates_total-1
  so we will also subtract the maximum period out of that 
  
  Before that though we need to run another check :
  Lets assume again you have a box with 5 golden bars.
  I cannot see in the box and i have my eyes closed
  Your task is to keep a tab of how many golden bars are in the box and how many i have seen.
  So at first 
  Golden Bars = 5 , I have seen =0 (i have not opened the box yet so i have not seen anything)
         then i open the box i see there is 5 Golden Bars you log it 
  Golden Bars = 5 , I have seen =5
         what if you add a Golden Bar in the box  
  Golden Bars = 6 , I have seen =5 
         now the next time i check the box you will know i saw 1 golden bar more 
  
  The box is the          indexes
  The golden bars is      rates_total
  How many i have seen is prev_calculated
  The looking event is    OnCalculate
  
  By looking at this its evident there are some variants which will assist in making your 
     indicator more efficient : 
     a.There have been no bars processed(seen) at all (prev_calculated=0)
     b.All bars have been processed(seen) and there are no new bars (prev_calculated=rates_total) 
       You can think of this as a tick in the latest bar 
     c.A new bar forms and all have been processed but not this one (rates_total=prev_calculated+1)
     d.New data has come in because the user went back in time or your broker filled a gap (rates_total>prev_calculated , prev_calculated!=0)
  So based on this lets create a variable that is going to tell you 
     -how many new bars are there 
     -manage the access loop with a from integer
  
  We first identify how many new bars exist (so if prev calculated is 0 it will mean all the bars are new)
  */    
  int to_calc=rates_total-prev_calculated;
  /* to_calc guides on how much we will access in the loop 
     and wether or not reset will be called 
  So , we create a from integer which holds where the loop is going to start 
  and we assign it to_calc value , why ?
      -> If no new bars exist you will get to_calc=0 and you will just check the live bar , from 0 to 0
      -> If one new bar comes in you will get to_calc=1 and you will just check bar [1] and the live bar [0]
      -> and then you can set a threshold for when you think a reset is needed
  Again , one may say : "But this code would crash the Apollo 1 cpu , how do you determine how many bars 
                         justify a reset ? "
      You estimate , usually you are interested if its bigger than your period 
      but lets say 100 . Its a relatively safe amount
  So , step 1 set from to calcs   
  */
  int from=to_calc;
  //and if its bigger than 100 , call reset 
  if(from>100){
  reset();
  /*
  and one more thing , set the from to the earliest valid bar (with data if you take into account your period)
  so 
  */
  from=rates_total-1-Nbr_Periods;
  /* from is total bars - 1 because we are counting from [0] , and minus the period 
  
     so let's enter the loop
  */  
  }
  double atr=0.0,SourcePrice=0.0;
  //loop from to 0
  for(int i=from; i>=0; i--) 
   {
      range[i] = High[i]-Low[i]; 
      ATRValue[i]=simpleSTR8forwardAndFastMaOnArray(range,i,Nbr_Periods,ATR_MA_Type,true,from-i,ATRValue[i+1]);
      atr=ATRValue[i];
      if(Source == 0){SourcePrice = Close[i];}
      else if(Source == 1){SourcePrice = Open[i];}
      else if(Source == 2){SourcePrice = High[i];}
      else if(Source == 3){SourcePrice = Low[i];}
      else if(Source == 4){SourcePrice = (High[i]+Low[i])/2;}
      else if(Source == 5){SourcePrice = (High[i]+Low[i]+Close[i])/3;}
      else if(Source == 6){SourcePrice = (High[i]+Low[i]+Close[i]+Close[i])/4;}
      
      /*
      dont forget prev up and prev down  are now buffers
      and so are trendup and trenddown and 
      we need to propagate (carry) the previous values of trendup and trendown
      */
      trendup[i]=trendup[i+1];
      trenddown[i]=trenddown[i+1];
      
      up[i] = SourcePrice - (Multiplier * atr);
      prev_up[i] = up[i+1];

      down[i] = SourcePrice + (Multiplier * atr);
      prev_down[i] = down[i+1];
      
      if(Close[i] > prev_up[i]){up[i] = MathMax(up[i],prev_up[i]);}
      
      if(Close[i] < prev_down[i]){down[i] = MathMin(down[i],prev_down[i]);}
      
      if(Close[i] > prev_down[i] && trendup[i+1] != 1)
      {
         trendup[i] = 1;
         trenddown[i] = 0;
      }
      if(Close[i] < prev_up[i] && trenddown[i] != -1)
      {
         trenddown[i] = -1;
         trendup[i] = 0;
      }
      
 
      if(trendup[i] == 1)   {TrendUpBuffer[i] = up[i];}
      if(trenddown[i] == -1){TrendDownBuffer[i] = down[i];}
         
   }
     
  return(rates_total);
  }
  
/* ma of array */
double simpleSTR8forwardAndFastMaOnArray(const double &which_array[],
                                                  int where,//start from where 
                                                  int period,
                                       ENUM_MA_METHOD mode,
                                                 bool is_series,
                                                  int calc_index,//this measures which calculation this is starting from 0
                                               double previous_ma){//and this receives the previous value 
double result=0.0;
//starting point 
  int from=0;
  int step=0;
  int until=where;
  if(!is_series){
  from=where-period+1;
  step=1;
  }
  else{
  from=where+period-1;
  step=-1;
  }
if(until>=0&&until<ArraySize(which_array)&&from>=0&&from<ArraySize(which_array)){
  //sma or first ema or first smma 
    if(mode==MODE_SMA||(mode==MODE_EMA&&calc_index==0)||(mode==MODE_SMMA&&calc_index==0)){
    int i=from-step;
    while(i!=until)
      {
      i+=step;
      result+=which_array[i];
      }
    result/=((double)period);
    }
  //ema non first 
    else if(mode==MODE_EMA){
    double w=2.00/((double)period+1.0);
    result=which_array[until]*w+previous_ma*(1-w);
    }  
  //smma non first 
    else if(mode==MODE_SMMA){
    result=((previous_ma*((double)period))-previous_ma+which_array[until])/((double)period);
    }
  //lwma
    else if(mode==MODE_LWMA){
    int i=from-step;
    double divider=0.0;
    int weight=0.0;
    while(i!=until)
      {
      i+=step;
      weight+=1.0;
      result+=which_array[i]*weight;
      divider+=weight;
      }
    result/=divider;    
    }
  }
return(result);
}

and the compact version :

#property copyright "Copyright © 2022, Ahmet Akçay."
#property link      "https://www.mql5.com/en/users/ahmetakcay"
#property version   "1.00"
#property strict 
#property indicator_buffers 8
#property indicator_plots   2
#property indicator_chart_window
#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_width1 2
#property indicator_width2 2
extern int Nbr_Periods = 10; 
extern double Multiplier = 3.0; 
input ENUM_MA_METHOD ATR_MA_Type = MODE_SMMA; 
input ENUM_APPLIED_PRICE Source = PRICE_MEDIAN; 
double TrendUpBuffer[],TrendDownBuffer[],ATRValue[],up[],down[],trendup[],trenddown[],range[];
string MA_Name;
//here is the reset function
void reset(){
ArrayFill(TrendUpBuffer,0,ArraySize(TrendUpBuffer),0.0);
ArrayFill(TrendDownBuffer,0,ArraySize(TrendDownBuffer),0.0);
ArrayFill(ATRValue,0,ArraySize(ATRValue),0.0);
ArrayFill(up,0,ArraySize(up),0.0);
ArrayFill(down,0,ArraySize(down),0.0);
ArrayFill(trendup,0,ArraySize(trendup),0.0);
ArrayFill(trenddown,0,ArraySize(trenddown),0.0);
ArrayFill(range,0,ArraySize(range),0.0);
}

int OnInit()
  {
   if (ATR_MA_Type == 0)
   {
      MA_Name="SMA";
   }
   else if (ATR_MA_Type == 1)
   {
      MA_Name="EMA";
   }
   else if (ATR_MA_Type == 2)
   {
      MA_Name="SMMA";
   }
   else if (ATR_MA_Type == 3)
   {
      MA_Name="LWMA";
   }
   SetIndexBuffer(0, TrendUpBuffer);
   SetIndexEmptyValue(0,0.0);
   SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(0, "ST Up"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexBuffer(1, TrendDownBuffer);
   SetIndexEmptyValue(1,0.0);
   SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexLabel(1, "ST Down"+" ("+Nbr_Periods+","+Multiplier+","+MA_Name+")");
   SetIndexStyle(2,DRAW_NONE);
   SetIndexBuffer(2,ATRValue);
   SetIndexStyle(3,DRAW_NONE);
   SetIndexBuffer(3,up);
   SetIndexStyle(4,DRAW_NONE);
   SetIndexBuffer(4,down);
   SetIndexStyle(5,DRAW_NONE);
   SetIndexBuffer(5,trendup);
   SetIndexStyle(6,DRAW_NONE);
   SetIndexBuffer(6,trenddown);
   SetIndexStyle(7,DRAW_NONE);
   SetIndexBuffer(7,range);
   return(INIT_SUCCEEDED);
  }

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 to_calc=rates_total-prev_calculated;
  int from=to_calc;
  if(from>100){
  reset();
  from=rates_total-1-Nbr_Periods;
  }
  double SourcePrice=0.0;
  for(int i=from; i>=0; i--) 
   {
      range[i] = High[i]-Low[i]; 
      ATRValue[i]=simpleSTR8forwardAndFastMaOnArray(range,i,Nbr_Periods,ATR_MA_Type,true,from-i,ATRValue[i+1]);
      if(Source == 0){SourcePrice = Close[i];}
      else if(Source == 1){SourcePrice = Open[i];}
      else if(Source == 2){SourcePrice = High[i];}
      else if(Source == 3){SourcePrice = Low[i];}
      else if(Source == 4){SourcePrice = (High[i]+Low[i])/2;}
      else if(Source == 5){SourcePrice = (High[i]+Low[i]+Close[i])/3;}
      else if(Source == 6){SourcePrice = (High[i]+Low[i]+Close[i]+Close[i])/4;}
      trendup[i]=trendup[i+1];
      trenddown[i]=trenddown[i+1];
      
      up[i] = SourcePrice - (Multiplier * ATRValue[i]);
      down[i] = SourcePrice + (Multiplier * ATRValue[i]);
      
      if(Close[i] > up[i+1]){up[i] = MathMax(up[i],up[i+1]);}    
      if(Close[i] < down[i+1]){down[i] = MathMin(down[i],down[i+1]);}
      
      if(Close[i] > down[i+1] && trendup[i+1] != 1)
      {
         trendup[i] = 1;
         trenddown[i] = 0;
      }
      if(Close[i] < up[i+1] && trenddown[i] != -1)
      {
         trenddown[i] = -1;
         trendup[i] = 0;
      }

      if(trendup[i] == 1)   {TrendUpBuffer[i] = up[i];}
      if(trenddown[i] == -1){TrendDownBuffer[i] = down[i];}       
   }    
  return(rates_total);
  }
  
/* ma of array */
double simpleSTR8forwardAndFastMaOnArray(const double &which_array[],
                                                  int where,//start from where 
                                                  int period,
                                       ENUM_MA_METHOD mode,
                                                 bool is_series,
                                                  int calc_index,//this measures which calculation this is starting from 0
                                               double previous_ma){//and this receives the previous value 
double result=0.0;
//starting point 
  int from=0;
  int step=0;
  int until=where;
  if(!is_series){
  from=where-period+1;
  step=1;
  }
  else{
  from=where+period-1;
  step=-1;
  }
if(until>=0&&until<ArraySize(which_array)&&from>=0&&from<ArraySize(which_array)){
  //sma or first ema or first smma 
    if(mode==MODE_SMA||(mode==MODE_EMA&&calc_index==0)||(mode==MODE_SMMA&&calc_index==0)){
    int i=from-step;
    while(i!=until)
      {
      i+=step;
      result+=which_array[i];
      }
    result/=((double)period);
    }
  //ema non first 
    else if(mode==MODE_EMA){
    double w=2.00/((double)period+1.0);
    result=which_array[until]*w+previous_ma*(1-w);
    }  
  //smma non first 
    else if(mode==MODE_SMMA){
    result=((previous_ma*((double)period))-previous_ma+which_array[until])/((double)period);
    }
  //lwma
    else if(mode==MODE_LWMA){
    int i=from-step;
    double divider=0.0;
    int weight=0.0;
    while(i!=until)
      {
      i+=step;
      weight+=1.0;
      result+=which_array[i]*weight;
      divider+=weight;
      }
    result/=divider;    
    }
  }
return(result);
}
 
Lorentzos Roussos #:

@Marzena Maria Szmit beat me to it , but here is a different adaptation . Lets say this has a carbon fiber exterior and is more aerodynamic .

Great work though @Marzena Maria Szmit @Ahmet Akçay   👏 👏 👏

and the compact version :

Thank you for your work.
I only know mql4 at the beginning stage, these codes are too heavy for me for now.But I will try to understand it :D