Req afl cpoding for a special moving average ALMA

#1
Hi experts

Here is a special moving average .
It is based on probability distribution-gaussian.

please read the pdf and try to code it if possible.

The code has something special.
why so?
==================
Why is ALMA SO SPECIAL?
LISTEN TO ITS DEVELOPERArnaud L.
================================================== ================================================== ==
In attempt to create a new kind of Moving Average
with some friends/colleagues (because i was a little bit tired of the classical set of MA everybodys use for the last 10 years),
weve created this new one (ALMA)..

It removes small price fluctuations and enhances the trend by applying a moving average twice, one from left to right and one from right to left. At the end of this process the phase shift (price lag) commonly associated with moving averages is significantly reduced.Zero-phase digital filtering reduces noise in the signal.
Conventional filtering reduces noise in the signal, but addS delay.

The ALMA can give some excellent results if you take the time to tweak the parameters (dont need to explain this part, it will be easy for you to find the right setting in less than hour)..

Arnaud L.
==========================================
it is this application of moving average from left to right and from right to left is what makes it special-
so far no such code exists in amibroker.
===================================
For those interested in mt4 code of alma, you can refer to attachment.

It can be prepared from adheer pai based afl probability and gaussian distribution already existing.
Here is the Amibroker code for probability and gaussian distribution
We need only the GUASSIAN PART.

In this some removal and additions are needed to be done.

removal= Remove probabilityDENSITY
ADDITION = add sigma value of 6, add offset of 0.85
I request the experts to handle this task
tHE ABOVE CODE BASIS WAS BY ADHEER PAI.Thanks to his solid content.

==========================================================
///////////////////////////////////////////////////////////////////////////////
// Name : Probability Density & Gaussian Distribution
// Description : Visual representation of distribution of the data-series
// (e.g. Price, Price Change, LogNormal Price Change etc).
// Identify whether the series exhibits normal Gaussian
// distribution.
// Author : Adheer Pai (adheer at gmail dot com)
// History : 1.0 (Original Release - July 08, 2009)
///////////////////////////////////////////////////////////////////////////////

// The input series for plotting the Probability Density and Gaussian Distribution
// Use the array SERIES or replace accordingly.

SERIES = ln(C/Ref(C,-1));

// Constants
PI = 3.14159;
SHOW_BELL_CURVE = "Show";
HIDE_BELL_CURVE = "Hide";

// AFL Inputs
nSample = Param("DataSet Size", 500, 100, 1000);
nSegments = Param("Density Segments", 15, 10, 20);
bGauss = ParamList("Gaussian Curve", SHOW_BELL_CURVE + "|" + HIDE_BELL_CURVE, 0);
nPrecision = Param("Precision Digits", 5, 0, 6);
nPrecision = 8 + nPrecision / 10;

// Constants - system and derived.
nBarIndex = SelectedValue(BarIndex());
nFirstValidBar = -1;
for( i = 0 ; i < BarCount ; i++ )
{
if( !IsEmpty(SERIES) )
{
nFirstValidBar = i;
break;
}
}
nSample = Max(Min(nBarIndex - nFirstValidBar , nSample),1);

//DataSize = 0; // Number of samples (it should be same as nPeriod)
arrMean = MA(SERIES, nSample );
arrMax = HHV(SERIES, nSample );
arrMin = LLV(SERIES, nSample );
arrSDev = StDev(SERIES, nSample );

currMax = arrMax[nBarIndex]; // Maximum of the range.
currMin = arrMin[nBarIndex]; // Minimum of the range.
Mu = arrMean[nBarIndex]; // Mean (Mu)
Sigma = arrSDev[nBarIndex]; // Standard Deviation of the Range (Sigma)

rangeOfBar = (currMax-currMin) / nSegments; // The range of each distribution bar.
barFrequency = 0; // Occurances within each bar.
MaxFrequency = 0; // Highest number of occurrances.


///////////////////////////////////////////////////////////////////////////////
// Graphics parameters
///////////////////////////////////////////////////////////////////////////////
pxWidth = Status("pxChartWidth");
pxHeight = Status("pxChartHeight");
pxMargin = 30;
SetChartBkGradientFill( colorLightGrey, colorLavender);


