sto_JMA_Stochastic_KDSL

Download script
Author: Dm_35
sto_JMA_Stochastic_KDSL

This script is designed for the MetaTrader platform to provide traders with a smoothed, responsive visual representation of price momentum. It combines two distinct mathematical concepts—the Stochastic Oscillator and the Jurik Moving Average (JMA)—to create a specialized trading indicator.

Here is a breakdown of how the logic works in non-technical terms:

1. The Foundation: Momentum Tracking

The script begins by looking at the Stochastic Oscillator. In standard trading, this tool identifies where the price is relative to its recent high and low range, helping traders see if a market is "overbought" or "oversold." Instead of plotting the raw, often jagged Stochastic lines directly onto your chart, this script uses them as the primary data source for further processing.

2. The Core Engine: Jurik Moving Average (JMA)

The "heart" of this script is the Jurik Moving Average. The JMA is highly regarded in trading circles because it solves a classic problem: standard moving averages often suffer from a trade-off between smoothness and lag (the delay in showing current price action).

The logic here applies a complex series of mathematical filters to the Stochastic data. It uses several internal "rings" and "buffers" to:

  • Reduce Noise: It filters out minor price flickers that might cause false signals.
  • Minimize Lag: It attempts to stay as close to the current price action as possible, reacting quickly to significant turns in the market.
  • Dynamic Adaptation: The script uses various calculations (logarithmic and power functions) to ensure the "smoothness" of the line adapts intelligently based on the volatility of the data.

3. Signal Processing (The Dual Lines)

The script generates two distinct lines on your visual window:

  • Primary Line (Red): This represents the smoothed JMA of the Stochastic values. It provides the main trend and momentum direction.
  • Signal Line (Orange): The script then takes that primary Red line and applies an additional Moving Average to it. This creates a "signal" line, similar to how many other oscillators work.

4. How a Trader Interprets the Logic

Because the script combines momentum (Stochastic) with sophisticated smoothing (JMA), the resulting visual output is intended to show clear trends in market energy:

  • Crossovers: When the Red line crosses the Orange line, it suggests a shift in momentum.
  • Trend Identification: The lines move together to show whether the "speed" of the market is accelerating or decelerating.
  • Overbought/Oversold Context: By keeping the underlying Stochastic logic, the indicator remains aware of extreme price reaches while providing a much cleaner visual path than a standard oscillator.

Summary for the User

Essentially, this script takes a very "noisy" and fast-moving momentum indicator (Stochastic) and puts it through a high-performance "filter" (Jurik Moving Average). The result is a pair of smooth lines that tell you where the market's momentum is heading with significantly less visual clutter and delayed reaction than standard tools.

Indicators Used
Stochastic oscillatorMoving average indicator
Miscellaneous
Implements a curve of type %1
13 Views
0 Downloads
0 Favorites
sto_JMA_Stochastic_KDSL
//+------------------------------------------------------------------+
//|                                                      JMA_WPR.mq4 |
//|                                                     JMA - Spiggy |
//|                                                       Dm_35 2008 |
//|  modJMA Sto KD                     http://www.fxexpert.ru/forum/ |
//+------------------------------------------------------------------+
//mod 
#property copyright "Dm_35"
#property link      "dm34@mail.ru"

//----
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Orange

#property indicator_level1 80
#property indicator_level2 50
#property indicator_level3 20
#property indicator_levelcolor DarkSlateGray

//---- input parameters
extern int StoKPeriod=14;
extern int StoDPeriod=3;
extern int StoSlowing=3;
extern int StoMAMethod=0;
extern int StoPriceField=1;

extern string stoPriceField_  = "0=Hi/Low   1=Close/Close";
extern string stoMA_Method_   = "SMA0 EMA1 SMMA2 LWMA3";
extern string stoKDLine_mode_ = "0 %K, 1 %D";

extern int stoKDmode=0;

extern int       JMALen=8;
extern int       JMAphase=0;
extern int       BarCount=900;

