ATRStopLoss_Ind

Author: Rosh Jardine (MQL5/MQL4)
2 Views
0 Downloads
0 Favorites
ATRStopLoss_Ind
//+------------------------------------------------------------------+
//|                                              ATRStopLoss_Ind.mq5 |
//|                                                     Rosh Jardine |
//|                                        https://roshjardine.com   |
//+------------------------------------------------------------------+
#property copyright "Rosh Jardine (MQL5/MQL4)"
#property link      "https://roshjardine.com"
#property version   "1.00"
#property description "Based on https://www.mql5.com/en/forum/349885 , this indicator will draw ATR based stop loss calculation with adjustable multiplier and ATR period."
#property description "This indicator includes helper functions and example to run calculation via function call so the calculation logic can be placed in external include file"
#property indicator_chart_window

#property indicator_buffers 5
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_color1  Orchid
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
#property indicator_type2   DRAW_LINE
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
#property indicator_color2  Blue
#property indicator_label1  "Up"
#property indicator_label2  "Dn"


//---- input parameters
input int    Length=10; //how many look back periods to check the price
input int    ATRperiod=10;
input double Kv=2.5;
//---- indicator buffers
double UpBuffer1[];
double DnBuffer1[];
double smin[];
double smax[];
double trend[];

int AtrHandle;
double AtrBfr[1];
int bars_calculated;
string short_name;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   bars_calculated = 0;

   short_name="ATRStopLoss_Ind";
   AtrHandle = iATR(_Symbol,_Period,ATRperiod);
   if(AtrHandle==INVALID_HANDLE)
     {
      return(INIT_FAILED);
     }
   ArrayInitialize(AtrBfr,EMPTY_VALUE);
   SetIndexBuffer(0,UpBuffer1);
   SetIndexBuffer(1,DnBuffer1);
   SetIndexBuffer(2,smin);
   SetIndexBuffer(3,smax);
   SetIndexBuffer(4,trend);
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   IndicatorSetString(INDICATOR_SHORTNAME,short_name);
   PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,Length);
   PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,Length);
   PlotIndexSetInteger(0,PLOT_SHIFT,0);
   PlotIndexSetInteger(1,PLOT_SHIFT,0);
   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 limit;
   if(rates_total<=Length)
      return(0);
   if(prev_calculated<1)
     {
      /*
      int shift;
      ArrayInitialize(UpBuffer1,EMPTY_VALUE);
      ArrayInitialize(DnBuffer1,EMPTY_VALUE);
      ArrayInitialize(smin,EMPTY_VALUE);
      ArrayInitialize(smax,EMPTY_VALUE);
      ArrayInitialize(trend,EMPTY_VALUE);
      ArraySetAsSeries(UpBuffer1,true);
      ArraySetAsSeries(DnBuffer1,true);
      ArraySetAsSeries(smin,true);
      ArraySetAsSeries(smax,true);
      ArraySetAsSeries(trend,true);

      limit = rates_total-Length-1;

      for (shift=limit;shift>=0;shift--)
      {
          smin[shift] = -100000; smax[shift] = 100000;
          for(int i=Length-1;i>=0;i--)
          {
              int copybuffer = CopyBuffer(AtrHandle,0,shift+i,1,AtrBfr);
              if (copybuffer<1)
              {
                  StopIndicator();
              }
              smin[shift] = MathMax( smin[shift], iHigh(_Symbol,_Period,shift+i) - Kv*AtrBfr[0]);
              smax[shift] = MathMin( smax[shift], iLow(_Symbol,_Period,shift+i) + Kv*AtrBfr[0]);
          }
          trend[shift]= trend[shift+1];
        if ( iClose(_Symbol,_Period,shift) > smax[shift+1] )
        {
            trend[shift] =  1;
        }
        if ( iClose(_Symbol,_Period,shift) < smin[shift+1] )
        {
            trend[shift] = -1;
        }
        if ( trend[shift] >0 )
        {
            if( smin[shift]<smin[shift+1] ) smin[shift]=smin[shift+1];
            UpBuffer1[shift] = smin[shift];
            DnBuffer1[shift] = EMPTY_VALUE;
        }
        if ( trend[shift] <0 )
        {
            if( smax[shift]>smax[shift+1] ) smax[shift]=smax[shift+1];
            UpBuffer1[shift] = EMPTY_VALUE;
            DnBuffer1[shift] = smax[shift];
        }
      }
      */
      limit = rates_total-Length-1;
      if(!AtrStopFirstRun(limit,UpBuffer1,DnBuffer1,smin,smax,trend,AtrHandle,AtrBfr,Length,_Symbol,_Period,Kv))
        {
         StopIndicator();
        }
      bars_calculated = limit;
      return(rates_total);
     }


   else
     {
      limit=prev_calculated-Length-1;

      if(limit>bars_calculated)
        {
         if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,AtrHandle,AtrBfr,Length,_Symbol,_Period,Kv,false))
           {
            StopIndicator();
           }
         bars_calculated +=1;
        }
      else
        {
         if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,AtrHandle,AtrBfr,Length,_Symbol,_Period,Kv,true))
           {
            StopIndicator();
           }
        }
      /*
      if (limit>bars_calculated)
      {
          ArrayResize(UpBuffer1,bars_calculated+1);
          ArrayResize(DnBuffer1,bars_calculated+1);
          ArrayResize(smin,bars_calculated+1);
          ArrayResize(smax,bars_calculated+1);
          ArrayResize(trend,bars_calculated+1);
          UpBuffer1[0] = DnBuffer1[0]= smin[0] = smax[0] = trend[0] = EMPTY_VALUE;
          bars_calculated +=1;
      }
      for(int j=0;j<=1;j++)
      {
          smin[j] = -100000; smax[j] = 100000;
          for(int k=0;k<=Length-1;k++)
          {
              int copybuffer = CopyBuffer(AtrHandle,0,j+k,1,AtrBfr);
              if (copybuffer<1)
              {
                  StopIndicator();

              }
              smin[j] = MathMax( smin[j], iHigh(_Symbol,_Period,j+k) - Kv*AtrBfr[0]);
              smax[j] = MathMin( smax[j], iLow(_Symbol,_Period,j+k) + Kv*AtrBfr[0]);
          }
          trend[j]= trend[j+1];
        if ( iClose(_Symbol,_Period,j) > smax[j+1] ) trend[j] =  1;
        if ( iClose(_Symbol,_Period,j) < smin[j+1] ) trend[j] = -1;

        if ( trend[j] >0 )
        {
            if( smin[j]<smin[j+1] ) smin[j]=smin[j+1];
            UpBuffer1[j] = smin[j];
            DnBuffer1[j] = EMPTY_VALUE;
        }
        if ( trend[j] <0 )
        {
            if( smax[j]>smax[j+1] ) smax[j]=smax[j+1];
            UpBuffer1[j] = EMPTY_VALUE;
            DnBuffer1[j] = smax[j];
        }
      }*/
      return(rates_total);
     }
  }