///////////////////////////////////////////////////////////////////////////////
// DisplayBorder
// Displays the charting borders.
///////////////////////////////////////////////////////////////////////////////
function DisplayBorder()
{
GfxSelectPen(colorBrown, 1, styleDashed );
GfxMoveTo(pxMargin, pxMargin); GfxLineTo(pxMargin, pxHeight - pxMargin);
GfxLineTo(pxWidth - pxMargin, pxHeight - pxMargin);
GfxLineTo(pxWidth - pxMargin, pxMargin); GfxLineTo(pxMargin, pxMargin);
}

///////////////////////////////////////////////////////////////////////////////
// computeSigmaBandDistribution
// Computes the % distribution withing the specified sigma band
// bounded by minvalue and maxvalue.
///////////////////////////////////////////////////////////////////////////////
function computeSigmaBandDistribution(MinValue, MaxValue)
{
nCount = 0;
for( i = nBarIndex ; i > nBarIndex - nSample && i >= 0 ; i-- )
{
if( SERIES >= MinValue && SERIES <= MaxValue)
{
nCount++;
}
}
return 100 * nCount / nSample ;
}



///////////////////////////////////////////////////////////////////////////////
// getGaussianValue
// Function to compute the Gaussian distribution value(Y) for a given value
// of X. (non-scaled).
///////////////////////////////////////////////////////////////////////////////
function getGaussianValue(inputValue)
{
// Steps to compute normal Gaussian distribution.
// 1) Compute (x - mu) squared, multiply it by -1
step_1 = -1 * (( inputValue - Mu ) ^ 2);
// 2) Compute twice of (sigma squared).
step_2 = 2 * (Sigma*Sigma);
// 3) Divide 1 by 2, and get the exp
step_3 = exp(step_1/step_2);
// 4) Now, divide step 3 by sigma.
step_4 = step_3 / Sigma;
// 5) Now, divide step 4 by square-root of ( 2 x PI );
step_5 = step_4 / sqrt(2*PI);

return (step_5);
};




DisplayBorder();

// Compute the arithmetic mean, minimum and maximum of the price series
// Compute the frequency of occurrances
for( nIndex = nBarIndex ; nIndex > (nBarIndex - nSample ) && nIndex >= 0; nIndex --)
{
nCurrIndex = int((SERIES[nIndex]- currMin)/rangeOfBar);
nCurrIndex = Max(Min(nSegments-1, nCurrIndex),0);
barFrequency[nCurrIndex]++;
MaxFrequency = Max(MaxFrequency, barFrequency[nCurrIndex]);
}

// Now display the frequency of occurrances - aka distribution
GfxSetBkMode(1); GfxSelectFont("Verdana", 8, 800); GfxSetTextAlign(6); GfxSetTextColor(colorRed);
pxScaleX = (pxWidth - 2 * pxMargin)/nSegments;
pxScaleY = 0.9*(pxHeight - 2 * pxMargin) / MaxFrequency;
for( i = 0 ; i < nSegments; i++ )
{
pxStartX = pxMargin + i * pxScaleX;
pxEndX = pxStartX + pxScaleX;
pxStartY = pxMargin + barFrequency * pxScaleY;
GfxGradientRect(pxStartX, pxHeight - pxStartY , pxEndX, pxHeight - pxMargin, ColorRGB(70,255,255), ColorRGB(70,20,255));
GfxTextOut(NumToStr(100*barFrequency/nSample , 4.2) + "%", (pxStartX+pxScaleX/2), pxHeight - pxStartY - 15);
}


// Now plot the mean and the standard-deviation bars range.
pxScaleX_PixelsPerPriceUnit = (pxWidth - 2 * pxMargin) / (currMax - currMin);

