Is MT4's default stoachastic indicator wrong?

 

Hi,

I have found a few pages around claiming that the default stochastic indicator for MT4 is incorrect. Is that REALLY true ??? Is there a broad consensus on the issue? I could not find enough people talking about this to be completely satisfied with a concrete answer.

To try and check, I re-wrote a version of the stochastic indicator (the so called "slow" stochastic, which is the version used in MT4), using the rules from StockChart.com's "ChartSchool".

http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:stochastic_oscillato

%K = (Current Close - Lowest Low)/(Highest High - Lowest Low) * 100

%D = 3-day SMA of %K

----------------------------------------

The Slow Stochastic Oscillator smooths %K with a 3-day SMA, which is exactly what %D is in the Fast Stochastic Oscillator. Notice that %K in the Slow Stochastic Oscillator equals %D in the Fast Stochastic Oscillator ...

My code for %K appears to give the same answer as the default MT4 indicator ONLY when there is no "smoothing" or SMA applied to it. Therefore, the calculation for "(Current Close - Lowest Low)/(Highest High - Lowest Low) * 100" seems to be the same in both cases.

However, once a "smoothing" or SMA is applied to that part of the calculation, then the resulting display values differ. The difference is hard to see visually and my version at first glance appears to be the same as the default indicator, but if you use the data window in the MT4 terminal you can see that the values are often (but not always ... ) several decimal places out from each other. The largest difference I found was nearly 2%! That actually does amount to many signals being given a bar early or a bar late. Here is the code I used:

#property copyright ""
#property link ""

#property indicator_separate_window

#property indicator_buffers 3
#property indicator_color1 White
#property indicator_color2 White
#property indicator_color3 Red

#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1

#property indicator_maximum 100
#property indicator_minimum 0

#property indicator_level1 80
#property indicator_level2 20
#property indicator_levelstyle STYLE_DOT
#property indicator_levelcolor Red

//--- Input parameters

extern double StochPeriod = 14;
extern double MAPeriod = 3;

//--- Buffers

double BufBase[];
double BufK[];
double BufD[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- Indicators

SetIndexStyle(0,DRAW_NONE);
SetIndexBuffer(0,BufBase);
SetIndexLabel(0,"Base");

SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,BufK);
SetIndexLabel(1,"K");

SetIndexStyle(2,DRAW_LINE);
SetIndexBuffer(2,BufD);
SetIndexLabel(2,"D");

IndicatorShortName("Stochastic (Check) ("+StochPeriod+","+MAPeriod+")");

//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int iBarsToCalc = Bars - IndicatorCounted();
if (iBarsToCalc < Bars) iBarsToCalc++;
for (int i=iBarsToCalc-1;i>=0;i--) {
//----

{
BufBase[i] = EMPTY_VALUE;
BufK[i] = EMPTY_VALUE;
BufD[i] = EMPTY_VALUE;
}

// Main ----

double highest = iHigh(Symbol(), 0, i);
double lowest = iLow(Symbol(), 0, i);

int counter = 1;
while (counter <= StochPeriod-1)
{
if ( iHigh(Symbol(), 0, i+counter) > highest )
{ highest = iHigh(Symbol(), 0, i+counter); }

if ( iLow(Symbol(), 0, i+counter) < lowest )
{ lowest = iLow(Symbol(), 0, i+counter); }
counter++;
}
{
BufBase[i] = ((iClose(Symbol(), 0, i) - lowest)/(highest - lowest))*100;
}

// K ----

double matemp;
matemp = BufBase[i];
for ( counter = 1; counter <= MAPeriod-1; counter++ )
{
matemp += BufBase[i+counter];
}

BufK[i] = matemp/MAPeriod;

// D ----

matemp = BufK[i];
for ( counter = 1; counter <= MAPeriod-1; counter++ )
{
matemp += BufK[i+counter];
}

BufD[i] = matemp/MAPeriod;

//----
}
return(0);
}
//+------------------------------------------------------------------+


The buffer I have called "Base" is simply the equation "(Current Close - Lowest Low)/(Highest High - Lowest Low) * 100". That gives the same answer as the MT4 indicator used without "smoothing" or SMA (ie. a value of 1 in the Smoothing and %D input boxes).

Once I apply a 3 period SMA to that "Base" buffer, to create the buffer "K", then it differs from the %K buffer that the MT4 indicator displays when that is set to a "smoothing" of 3.

(The %D values are obviously different as well, because they are calculated from the %K).

SO WHAT IS GOING ON HERE ???

As far as I can tell I am implementing the 3 period SMA correctly to get the %K. Is there something really obvious I am missing? I have tried three different ways to calculate the SMA (simple sums, cycle operations and iMAOnArray) which all give the same answer.

I downloaded an alternative stochastic indicator from the codebase, and that gives the same answer as the default MT4 indicator. The code it seems to be using to calculate the "smoothing" for %K is:

// ---- %K line
i=Bars-draw_begin1;
if(counted_bars>draw_begin1) i=Bars-counted_bars-1;
while(i>=0)
{
double sumlow=0.0;
double sumhigh=0.0;
for(k=(i+Slowing-1);k>=i;k--)
{
sumlow+=Close[k]-LowesBuffer[k];
sumhigh+=HighesBuffer[k]-LowesBuffer[k];
}
if(sumhigh==0.0) MainBuffer[i]=100.0;
else MainBuffer[i]=sumlow/sumhigh*100;
i--;
}

I presume this is the same calculation used in the default indicator as well.

Obviously this is calculating it in a slightly different way to the method I used, but as far as I can see they SHOULD still give the same answer because it is basically the same equation just written in a different way. Isn't it ?

