ALMA next day value

I have used ALMA on multiple platforms. Without getting into the discussion about the worth of the information and purpose, it has always given a next day value. It does not do this in Amibroker. If you reference the next day Amibroker gives the same value as the current day.

How can I reference the next day value of ALMA? Is there some setting that I have missed?

Thanks for any help.

Nobody knows what formula you are using, unless you send it.

If you are using formula that was shipped with AmiBroker there is an "offset" parameter that you can use.

Alternatively any array can be shifted backwards/forwards using Ref() function
https://www.amibroker.com/f?ref

Typically however, tomorrow's value of indicator is not known until well... tomorrow.

1 Like

I have tried both of this code found from Amibroker. I did not say this explicitly, sorry for that.

function ALMA(priceField, windowSize, sigma, Offset)
{
	m = floor(Offset * (windowSize - 1));
	s = windowSize / sigma;

	w = 0;
	wSum = 0;

	for(i = 1; i < windowSize; i++)
	{
		w[i] = exp(-((i-m)*(i-m))/(s*s)); // 2 should be there?
		wSum += w[i];
	}

	for(i = 1; i < windowSize; i++)
	{
		w[i] = w[i] / wSum;
	}

	outalma = Null;

	for(j = 0; j < BarCount; j++)
	{
		alSum = 0;

		if(j < windowSize)
		{
			outalma[j] = Null;
		}
		else
		{
			for(i = 1; i < windowSize; i++)
			{
				alSum += priceField[j - (windowSize - 1 - i)] * w[i];
			}

			outalma[j] = alSum;
		}
	}
	
	return outalma;
}

p = ParamField("Price Field");
windowSize = Param("Window Size", 9, 5, 201, 2);
sigma = Param("Sigma", 6, 1, 20);
Offset = Param("Offset", 0.85, 0.05, 1.0, 0.05);