meanLineX = pxMargin + (Mu - currMin) * pxScaleX_PixelsPerPriceUnit;
GfxSelectPen(colorBlue, 2, 3 );
GfxMoveTo(meanLineX, pxMargin); GfxLineTo(meanLineX, pxHeight - pxMargin);
GfxTextOut("Mean", meanLineX, pxHeight - pxMargin);
GfxTextOut(NumToStr(Mu, nPrecision), meanLineX, pxHeight - pxMargin/3);
for( i = 1 ; i <= 6 ; i++ )
{
// Now plot the Mean +/- 1-StDev
sDevBand = pxMargin + (Mu + i*Sigma- currMin) * pxScaleX_PixelsPerPriceUnit;
if( sDevBand < pxWidth - pxMargin )
{
GfxSelectPen(ColorRGB(128,128,128), 1, 4 ); GfxMoveTo(sDevBand , pxMargin); GfxLineTo(sDevBand , pxHeight - pxMargin);
GfxTextOut("+" + NumToStr(i,1.0) + " SD", sDevBand, pxHeight - pxMargin);
GfxTextOut(NumToStr(Mu + i*sigma, nPrecision), sDevBand, pxHeight - pxMargin/3);
}
sDevBand = pxMargin + (Mu - i*Sigma- currMin) * pxScaleX_PixelsPerPriceUnit;
if( sDevBand > pxMargin )
{
GfxSelectPen(ColorRGB(128,128,128), 1, 4 ); GfxMoveTo(sDevBand , pxMargin); GfxLineTo(sDevBand , pxHeight - pxMargin);
GfxTextOut("-" + NumToStr(i,1.0) + " SD", sDevBand, pxHeight - pxMargin);
GfxTextOut(NumToStr(Mu - i*sigma, nPrecision), sDevBand, pxHeight - pxMargin/3);
}
}

// Legend and data information.
GfxSetBkMode(1); GfxSetTextAlign(0 | 24); GfxSelectFont("Verdana", 8, 400); GfxSetTextColor(colorBlue);
GfxTextOut("Latest = " + NumToStr(SERIES[nBarIndex], nPrecision), pxMargin + 10, pxMargin + 15);
GfxTextOut("Mean = " + NumToStr(Mu, nPrecision), pxMargin + 10, pxMargin + 30);
GfxTextOut("Sigma = " + NumToStr(Sigma, nPrecision), pxMargin + 10, pxMargin + 45);

// Now display the distribution of the first 10 standard deviations or less.
nLastPixelY = pxMargin + 60;
for( numOfStDevs = 1 ; numOfStDevs <= 10 ; numOfStDevs ++ )
{
nCount = computeSigmaBandDistribution(Mu - numOfStDevs * Sigma, Mu + numOfStDevs * Sigma);
GfxTextOut(NumToStr(numOfStDevs, 1.0) + "-Sigma = " + NumToStr(nCount,5.2) + "%", pxMargin + 10, nLastPixelY);
nLastPixelY = nLastPixelY + 15;
if( nCount >= 100 ) numOfStDevs = 100;
}

currLineX = pxMargin + (SERIES[nBarIndex] - currMin) * pxScaleX_PixelsPerPriceUnit;
GfxSelectPen(colorGreen, 2, 3 );
GfxMoveTo(currLineX , pxMargin); GfxLineTo(currLineX , pxHeight - pxMargin);
GfxSetTextAlign(6); GfxSetTextColor(colorGreen);
GfxTextOut("Latest", CurrLineX, pxMargin/2);


/////////////////////////////////////////////////////////////////////////////////
// Display the Gaussian Distribution if requested by the user.
/////////////////////////////////////////////////////////////////////////////////
if( bGauss == SHOW_BELL_CURVE )
{
// Now display the normal distribution curve based on sigma and mu.
graphStepX = (CurrMax - Mu) / Max(100, pxWidth-2*pxMargin);
if( graphStepX != 0 )
{
Gaussian_Maxima = 0;
for( x = CurrMin ; x <= CurrMax ; x = x + graphStepX)
{
Gaussian_Maxima = Max(Gaussian_Maxima, getGaussianValue(x));
}

pxGaussianScaleY = 0.9*(pxHeight - 2 * pxMargin) / Gaussian_Maxima;
GfxSelectPen(colorOrange, 2, 0);
for( x = CurrMin ; x <= CurrMax ; x = x + graphStepX)
{
gaussianValue = getGaussianValue(x);
pxPointX = ( x - CurrMin ) * pxScaleX_PixelsPerPriceUnit + pxMargin;
pxPointY = pxHeight - ( gaussianValue - 0 ) * pxGaussianScaleY - pxMargin;
if( x == CurrMin )
{
GfxMoveTo(pxPointX, pxPointY);
}
GfxLineTo(pxPointX, pxPointY);
}
}
}

