ATRStopLoss_Ind

Author: Rosh Jardine (MQL5/MQL4)
Price Data Components
Series array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains close prices for each bar
Indicators Used
Indicator of the average true range
Miscellaneous
Implements a curve of type %1
0 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

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---