Can some smart person please enlighten me please? I've tried for AGES to figure out what is wrong, and I am leaning towards saying that MT4 is wrong ... but I want to be sure. Am I missing something important??

 
I have found the same issue - that the default Stochastic Oscillator on MetaTrader is wrong. I also did the same research as you on Chart School and created my own Excel spreadsheet so I can verify the data. What I found is that the attached indicator (which I found on Forex Factory here: http://www.forexfactory.com/showthread.php?t=299537) corresponds with my Excel calculations so I'm going to use it instead of the default one.



clerin6:

Hi,

I have found a few pages around claiming that the default stochastic indicator for MT4 is incorrect. Is that REALLY true ??? Is there a broad consensus on the issue? I could not find enough people talking about this to be completely satisfied with a concrete answer.

To try and check, I re-wrote a version of the stochastic indicator (the so called "slow" stochastic, which is the version used in MT4), using the rules from StockChart.com's "ChartSchool".

http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:stochastic_oscillato

My code for %K appears to give the same answer as the default MT4 indicator ONLY when there is no "smoothing" or SMA applied to it. Therefore, the calculation for "(Current Close - Lowest Low)/(Highest High - Lowest Low) * 100" seems to be the same in both cases.

However, once a "smoothing" or SMA is applied to that part of the calculation, then the resulting display values differ. The difference is hard to see visually and my version at first glance appears to be the same as the default indicator, but if you use the data window in the MT4 terminal you can see that the values are often (but not always ... ) several decimal places out from each other. The largest difference I found was nearly 2%! That actually does amount to many signals being given a bar early or a bar late. Here is the code I used:

#property copyright ""
#property link ""

#property indicator_separate_window

#property indicator_buffers 3
#property indicator_color1 White
#property indicator_color2 White
#property indicator_color3 Red

#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1

#property indicator_maximum 100
#property indicator_minimum 0

#property indicator_level1 80
#property indicator_level2 20
#property indicator_levelstyle STYLE_DOT
#property indicator_levelcolor Red

//--- Input parameters

extern double StochPeriod = 14;
extern double MAPeriod = 3;

//--- Buffers

double BufBase[];
double BufK[];
double BufD[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- Indicators

SetIndexStyle(0,DRAW_NONE);
SetIndexBuffer(0,BufBase);
SetIndexLabel(0,"Base");

SetIndexStyle(1,DRAW_LINE);
SetIndexBuffer(1,BufK);
SetIndexLabel(1,"K");

SetIndexStyle(2,DRAW_LINE);
SetIndexBuffer(2,BufD);
SetIndexLabel(2,"D");

IndicatorShortName("Stochastic (Check) ("+StochPeriod+","+MAPeriod+")");

//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----

//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int iBarsToCalc = Bars - IndicatorCounted();
if (iBarsToCalc < Bars) iBarsToCalc++;
for (int i=iBarsToCalc-1;i>=0;i--) {
//----

{
BufBase[i] = EMPTY_VALUE;
BufK[i] = EMPTY_VALUE;
BufD[i] = EMPTY_VALUE;
}

// Main ----

double highest = iHigh(Symbol(), 0, i);
double lowest = iLow(Symbol(), 0, i);

int counter = 1;
while (counter <= StochPeriod-1)
{
if ( iHigh(Symbol(), 0, i+counter) > highest )
{ highest = iHigh(Symbol(), 0, i+counter); }

if ( iLow(Symbol(), 0, i+counter) < lowest )
{ lowest = iLow(Symbol(), 0, i+counter); }
counter++;
}
{
BufBase[i] = ((iClose(Symbol(), 0, i) - lowest)/(highest - lowest))*100;
}

// K ----

double matemp;
matemp = BufBase[i];
for ( counter = 1; counter <= MAPeriod-1; counter++ )
{
matemp += BufBase[i+counter];
}

BufK[i] = matemp/MAPeriod;

// D ----

matemp = BufK[i];
for ( counter = 1; counter <= MAPeriod-1; counter++ )
{
matemp += BufK[i+counter];
}

BufD[i] = matemp/MAPeriod;

//----
}
return(0);
}
//+------------------------------------------------------------------+


The buffer I have called "Base" is simply the equation "(Current Close - Lowest Low)/(Highest High - Lowest Low) * 100". That gives the same answer as the MT4 indicator used without "smoothing" or SMA (ie. a value of 1 in the Smoothing and %D input boxes).

Once I apply a 3 period SMA to that "Base" buffer, to create the buffer "K", then it differs from the %K buffer that the MT4 indicator displays when that is set to a "smoothing" of 3.

(The %D values are obviously different as well, because they are calculated from the %K).

SO WHAT IS GOING ON HERE ???

As far as I can tell I am implementing the 3 period SMA correctly to get the %K. Is there something really obvious I am missing? I have tried three different ways to calculate the SMA (simple sums, cycle operations and iMAOnArray) which all give the same answer.

I downloaded an alternative stochastic indicator from the codebase, and that gives the same answer as the default MT4 indicator. The code it seems to be using to calculate the "smoothing" for %K is:

I presume this is the same calculation used in the default indicator as well.

Obviously this is calculating it in a slightly different way to the method I used, but as far as I can see they SHOULD still give the same answer because it is basically the same equation just written in a different way. Isn't it ?

Can some smart person please enlighten me please? I've tried for AGES to figure out what is wrong, and I am leaning towards saying that MT4 is wrong ... but I want to be sure. Am I missing something important??

Files:
 

MT4 averages C-LL then divided by average of HH-LL instead of taking the average of (C-LL)/(HH-LL) ....