SAR index based on MA

Author: Copyright © 2018, Vladimir Karputov
Price Data Components
Indicators Used
Moving average indicator
0 Views
0 Downloads
0 Favorites
SAR index based on MA
ÿþ//+------------------------------------------------------------------+

//|                                        SAR index based on MA.mq5 |

//|                              Copyright © 2018, Vladimir Karputov |

//|                                           http://wmua.ru/slesar/ |

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

#property copyright "Copyright © 2018, Vladimir Karputov"

#property link      "http://wmua.ru/slesar/"

#property version   "1.008"

//--- indicator settings

#property indicator_chart_window

#property indicator_buffers 4

#property indicator_plots   2

#property indicator_type1   DRAW_ARROW

#property indicator_color1  clrDodgerBlue

#property indicator_type2   DRAW_LINE

#property indicator_color2  clrRed

//--- External parametrs

input double         InpSARStep=0.02;        // SAR: Step

input double         InpSARMaximum=0.04;     // SAR: Maximum

input int            InpMAPeriod=13;         // MA: Period

input int            InpMAShift=0;           // MA: Shift

input ENUM_MA_METHOD InpMAMethod=MODE_SMMA;  // MA: Method

//---- buffers

double               ExtSARBuffer[];

double               ExtMABuffer[];

double               ExtEPBuffer[];

double               ExtAFBuffer[];

//--- global variables

int                  ExtLastRevPos;

bool                 ExtDirectionLong;

double               ExtSarStep;

double               ExtSarMaximum;

//---

int    handle_iMA;                           // variable for storing the handle of the iMA indicator 

//--- we will keep the number of values in the Moving Average indicator 

int    bars_calculated=0;

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

//| Custom indicator initialization function                         |

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

int OnInit()

  {

//--- checking input data

   if(InpSARStep<0.0)

     {

      ExtSarStep=0.02;

      Print("Input parametr InpSARStep has incorrect value. Indicator will use value",

            ExtSarStep,"for calculations.");

     }

   else

      ExtSarStep=InpSARStep;

   if(InpSARMaximum<0.0)

     {

      ExtSarMaximum=0.2;

      Print("Input parametr InpSARMaximum has incorrect value. Indicator will use value",

            ExtSarMaximum,"for calculations.");

     }

   else

      ExtSarMaximum=InpSARMaximum;

//--- indicator buffers

   SetIndexBuffer(0,ExtSARBuffer,INDICATOR_DATA);

   SetIndexBuffer(1,ExtMABuffer,INDICATOR_DATA);

   SetIndexBuffer(2,ExtEPBuffer,INDICATOR_CALCULATIONS);

   SetIndexBuffer(3,ExtAFBuffer,INDICATOR_CALCULATIONS);

//--- set arrow symbol

   PlotIndexSetInteger(0,PLOT_ARROW,159);

//--- set indicator digits

   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);

//--- set label name

   PlotIndexSetString(0,PLOT_LABEL,"SAR("+

                      DoubleToString(ExtSarStep,2)+","+

                      DoubleToString(ExtSarMaximum,2)+")");

//--- set global variables

   ExtLastRevPos=0;

   ExtDirectionLong=false;

//--- create handle of the indicator iMA

   handle_iMA=iMA(Symbol(),Period(),InpMAPeriod,InpMAShift,InpMAMethod,PRICE_CLOSE);

//--- if the handle is not created 

   if(handle_iMA==INVALID_HANDLE)

     {

      //--- tell about the failure and output the error code 

      PrintFormat("Failed to create handle of the iMA indicator for the symbol %s/%s, error code %d",

                  Symbol(),

                  EnumToString(Period()),

                  GetLastError());

      //--- the indicator is stopped early 

      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[])

  {

//--- check for minimum rates count

   if(rates_total<3)

      return(0);

//--- number of values copied from the iMA indicator 

   int values_to_copy;

//--- determine the number of values calculated in the indicator 

   int calculated=BarsCalculated(handle_iMA);

   if(calculated<=0)

     {

      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());

      return(0);

     }

//--- if it is the first start of calculation of the indicator or if the number of values in the iMA indicator changed 

//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history) 

   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)

     {

      //--- if the iMABuffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything  

      //--- otherwise, we copy less than the size of indicator buffers 

      if(calculated>rates_total)

         values_to_copy=rates_total;

      else

         values_to_copy=calculated;

     }

   else

     {

      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate() 

      //--- for calculation not more than one bar is added 

      values_to_copy=(rates_total-prev_calculated)+1;

     }

//--- fill the iMABuffer array with values of the Moving Average indicator 

//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation 

   if(!FillArrayFromBuffer(ExtMABuffer,0/*ma_shift*/,handle_iMA,values_to_copy))

      return(0);

//--- memorize the number of values in the Moving Average indicator 

   bars_calculated=calculated;



//--- detect current position 

   int pos=rates_total-values_to_copy/*prev_calculated-1*/;

