errors in my trendline scanner

 
//+------------------------------------------------------------------+
//| Multi Trendline Alert Scanner (MT5)                              |
//| Monitors multiple manual trendlines by name and sends alerts     |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 0

input string TrendlineNames = "TL_1,TL_2,Support,Resistance"; // Comma-separated list of trendline names
input bool   AlertOnTouch   = true;
input bool   AlertOnBreak   = true;
input bool   AlertOnBounce  = true;

datetime lastAlertTime; // To avoid duplicate alerts per candle

//+------------------------------------------------------------------+
//| Helper: split string by commas                                   |
//+------------------------------------------------------------------+
int StringSplitByComma(string input, string &output[])
{
   ushort sep = (ushort)',';
   int count = StringSplit(input, sep, output);
   return count;
}

//+------------------------------------------------------------------+
//| Main 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[])
{
   string lines[];
   int total = StringSplitByComma(TrendlineNames, lines);

   // Prevent duplicate alerts
   if(time[0] == lastAlertTime) return rates_total;

   for(int i = 0; i < total; i++)
   {
      string name = lines[i];
      StringTrimLeft(name);
      StringTrimRight(name);
      
      if(ObjectFind(0, name) < 0) continue; // line not found

      double linePrice = ObjectGetValueByTime(0, name, time[0]);
      if(linePrice == 0.0) continue;

      double cClose = close[0];
      double cHigh  = high[0];
      double cLow   = low[0];
      double prevClose = (rates_total > 1) ? close[1] : cClose;

      // --- Touch Alert ---
      if(AlertOnTouch && cLow <= linePrice && cHigh >= linePrice)
      {
         Alert("Trendline Touched: ", name, " at ", DoubleToString(linePrice, _Digits));
         lastAlertTime = time[0];
      }

      // --- Breakout Alert ---
      if(AlertOnBreak)
      {
         if(prevClose < linePrice && cClose > linePrice)
         {
            Alert("Trendline Break UP: ", name, " at close ", DoubleToString(cClose, _Digits));
            lastAlertTime = time[0];
         }
         else if(prevClose > linePrice && cClose < linePrice)
         {
            Alert("Trendline Break DOWN: ", name, " at close ", DoubleToString(cClose, _Digits));
            lastAlertTime = time[0];
         }
      }

      // --- Bounce Alert ---
      if(AlertOnBounce && cLow <= linePrice && cClose > linePrice)
      {
         Alert("Bounce UP from Trendline: ", name);
         lastAlertTime = time[0];
      }
      else if(AlertOnBounce && cHigh >= linePrice && cClose < linePrice)
      {
         Alert("Bounce DOWN from Trendline: ", name);
         lastAlertTime = time[0];
      }
   }

   return rates_total;
}
 
Your topic has been moved to the section: Technical Indicators
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
 
When asking a question, please explain in detail, and if relevant, also include screenshots, log output, etc.
 
Daniel Afolabi:
//+------------------------------------------------------------------+
//| Helper: split string by commas                                   |
//+------------------------------------------------------------------+
int StringSplitByComma(string input, string &output[])
{
   ushort sep = (ushort)',';
   int count = StringSplit(input, sep, output);
   return count;
}
input is a reserved word - change it to input_str or something similar.
 
Daniel Afolabi:

You are should have stated the problem(s) explicitly. Like what are these errors? How did you try to solve them? (it would save time for who is thinking of such a solution)

datetime lastAlertTime; // To avoid duplicate alerts per candle
string lines[];
int totalLines = 0;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   lastAlertTime = 0;
   totalLines = StringSplitByComma(TrendlineNames, lines);

//---
   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[])
  {
// Prevent duplicate alerts
   if(time[0] <= lastAlertTime)
      return rates_total;

   ArraySetAsSeries(close, true);
   ArraySetAsSeries(high, true);
   ArraySetAsSeries(low, true);
   ArraySetAsSeries(time, true);

   double cClose = close[0],
          cHigh  = high[0],
          cLow   = low[0],
          prevClose = close[1],
          linePrice;
   string name;

   for(int i = 0; i < totalLines; i++)
     {
      name = lines[i];

      //--- line not found
      if(ObjectFind(0, name) < 0)			// This can be improved or removed, since if the object does not exist, it would return 0, which would be caught by "linePrice==0"
         continue;

      linePrice = ObjectGetValueByTime(0, name, time[0]);
      if(linePrice == 0.0)
         continue;

      // --- Touch Alert ---
      if(AlertOnTouch && cLow <= linePrice && cHigh >= linePrice)
        {
         Alert("Trendline Touched: ", name, " at ", DoubleToString(linePrice, _Digits));
         lastAlertTime = time[0];
        }

      // --- Breakout Alert ---
      if(AlertOnBreak)
        {
         if(prevClose < linePrice && cClose > linePrice)
           {
            Alert("Trendline Break UP: ", name, " at close ", DoubleToString(cClose, _Digits));
            lastAlertTime = time[0];
           }
         else
            if(prevClose > linePrice && cClose < linePrice)
              {
               Alert("Trendline Break DOWN: ", name, " at close ", DoubleToString(cClose, _Digits));
               lastAlertTime = time[0];
              }
        }

      // --- Bounce Alert ---
      if(AlertOnBounce && cLow <= linePrice && cClose > linePrice)
        {
         Alert("Bounce UP from Trendline: ", name);
         lastAlertTime = time[0];
        }
      else
         if(AlertOnBounce && cHigh >= linePrice && cClose < linePrice)
           {
            Alert("Bounce DOWN from Trendline: ", name);
            lastAlertTime = time[0];
           }
     }

//--- return value of prev_calculated for next call
   return(rates_total);
  }
  

//+------------------------------------------------------------------+
//| Helper: split string by commas                                   |
//+------------------------------------------------------------------+
int StringSplitByComma(string text, string &output[])
  {
   ushort sep = StringGetCharacter(",", 0);
   int count = StringSplit(text, sep, output);
   for(int i=0; i<count; i++)
     {
      StringTrimLeft(output[i]);
      StringTrimRight(output[i]);
     }
   return count;
  }  

You can further improve the performance. Good luck.