//+------------------------------------------------------------------+
//|                                         MA-Price-Cross-Alert.mq5 |
//|                                          Copyright 2024,JBlanked |
//|                                        https://www.jblanked.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024,JBlanked"
#property link      "https://www.jblanked.com/"
#property version   "1.00"
#property indicator_chart_window

#property indicator_buffers 1
#property indicator_plots 1

#property indicator_label1 "MA"
#property indicator_color1 clrRed
#property indicator_type1 DRAW_LINE
#property indicator_width1 2
#property indicator_style1 STYLE_SOLID

input int                  inpMAPeriod = 26;           // MA Period
input ENUM_MA_METHOD       inpMAMethod = MODE_SMMA;    // Ma Method
input ENUM_APPLIED_PRICE   inpMAPrice  = PRICE_MEDIAN; // MA Price

int maHandle;
double ma[];
datetime lastAlertTime;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, ma, INDICATOR_DATA);
//---
#ifdef __MQL5__
   maHandle = iMA(_Symbol, PERIOD_CURRENT, inpMAPeriod, 0, inpMAMethod, inpMAPrice);
   if(maHandle == INVALID_HANDLE)
     {
      return INIT_FAILED;
     }
#endif
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//---
   int limit = rates_total - prev_calculated;
   if(prev_calculated < 1)
     {
      ArrayInitialize(ma, EMPTY_VALUE);
      ArraySetAsSeries(ma, true);
     }
   else
     {
      limit++;
     }
//---
#ifdef __MQL5__
   CopyBuffer(maHandle, 0, 0, rates_total, ma);
#else
   for(int i = limit - 1; i >= 0; i--)
     {
      ma[i] = iMA(_Symbol, PERIOD_CURRENT, inpMAPeriod, 0, inpMAMethod, inpMAPrice, i);
     }
#endif
//---
   doAlert();
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void doAlert()
  {
   if(lastAlertTime == iTime(_Symbol, PERIOD_CURRENT, 0))
     {
      return;
     }

   lastAlertTime = iTime(_Symbol, PERIOD_CURRENT, 0);

   switch(cross(1))
     {
      case 1:
         Alert(_Symbol + " has crossed the " + (string)inpMAPeriod + " MA up. Buy at " + (string)SymbolInfoDouble(_Symbol, SYMBOL_ASK));
         break;

      case -1:
         Alert(_Symbol + " has crossed the " + (string)inpMAPeriod + " MA down. Sell at " + (string)SymbolInfoDouble(_Symbol, SYMBOL_BID));
         break;
     }
  }
//+------------------------------------------------------------------+
int cross(const int i)
  {
   return
      iClose(_Symbol, PERIOD_CURRENT, i + 1) > ma[i + 1] && iClose(_Symbol, PERIOD_CURRENT, i) < ma[i] ? -1 :
      iClose(_Symbol, PERIOD_CURRENT, i + 1) < ma[i + 1] && iClose(_Symbol, PERIOD_CURRENT, i) > ma[i] ? 1 :
      0;
  }
//+------------------------------------------------------------------+