//---main cycle

   for(int i=pos;i<rates_total-1 && !IsStopped();i++)

     {

      if(i<14)

        {

         //--- first pass, set as SHORT

         //pos=1;

         ExtAFBuffer[i]=ExtSarStep;

         ExtSARBuffer[i]=ExtMABuffer[14];

         ExtLastRevPos=0;

         ExtDirectionLong=false;

         ExtEPBuffer[i]=ExtMABuffer[14];

         continue;

        }

      //--- check for reverse

      double high_curr=ExtMABuffer[i]+Point();

      double low_curr=ExtMABuffer[i]-Point();



      double high_prev=ExtMABuffer[i-1]+Point();

      double low_prev=ExtMABuffer[i-1]-Point();



      if(ExtDirectionLong)

        {

         if(ExtSARBuffer[i]>low_curr)

           {

            //--- switch to SHORT

            ExtDirectionLong=false;

            ExtSARBuffer[i]=GetHigh(i,ExtLastRevPos,ExtMABuffer);

            ExtEPBuffer[i]=low_curr;

            ExtLastRevPos=i;

            ExtAFBuffer[i]=ExtSarStep;

           }

        }

      else

        {

         if(ExtSARBuffer[i]<high_curr)

           {

            //--- switch to LONG

            ExtDirectionLong=true;

            ExtSARBuffer[i]=GetLow(i,ExtLastRevPos,low);

            ExtEPBuffer[i]=high_curr;

            ExtLastRevPos=i;

            ExtAFBuffer[i]=ExtSarStep;

           }

        }

      //--- continue calculations

      if(ExtDirectionLong)

        {

         //--- check for new High

         if(high_curr>ExtEPBuffer[i-1] && i!=ExtLastRevPos)

           {

            ExtEPBuffer[i]=high_curr;

            ExtAFBuffer[i]=ExtAFBuffer[i-1]+ExtSarStep;

            if(ExtAFBuffer[i]>ExtSarMaximum)

               ExtAFBuffer[i]=ExtSarMaximum;

           }

         else

           {

            //--- when we haven't reversed

            if(i!=ExtLastRevPos)

              {

               ExtAFBuffer[i]=ExtAFBuffer[i-1];

               ExtEPBuffer[i]=ExtEPBuffer[i-1];

              }

           }

         //--- calculate SAR for tomorrow

         ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]);

         //--- check for SAR

         if(ExtSARBuffer[i+1]>low_curr || ExtSARBuffer[i+1]>low_prev)

            ExtSARBuffer[i+1]=MathMin(low_curr,low_prev);

        }

      else

        {

         //--- check for new Low

         if(low_curr<ExtEPBuffer[i-1] && i!=ExtLastRevPos)

           {

            ExtEPBuffer[i]=low_curr;

            ExtAFBuffer[i]=ExtAFBuffer[i-1]+ExtSarStep;

            if(ExtAFBuffer[i]>ExtSarMaximum)

               ExtAFBuffer[i]=ExtSarMaximum;

           }

         else

           {

            //--- when we haven't reversed

            if(i!=ExtLastRevPos)

              {

               ExtAFBuffer[i]=ExtAFBuffer[i-1];

               ExtEPBuffer[i]=ExtEPBuffer[i-1];

              }

           }

         //--- calculate SAR for tomorrow

         ExtSARBuffer[i+1]=ExtSARBuffer[i]+ExtAFBuffer[i]*(ExtEPBuffer[i]-ExtSARBuffer[i]);

         //--- check for SAR

         if(ExtSARBuffer[i+1]<high_curr || ExtSARBuffer[i+1]<high_prev)

            ExtSARBuffer[i+1]=MathMax(high_curr,high_prev);

        }

     }

//---- OnCalculate done. Return new prev_calculated.

   return(rates_total);

  }

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

//| Find highest price from start to current position                |

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

double GetHigh(int nPosition,int nStartPeriod,const double &HiData[])

  {

//--- calculate

   double result=HiData[nStartPeriod];

   for(int i=nStartPeriod;i<=nPosition;i++)

      if(result<HiData[i])

         result=HiData[i];

   return(result);

  }

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

//| Find lowest price from start to current position                 |

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

double GetLow(int nPosition,int nStartPeriod,const double &LoData[])

  {

//--- calculate

   double result=LoData[nStartPeriod];

   for(int i=nStartPeriod;i<=nPosition;i++)

      if(result>LoData[i])

         result=LoData[i];

   return(result);

  }

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

//| Filling indicator buffers from the MA indicator                  | 

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

bool FillArrayFromBuffer(double &values[],   // indicator buffer of Moving Average values 

                         int shift,          // shift 

                         int ind_handle,     // handle of the iMA indicator 

                         int amount          // number of copied values 

                         )

  {

//--- reset error code 

   ResetLastError();

//--- fill a part of the iMABuffer array with values from the indicator buffer that has 0 index 

   if(CopyBuffer(ind_handle,0,-shift,amount,values)<0)

     {

      //--- if the copying fails, tell the error code 

      PrintFormat("Failed to copy data from the iMA indicator, error code %d",GetLastError());

      //--- quit with zero result - it means that the indicator is considered as not calculated 

      return(false);

     }

//--- everything is fine 

   return(true);

  }

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

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 ---