/************************************ AS HELPERS ************************************/
bool AtrStopNextRun(int newlimit,double &upbfr[],
                    double &dnbfr[],double &min[],
                    double &max[],double &trd[],int &atrhandler,
                    double &atrbuffer[],int atrlength,
                    const string symbol,ENUM_TIMEFRAMES tframe,
                    double multiplier,bool samebar)
  {
   if(!samebar)
     {
      ArrayResize(upbfr,newlimit);
      ArrayResize(dnbfr,newlimit);
      ArrayResize(min,newlimit);
      ArrayResize(max,newlimit);
      ArrayResize(trd,newlimit);
      upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE;
     }
   else
     {
      upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE;
     }
   for(int j=0; j<=1; j++)
     {
      min[j] = -100000;
      max[j] = 100000;
      for(int k=0; k<=atrlength-1; k++)
        {
         int copybuffer = CopyBuffer(atrhandler,0,j+k,1,atrbuffer);
         if(copybuffer<1)
           {
            return(false);
           }
         min[j] = MathMax(smin[j], iHigh(symbol,tframe,j+k) - multiplier*AtrBfr[0]);
         max[j] = MathMin(smax[j], iLow(symbol,tframe,j+k) + multiplier*AtrBfr[0]);
        }
      trd[j]= trd[j+1];
      if(iClose(symbol,tframe,j) > max[j+1])
        {
         trd[j] =  1;
        }
      if(iClose(symbol,tframe,j) < min[j+1])
        {
         trd[j] = -1;
        }
      if(trd[j] >0)
        {
         if(min[j]<min[j+1])
           {
            min[j] = min[j+1];
           }
         upbfr[j] = min[j];
         dnbfr[j] = EMPTY_VALUE;
        }
      if(trend[j] <0)
        {
         if(max[j]>max[j+1])
           {
            max[j]=max[j+1];
           }
         upbfr[j] = EMPTY_VALUE;
         dnbfr[j] = max[j];
        }
     }
   return(true);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool AtrStopFirstRun(int limit,double &upbfr[],
                     double &dnbfr[],double &min[],
                     double &max[],double &trd[],int &atrhandler,
                     double &atrbuffer[],int atrlength,
                     const string symbol,ENUM_TIMEFRAMES tframe,
                     double multiplier
                    )
  {
   ArrayInitialize(upbfr,EMPTY_VALUE);
   ArrayInitialize(dnbfr,EMPTY_VALUE);
   ArrayInitialize(min,EMPTY_VALUE);
   ArrayInitialize(max,EMPTY_VALUE);
   ArrayInitialize(trd,EMPTY_VALUE);
   ArraySetAsSeries(upbfr,true);
   ArraySetAsSeries(dnbfr,true);
   ArraySetAsSeries(min,true);
   ArraySetAsSeries(max,true);
   ArraySetAsSeries(trd,true);
   int shift = 0;
   for(shift=limit; shift>=0; shift--)
     {
      min[shift] = -100000;
      max[shift] = 100000;
      for(int i=atrlength-1; i>=0; i--)
        {
         int copybuffer = CopyBuffer(atrhandler,0,shift+i,1,atrbuffer);
         if(copybuffer<1)
           {
            return(false);
           }
         min[shift] = MathMax(min[shift], iHigh(symbol,tframe,shift+i) - multiplier*atrbuffer[0]);
         max[shift] = MathMin(max[shift], iLow(symbol,tframe,shift+i) + multiplier*atrbuffer[0]);
        }
      trd[shift] = trd[shift+1];
      if(iClose(symbol,tframe,shift) > max[shift+1])
        {
         trd[shift] =  1;
        }
      if(iClose(symbol,tframe,shift) < min[shift+1])
        {
         trd[shift] = -1;
        }
      if(trd[shift] >0)
        {
         if(min[shift]<min[shift+1])
           {
            min[shift] = min[shift+1];
           }
         upbfr[shift] = min[shift];
         dnbfr[shift] = EMPTY_VALUE;
        }
      if(trd[shift] <0)
        {
         if(max[shift]>max[shift+1])
           {
            max[shift] = max[shift+1];
           }
         upbfr[shift] = EMPTY_VALUE;
         dnbfr[shift] = max[shift];
        }
     }
   return(true);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void StopIndicator()
  {
   IndicatorRelease(AtrHandle);
   ChartIndicatorDelete(ChartID(),0,short_name);
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(AtrHandle!=INVALID_HANDLE)
      IndicatorRelease(AtrHandle);
  }


//---
//--- MQL4
//---

#ifdef __MQL4__
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
//---- input parameters
extern int    Length=10;
extern int    ATRperiod=10;
extern double Kv=2.5;
double UpBuffer1[];
double DnBuffer1[];
double smin[];
double smax[];
double trend[];

double AtrBfr[1];
int bars_calculated;
string short_name;
int OnInit()
  {
   bars_calculated = 0;

   short_name="ATRStopLoss_Ind";
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   IndicatorBuffers(5);
   SetIndexBuffer(0,UpBuffer1);
   SetIndexBuffer(1,DnBuffer1);
   SetIndexBuffer(2,smin);
   SetIndexBuffer(3,smax);
   SetIndexBuffer(4,trend);
   IndicatorShortName(short_name);
   SetIndexLabel(0,"Up");
   SetIndexLabel(1,"Dn");
   SetIndexDrawBegin(0,Length);
   SetIndexDrawBegin(1,Length);
   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 limit;
   if(rates_total<=Length)
     {
      return(0);
     }
   if(prev_calculated<1)
     {
      /*
      int shift;
      ArrayInitialize(UpBuffer1,EMPTY_VALUE);
      ArrayInitialize(DnBuffer1,EMPTY_VALUE);
      ArrayInitialize(smin,EMPTY_VALUE);
      ArrayInitialize(smax,EMPTY_VALUE);
      ArrayInitialize(trend,EMPTY_VALUE);
      ArraySetAsSeries(UpBuffer1,true);
      ArraySetAsSeries(DnBuffer1,true);
      ArraySetAsSeries(smin,true);
      ArraySetAsSeries(smax,true);
      ArraySetAsSeries(trend,true);
      limit = rates_total-Length-1;
      for (shift=limit;shift>=0;shift--)
      {
          smin[shift] = -100000;
      smax[shift] = 100000;
          for(int i=Length-1;i>=0;i--)
          {
              smin[shift] = MathMax( smin[shift], iHigh(_Symbol,_Period,shift+i) - Kv*iATR(Symbol(),Period(),ATRperiod,shift+i));
              smax[shift] = MathMin( smax[shift], iLow(_Symbol,_Period,shift+i) + Kv*iATR(Symbol(),Period(),ATRperiod,shift+i));
          }
          trend[shift]= trend[shift+1];
        if ( iClose(_Symbol,_Period,shift) > smax[shift+1] )
        {
            trend[shift] =  1;
        }
        if ( iClose(_Symbol,_Period,shift) < smin[shift+1] )
        {
            trend[shift] = -1;
        }
        if ( trend[shift] >0 )
        {
            if( smin[shift]<smin[shift+1] ) smin[shift]=smin[shift+1];
            UpBuffer1[shift] = smin[shift];
            DnBuffer1[shift] = EMPTY_VALUE;
        }
        if ( trend[shift] <0 )
        {
            if( smax[shift]>smax[shift+1] ) smax[shift]=smax[shift+1];
            UpBuffer1[shift] = EMPTY_VALUE;
            DnBuffer1[shift] = smax[shift];
        }
      }
      */

      /*** AS FUNCTION CALL EXAMPLE ***/

      limit = rates_total-Length-1;
      if(!AtrStopFirstRun(limit,UpBuffer1,DnBuffer1,smin,smax,trend,Length,Symbol(),Period(),Kv))
        {
         return(0);
        }
      bars_calculated = limit;
      return(rates_total);
     }
   else
     {
      limit = prev_calculated-Length-1;
      /*** AS FUNCTION CALL EXAMPLE ***/
      if(limit>bars_calculated)
        {
         if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,Length,Symbol(),Period(),Kv,false))
           {
            return(0);
           }
        }
      if(!AtrStopNextRun(bars_calculated+1,UpBuffer1,DnBuffer1,smin,smax,trend,Length,Symbol(),Period(),Kv,true))
        {
         return(0);
        }
      /*
      if (limit>bars_calculated)
      {
          ArrayResize(UpBuffer1,bars_calculated+1);
          ArrayResize(DnBuffer1,bars_calculated+1);
          ArrayResize(smin,bars_calculated+1);
          ArrayResize(smax,bars_calculated+1);
          ArrayResize(trend,bars_calculated+1);
          UpBuffer1[0] = DnBuffer1[0]= smin[0] = smax[0] = trend[0] = EMPTY_VALUE;
          bars_calculated +=1;
      }
      for(int j=0;j<=1;j++)
      {
          smin[j] = -100000;
      smax[j] = 100000;
          for(int k=0;k<=Length-1;k++)
          {
              smin[j] = MathMax( smin[j], iHigh(Symbol(),Period(),j+k) - Kv*iATR(Symbol(),Period(),ATRperiod,j+k));
              smax[j] = MathMin( smax[j], iLow(Symbol(),Period(),j+k) + Kv*AtrBfr[0]);
          }
          trend[j]= trend[j+1];
        if ( iClose(Symbol(),Period(),j) > smax[j+1] ) trend[j] =  1;
        if ( iClose(Symbol(),Period(),j) < smin[j+1] ) trend[j] = -1;

        if ( trend[j] >0 )
        {
            if( smin[j]<smin[j+1] ) smin[j]=smin[j+1];
            UpBuffer1[j] = smin[j];
            DnBuffer1[j] = EMPTY_VALUE;
        }
        if ( trend[j] <0 )
        {
            if( smax[j]>smax[j+1] ) smax[j]=smax[j+1];
            UpBuffer1[j] = EMPTY_VALUE;
            DnBuffer1[j] = smax[j];
        }
      }
      */
      return(rates_total);
     }
  }