extern int SigMa_Period =3;
extern int SigMa_Method =0;



//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBuffer1);

   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,ExtMapBuffer2);


//----
   string short_name="STO JMA ("+StoKPeriod+","+StoDPeriod+","+StoSlowing+" ; "+ JMALen+ ","+ JMAphase+ ")";
   IndicatorShortName(short_name);
   SetIndexLabel(0, short_name);

   return(0);
  }
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//---- 
   // variable definitions
   int jj=0;
   int ii=0;
   int shift=0;
   double series=0;
//----
   double vv=0;
   double v1=0;
   double v2=0;
   double v3=0;
   double v4=0;
   double s8=0;
   double s10=0;
   double s18=0;
   double s20=0;
   int v5=0;
   int v6=0;
   double s28=0;
   double s30=0;
   int s38=0;
   int s40=0;
   int s48=0;
   int s50=0;
   int s58=0;
   int s60=0;
   double s68=0;
   double s70=0;
   double f8=0;
   double f10=0;
   double f18=0;
   double f20=0;
   double f28=0;
   double f30=0;
   double f38=0;
   double f40=0;
   double f48=0;
   double f50=0;
   double f58=0;
   double f60=0;
   double f68=0;
   double f70=0;
   double f78=0;
   double f80=0;
   double f88=0;
   double f90=0;
   double f98=0;
   double fA0=0;
   double fA8=0;
   double fB0=0;
   double fB8=0;
   double fC0=0;
   double fC8=0;
   double fD0=0;
   double f0=0;
   double fD8=0;
   double fE0=0;
   double fE8=0;
   int fF0=0;
   double fF8=0;
   int value2=0;
   double JMA=0;

//----
   double list[127];
   double ring1[127];
   double ring2[10];
   double buffer[61];
//----
   ArrayInitialize(list,0);
   ArrayInitialize(ring1,0);
   ArrayInitialize(ring2,0);
   ArrayInitialize(buffer,0);
//----

      s28=63;
      s30=64;
      for( ii=1;ii<=s28;ii++)
        {
         list[ii]=-1000000;
        }
      for( ii=s30;ii<=127 ;ii++ )
        {
         list[ii]=1000000;
        }
      f0=1;
