Merge Multple Alerts in to ONE Variable Alert

Please see code below. I have written code that searches in real-time ALL available markets in MetaTrader and returns their lowest price from the last 10 bars (1 hour period) as an Alert. It is working however the “Alert” results are shown individually for each market. I need ALL the results in ONE Alert. How do I approach this? The number of markets is very large and their number can change. As such, flexible code code is required. I suspect some kind of variable Array or Enum may be a solution (correct me if I am wrong) but I am unsure how to approach this. Could you kindly point me in the right direction? Thanks in advance for the help and feedback.


extern string     Input_Period = PERIOD_H1;
extern int        User_Specified_Bars = 10; // Enter a total number of bars.

int start()
{
   string SymbolLow;
   for (int i = SymbolsTotal(false); i > 0; i--)
   {
      SymbolLow = StringConcatenate(
      SymbolName(i,false),
      "  LOW: ",iLow(SymbolName(i,false),Input_Period,iLowest(SymbolName(i,false),Input_Period,MODE_LOW,User_Specified_Bars,0))
      );
      Alert (SymbolLow);         
   }
return (0);
}

Hi CT,

There are several issues with this code snippet. Please allow me to offer you some friendly constructive criticism.

  1. The time-frame input should be ENUM_TIMEFRAMES instead of string.
  2. Only use extern if you need to programmatically change the user input (almost never), otherwise use input.
  3. The loop is incorrect. It needs to start the index one less than the total symbols and end up at 0
  4. There is no checking to see if the data is ready for the iterated symbol. An easy way to get around this is to use CopyX instead.
  5. The result string needs to concatenate during each loop.
  6. The final alert needs to happen outside of the loop.

Stylistically:

  1. Variable names should begin with a lower-case letter. CamelCase is used to define ClassNames.
  2. When you continue a function call or expression to the next line you should indent it.
  3. Instead of StringConcatenate you can use StringFormat which is cleaner and you can see exactly how the string will turn out.
  4. You should alway initialize your variables. This is a good habit to get into for when you switch to MQL5 and/or you begin to make your own classes.

The end result would look something like this:

#property strict

input ENUM_TIMEFRAMES  inp_period         = PERIOD_H1;
input int              inp_specified_bars  = 10; // Enter a total number of bars.

int start()
{
   string alert_string = NULL;
   for(int i=SymbolsTotal(false)-1; i>=0; i--)
   {
      string symbol = SymbolName(i, false);
      double lows[];
      if(CopyLow(symbol, inp_period, 0, inp_specified_bars, lows) > 0)
      {
         double lowest = lows[ArrayMinimum(lows)];
         int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
         alert_string += StringFormat(
            "%s LOW: %s | ", 
            symbol, 
            DoubleToString(lowest, digits)
         );
      }
   }
   Alert(alert_string);
   return 0;
}

Thanks for the reply and feedback. If I wanted to also include the “highs” (or other results) as well, how would I include that? In other words, how I would I format this example so the Alert has the ability to return more than just one result? Thanks.

You need to tweak the StringFormat to format however you like.

#property strict

input ENUM_TIMEFRAMES  inp_period         = PERIOD_H1;
input int              inp_specified_bars  = 10; // Enter a total number of bars.

int start()
{
   string alert_string = NULL;
   for(int i=SymbolsTotal(false)-1; i>=0; i--)
   {
      string symbol = SymbolName(i, false);
      double lows[];
      double highs[];
      if(CopyLow(symbol, inp_period, 0, inp_specified_bars, lows) > 0
         && CopyHigh(symbol, inp_period, 0, inp_specified_bars, highs) > 0
      ){
         double lowest = lows[ArrayMinimum(lows)];
         double highest = highs[ArrayMaximum(highs)];
         int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
         alert_string += StringFormat("%s: low=%s, high=%s | ", 
            symbol, 
            DoubleToString(lowest, digits),
            DoubleToString(highest, digits)
         );
      }
   }
   Alert(alert_string);
   return 0;
}

Perfect. This gets me started. Thanks for the assistance!