Attachments forums

Re: TASC magazine indicators

Banzai, Fri Oct 16, 2026 9:24 am

The UniEMA: A Universal Exponential Moving Average

Links: | Tradingview | TradeStation | NinjaTrader | MT4 | MT5 | Python |

TradeStation: November 2026
In the article “The UniEMA: A Universal Exponential Moving Average” in this issue, Igor Durkin presents a universal EMA designed to manage the tradeoff between lag and noise. The approach consolidates EMA, DEMA, TEMA, and related smoothing methods into a single indicator controlled by four parameters. The EasyLanguage implementation contains two functions and two corresponding indicators. The UniEMA indicator plots a single universal EMA line, while the UniEMA Cascade indicator plots intermediate smoothing stages as a cascade. The UniEMA indicator can be applied multiple times with different inputs to compare varying degrees of smoothing and observe crossovers as turning points.

Code: Select all

Function: UniXMA

{*******************************************************
TASC NOV 2026
Description : UniXMA Function
Provided By : (C) 2011-2026 Igor Durkin, trendlaboratory.net
*******************************************************}

inputs: 
	price( numericseries ),
	length( numericsimple ),
	poles( numericsimple ),
	order( NumericSimple ),
	wf( numericsimple ),
	df( NumericSimple );

variables: 
	alpha(0), 
	bet(0), 
	k(0), 
	j(0), 
	uniema(0), 
	uni_size(0);

arrays: 
	uniema_tmp[](0);
{ calculate alpha once—lag is preserved across all Order 
values }
once 
begin
	alpha = wf*order / (length + wf*order - 1);
	bet = 1 - alpha;
	uni_size = poles * order;
	Array_SetMaxIndex( uniema_tmp, uni_size - 1 );
end;

uniema = price;

if currentbar >= 1 then 
begin
 { outer loop—Order passes }
 for k=0 to order-1 
 begin
 	{ inner loop—Poles correction }
 	for j=0 to poles-1 
 	begin
 		{ initialise filter state at first call }
 		if currentbar = 1 then
 			uniema_tmp[poles*k+j] = price
 		else 
 		begin
 			uniema_tmp[poles*k+j] = bet 
 			 * uniema_tmp[poles*k+j][1] 
 			 + alpha * uniema; 
 			if j > 0 then
 				uniema = uniema 
 				 + df 
 				 * (uniema_tmp[poles*k] 
 				 - uniema_tmp[poles*k+j])
 			else
 				uniema = uniema_tmp[poles*k+j];
 			end;
 		end;
	end;
end;

UniXMA = uniema;


Function: UniXMA_arr

{*******************************************************
TASC NOV 2026
Description : UniXMA_arr Function
Provided By : (C) 2011-2026 Igor Durkin, trendlaboratory.net
*******************************************************}

inputs: 
	price( numericseries ),
	length( numericsimple ),
	poles( numericsimple ),
	order( numericsimple ),
	wf( numericsimple ),
	df( numericsimple ),
	outarray[n]( numericarrayref );

variables: 
	alpha( 0 ), 
	bet( 0 ), 
	k( 0 ), 
	j( 0 ), 
	uniema( 0 ), 
	uni_size( 0 );
	
arrays: 
	uniema_tmp[]( 0 );
{ calculate alpha once—lag is preserved across all Order
values }
once 
begin
	alpha = wf * order / (length + wf * order - 1);
	bet = 1 - alpha;
	uni_size = poles*order;
 	Array_SetMaxIndex(uniema_tmp, uni_size-1);
end;

uniema = price;

if currentbar >= 1 then 
begin
 { outer loop—Order passes }
	for k=0 to order-1 
 	begin
 		{ inner loop—Poles correction }
 		for j=0 to poles-1 begin
 			{ initialise filter state at first call }
 			if currentbar = 1 then
 				uniema_tmp[poles*k+j] = price
 			else 
 			begin
 				uniema_tmp[poles*k+j] = bet
 		 	 	 * uniema_tmp[poles*k+j][1] + alpha * uniema;
 				if j > 0 then
 				uniema = uniema + df*(uniema_tmp[poles*k]
		 	 	- uniema_tmp[poles*k+j])
 				else
					uniema = uniema_tmp[poles*k+j];
			end;
		end;
 		outarray[k] = uniema;
 	end;
end;

UniXMA_arr = uniema;


Indicator: UniEMA

{*******************************************************
TASC NOV 2026
Description : This Indicator plots UniEMA
Provided By : (C) 2011-2026 Igor Durkin, trendlaboratory.net
*******************************************************}