//----
   for( shift=BarCount;shift>=0;shift-- )
     {
      
      series=iStochastic(NULL,0,StoKPeriod,StoDPeriod,StoSlowing,StoMAMethod,StoPriceField,stoKDmode,shift);
       
      if (fF0 < 61)
        {
         fF0= fF0 + 1;
         buffer[fF0]=series;
        } //{ main cycle } 
      if (fF0 > 30)
        {
         if (JMALen < 1.0000000002)
           {
            f80=0.0000000001; //{1.0e-10} 
           }
         else
           {
            f80=(JMALen - 1)/2.0;
           }
         if (JMAphase < -100)
           {
            f10=0.5;
           }
         else
           {
            if (JMAphase > 100)
              {
               f10=2.5;
              }
            else
              {
               f10=JMAphase/100 + 1.5;
              }
           }
         v1=MathLog(MathSqrt(f80));
         v2=v1;
         if (v1/MathLog(2.0) + 2.0 < 0.0)
           {
            v3=0;
           }
         else
           {
            v3=v2/MathLog(2.0) + 2.0;
           }
         f98=v3;
//----
         if (0.5<=f98 - 2.0)
           {
            f88=f98 - 2.0;
           }
         else
           {
            f88=0.5;
           }
         f78=MathSqrt(f80) * f98;
         f90=f78/(f78 + 1.0);
         f80=f80 * 0.9;
         f50=f80/(f80 + 2.0);
//----
         if (f0!=0)
           {
            f0=0;
            v5=0;
            for( ii=1;ii <=29;ii++)
              {
               if (buffer[ii+1]!=buffer[ii])
                 {
                  v5=1.0;
                 }
              }
            fD8=v5*30.0;
            if (fD8==0)
              {
               f38=series;
              }
            else
              {
               f38=buffer[1];
              }
            f18=f38;
            if (fD8 > 29)
               fD8=29;
           }
         else
            fD8=0;
//----
         for( ii=fD8;ii>=0;ii-- )
           { //{ another bigcycle...} 
            value2=31-ii;
            if (ii==0)
              {
               f8=series;
              }
            else
              {
               f8=buffer[value2];
              }
            f28=f8 - f18;
            f48=f8 - f38;
            if (MathAbs(f28) > MathAbs(f48))
              {
               v2=MathAbs(f28);
              }
            else
              {
               v2=MathAbs(f48);
              }
            fA0=v2;
            vv=fA0 + 0.0000000001; //{1.0e-10;} 
//----
            if (s48<=1)
              {
               s48=127;
              }
            else
              {
               s48=s48 - 1;
              }
            if (s50<=1)
              {
               s50=10;
              }
            else
              {
               s50=s50 - 1;
              }
            if (s70 < 128)
               s70=s70 + 1;
            s8=s8 + vv - ring2[s50];
            ring2[s50]=vv;
            if (s70 > 10)
              {
               s20=s8/10;
              }
            else
               s20=s8/s70;
//----
            if (s70 > 127)
              {
               s10=ring1[s48];
               ring1[s48]=s20;
               s68=64;
               s58=s68;
               while(s68 > 1)
                 {
                  if (list[s58] < s10)
                    {
                     s68=s68 *0.5;
                     s58=s58 + s68;
                    }
                  else
                     if (list[s58]<=s10)
                       {
                        s68=1;
                       }
                     else
                       {
                        s68=s68 *0.5;
                        s58=s58 - s68;
                       }
                 }
              }
            else
              {
               ring1[s48]=s20;
               if (s28 + s30 > 127)
                 {
                  s30=s30 - 1;
                  s58=s30;
                 }
               else
                 {
                  s28=s28 + 1;
                  s58=s28;
                 }
               if (s28 > 96)
                 {
                  s38=96;
                 }
               else
                  s38=s28;
               if (s30 < 32)
                 {
                  s40=32;
                 }
               else
                  s40=s30;
              }
//----
            s68=64;
            s60=s68;
            while(s68 > 1)
              {
               if (list[s60]>=s20)
                 {
                  if (list[s60 - 1]<=s20)
                    {
                     s68=1;
                    }
                  else
                    {
                     s68=s68 *0.5;
                     s60=s60 - s68;
                    }
                 }
               else
                 {
                  s68=s68 *0.5;
                  s60=s60 + s68;
                 }
               if ((s60==127) && (s20 > list[127]))
                  s60=128;
              }

            if (s70 > 127)
              {
               if (s58>=s60)
                 {
                  if ((s38 + 1 > s60) && (s40 - 1 < s60))
                    {
                     s18=s18 + s20;
                    }
                  else
                     if ((s40 > s60) && (s40 - 1 < s58))
                        s18=s18 + list[s40 - 1];
                 }
               else
                  if (s40>=s60)
                    {
                     if ((s38 + 1 < s60) && (s38 + 1 > s58))
                        s18=s18 + list[s38 + 1];
                    }
                  else
                     if (s38 + 2 > s60)
                       {
                        s18=s18 + s20;
                       }
                     else
                        if ((s38 + 1 < s60) && (s38 + 1 > s58))
                           s18=s18 + list[s38 + 1];

               if (s58 > s60)
                 {
                  if ((s40 - 1 < s58) && (s38 + 1 > s58))
                    {
                     s18=s18 - list[s58];
                    }
                  else
                     if ((s38 < s58) && (s38 + 1 > s60))
                        s18=s18 - list[s38];
                 }
               else
                 {
                  if ((s38 + 1 > s58) && (s40 - 1 < s58))
                    {
                     s18=s18 - list[s58];
                    }
                  else
                     if ((s40 > s58) && (s40 < s60))
                        s18=s18 - list[s40];
                 }
              }
            if (s58<=s60)
              {
               if (s58>=s60)
                 {
                  list[s60]=s20;
                 }
               else
                 {
                  for( jj=s58 + 1;jj<=s60 - 1;jj++)
                    {
                     list[jj - 1]=list[jj];
                    }
                  list[s60 - 1]=s20;
                 }
              }
            else
              {
               for( jj=s58 - 1;jj>=s60;jj-- )
                 {
                  list[jj + 1]=list[jj];
                 }
               list[s60]=s20;
              }
            if (s70<=127)
              {
               s18=0;
               for(jj=s40;jj<=s38;jj++)
                 {
                  s18=s18 + list[jj];
                 }
              }
            f60=s18/(s38 - s40 + 1);
            if (fF8 + 1 > 31)
              {
               fF8=31;
              }
            else
               fF8=fF8 + 1;
//----
            if (fF8<=30)
              {
               if (f28 > 0)
                 {
                  f18=f8;
                 }
               else
                  f18=f8 - f28 * f90;
               if (f48 < 0)
                 {
                  f38=f8;
                 }
               else
                  f38=f8 - f48 * f90;
               fB8=series;
//{EasyLanguage does not have "continue" statement} 
               if (fF8!=30)
                 {
                  continue;
                 }
               if (fF8==30)
                 {
                  fC0=series;
                  if (MathCeil(f78)>=1)
                    {
                     v4=MathCeil(f78);
                    }
                  else
                     v4=1;
                  fE8=MathCeil(v4);
                  if (MathFloor(f78)>=1)
                    {
                     v2=MathFloor(f78);
                    }
                  else
                     v2=1;
                  fE0=MathCeil(v2);
                  if (fE8==fE0)
                    {
                     f68=1;
                    }
                  else
                    {
                     v4=fE8 - fE0;
                     f68=(f78 - fE0)/v4;
                    }
                  if (fE0<=29)
                    {
                     v5=fE0;
                    }
                  else
                     v5=29;
                  if (fE8<=29)
                    {
                     v6=fE8;
                    }
                  else
                     v6=29;
                  fA8=(series - buffer[fF0 - v5]) * (1 - f68)/fE0 + (series - buffer[fF0 - v6]) * f68/fE8;
                 }
              }
            else
              {
               if (f98>=MathPow(fA0/f60, f88))
                 {
                  v1=MathPow(fA0/f60, f88);
                 }
               else
                  v1=f98;
               if (v1 < 1)
                 {
                  v2=1;
                 }
               else
                 {
                  if (f98>=MathPow(fA0/f60, f88))
                    {
                     v3=MathPow(fA0/f60, f88);
                    }
                  else
                     v3=f98;
                  v2=v3;
                 }
               f58=v2;
               f70=MathPow(f90, MathSqrt(f58));
               if (f28 > 0)
                 {
                  f18=f8;
                 }
               else
                 {
                  f18=f8 - f28 * f70;
                 }
               if (f48 < 0)
                 {
                  f38=f8;
                 }
               else
                 {
                  f38=f8 - f48 * f70;
                 }
              }
           }
         if (fF8 > 30)
           {
            f30=MathPow(f50, f58);
            fC0=(1 - f30) * series + f30 * fC0;
            fC8=(series - fC0) * (1 - f50) + f50 * fC8;
            fD0=f10 * fC8 + fC0;
            f20=-f30 * 2;
            f40=f30 * f30;
            fB0=f20 + f40 + 1;
            fA8=(fD0 - fB8) * fB0 + f40 * fA8;
            fB8=fB8 + fA8;
           }
         JMA= fB8;
        }
      if (fF0<=30)
        {
         JMA=0;
        }
//Print ("JMA is " + JMA + " shift is " + shift); 
      ExtMapBuffer1[shift]=JMA;
        
     }
        
     for( shift=BarCount;shift>=0;shift-- )
     ExtMapBuffer2[shift]=iMAOnArray(ExtMapBuffer1,0,SigMa_Period,0,SigMa_Method,shift);

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

Comments