Need some help with my simple alert indicator

 

Hey, I'm trying my hand at creating a simple alert indicator. I keep getting what look like simple syntax errors, but can't figure out what's wrong. 

 

#property copyright "Me"

#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Alert
#property indicator_label1  "Alert"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input double   AlertPrice;
//--- indicator buffers
double         AlertBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,AlertBuffer);
   
//---
   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[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }

int start()                                     
  {
   int i;                                     
   for (i=1)           
     {                       
      if (Open[i]<AlertPrice && Close[i]>AlertPrice)MessageBox("Buy")                     
         
      return(0);               
     }
  }
       

 Errrors

Any help would be greatly appreciated :) 

 

It looks like you've cobbled together some old-style code to make some modifications. 

I suggest you start with a basic, blank layout of the new style. For an indicator it should look something like this:

#property strict
#property indicator_chart_window

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }

//+------------------------------------------------------------------+
//| 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[])
  {

   return(rates_total);
  }


If this is an indicator, you can't use MessageBox().

You can read about why in the documentation, which is a great place to learn.

In MetaEditor, move your cursor inside the word MessageBox and press F1.

So you will need to use Alert() instead.

Also, keep your code simple.

#property strict
#property indicator_chart_window

input double AlertPrice = 1.5000;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }

//+------------------------------------------------------------------+
//| 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[])
  {
   if(Open[1] < AlertPrice && Close[1] > AlertPrice) Alert("Buy");  
   return(rates_total);
  }

Your code only checks the Open / Close of the previous bar. So next, you may want to make your code only check this condition once per bar, rather than every tick.

HTH 

PS don't forget you need a semicolon ; at the end of each line in MQL
 

I edited my original post to show the whole code :)


Thank you so much for the detailed reply! 

I'm going to get that alert set, instead of the messagebox. That will print in the terminal, correct?

I've been learning from a youtube series, but they are old videos, so I realize there might be some discrepancies.

I'll also look at getting it to focus on bar closes, not sure why I didn't think of that! :D 

 
gagebrk:

I've been learning from a youtube series, but they are old videos, so I realize there might be some discrepancies.

Yes, unfortunately a lot! MQL4 was majorly overhauled back in 2014 (from Build 600 onwards). Sadly much of the information you will find in tutorials pre-dates this change.

OK, a few things.

Forget about:

int start()

That's the old stuff. If you are writing an indicator it is:

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[])

And for an EA it is:

void OnTick()

__________________________

gagebrk:

I'm going to get that alert set, instead of the messagebox. That will print in the terminal, correct?

 No, that would be Print().

Alert() will pop up on the screen, kind of like a messagebox (but not a messagebox).

__________________________

 

#property copyright "Me"

#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Alert
#property indicator_label1  "Alert"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input double   AlertPrice;
//--- indicator buffers
double         AlertBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,AlertBuffer);
  
//---
   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[])
  {
//---
  
//--- return value of prev_calculated for next call
   return(rates_total);
  }

int start()                                    
  {
   int i;                                    
   for (i=1)          
     {                      
      if (Open[i]<AlertPrice && Close[i]>AlertPrice)MessageBox("Buy")                    
        
      return(0);              
     }
  }

You have created a buffer but I'm not seeing any use for it in your code. If you don't need it, get rid of it.

 
honest_knave:

Yes, unfortunately a lot! MQL4 was majorly overhauled back in 2014 (from Build 600 onwards). Sadly much of the information you will find in tutorials pre-dates this change.

OK, a few things.

Forget about:

int start()

That's the old stuff. If you are writing an indicator it is:

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[])

And for an EA it is:

void OnTick()

__________________________

 No, that would be Print().

Alert() will pop up on the screen, kind of like a messagebox (but not a messagebox).

__________________________

 

#property copyright "Me"

#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot Alert
#property indicator_label1  "Alert"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

//--- input parameters
input double   AlertPrice;
//--- indicator buffers
double         AlertBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,AlertBuffer);
  
//---
   return(INIT_SUCCEEDED);
  }

You have created a buffer but I'm not seeing any use for it in your code. If you don't need it, get rid of it.

I want a line to be drawn at the level I use for the "AlertPrice" input. I thought you needed buffers to have it drawn? I haven't gotten to that part yet, but basiaclly I'd like a horizontal line drawn at my "AlertPrice" level. I think those buffers were auto-populated in the code when I started building the indicator..

But! I just did a test on a live chart. I used the "PlaySound" function to make it easy see if it would work, and it did! 

alert sound played over and over after it got activated, I'm assuming this is because I am having it call per-tick, like you said? I'm thinking a FOR loop, which would check using the "Bars" function? Or is there a much simpler way to do this?

I'm going to try to find an updated video tutorial series, if you had any suggestions, it would be GREATLY appreciated! :D

 
gagebrk:

I want a line to be drawn at the level I use for the "AlertPrice" input. I thought you needed buffers to have it drawn? I haven't gotten to that part yet, but basiaclly I'd like a horizontal line drawn at my "AlertPrice" level. I think those buffers were auto-populated in the code when I started building the indicator..

But! I just did a test on a live chart. I used the "PlaySound" function to make it easy see if it would work, and it did! 

alert sound played over and over after it got activated, I'm assuming this is because I am having it call per-tick, like you said? I'm thinking a FOR loop, which would check using the "Bars" function? Or is there a much simpler way to do this?

I'm going to try to find an updated video tutorial series, if you had any suggestions, it would be GREATLY appreciated! :D

You could use a buffer to draw your horizontal line, but it might be easier to create an OBJECT_HLINE

Restricting code to running once per bar is very simple e.g. 

//+------------------------------------------------------------------+
//| 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[])
  {
   static datetime last_bar = 0;
   datetime this_bar = Time[0];
   if(last_bar != this_bar)
     {
      // do stuff here only once per bar
      last_bar = this_bar;
     }
   return(rates_total);
  }


I don't really know of any up-to-date tutorials. Fortunately, much of the MQL5 material now works on MQL4 (notable exceptions being iCustom and trade functions).

 
honest_knave:

You could use a buffer to draw your horizontal line, but it might be easier to create an OBJECT_HLINE

Hey! I'm currently looking up how to draw a line on the chart. I would want to put that code in the "indicator initialization function" area, correct? Because I'd want the object (line) drawn when I drop the indicator on the chart?

Ok! I got it figured out!

Here's the finished code!

Lastly, I want to add the option to change the color of the line. But, it looks like it works! I need to wait for markets to open to test it, but it looks good, and THERE'S NO ERRORS! hahaha 

#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
//--- input parameters
input double   AlertPrice;
//--- indicator buffers
double         AlertBuffer[];
string obj_name = "AlertLine";
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
    
   ObjectCreate("AlertLine",OBJ_HLINE,0,TimeCurrent(),AlertPrice);
   ObjectSet("AlertLine",OBJPROP_COLOR,clrDarkOrchid);
   ObjectSet("AlertLine",OBJPROP_STYLE,STYLE_DASH);
   ObjectSet("AlertLine",OBJPROP_WIDTH,1);
//---
   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[])
  {
//---
   static datetime last_bar = 0;
   datetime this_bar = Time[0];
   if(last_bar != this_bar)
     {
      if (Open[1]<AlertPrice && Close[1]>AlertPrice) Alert("Bullish Breakout");
      if (Open[1]>AlertPrice && Close[1]<AlertPrice) Alert("Bearish Breakout");
      last_bar = this_bar;
     }
    
//--- return value of prev_calculated for next call
   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete("AlertLine");
  }

 

 @honest_knave Thank you so much for your help!

 



 

 

Nice!

Just be careful with your naming. You did create a name then you didn't use it, and used 2 different names!

int OnInit()
  {
//--- indicator buffers mapping
   string obj_name = "AlertLine";
   ObjectCreate("Hline",OBJ_HLINE,0,TimeCurrent(),AlertPrice);
   ObjectSet("AlertLine",OBJPROP_COLOR,clrDarkOrchid);
   ObjectSet("AlertLine",OBJPROP_STYLE,STYLE_DASH);
   ObjectSet("AlertLine",OBJPROP_WIDTH,1);
//---
   return(INIT_SUCCEEDED);
  }

You will also probably want your code to delete your object when you remove the indicator:

void OnDeinit(const int reason)
  {
   ObjectDelete(0,"AlertLine");
  }

Tip: typos with object names can be easy to miss because the compiler won't throw up an error. Try something like this:

#define alert_line "AlertLine"
input double   AlertPrice;
//--- indicator buffers
double         AlertBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   ObjectCreate(alert_line,OBJ_HLINE,0,TimeCurrent(),AlertPrice);
   ObjectSet(alert_line,OBJPROP_COLOR,clrDarkOrchid);
   ObjectSet(alert_line,OBJPROP_STYLE,STYLE_DASH);
   ObjectSet(alert_line,OBJPROP_WIDTH,1);
//---
  return(INIT_SUCCEEDED);
}
 

Oops, looks like I edited my post while you were replying :)

It's all nicely figured out! I spotted that error after I posted, hadn't had my coffee yet hahaha
 

 
gagebrk:


Lastly, I want to add the option to change the color of the line. But, it looks like it works! I need to wait for markets to open to test it, but it looks good, and THERE'S NO ERRORS! hahaha  

You can test it now through the strategy tester.

You won't see the Alert() popup, but it will print in the Journal.
 
I just used the strat tester, and it worked beautifully!

So when the Alert is activated, it will pop up a message ? I'm going to make it so that the alert says "EURUSD bullish breakout" or "EURUSD bearish breakout" depending on what the alert is.
Also, I'd like to tie the horizontal line to the alert better, so that you can drag the line and it will drag the alert, also. I think I saw something about that in my searches :)
Also going to add inputs so they can change the color/type of the horizontal line.

I'm really loving this! Once you understand the format of how to write the code, it really all comes together beautifully! :)
Reason: