Author: Weld
JMA_v5

The logic within this script is designed to create a sophisticated technical indicator that smooths out price data while attempting to minimize "lag"—the delay between a price movement occurring and the indicator reflecting that change.

At its core, the logic functions through several distinct mathematical stages:

Dynamic Adaptation

Instead of using a standard moving average (which treats all past data points equally), this script calculates how much weight to give to recent price changes versus older data. It uses "Phase" and "Length" inputs to determine how aggressively the indicator should react. By calculating various powers and roots based on these inputs, it creates a curve that can be adjusted to be more sensitive or more stable depending on the market conditions.

Signal Filtering

The script employs a unique mechanism to identify and process price momentum. It tracks the difference between current prices and historical values, identifying whether the "swing" in price is increasing or decreasing. This allows the logic to "anticipate" some of the curvature of the trend rather than just trailing behind it.

Complex Smoothing Layers

The indicator does not produce its final line in a single step. It passes the data through multiple layers of processing:

  1. Initial Filtering: The raw price data is stored in a memory buffer to establish a baseline.
  2. Momentum Analysis: It calculates the "velocity" of price movement.
  3. Weighted Smoothing: It applies specific weights to the filtered results to ensure the line remains fluid and doesn't create erratic spikes or "noise."
  4. Phase Shifting: It uses a secondary calculation to adjust the position of the indicator, aiming to keep it as close to the current price action as possible without being overwhelmed by minor fluctuations.

Final Output

The final result is a smoothed line that represents a balanced middle ground between two extremes:

  • A standard moving average (which is very smooth but very slow/laggy).
  • A raw price line (which is very fast but very noisy/erratic).

By using this multi-layered mathematical approach, the script provides a visual representation of the trend that aims to be "smart"—reacting quickly to significant shifts in direction while ignoring the minor "jitter" of the market.

15 Views
0 Downloads
0 Favorites
JMA_v5
//+------------------------------------------------------------------+
//|                                                          JMA.mq4 |
//|                                             Weld, Jurik Research |
//|                                          http://weld.torguem.net |
//+------------------------------------------------------------------+
#property copyright "Weld"
#property link      "http://weld.torguem.net"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Aqua
//---- input parameters
extern int       Length = 14;
extern int       Phase  = 0;
//---- buffers
double JMABuffer [];
double fC0Buffer [];
double fA8Buffer [];
double fC8Buffer [];

double list[128], ring1[128], ring2[11], buffer[62];

bool   initial;  
int    s28, s30, s48, s68, s50, s70, fF0, s58, s60, s40, s38, v5, v6, fD8, fE8, fE0;
double vv, v1, v2, v3, v4, s8, s10, s18, s20, f8, f10, f18, f20, f28, f30, f38, f40,  f48, f50, f58, f60, f68, 
         f70, f78, f80, f88, f90, f98, fA0, fB0, fB8, fC0, fD0,  fF8, JMA, series;