Plot(ALMA(p, windowSize, sigma, Offset), "ALMA", ParamColor("Color", colorBlue), ParamStyle("Style"));`

and yes '2' should be there,

OR

// ALMA (Arnaud Legoux Moving Average) 
// ALMA is shifted Gaussian distribution FIR filter, 
// more info: http://www.arnaudlegoux.com
// http://en.wikipedia.org/wiki/Arnaud_Legoux_Moving_Average 
// AFL code (C)2011 AmiBroker.com

function ALMA_AFL( input, range, offset, sigma )
{
  local m, im, s, Coeff;

  m = ( Offset * (range - 1) ); 
  s = range / sigma;

  for( i = 0; i < Min( range, BarCount ); i++ )
  {
    im = i - m; // apply shift
    Coeff[ i ] = exp( - ( im * im ) / ( 2 * s * s ) ); // Gaussian distribution 
  }

  return FIR( input, Coeff, range );
}

P = ParamField("Price field",-1);
range = Param("range",  9, 5, 201, 2 );
Offset = Param("Offset", 6, 1, 20 );
sigma = Param("Sigma", 0.85, 0.05, 1.0, 0.05 );
dynamic_color = IIf( Ref(ALMA_AFL(p, range, sigma, Offset), 0) > Ref(ALMA_AFL(p, range, sigma, Offset), -1), colorGreen, colorRed );
Plot( ALMA_AFL( P, range, Offset, Sigma ), _DEFAULT_NAME(), dynamic_color, ParamStyle("Style") );

A description is "The offset parameter is used to control the weighting function, which in turn affects the responsiveness of the indicator."

Using the Ref() function to shift the array, Ref( ALMA_AFL( p, range, offset, sigma ), 1) gives the same value as Ref( ALMA_AFL( p, range, offset, sigma ), 0). It is my understanding that ALMA produces a next day value because of its formulation.

Neither the REF() or Offset appear to give the next day value. I understand "tomorrow" doesn't exist. I do believe ALMA produces a tomorrow value that also does not exist except as an extrapolated guess.

I have seen ALMA plots that extend past the last tick by an additional tick. In Amibroker the extended plot cannot be seen or accessed using Ref().

My question is how can the last value be accessed?

Thanks

This is an aside about ALMA. Some years ago I literally looked at many moving averages. If you superimpose plots of these averages you can visually see their response to input and the effects of the different formulas. Many very fast averages had over-shoot, they produced values sometimes much greater than the input but rose to that value very quickly. Others were much slower and reached the input after a delay. ALMA plotted a relatively accurate response, fast but with very little overshot.

If one were to plot a square wave, a exact match would be an instant rise to the input value, without going over or under that input value. It was for this response curve I thought ALMA might be useful. I did not necessarily try and understand the formulation but simply examined the results.

Some of my background is in electronics and I have spent time looking at various plots trying to recognize ones that introduced little distortion of the input to produce an accurate output. Some look better than others. This look does not always produce the best results but does offer some insight to their performance.

All I can say is that ALMA AFL code is based on original published on Wikipedia and it is 100% true to original description and 100% the same output as the original. For some reason Wikipedia article does not exist anymore. If you want something else, provide formula (in any language). That applies to 'extrapolation' step you are asking for. It wasn't done in original ALMA. Ref( array, 1 ) on last bar is obviously not doing anything as there is no "future" to be known today.

ALMA as far as I can know produces a future value. I have checked on other platforms, with identical translated code to a different language. In this case it is ThinkOrSwim and uses this code to produce the screenshot below:

# ALMA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ input ALMA_prd = 9; input Offset = 0.85; input Sigma = 6; def m = (Offset * (ALMA_prd - 1)); def s = ALMA_prd / Sigma; def Wtd = fold k = 0 to ALMA_prd - 1 with WtdSum = 0 do WtdSum + ((Exp(-((k - m) * (k - m)) / (2 * s * s)) * GetValue(price, ALMA_prd - 1 - k))); def CumWt = fold j = 0 to ALMA_prd - 1 with CW = 0 do CW + Exp(-((j - m) * (j - m)) / (2 * s * s)); plot ALMA = Wtd / CumWt; ALMA.AssignValueColor(if ALMA > ALMA[1] then Color.GREEN else Color.RED);

This screen shot clearly shows a future ALMA value one tick beyond the last EOD bar. Please notice the red down trend is different from the green up trend indicating a new calculated value.

It appears a future value is produced by the ALMA function.

My question is not about the validity of code, which I believe as you say, is correct and works as originally published. I have no question you coded it correctly. I question why this last value is not produced in Amibroker. I am not trying to even suggest a plausible explanation.

That is my question, what happened to the missing data it appears the ALMA function can produce?

Thank you

It seems that they are just shifting ALMA one bar into the future. The same effect can be achieved using XShift argument as shown in the code below:

// ALMA (Arnaud Legoux Moving Average) 
// ALMA is shifted Gaussian distribution FIR filter, 
// more info: http://www.arnaudlegoux.com
// http://en.wikipedia.org/wiki/Arnaud_Legoux_Moving_Average 
// AFL code (C)2011 AmiBroker.com

function ALMA_AFL( input, range, offset, sigma )
{
  local m, im, s, Coeff;

  m = ( Offset * (range - 1) ); 
  s = range / sigma;

  for( i = 0; i < Min( range, BarCount ); i++ )
  {
    im = i - m; // apply shift
    Coeff[ i ] = exp( - ( im * im ) / ( 2 * s * s ) ); // Gaussian distribution 
  }

  return FIR( input, Coeff, range );
}

P = ParamField("Price field",-1);
range = Param("range",  9, 5, 201, 2 );
Offset = Param("Offset", 6, 1, 20 );
sigma = Param("Sigma", 0.85, 0.05, 1.0, 0.05 );
dynamic_color = IIf( Ref(ALMA_AFL(p, range, sigma, Offset), 0) > Ref(ALMA_AFL(p, range, sigma, Offset), -1), colorGreen, colorRed );

Plot( C, "Price", colorDefault, styleCandle );

Plot( ALMA_AFL( P, range, Offset, Sigma ), _DEFAULT_NAME(), dynamic_color, ParamStyle("Style"), 0, 0, 1 );

Tomasz,

Thank you. Thinkscript uses a convoluted folding structure to implement loops. I am certainly not an expert in either language and appreciate your expertise as well as others here in Amibroker.

I guessed that something like a shift had not happened but had no idea where in code to find it.

When I researched various averages years ago there was much more information about ALMA. Its response curve was why I liked it, not to fast and not too slow, but somewhere it also described an intriguing notion of this future value.

I know the future is unknown, but all traders claim to be able to see the future using whatever methods they have. We know that is not true yet we still trade, tying to exploit the inefficiencies in the market.

Good fortune to all who put in the effort and time, tread cautiously and are bold enough to try.

Thanks again!

Tomasz,

I am not sure what I was thinking. I cannot find a XShift argument in the code you sent. I must be missing something.

Let me know, thanks!

@rloftinbiz, the XShift is achieved via the Plot() in the last line of the code posted by @Tomasz.

In the case, it is the the last argument passed to the function set to 1.

1 Like

As @beppe wrote the 1 as the LAST parameter in Plot call is XShift

Plot( ALMA_AFL( P, range, Offset, Sigma ), 
_DEFAULT_NAME(), 
dynamic_color, 
ParamStyle("Style"), 
0, 0, 
1 /*this is XShift */);

I am sorry I did not find the XShift argument for Plot. I did look but obviously not well enough.
Thanks you beppe for the edification.

I cleaned up the Thinkscript code, however I do not see any use of an offset or shift. Thinkscript syntax uses [n] to reference array values, positive for past and negative for future.

input period = 9; 
input Offset = 0.85; 
input Sigma = 6; 
def m = (Offset * (period - 1)); 
def s = period  / Sigma; 
def Wtd = fold k = 0 to period  - 1 with WtdSum = 0 do WtdSum + ((Exp(-((k - m) * (k - m)) / (2 * s * s)) * GetValue(price, period  - 1 - k))); 
def CumWt = fold j = 0 to period  - 1 with CW = 0 do CW + Exp(-((j - m) * (j - m)) / (2 * s * s)); 
plot ALMA = Wtd / CumWt; 

The above Thinkscript code translates to AFL as follows:

_SECTION_BEGIN( "ALMA" );
function ALMA( priceField, period, offset, sigma )
// This AFL does not use FIR() because it is not supported in Thinkscript .
{
    local m, s, im, W;

    m = offset * ( period - 1 );
    s = period / sigma;

    //for( i = 0; i < period - 1; i++ )
    for( i = 0; i < Min( period - 1, BarCount ); i++ )
    {
        im = i - m;
        W[i] = exp( - ( im * im ) / ( 2 * s * s ) );
    }

    WtdSum = 0;
    CumWtd = 0;

    //for( k = 0; k < period - 1; k++ )
    for(k = 0; k < Min( period - 1, BarCount ); k++)
    {
        CumWtd  += W[k] * Ref( priceField, - ( period ) + k + 1 );
        WtdSum  += W[k];
    }

    return CumWtd / WtdSum;
}
period = Param("period",  9, 5, 201, 2 );
offset = Param("Offset", 0.85, 0.05, 1.0, 0.05);
sigma = Param("Sigma", 6, 1, 20);
AA = ALMA( p, period, offset, sigma);
dynamic_color = IIf( Ref(AA, 0) > Ref(AA, -1), colorGreen, colorRed );
Plot( AA, "ALMA", dynamic_color, ParamStyle( "Style", 4 ),0,0,0);
_SECTION_END();

I have verified that both functions produce identical results given identical data.

Thinkscript with no offset (zero is default)
Plot ALMA-Present = ALMA[0];
produces this screenshot:

A new value is plotted past the last bar which can be referenced using ALMA[-1];

Continued...

AFL Xshift code:

Plot( AA, "ALMA", dynamic_color, ParamStyle( "Style", 4 ),0,0,1);

produces this screenshot where all values are shifted but with no new calculation.

Continued...

A comparison of both with no shift

shows ALMA calculates a value past the last bar which can be referenced. (upper screenshot).

I do not believe an offset or XShift is correct.

Whether I use Ref(ALMA, 1) or ALMA[-1] , shouldn't both return the value past the last bar?

My question is how can Amibroker access this calculated value using Ref(ALMA, 1)?

Please note: all data/screen shots above are today's EOD to eliminate the possibility of future leaks.

It appears I may not post more than one picture at a time.

After all this I have found that the FIR() function may indeed produce a value past the last bar.

Is this possible?? Does the FIR() function make this work vs the code below?

WtdSum = 0;
    CumWtd = 0;

    //for( k = 0; k < period - 1; k++ )
    for(k = 0; k < Min( period - 1, BarCount ); k++)
    {
        CumWtd  += W[k] * Ref( priceField, - ( period ) + k + 1 );
        WtdSum  += W[k];
    }

    return CumWtd / WtdSum;

I cannot compare the function results because they produce different output.

However it appears when using the FIR() and Xshift there is a new calculated value. Am I seeing things or does the FIR() version of ALMA_AFL actually produce the future value as questioned above.

I used the above code because it created comparable values. I thought because Thinkscript produced a value past the last bar, the above AFL would also, as they appear functionally identical.

It is obvious the Thinkscript code produces this future value. It appears AMLA_AFL using FIR() and XShift also produces a value past the last bar.

I cannot match the outputs of the different code but I can believe using FIR() with Xshift may work similarly to Thinkscript. I cannot explain why using FIR() makes this difference and have no insight into Thinkscript's implementation. As a user I cannot see how it actually works. I am dependent upon believing the platforms work as described.

It appears I am back to my first response that it works. Hope you can verify my suppositions, please.

Thanks for all the help. I try to make sure it works before I consider using it.

I explained many times already that:

  • XShift is an argument of Plot and yes it shifts the chart into the future
  • mathematically you can't know the future
  • what FIR function is doing is documented in great deal of detail the manual
  • what I believe your ThinkScript is doing is just shifting data one bar
  • there is no mathematical difference between shifting input data one bar prior to calculation and shifting the output one bar after calculation, in other words
Y = Function( Ref( X, -1 ) );
// is mathematically the same as
Y = Ref( Function( X ), -1 );

The whole point of XShift argument in Plot() as compared to Ref() is that XShift allows to draw array content past the last bar. But it does not change the calculation.

This forum is not for ThinkScript support. We are not here to decipher what ThinkScript is doing and what not. And ThinkScript thing is NOT any kind of "reference" or "correct".

AmiBroker's ALMA IS CORRECT ONE. Actually the author of ALMA personally used AmiBroker code!!!

You have been given formulas for both shifted and not shifted version. You also have been given version with FIR() function and with plain loop that does the same. There is really nothing more to add.

Update: June 12:

Here is a version that plots that extrapolated bar. Such extrapolation is nonsense, but here it is anyway, since you were insisting:

// ALMA (Arnaud Legoux Moving Average) 
// ALMA is shifted Gaussian distribution FIR filter, 
// 
// default:
// sigma = 6 
// offset = 0.5 (symmetric distribution), 0.85 (asymetric distribution)
// 
// AFL code (C)2011 AmiBroker.com

function ALMA_AFL( input, range, offset, sigma, shift )
{
  local m, im, s, Coeff;

  m = floor( Offset * (range - 1) ); 
  s = range / sigma;

  for( i = 0; i < Min( range, BarCount ); i++ )
  {
    im = i - m; // apply shift
    Coeff[ i ] = exp( - ( im * im )/ ( 2 * s * s ) ); // Gaussian distribution 
  }

  return FIR( Ref( input, shift ), Coeff, range );
}

P = ParamField("Price field",-1);
Periods = Param("Periods", 15, 2, 300, 1, 10 );
Offset = Param("Offset", 0.85, 0, 1, 0.01 );
sigma = Param("Sigma", 6, 1, 10, 0.1 );
Plot( ALMA_AFL( P, Periods, Offset, Sigma, 1 ), "ALMA with extrapolation", ParamColor( "Color", colorCycle ), ParamStyle("Style"), Null, Null, 1 ); 
Plot( ALMA_AFL( P, Periods, Offset, Sigma, 0 ), "ALMA without extrapolation", ParamColor( "Color2", colorCycle ), ParamStyle("Style"), Null, Null, 0 );