inputs: 
	double Price( Close), // Applied to
	int Length( 14 ), // Period
	int Poles( 2 ), // Poles: 1-EMA, 2-DEMA, 3-TEMA, 4-QEMA
	int Order( 3 ), // Smoothing Order (min. 1)
	double WeightFactor( 2 ), // (Wilder=1,EMA=2)
	double DampingFactor( 0.5 ), // Damping Factor (ex. 0.7)
	int Displace( 0 ), // Displace in bars
	bool ShowColorLine( true ), // Show Color Line
	int UpTrendColor( blue ), // UpTrend Color
	int DnTrendColor( red ), // DownTrend Color
	int ColorBarsBack( 1 ); // Color Bars Back (0 or 1)
	
variable: 
	UniEMA( 0 ), 
	trend( 0 );
	
if Displace >= 0 or CurrentBar > AbsValue(Displace) then
begin
	UniEMA = UniXMA(Price, Length, Poles, Order,
	 WeightFactor, DampingFactor);
 	
 	Plot1[Displace]( UniEMA,"UniEMA" );
 	
 	if ShowColorLine then 
 	begin
 		trend = trend[1];
 		
 		if UniEMA > UniEMA[1] then trend = 1;
 		
 		if UniEMA < UniEMA[1] then trend = -1;
 		
 		if trend > 0 then 
 			SetPlotColor[Displace + ColorBarsBack]
 			 (1, UpTrendColor);
 		if trend < 0 then
 			SetPlotColor[Displace + ColorBarsBack]
 		 	(1, DnTrendColor);
 	end;
 		
 	if Displace <= 0 then 
 	begin
 		if Price > UniEMA and UniEMA > UniEMA[1] 
 		and UniEMA[1] <= UniEMA[2] then
			Alert( "Indicator turning up" )
		else if Price < UniEMA and UniEMA < UniEMA[1] 
		 and UniEMA[1] >= UniEMA[2] then
 			Alert( "Indicator turning down" );
 	end;
end;


Indicator: UniEMA Cascade

{*******************************************************
TASC NOV 2026
Description : This Indicator plots UniEMA Cascade
Provided By : (C) 2011-2026 Igor Durkin, trendlaboratory.net
*******************************************************}

inputs: 
	double Price( Close ), 		// Applied to
	int Length( 14), 			// Period
	int Poles( 1 ), 			// Poles (min. 1)
	int Order( 20 ), 			// Smoothing Order (min. 1)
	double WeightFactor( 2 ), 	// (Wilder=1,EMA=2)
	double DampingFactor( 0 ), 	// Damping Factor
	int UpTrendColor( Green ), 	// UpTrend Color
	int DnTrendColor( Red ); 	// DownTrend Color

variables: 
	int k( 0 ), 
	double UniEMA( 0 );

array: 
	smooths[](0), 
	trend[](0);

once 
begin
	Array_SetMaxIndex( smooths, Order - 1 );
	Array_SetMaxIndex( trend, Order - 1 );
end;

if CurrentBar > 1 then 
begin
	UniEMA = UniXMA_arr( Price, Length, Poles, Order,
	 WeightFactor, DampingFactor, smooths);

	for k = 0 to Order-1 
	begin
		trend[k] = trend[k][1];
		
		if smooths[k] > smooths[k][1] then 
			trend[k] = 1;
		if smooths[k] < smooths[k][1] then 
			trend[k] = -1;

		switch(k) 
		begin
			case 0: Plot1( smooths[k],"Order #1" );
			case 1: Plot2( smooths[k],"Order #2" );
			case 2: Plot3( smooths[k],"Order #3" );
			case 3: Plot4( smooths[k],"Order #4" );
			case 4: Plot5( smooths[k],"Order #5" );
			case 5: Plot6( smooths[k],"Order #6" );
			case 6: Plot7( smooths[k],"Order #7" );
			case 7: Plot8( smooths[k],"Order #8" );
			case 8: Plot9( smooths[k],"Order #9" );
			case 9: Plot10( smooths[k],"Order #10" );
			case 10: Plot11( smooths[k],"Order #11" );
			case 11: Plot12( smooths[k],"Order #12" );
			case 12: Plot13( smooths[k],"Order #13" );
			case 13: Plot14( smooths[k],"Order #14" );
			case 14: Plot15( smooths[k],"Order #15" );
			case 15: Plot16( smooths[k],"Order #16" );
			case 16: Plot17( smooths[k],"Order #17" );
			case 17: Plot18( smooths[k],"Order #18" );
			case 18: Plot19( smooths[k],"Order #19" );
			case 19: Plot20( smooths[k],"Order #20" );
		end;
		
		if trend[k] > 0 then 
			SetPlotColor[1]( k + 1, UpTrendColor)
		else 
			SetPlotColor[1]( k + 1, DnTrendColor);
	end;
end;


A sample chart is shown in Figure 1.

Sample Chart
FIGURE 1: TRADESTATION. This shows a daily chart of the S&P 500 ETF SPY, showing a portion of 2026 with the UniEMA Cascade indicator applied.
All files in topic