Custom Start for indicator calculation

 

Hello mql4 Community,

Recently I stumbled accross a problem which I can't seem to solve by my own, neither have I found any solution in this forum and I'm really not an expert in setting up indicators in mql4...

The issue may be trivial: I want to set a custom start for the standard Parabolic SAR Indicator calculation. So I need to be able to input two variables. 

Fore example: input double CandlesBack = 10; input bool Direction = true;   --> The SAR dots calculation should now start on the lowest candle within the last 10 candles.

If you can help me with the issue or give me a gross direction where I should start changing the code I would be very thankful. 

Cheers 

 

Here is the code:

//+------------------------------------------------------------------+
//|                                                    Parabolic.mq4 |
//|                   Copyright 2005-2014, MetaQuotes Software Corp. |
//|                                              https://www.mql4.com |
//+------------------------------------------------------------------+
#property copyright   "2005-2014, MetaQuotes Software Corp."
#property link        "https://www.mql4.com"
#property description "Parabolic Stop-And-Reversal system"
#property strict

//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1  Lime
//--- input parameters
input double InpSARStep=0.02;    // Step
input double InpSARMaximum=0.2;  // Maximum
//---- buffers
double       ExtSARBuffer[];
//--- global variables
double       ExtSarStep;
double       ExtSarMaximum;
int          ExtLastReverse;
bool         ExtDirectionLong;
double       ExtLastStep,ExtLastEP,ExtLastSAR;
double       ExtLastHigh,ExtLastLow;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void 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;
//--- drawing settings
   IndicatorDigits(Digits);
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,159);
//---- indicator buffers
   SetIndexBuffer(0,ExtSARBuffer);
//--- set short name
   IndicatorShortName("SAR("+DoubleToString(ExtSarStep,2)+","+DoubleToString(ExtSarMaximum,2)+")");
//--- set global variables
   ExtLastReverse=0;
   ExtDirectionLong=false;
   ExtLastStep=ExtLastEP=ExtLastSAR=0.0;
   ExtLastHigh=ExtLastLow=0.0;
//----
  }
//+------------------------------------------------------------------+
//| Parabolic SAR                                                    |
//+------------------------------------------------------------------+
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[])
  {
   bool   dir_long;
   double last_high,last_low,ep,sar,step;
   int    i;
//--- check for minimum rates count
   if(rates_total<3)
      return(0);
//--- counting from 0 to rates_total
   ArraySetAsSeries(ExtSARBuffer,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
//--- detect current position for calculations 
   i=prev_calculated-1;
//--- calculations from start?
   if(i<1)
     {
      ExtLastReverse=0;
      dir_long=true;
      step=ExtSarStep;
      last_high=-10000000.0;
      last_low=10000000.0;
      sar=0;
      i=1;
      while(i<rates_total-1)
        {
         ExtLastReverse=i;
         if(last_low>low[i])
            last_low=low[i];
         if(last_high<high[i])
            last_high=high[i];
         if(high[i]>high[i-1] && low[i]>low[i-1])
            break;
         if(high[i]<high[i-1] && low[i]<low[i-1])
           {
            dir_long=false;
            break;
           }
         i++;
        }
      //--- initialize with zero
      ArrayInitialize(ExtSARBuffer,0.0);
      //--- go check
      if(dir_long)
        {
         ExtSARBuffer[i]=low[i-1];
         ep=high[i];
        }
      else
        {
         ExtSARBuffer[i]=high[i-1];
         ep=low[i];
        }
      i++;
     }
   else
     {
      //--- calculations to be continued. restore last values
      i=ExtLastReverse;
      step=ExtLastStep;
      dir_long=ExtDirectionLong;
      last_high=ExtLastHigh;
      last_low=ExtLastLow;
      ep=ExtLastEP;
      sar=ExtLastSAR;
     }
//---main cycle
   while(i<rates_total)
     {
      //--- check for reverse
      if(dir_long && low[i]<ExtSARBuffer[i-1])
        {
         SaveLastReverse(i,true,step,low[i],last_high,ep,sar);
         step=ExtSarStep;
         dir_long=false;
         ep=low[i];
         last_low=low[i];
         ExtSARBuffer[i++]=last_high;
         continue;
        }
      if(!dir_long && high[i]>ExtSARBuffer[i-1])
        {
         SaveLastReverse(i,false,step,last_low,high[i],ep,sar);
         step=ExtSarStep;
         dir_long=true;
         ep=high[i];
         last_high=high[i];
         ExtSARBuffer[i++]=last_low;
         continue;
        }
      //---
      sar=ExtSARBuffer[i-1]+step*(ep-ExtSARBuffer[i-1]);
      //--- LONG?
      if(dir_long)
        {
         if(ep<high[i])
           {
            if((step+ExtSarStep)<=ExtSarMaximum)
               step+=ExtSarStep;
           }
         if(high[i]<high[i-1] && i==2)
            sar=ExtSARBuffer[i-1];
         if(sar>low[i-1])
            sar=low[i-1];
         if(sar>low[i-2])
            sar=low[i-2];
         if(sar>low[i])
           {
            SaveLastReverse(i,true,step,low[i],last_high,ep,sar);
            step=ExtSarStep; dir_long=false; ep=low[i];
            last_low=low[i];
            ExtSARBuffer[i++]=last_high;
            continue;
           }
         if(ep<high[i])
            ep=last_high=high[i];
        }
      else // SHORT
        {
         if(ep>low[i])
           {
            if((step+ExtSarStep)<=ExtSarMaximum)
               step+=ExtSarStep;
           }
         if(low[i]<low[i-1] && i==2)
            sar=ExtSARBuffer[i-1];
         if(sar<high[i-1])
            sar=high[i-1];
         if(sar<high[i-2])
            sar=high[i-2];
         if(sar<high[i])
           {
            SaveLastReverse(i,false,step,last_low,high[i],ep,sar);
            step=ExtSarStep;
            dir_long=true;
            ep=high[i];
            last_high=high[i];
            ExtSARBuffer[i++]=last_low;
            continue;
           }
         if(ep>low[i])
            ep=last_low=low[i];
        }
      ExtSARBuffer[i++]=sar;
     }
//---- OnCalculate done. Return new prev_calculated.
   return(rates_total);
  }
//+------------------------------------------------------------------+
//|  save last values to continue further calculations               |
//+------------------------------------------------------------------+
void SaveLastReverse(int reverse,bool dir,double step,double last_low,double last_high,double ep,double sar)
  {
   ExtLastReverse=reverse;
   if(ExtLastReverse<2)
      ExtLastReverse=2;
   ExtDirectionLong=dir;
   ExtLastStep=step;
   ExtLastLow=last_low;
   ExtLastHigh=last_high;
   ExtLastEP=ep;
   ExtLastSAR=sar;
  }
//+------------------------------------------------------------------+
 

dignitas123:

The issue may be trivial: I want to set a custom start for the standard Parabolic SAR Indicator calculation. So I need to be able to input two variables. 

Fore example: input double CandlesBack = 10; input bool Direction = true;   --> The SAR dots calculation should now start on the lowest candle within the last 10 candles.

That is not how SAR works, so what you ask is not trivial. What you want will be almost a complete rewrite. All the SaveReverse and dir_long will be gone and two sets of variables (one for each direction) will be required.
 

WHRoeder:
That is not how SAR works, so what you ask is not trivial. What you want will be almost a complete rewrite. All the SaveReverse and dir_long will be gone and two sets of variables (one for each direction) will be required. 

 Thank you for answering WHRoeder.

As it was too complicated for me to rewrite the Indicator I have written an EA that does the job for me :)