//+------------------------------------------------------------------+
//| JMA initialization function                                      |
//+------------------------------------------------------------------+
int init()
  {
   int i;
//---- 2 additional buffers are used for counting.
   IndicatorBuffers(4);
//---- drawing settings
   SetIndexStyle  (0, DRAW_LINE, STYLE_SOLID, 2);
   SetIndexDrawBegin(0, 30);
//---- 2 indicator buffers mapping
   SetIndexBuffer (0, JMABuffer);
   SetIndexBuffer (1, fC0Buffer);
   SetIndexBuffer (2, fA8Buffer);
   SetIndexBuffer (3, fC8Buffer);                 
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName ("JMA(" + Length + "," + Phase + ")");
   SetIndexLabel (0, "JMA");
//---- initial part
   s28 = 63; s30 = 64;
   
   for (i = 0; i <= s28; i++)   list [i] = -1000000; 
   for (i = s30; i <= 127; i++) list [i] = 1000000; 

   initial  = true;

   if (Length < 1.0000000002) f80 = 0.0000000001;
   else f80 = (Length - 1) / 2.0;
   
   if (Phase < -100) f10 = 0.5;
   else if (Phase > 100) f10 = 2.5;
   else f10 = Phase / 100.0 + 1.5;

   v1 = MathLog (MathSqrt (f80)); 
   v2 = v1;
   if (v1 / MathLog(2.0) + 2.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);

   return;
}
//+------------------------------------------------------------------+
//| JMA iteration function                                           |
//+------------------------------------------------------------------+
int start()
  {
   int ii, jj, shift, limit;
   int counted_bars = IndicatorCounted();
//---- check for possible errors
   if (counted_bars < 0) return (-1);
   limit = Bars - counted_bars - 1;
//----
   for (shift = limit; shift >= 0; shift--) {
      series = Close [shift];
 
      if (fF0 < 61) { 
         fF0++; 
         buffer [fF0] = series; 
      } 
      if (fF0 > 30) {
         if (initial) { 
            initial = false;
             
            v5 = 0; 
            for (ii = 1; ii <= 29; ii++) { 
               if (buffer [ii+1] != buffer[ii]) v5 = 1;
            }  
            fD8 = v5 * 30;
             
            if (fD8 == 0) f38 = series;
            else f38 = buffer[1];
             
            f18 = f38; 
            if (fD8 > 29) fD8 = 29; 
         } else 
            fD8 = 0;
//---- big cycle            
         for (ii = fD8; ii >= 0; ii--) { 
			   if (ii == 0) f8 = series; else f8 = buffer [31 - ii]; 
			   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--; 
			   if (s50 <= 1) s50 = 10; else s50--; 
			   if (s70 < 128) s70++; 
			   s8 += (vv - ring2 [s50]); 
			   ring2 [s50] = vv; 
			   if (s70 > 10) s20 = s8 / 10.0; 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 / 2.0; 
						   s58 += s68; 
					   } else 
					   if (list [s58] <= s10) { 
						   s68 = 1; 
					   } else { 
						   s68 = s68 / 2.0; 
						   s58 -= s68; 
					   }
               } 
            } else {
			      ring1 [s48] = s20; 
			      if ((s28 + s30) > 127) {
				      s30--; 
				      s58 = s30; 
			      } else {
				      s28++; 
				      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 / 2.0; 
					      s60 -= s68; 
				      }
			      }
			      else {
				      s68 = s68 / 2.0; 
				      s60 += s68; 
			      }
			      if ((s60 == 127) && (s20 > list[127])) s60 = 128; 
		      }
			   if (s70 > 127) {
				   if (s58 >= s60) {
					   if (((s38 + 1) > s60) && ((s40 - 1) < s60)) 
						    s18 += s20; 
					   else if ((s40 > s60) && ((s40 - 1) < s58)) 
						    s18 += list [s40 - 1]; 
				   }
				   else if (s40 >= s60) {
					   if (((s38 + 1) < s60) && ((s38 + 1) > s58)) 
							    s18 += list[s38 + 1]; 
					}
				   else if ((s38 + 2) > s60) 
						   s18 += s20; 
				   else if (((s38 + 1) < s60) && ((s38 + 1) > s58)) 
						   s18 += list[s38 + 1]; 
			
				   if (s58 > s60) {
					   if (((s40 - 1) < s58) && ((s38 + 1) > s58)) 
						   s18 -= list [s58]; 
					   else if ((s38 < s58) && ((s38 + 1) > s60)) 
						   s18 -= list [s38]; 
				   }
				   else {
					   if (((s38 + 1) > s58) && ((s40 - 1) < s58)) 
						   s18 -= list [s58]; 
					   else if ((s40 > s58) && (s40 < s60)) 
						   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 += list[jj]; 
				   }
			   }
			   f60 = s18 / (s38 - s40 + 1);
//----			    
			   if ((fF8 + 1) > 31) fF8 = 31; else fF8++; 
			   
			   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;
				 
				   if (fF8 == 30) { 
				     fC0Buffer [shift] = series;
				      
				     if (MathCeil(f78) >= 1) v4 = MathCeil(f78); else v4 = 1; 
				     fE8 = IntPortion (v4); 
				     if (MathFloor(f78) >= 1) v2 = MathFloor(f78); else v2 = 1; 
				     fE0 = IntPortion (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; 
				     fA8Buffer [shift] = (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; 
   		   }
         }
// ---- end of big cycle                  			   
         if (fF8 > 30) {
				fB8 = JMABuffer [shift + 1];
            f30 = MathPow (f50, f58);
             
				fC0 = (1 - f30) * series + f30 * fC0Buffer [shift + 1];
            fC8Buffer [shift] = (series - fC0) * (1 - f50) + f50 * fC8Buffer [shift + 1];
             
            fD0 = f10 * fC8Buffer [shift] + fC0; 
            f20 = f30 * (-2.0); 
            f40 = f30 * f30; 
            fB0 = f20 + f40 + 1;
            
            fA8Buffer [shift] = (fD0 - fB8) * fB0 + f40 * fA8Buffer [shift + 1];  
            fB8 += fA8Buffer [shift]; 
            
            fC0Buffer [shift] = fC0;
         }
         JMA = fB8;
      }
      if (fF0 <= 30) JMA = 0;
      JMABuffer [shift] = JMA;
//---- End of main cycle "for"
   } 
   return;
}

//+------------------------------------------------------------------+
int IntPortion (double param) {
   if (param > 0) return (MathFloor (param));
   if (param < 0) return (MathCeil (param));
   return (0.0);
}
//+------------------------------------------------------------------+

Comments