===================================================

mt4 code is as follows
=======================================

#property copyright "Copyright 2010, TrendLaboratory"
#property link "http://finance.groups.yahoo.com/group/TrendLaboratory"
//---- indicator settings
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 Yellow
#property indicator_color2 LightBlue
#property indicator_color3 Tomato
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 2
//---- indicator parameters
extern int Price = 0; //Price Mode (0...6)
extern int WindowSize = 9; //Window Size
extern double Sigma = 6.0; //Sigma parameter
extern double Offset =0.85; //Offset of Gaussian distribution (0...1)
extern double PctFilter = 0; //Dynamic filter in decimal
extern int Shift = 0; //
extern int ColorMode = 0; //0-on,1-off
extern int ColorBarBack = 1; //
extern int AlertMode = 0; //Sound Alert switch (0-off,1-on)
extern int WarningMode = 0; //Sound Warning switch(0-off,1-on)
//---- indicator buffers
double ALMA[];
double Uptrend[];
double Dntrend[];
double trend[];
double Del[];

int draw_begin;
bool UpTrendAlert=false, DownTrendAlert=false;
double wALMA[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicator buffers mapping
IndicatorBuffers(5);
SetIndexBuffer(0,ALMA);
SetIndexBuffer(1,Uptrend);
SetIndexBuffer(2,Dntrend);
SetIndexBuffer(3,trend);
SetIndexBuffer(4,Del);
//---- drawing settings
SetIndexStyle(0,DRAW_LINE);
SetIndexStyle(1,DRAW_LINE);
SetIndexStyle(2,DRAW_LINE);
draw_begin = WindowSize;
SetIndexDrawBegin(0,draw_begin);
SetIndexDrawBegin(1,draw_begin);
SetIndexDrawBegin(2,draw_begin);
SetIndexShift(0,Shift);
SetIndexShift(1,Shift);
SetIndexShift(2,Shift);
IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+1);
//---- name for DataWindow and indicator subwindow label
IndicatorShortName("ALMA("+WindowSize +")");
SetIndexLabel(0,"ALMA");
SetIndexLabel(1,"ALMA Uptrend");
SetIndexLabel(2,"ALMA Dntrend");
//----

double m = MathFloor(Offset * (WindowSize - 1));
double s = WindowSize/Sigma;

ArrayResize(wALMA,WindowSize);
double wsum = 0;
for (int i=0;i < WindowSize;i++)
{
wALMA = MathExp(-((i-m)*(i-m))/(2*s*s));
wsum += wALMA;
}

for (i=0;i < WindowSize;i++) wALMA = wALMA/wsum;