/************************************ AS HELPERS ************************************/

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool AtrStopFirstRun(int limit,double &upbfr[],
                     double &dnbfr[],double &min[],
                     double &max[],double &trd[],int atrlength,
                     const string symbol,const int tframe,
                     double multiplier
                    )
  {
   ArrayInitialize(upbfr,EMPTY_VALUE);
   ArrayInitialize(dnbfr,EMPTY_VALUE);
   ArrayInitialize(min,EMPTY_VALUE);
   ArrayInitialize(max,EMPTY_VALUE);
   ArrayInitialize(trd,EMPTY_VALUE);
   ArraySetAsSeries(upbfr,true);
   ArraySetAsSeries(dnbfr,true);
   ArraySetAsSeries(min,true);
   ArraySetAsSeries(max,true);
   ArraySetAsSeries(trd,true);
   int shift = 0;
   for(shift=limit; shift>=0; shift--)
     {
      min[shift] = -100000;
      max[shift] = 100000;
      for(int i=atrlength-1; i>=0; i--)
        {
         min[shift] = MathMax(min[shift], iHigh(symbol,tframe,shift+i) - multiplier*iATR(symbol,tframe,ATRperiod,shift+1));
         max[shift] = MathMin(max[shift], iLow(symbol,tframe,shift+i) + multiplier*iATR(symbol,tframe,ATRperiod,shift+1));
        }
      trd[shift] = trd[shift+1];
      if(iClose(symbol,tframe,shift) > max[shift+1])
        {
         trd[shift] =  1;
        }
      if(iClose(symbol,tframe,shift) < min[shift+1])
        {
         trd[shift] = -1;
        }
      if(trd[shift] >0)
        {
         if(min[shift]<min[shift+1])
           {
            min[shift] = min[shift+1];
           }
         upbfr[shift] = min[shift];
         dnbfr[shift] = EMPTY_VALUE;
        }
      if(trd[shift] <0)
        {
         if(max[shift]>max[shift+1])
           {
            max[shift]= max[shift+1];
           }
         upbfr[shift] = EMPTY_VALUE;
         dnbfr[shift] = max[shift];
        }
     }
   return(true);
  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool AtrStopNextRun(int newlimit,double &upbfr[],
                    double &dnbfr[],double &min[],
                    double &max[],double &trd[],int atrlength,
                    const string symbol,const int tframe,
                    double multiplier,bool samebar)
  {
   if(!samebar)
     {
      ArrayResize(upbfr,newlimit);
      ArrayResize(dnbfr,newlimit);
      ArrayResize(min,newlimit);
      ArrayResize(max,newlimit);
      ArrayResize(trd,newlimit);
      upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE;
     }
   else
     {
      upbfr[0] = dnbfr[0]= min[0] = max[0] = trd[0] = EMPTY_VALUE;
     }
   for(int j=0; j<=1; j++)
     {
      min[j] = -100000;
      max[j] = 100000;
      for(int k=0; k<=atrlength-1; k++)
        {
         min[j] = MathMax(smin[j], iHigh(symbol,tframe,j+k) - multiplier*iATR(symbol,tframe,ATRperiod,j+k));
         max[j] = MathMin(smax[j], iLow(symbol,tframe,j+k) + multiplier*iATR(symbol,tframe,ATRperiod,j+k));
        }
      trd[j] = trd[j+1];
      if(iClose(symbol,tframe,j) > max[j+1])
        {
         trd[j] = 1;
        }
      if(iClose(symbol,tframe,j) < min[j+1])
        {
         trd[j] = -1;
        }
      if(trd[j] >0)
        {
         if(min[j]<min[j+1])
           {
            min[j] = min[j+1];
           }
         upbfr[j] = min[j];
         dnbfr[j] = EMPTY_VALUE;
        }
      if(trend[j] <0)
        {
         if(max[j]>max[j+1])
           {
            max[j] = max[j+1];
           }
         upbfr[j] = EMPTY_VALUE;
         dnbfr[j] = max[j];
        }
     }
   return(true);
  }
#endif

//+------------------------------------------------------------------+

Comments