//+------------------------------------------------------------------+
//| Lesson 4 - First indicator: simple moving average |
//+------------------------------------------------------------------+
#property copyright "Strategist Academy"
#property version "1.00"
#property description "Hand-rolled SMA so you can see how buffers work."
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_width1 2
input int SMA_Period = 20; // Period
double SMABuffer[];
int OnInit()
{
if(SMA_Period < 2)
{
Print("SMA_Period must be at least 2");
return(INIT_FAILED);
}
SetIndexBuffer(0, SMABuffer, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, SMA_Period - 1);
PlotIndexSetString(0, PLOT_LABEL, "SMA(" + IntegerToString(SMA_Period) + ")");
IndicatorSetString(INDICATOR_SHORTNAME, "Lesson 4 SMA(" + IntegerToString(SMA_Period) + ")");
// NOTE: we do NOT call ArraySetAsSeries() here, so index 0 is the OLDEST bar.
// This is MQL5's default. Mixing conventions is the classic beginner bug.
return(INIT_SUCCEEDED);
}
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
if(rates_total < SMA_Period)
return(0); // not enough bars yet - nothing to draw
int start;
if(prev_calculated == 0)
start = SMA_Period - 1; // first bar that CAN be calculated
else
start = prev_calculated - 1; // only recompute the newest bars
if(start < SMA_Period - 1)
start = SMA_Period - 1;
for(int i = start; i < rates_total && !IsStopped(); i++)
{
double sum = 0.0;
for(int k = 0; k < SMA_Period; k++)
sum += close[i - k]; // i is oldest-first: look backwards
SMABuffer[i] = sum / SMA_Period;
}
return(rates_total);
}