return(0);
}
//+------------------------------------------------------------------+
//| ALMA_v1 |
//+------------------------------------------------------------------+
int start()
{
int limit,shift,i;
int counted_bars=IndicatorCounted();
//----
if(counted_bars<1)
{
for(i=Bars-1;i>0;i--)
{
ALMA=EMPTY_VALUE;
Uptrend=EMPTY_VALUE;
Dntrend=EMPTY_VALUE;
}
}
//----
if(counted_bars>0) counted_bars--;
limit=Bars-counted_bars;

//----
for(shift=limit; shift>=0; shift--)
{

if (shift > Bars - WindowSize) continue;

double sum = 0;
double wsum = 0;

for(i=0;i < WindowSize;i++)
{
if (i < WindowSize)
{
sum += wALMA * iMA(NULL,0,1,0,0,Price,shift + (WindowSize - 1 - i));

}
}

//if(wsum != 0)
ALMA[shift] = sum;

if(PctFilter>0)
{
Del[shift] = MathAbs(ALMA[shift] - ALMA[shift+1]);

double sumdel=0;
for (int j=0;j<=WindowSize-1;j++) sumdel = sumdel+Del[shift+j];
double AvgDel = sumdel/WindowSize;

double sumpow = 0;
for (j=0;j<=WindowSize-1;j++) sumpow+=MathPow(Del[j+shift]-AvgDel,2);
double StdDev = MathSqrt(sumpow/WindowSize);

double Filter = PctFilter * StdDev;

if( MathAbs(ALMA[shift]-ALMA[shift+1]) < Filter ) ALMA[shift]=ALMA[shift+1];
}
else
Filter=0;


if (ColorMode>0)
{
trend[shift] = trend[shift+1];
if (ALMA[shift] - ALMA[shift+1] > Filter) trend[shift] = 1;
if (ALMA[shift+1] - ALMA[shift] > Filter) trend[shift] =-1;

if (trend[shift]>0)
{
Uptrend[shift] = ALMA[shift];
if (trend[shift+ColorBarBack]<0) Uptrend[shift+ColorBarBack]=ALMA[shift+ColorBarBack];
Dntrend[shift] = EMPTY_VALUE;
if (WarningMode>0 && trend[shift+1]<0 && i==0) PlaySound("alert2.wav");
}
else
if (trend[shift]<0)
{
Dntrend[shift] = ALMA[shift];
if (trend[shift+ColorBarBack]>0) Dntrend[shift+ColorBarBack]=ALMA[shift+ColorBarBack];
Uptrend[shift] = EMPTY_VALUE;
if (WarningMode>0 && trend[shift+1]>0 && i==0) PlaySound("alert2.wav");
}
}
}
//----------
string Message;

if ( trend[2]<0 && trend[1]>0 && Volume[0]>1 && !UpTrendAlert)
{
Message = " "+Symbol()+" M"+Period()+": HMA Signal for BUY";
if ( AlertMode>0 ) Alert (Message);
UpTrendAlert=true; DownTrendAlert=false;
}

if ( trend[2]>0 && trend[1]<0 && Volume[0]>1 && !DownTrendAlert)
{
Message = " "+Symbol()+" M"+Period()+": HMA Signal for SELL";
if ( AlertMode>0 ) Alert (Message);
DownTrendAlert=true; UpTrendAlert=false;
}



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

========================================
The mt4 code is poosted to provide some kind of hint for coding in afl.

looking forawrd to alma code in afl here on traderji as it doesnt exist anywhere else as of now
regards
ford
 

asnavale

Well-Known Member
#4
Hi experts

Here is a special moving average .
It is based on probability distribution-gaussian.

please read the pdf and try to code it if possible.

For those interested in mt4 code of alma, you can refer to attachment.


looking forawrd to alma code in afl here on traderji as it doesnt exist anywhere else as of now
regards
ford
Where is the pdf file? where is the attachment?

-Anant
 
#6
Last edited:

asnavale

Well-Known Member
#7
By googling ,found following :

pdf file is available at---

http://www.arnaudlegoux.com/wp-content/uploads/2010/05/alma.pdf

Nijatrader version of above alma ma is available at---

http://www.arnaudlegoux.com/?p=1

MQL4, MQL5 AND Tradestation version ALMA are available at---

http://www.arnaudlegoux.com/?author=1

Regards
Hi Sirasangi,

I already have all of these. Now the major task is to translate the Nt or MqL code into AFL. Need to learn the syntax of these languages.

-Anant
 
#8
Here is AFL for ALMA !!

Code:
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"));
 

asnavale

Well-Known Member
#9
Hi Nisha,

Thanks for the code. but I am facing a problem.

1) If I drag and drop the AFL twice on the price chart, the second instance of the ALMA gives error. I wanted to plot ALMA with two different periods (windowsize).

2) If I use windowsize larger than default 9, say windowsize=20, there is a gap in ALMA curve at the left side.

Can you find the reasons?

-Anant