It is not important that it is a EMA. Important is the concept. It is an easy example to demonstrate how to create a ChartWindow indicator.
Code: Select all
//---------------------------------------------------------------------------
// My Moving Average
//---------------------------------------------------------------------------
library MyMovingAverage;
uses
SysUtils,
Math,
Graphics,
IndicatorInterfaceUnit,
TechnicalFunctions;
var
// External variables
Period: integer;
EMAyesterday: double = 0;
// Buffers
MMABuffer: TIndexBuffer;
//---------------------------------------------------------------------------
// Initialize indicator
//---------------------------------------------------------------------------
procedure Init; stdcall;
begin
// define properties
IndicatorShortName('My Moving Average');
SetOutputWindow(ow_ChartWindow);
// register options
AddSeparator('Options');
RegOption('Period', ot_Integer, Period);
SetOptionRange('Period', 1, MaxInt);
Period := 5;
// create buffers
MMABuffer := CreateIndexBuffer;
IndicatorBuffers(1);
SetIndexBuffer(0, MMABuffer);
SetIndexStyle(0, ds_Line, psSolid, 3, clLime);
SetIndexLabel(0, 'MA');
IndicatorDigits(2);
//SetFixedMinMaxValues(0, 400);
end;
//---------------------------------------------------------------------------
// Deinitialize indicator
//---------------------------------------------------------------------------
procedure Done; stdcall;
begin
end;
//---------------------------------------------------------------------------
// Calculate requested bar
//---------------------------------------------------------------------------
procedure Calculate(index: integer); stdcall;
var
i: integer;
sum,k,result: double;
emaTemp: double;
begin
if (EMAyesterday = 0) then
Begin
sum := 0;
for i:=1 to period do
sum := sum + Close(i);
emaTemp := sum/period;
EMAyesterday := emaTemp
end;
k := 2/(period + 1);
result := (Close(index) * k) + (EMAyesterday * (1 - k));
EMAyesterday := result;
MMABuffer[index] := result;
end;
exports
Init, Done, Calculate;
end.