Parabolic SAR |
Parabolic SAR |
Parabolic SAR |
Parabolic SAR |
The parabolic SAR is a technical indicator that is used by many traders to determine the direction of an asset's momentum and the point in time when this momentum has a higher-than-normal probability of switching directions. Parabolic SAR (Sometimes known as the - stop and reverse) is a method devised by J. Welles Wilder, Jr., to find trends in market prices or securities. (Wilder introduced the Parabolic SAR in his book, New Concepts in Technical Trading Systems. This book also includes RSI, Average True Range and the Concept ADX). It may be used as a trailing stop loss based on prices tending to stay within a parabolic curve during a strong trend. A parabola below the price is generally bullish, while a parabola above is generally bearish.
Mathematical Formula:
SARn+1 = SARn + α ( EP – SARn )
Parabilic SAR MQ4 Code Base (Copy Code)
//+------------------------------------------------------------------+
//| Parabolic SAR.mq4 |
//| Copyright © 2004, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net/"
//----
//Added Fix1 September 6, 2006 Advance Index if new bar by Stanley Fiala http://merlin4x.com
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 DodgerBlue
//---- input parameters
extern double Step = 0.02;
extern double Maximum = 0.2;
//---- buffers
double SarBuffer[];
//----
int save_lastreverse;
bool save_dirlong;
double save_start;
double save_last_high;
double save_last_low;
double save_ep;
double save_sar;
int bartime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
SetIndexStyle(0, DRAW_ARROW);
SetIndexArrow(0, 159);
SetIndexBuffer(0, SarBuffer);
//----
return(0);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SaveLastReverse(int last, int dir, double start, double low, double high,
double ep, double sar)
{
save_lastreverse = last;
save_dirlong = dir;
save_start = start;
save_last_low = low;
save_last_high = high;
save_ep = ep;
save_sar = sar;
}
//+------------------------------------------------------------------+
//| Parabolic Sell And Reverse system |
//+------------------------------------------------------------------+
int start()
{
static bool first = true;
bool dirlong;
double start, last_high, last_low;
double ep, sar, price_low, price_high, price;
int i, counted_bars = IndicatorCounted();
//----
if(Bars < 3)
return(0);
//---- initial settings
i = Bars - 2;
//----
if(counted_bars == 0 || first)
{
first = false;
dirlong = true;
start = Step;
last_high = -10000000.0;
last_low = 10000000.0;
//----
while(i > 0)
{
save_lastreverse = i;
price_low = Low[i];
//----
if(last_low > price_low)
last_low = price_low;
price_high = High[i];
//----
if(last_high < price_high)
last_high = price_high;
//----
if(price_high > High[i+1] && price_low > Low[i+1])
break;
//----
if(price_high < High[i+1] && price_low < Low[i+1])
{
dirlong = false;
break;
}
i--;
}
//---- initial zero
int k = i;
Print(" k=", k, " Bars=", Bars);
//----
while(k < Bars)
{
SarBuffer[k] = 0.0;
k++;
}
//---- check further
if(dirlong)
{
SarBuffer[i] = Low[i+1];
ep = High[i];
}
else
{
SarBuffer[i] = High[i+1];
ep = Low[i];
}
i--;
}
else
{
i = save_lastreverse;
start = save_start;
dirlong = save_dirlong;
last_high = save_last_high;
last_low = save_last_low;
ep = save_ep;
sar = save_sar;
// Fix1 start
// If new bar increment index
if(Time[0] != bartime)
{
bartime = Time[0];
i++;
}
//Fix1 end
}
//----
while(i >= 0)
{
price_low = Low[i];
price_high = High[i];
//--- check for reverse from long to short
if(dirlong && price_low < SarBuffer[i+1])
{
SaveLastReverse(i, true, start, price_low, last_high, ep, sar);
start = Step;
dirlong = false;
ep = price_low;
last_low = price_low;
SarBuffer[i] = last_high;
i--;
continue;
}
//--- check for reverse from short to long
if(!dirlong && price_high > SarBuffer[i+1])
{
SaveLastReverse(i, false, start, last_low, price_high, ep, sar);
start = Step;
dirlong = true;
ep = price_high;
last_high = price_high;
SarBuffer[i] = last_low;
i--;
continue;
}
//sar(i) = sar(i+1)+start*(ep-sar(i+1))
price = SarBuffer[i+1];
sar = price + start*(ep - price);
//----
if(dirlong)
{
if(ep < price_high && (start + Step) <= Maximum)
start += Step;
//----
if(price_high < High[i+1] && i == Bars - 2)
sar = SarBuffer[i+1];
price = Low[i+1];
//----
if(sar > price)
sar = price;
price = Low[i+2];
//----
if(sar > price)
sar = price;
//----
if(sar > price_low)
{
SaveLastReverse(i, true, start, price_low, last_high, ep, sar);
start = Step;
dirlong = false;
ep = price_low;
last_low = price_low;
SarBuffer[i] = last_high;
i--;
continue;
}
//----
if(ep < price_high)
{
last_high = price_high;
ep = price_high;
}
} //dir-long
else
{
if(ep > price_low && (start + Step) <= Maximum)
start += Step;
//----
if(price_low < Low[i+1] && i == Bars - 2)
sar = SarBuffer[i+1];
price = High[i+1];
//----
if(sar < price)
sar = price;
price = High[i+2];
//----
if(sar < price)
sar = price;
//----
if(sar < price_high)
{
SaveLastReverse(i, false, start, last_low, price_high, ep,sar);
start = Step;
dirlong = true;
ep = price_high;
last_high = price_high;
SarBuffer[i] = last_low;
i--;
continue;
}
//----
if(ep > price_low)
{
last_low = price_low;
ep = price_low;
}
} //dir-short
SarBuffer[i] = sar;
i--;
} //while
// sar=SarBuffer[0];
// price=iSAR(NULL,0,Step,Maximum,0);
// if(sar!=price) Print("custom=",sar," SAR=",price," counted=",counted_bars);
// if(sar==price) Print("custom=",sar," SAR=",price," counted=",counted_bars);
//----
return(0);
}
//+------------------------------------------------------------------+
Parabilic SAR MQ5 Code Base (Copy Code)
//+------------------------------------------------------------------+
//| ParabolicSAR.mq5 |
//| Copyright 2009, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
//--- indicator settings
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 1
#property indicator_type1 DRAW_ARROW
#property indicator_color1 DodgerBlue
//--- External parametrs
input double InpSARStep=0.02; // Step
input double InpSARMaximum=0.2; // Maximum
//---- buffers
double ExtSARBuffer[];
double ExtEPBuffer[];
double ExtAFBuffer[];
//--- global variables
int ExtLastRevPos;
bool ExtDirectionLong;
double ExtSarStep;
double ExtSarMaximum;
//+------------------------------------------------------------------+
//| 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;
//---- indicator buffers
SetIndexBuffer(0,ExtSARBuffer);
SetIndexBuffer(1,ExtEPBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(2,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;
//----
}
//+------------------------------------------------------------------+
//| 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 &TickVolume[],
const long &Volume[],
const int &Spread[])
{
//--- check for minimum rates count
if(rates_total<3)
return(0);
//--- detect current position
int pos=prev_calculated-1;
//--- correct position
if(pos<1)
{
//--- first pass, set as SHORT
pos=1;
ExtAFBuffer[0]=ExtSarStep;
ExtAFBuffer[1]=ExtSarStep;
ExtSARBuffer[0]=High[0];
ExtLastRevPos=0;
ExtDirectionLong=false;
ExtSARBuffer[1]=GetHigh(pos,ExtLastRevPos,High);
ExtEPBuffer[0]=Low[pos];
ExtEPBuffer[1]=Low[pos];
}
//---main cycle
for(int i=pos;i<rates_total-1 && !IsStopped();i++)
{
//--- check for reverse
if(ExtDirectionLong)
{
if(ExtSARBuffer[i]>Low[i])
{
//--- switch to SHORT
ExtDirectionLong=false;
ExtSARBuffer[i]=GetHigh(i,ExtLastRevPos,High);
ExtEPBuffer[i]=Low[i];
ExtLastRevPos=i;
ExtAFBuffer[i]=ExtSarStep;
}
}
else
{
if(ExtSARBuffer[i]<High[i])
{
//--- switch to LONG
ExtDirectionLong=true;
ExtSARBuffer[i]=GetLow(i,ExtLastRevPos,Low);
ExtEPBuffer[i]=High[i];
ExtLastRevPos=i;
ExtAFBuffer[i]=ExtSarStep;
}
}
//--- continue calculations
if(ExtDirectionLong)
{
//--- check for new High
if(High[i]>ExtEPBuffer[i-1] && i!=ExtLastRevPos)
{
ExtEPBuffer[i]=High[i];
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[i] || ExtSARBuffer[i+1]>Low[i-1])
ExtSARBuffer[i+1]=MathMin(Low[i],Low[i-1]);
}
else
{
//--- check for new Low
if(Low[i]<ExtEPBuffer[i-1] && i!=ExtLastRevPos)
{
ExtEPBuffer[i]=Low[i];
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[i] || ExtSARBuffer[i+1]<High[i-1])
ExtSARBuffer[i+1]=MathMax(High[i],High[i-1]);
}
}
//---- 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);
}
//+------------------------------------------------------------------+