Normalised Moving Average

Hello,
I am trying to build an indicator that displays a curve like a 20 day moving average, but on a standard scale of 1-10 for all stocks regardless of price. So the code below is pretty simple, but the question is how do I code the MA so it displays a scale of 1-10 (or any other standard scale) so that a score above 5 on one stock is the same as a score above 5 for another stock? Does that make sense? In other words I want a relative score that can be used to search for all stocks where the indicator value is above x on the relative scale.

Thanks in advance....PS my first post here so if I have not got the protocol right, soz.

_SECTION_BEGIN("Steve Momentum Indicator 4");

mom = MA(C,30);

Plot( mom, _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style") );
_SECTION_END();

Welcome to the forum.

That depends on what version you are using, in version 6.30 you can use Remap() function to achieve this:

Version( 6.30 );
mom = MA(C,30);
mom = Remap( mom, LowestVisibleValue( mom ), HighestVisibleValue( mom ), 1, 10 );

Plot( mom, _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style") );

Please note that it uses only visible bars to normalize.

5 Likes

Awesome, thank you so much...

1 Like

Okay, I see the problem with "only visible bars to normalize". Is there another way...so that the displayed indicator does not change as the data is scrolled...

One possibility is using BeginValue/EndValue.
If no range is selected (via range markers -> two times chart double click -> to set start and end of range) then it is applied on entire array (-> QuickAFL off). Graph remains unchanged on scroll/zoom (since min/max of set range are used).

bi = BarIndex(); 

function NormalizedIndicator(indicator, dstMin, dstMax) {
	/// Normalized indicator of a set range
	/// (remains unchanged on scroll/zoom)
	/// @link https://forum.amibroker.com/t/normalised-moving-average/13467/5
	/// derived from
	/// @link https://forum.amibroker.com/t/normalised-moving-average/13467/2
	local start_bi, end_bi, indicator_range, min_val, max_val, norm_indicator; 
	start_bi = BeginValue(bi);
	end_bi = EndValue(bi);
	indicator_range = IIf(bi >= start_bi AND bi <= end_bi, indicator, Null);
	min_val = EndValue(Lowest(indicator_range));
	max_val = EndValue(Highest(indicator_range));
	norm_indicator = Remap(indicator_range, Nz(min_val), Nz(max_val), dstMin, dstMax );
	return norm_indicator;
}

Version( 6.30 );
indicator = MA(C, 30);// your indicator
norm_indicator = NormalizedIndicator(indicator, 1, 10);

Plot( norm_indicator, _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style") );
3 Likes

If you don't want to use visible bars, you can just use ALL bars as shown below:

Version( 6.30 );
mom = MA(C,30);
mom = Remap( mom, LastValue( Lowest( mom ) ), LastValue( Highest( mom ) ), 1, 10 );

Plot( mom, _DEFAULT_NAME(), ParamColor( "Color", colorCycle ), ParamStyle("Style") );
4 Likes

cheers...thankyou :slight_smile: :slight_smile:

This is a very late response, but here’s sample AFL to normalize an array called X (could be your MA), and a graph of the resulting normalization, which will always lie between 0 and 1, and which will give you the same normalized value for every occurence of the same value of X. Inputs are Alpha, X_high, and X_low. x_high and x_low are your best guesses for the range of X, but the normalized value will always lie betwen 0 and 1, regardless of how accurately you estimate those values.

Alpha = 0.05;
X_high = 85;
X_low = -60;
A = 2log(alpha/(1-alpha))/(x_high-x_low);
B = log(alpha/(1-alpha))
(x_high+x_low)/(x_high-x_low);
Normalization = 1 / (1+exp(-(A * x + B)));

Graph of Normalization

@DPW - When posting the formula, please make sure that you use Code Tags (using </> code button) as explained here: How to use this site.

Using code button

Code tags are required so formulas can be properly displayed and copied without errors.