I wanted to use the SAR not for spotting Trends but instead for trailing my stop out of a Trend Correction.

Here is the code when someone needs it ^^

 

//+------------------------------------------------------------------+
//|                                                   ParabolicExpert|
//|                                                       by dignitas|
//|                                                niclashumm@aol.com|
//+------------------------------------------------------------------+

//--- input parameters
input double InpSARStep=0.02;    // Step
input double InpSARMaximum=0.2;  // Maximum
extern int   BarsBack = 8;       // length (bars)
extern int   Direction = 0;      // 0 = long; 1 = short
extern color Color = Black;      // Channel color
//--- global parameters
int bars, initialbars;double lastSar, pivot, acc = InpSARStep;
//--------------------------------------------------------------- 1 --
void OnInit()
  {
   if(Direction==0){
   bars = iLowest(NULL,0,MODE_LOW,BarsBack,1);
   } else {
   bars = iHighest(NULL,0,MODE_HIGH,BarsBack,1);
   }
   Create();
   return; 
   initialbars = Bars;
  }
//--------------------------------------------------------------- 2 --
void OnTick()
  {
   
   if(Bars!=initialbars){
   initialbars = Bars;
   bars++;
   Create();
   }
   
  }
//--------------------------------------------------------------- 5 --
void OnDeinit(const int reason)
  {
   for(int i = bars;i > 0;i--) {
      ObjectDelete("Dot"+i);
   }
   acc = InpSARStep;
  }
  
  
  
//--------------------------------------------------------------- 6 --
void Create()
  {
   for(int i = bars;i > 0;i--) {
   
   datetime time = Time[i];
   string objName = "Dot"+i;
   double preis = function(i);
   
   ObjectCreate(objName,OBJ_TEXT,0,time,preis+100*Point);
   ObjectSetText(objName, CharToStr(159), 14, "Wingdings", White);
   WindowRedraw();
   }
  }
double function(int i) {
double sar;

// LONG
if(Direction == 0) {

if(i==bars) {
sar = Low[i];
lastSar = sar;
pivot = High[i];

} else {
sar = lastSar + acc * (High[i+1] - lastSar);
lastSar = sar;
if(acc < InpSARMaximum) {
   if(High[i]>pivot){
   acc+=InpSARStep;
   pivot = High[iHighest(NULL,0,MODE_HIGH,bars-i,i)];
   }
}
}

// SHORT
} else {

if(i==bars) {
sar = High[i];
lastSar = sar;
pivot = Low[i];

} else {
sar = lastSar + acc * (Low[i+1] - lastSar);
lastSar = sar;
if(acc < InpSARMaximum) {
   if(Low[i]<pivot){
   acc+=InpSARStep;
   pivot = Low[iLowest(NULL,0,MODE_LOW,bars-i,i)];
   }
}
}

}

return(sar);

}
 
dignitas123: I wanted to use the SAR not for spotting Trends but instead for trailing my stop out of a Trend Correction
For that all you need to do is verify that iSar was on the correct side of price and use the value.
double sar = iSar(...);
if(sar < Bid && OrderType() == OP_BUY) MoveSL( OrderTicket(), sar);
Reason: