Forex Blog

First-hand Forex trading experience and information about foreign exchange market that will be useful to traders

Archives

How to Add Alerts to MetaTrader Indicators

March 22, 2016 (Last updated on December 21, 2016) by Andriy Moraru

Originally, I intended this post as a do-it-yourself guide on how to add alerts to MetaTrader indicators without knowing how to code at all. But writing it, I came to realization that even if a trader knows nothing about MQL language and coding he will have to learn some basics through this guide because adding alerts does require some thoughtful code analysis and modifications.

One important thing to understand is that it is not possible to add alerts to indicator without at least some coding. The good thing is that what you will require is so simple that even a 5-year old could do it after reading this post. You have to do three things to add an alert to an indicator:

  1. Add input parameters for turning alerts on/off and adjusting some alert settings — all entirely optional but it is better to have some easy way of configuring things than to re-code everything each time your needs shift.
  2. Identify indicator buffers that are used by an indicator and contain the data you want to be alerted about.
  3. Formulate conditions for alerts to fire up. For example, a classic condition for MACD buy alert could be formulated as: current MACD Signal below current MACD Main and previous MACD Signal above previous MACD Main and both current MACD Signal and MACD Main are below zero. Conditions can be simpler or more complex, but you should already know what you want to be alerted about if you are looking to add alerts to an indicator.

Input parameters

Theory

You are probably familiar with the different types alerts that exist in MetaTrader:

  • Native alert (popup)
  • Sound alert
  • Email alert

Most of the time, traders want the plain native alerts but it is a good practice to implement all three at once and to give a choice (via input parameters) to enable and disable certain types of alert. You will learn to add three input parameters: EnableNativeAlerts, EnableSoundAlerts, EnableEmailAlerts.

Another important input parameter is the candle to use for triggering the alert. Normally, you want the alert to be triggered on the close of the candle #1 when the latest candle (#0) has just started forming — that way you get a final and true alert (unless your indicator repaints itself). Sometimes, traders want to receive their alerts as fast as possible, then looking for alert conditions on candle #0 can be a better choice. Of course, the alert may turn out to be false as the indicator values on candle #0 a susceptible to changes with each new tick. The input parameter that controls the number of trigger candle will be called TriggerCandle. It will be equal to 1 by default, but a trader will be able to change it to 0.

If you plan using email alerts, adding an input parameter for an email subject is also a must. EmailAlertSubject can be set to some fixed string or it can be modified by the alert code during run-time. The former case is much simpler of course. Do not forget to enable and configure email alerts in your platform via menu Tools->Options->Email.

Both native and email alerts need some text to display or to send in the email’s body. AlertText will probably contain some preset text, which will also be modified according to the particular alert’s parameters.

One additional parameter is useful when using sound alerts — SoundAlertFile. It can be used to set the name of the audio file for the platform to play during alert.

Practice

Find the last line starting with extern (older MT4 indicators) or input (MT5 and newer MT4 indicators) statement. Insert the following code after that line:

input int    TriggerCandle 	= 1;
input bool   EnableNativeAlerts = true;
input bool   EnableSoundAlerts  = true;
input bool   EnableEmailAlerts  = true;
input string AlertEmailSubject  = "";
input string AlertText  	= "";
input string SoundFileName	= "alert.wav";
 
datetime LastAlertTime = D'01.01.1970';
int LastAlertDirection = 0;

This code uses empty initial alert text and email subject. They will be filled during alert evaluation.

Identifying indicator buffers

Explanation

Indicator buffers are the vital part of almost any MetaTrader indicator. They contain the data, which is displayed on the chart or is used in calculations. Finding indicator buffers is very easy. Search for SetIndexBuffer call. You will see one or more lines that look like this (in old MT4 indicators):

SetIndexBuffer(N, Buffer_Name);

or like this (in newer MT4 or MT5 indicators):

SetIndexBuffer(N, Buffer_Name, INDICATOR_*);

Where N is the buffer’s number (you do not need it for alerts) and Buffer_Name is the buffer’s name, which you need to formulate the alert conditions.

Now, the tricky part is to find the right buffers if there are more than one. In MT5 and newer MT4 indicators, you will see this INDICATOR_* parameter in SetIndexBuffer call, which can help determining the right buffers for alert – you will want those with INDICATOR_DATA (they produce the actual display on the chart).

In some cases, determining the right buffer is easy – there might be only one, or it is called appropriately, or you know how the indicator works. In other cases, I would recommend some trial and error work if you do not want to study the code.

Examples

Looking at some real life examples of SetIndexBuffer calls might help you finding the buffer names in the indicators you work on.

Lines 40-41 of the default MACD indicator in MetaTrader 4 show two buffers:

SetIndexBuffer(0,ExtMacdBuffer);
SetIndexBuffer(1,ExtSignalBuffer);

Obviously, ExtMacdBuffer is the main line buffer and ExtSignalBuffer is the signal line buffer.

If you look at the lines 29-31 of the .mq4 source of the CCI Arrows indicator, you will see three buffers there:

SetIndexBuffer(0,dUpCCIBuffer);
SetIndexBuffer(1,dDownCCIBuffer);  
SetIndexBuffer(2,dSellBuffer);

Naturally, you would think that dUpCCIBuffer is for Up-arrows and dDownCCIBuffer is for Down-arrows. But what is dSellBuffer? The thing is that if you search the code for it, you will find that it is not used anywhere at all. It means that you can safely ignore it and base all your alerts on the former two buffers.

The MT5 version of the Aroon Up & Down indicator contains the following lines:

SetIndexBuffer(0, AroonUpBuffer, INDICATOR_DATA);
SetIndexBuffer(1, AroonDnBuffer, INDICATOR_DATA);

Both SetIndexBuffer function calls have INDICATOR_DATA parameters, which means that both buffers (AroonUpBuffer and AroonDnBuffer) contain values plotted on the chart. Clearly, AroonUpBuffer is used for calculation of the Up-line and AroonDnBuffer is used for the Down-line.

Lines 46-47 of the MT5 Coppock indicator also show two buffers:

SetIndexBuffer(0, Coppock, INDICATOR_DATA);
SetIndexBuffer(1, ROCSum, INDICATOR_CALCULATIONS);

The INDICATOR_CALCULATIONS parameter tells us that ROCSum is not an indicator buffer used for display but rather a buffer used for intermediate calculations. Coppock is the only buffer that can be used for alerts here – unsurprisingly so because Coppock indicator is represented by a single histogram.

Alert conditions

Where

Now after you have successfully identified the names of the indicator buffers that you plan using in your alerts, it is time to add the actual alert conditions.

All alerts are appended to the end of the indicator’s main calculation function. In older MetaTrader 4 indicators, it is called int start(). The alert conditions code should be inserted just above the last return(0); statement inside that function. In newer MT4 and in MT5 indicators, the function is called OnCalculate and its declaration can vary from one indicator to another. You have to insert the alert conditions code just above the last return(rates_total); statement inside that function.

What

The actual conditions will differ depending on the alert type you wish to add to the given indicator. This guide will cover the three most popular cases: signal, level, and cross.

Signal

Signal is a type of alert that is triggered when some indicator buffer assumes some non-zero level. Arrow indicators would use this kind of alert normally. Adding alert to the aforementioned MT4 CCI Arrows indicator would look like this:

if (((TriggerCandle > 0) && (Time[0] > LastAlertTime)) || (TriggerCandle == 0))
{
	string Text;
	// Up Arrow Alert
	if ((dUpCCIBuffer[TriggerCandle] > 0) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))
	{
		Text = AlertText + "CCI Arrows: " + Symbol() + " - " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - Up.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "CCI Arrows Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = Time[0];
		LastAlertDirection = 1;
	}
	// Down Arrow Alert
	if ((dUpCCIBuffer[TriggerCandle] > 0) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != -1))))
	{
		Text = AlertText + "CCI Arrows: " + Symbol() + " - " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - Down.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "CCI Arrows Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = Time[0];
		LastAlertDirection = -1;
	}
}

The code should be added just before the latest return(0); statement inside the start() function.

Adding the same alerts to MT5 version of CCI Arrows is only marginally different:

if (((TriggerCandle > 0) && (time[rates_total - 1] > LastAlertTime)) || (TriggerCandle == 0))
{
	string Text;
	// Up Arrow Alert
	if ((dUpCCIBuffer[rates_total - 1 - TriggerCandle] > 0) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))
	{
		Text = AlertText + "CCI Arrows: " + Symbol() + " - " + EnumToString(Period()) + " - Up.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "CCI Arrows Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = time[rates_total - 1];
		LastAlertDirection = 1;
	}
	// Down Arrow Alert
	if ((dUpCCIBuffer[rates_total - 1 - TriggerCandle] > 0) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != -1))))
	{
		Text = AlertText + "CCI Arrows: " + Symbol() + " - " + EnumToString(Period()) + " - Down.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "CCI Arrows Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = time[rates_total - 1];
		LastAlertDirection = -1;
	}
}

That code should be inserted just above the latest return(rates_total); statement inside the OnCalculate function. It assumes that the time and buffer arrays are not set as series. If they are, you would need to substitute TriggerCandle for rates_total - 1 - TriggerCandle and time[0] for time[rates_total - 1].

Level

Level alerts are also very simple. If an indicator reaches a certain value (from above or from below), the alert is triggered. Single-line indicators shown in separate window use this kind of alert normally. Here is how the alert conditions for crossing of zero level would look in the MT4 version of Coppock indicator:

if (((TriggerCandle > 0) && (Time[0] > LastAlertTime)) || (TriggerCandle == 0))
{
	string Text;
	// Above Zero Alert
	if (((Coppock[TriggerCandle] > 0) && (Coppock[TriggerCandle+ 1] <= 0)) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))
	{
		Text = AlertText + "Coppock: " + Symbol() + " - " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - Above Zero.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Coppock Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = Time[0];
		LastAlertDirection = 1;
	}
	// Below Zero Alert
	if (((Coppock[TriggerCandle] < 0) && (Coppock[TriggerCandle+ 1] >= 0)) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != -1))))
	{
		Text = AlertText + "Coppock: " + Symbol() + " - " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - Below Zero.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Coppock Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = Time[0];
		LastAlertDirection = -1;
	}
}

The same for the MT5 version would look like this:

if (((TriggerCandle > 0) && (time[rates_total - 1] > LastAlertTime)) || (TriggerCandle == 0))
{
	string Text;
	// Above Zero Alert
	if (((Coppock[rates_total - 1 - TriggerCandle] > 0) && (Coppock[rates_total - 2 - TriggerCandle] <= 0)) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))
	{
		Text = AlertText + "Coppock: " + Symbol() + " - " + EnumToString(Period()) + " - Above Zero.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Coppock Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = time[rates_total - 1];
		LastAlertDirection = 1;
	}
	// Below Zero Alert
	if (((Coppock[rates_total - 1 - TriggerCandle] < 0) && (Coppock[rates_total - 2 - TriggerCandle] >= 0)) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != -1))))
	{
		Text = AlertText + "Coppock: " + Symbol() + " - " + EnumToString(Period()) + " - Below Zero.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Coppock Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = time[rates_total - 1];
		LastAlertDirection = -1;
	}
}

As is the case with the previously discussed signal alert for MT5, you would need to substitute TriggerCandle for rates_total - 1 - TriggerCandle and time[0] for time[rates_total - 1] if the indicator sets its buffers as series. Also, rates_total - 2 - TriggerCandle would have to be changed to TriggerCandle+ 1.

Cross

Cross alerts are more complex than the previous two types. They are triggered when some indicator buffer crosses the price line or when two lines of an indicator cross each other, or when several lines cross each other. Let’s look at the cross alert implementation for MT4 Aroon Up & Down indicator. We will look for the Up-line crossing the Down-line from below and from above as two distinct alerts:

if (((TriggerCandle > 0) && (Time[0] > LastAlertTime)) || (TriggerCandle == 0))
{
	string Text;
	// Up-Line Crosses Down-Line from Below
	if (((AroonUpBuffer[TriggerCandle] > AroonDnBuffer[TriggerCandle]) && (AroonUpBuffer[TriggerCandle+ 1] <= AroonDnBuffer[TriggerCandle+ 1])) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))
	{
		Text = AlertText + "Aroon Up & Down: " + Symbol() + " - " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - Up-Line Crosses Down-Line from Below.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Aroon Up & Down Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = Time[0];
		LastAlertDirection = 1;
	}
	// Up-Line Crosses Down-Line from Above
	if (((AroonUpBuffer[TriggerCandle] < AroonDnBuffer[TriggerCandle]) && (AroonUpBuffer[TriggerCandle+ 1] >= AroonDnBuffer[TriggerCandle+ 1])) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != -1))))
	{
		Text = AlertText + "Aroon Up & Down: " + Symbol() + " - " + EnumToString((ENUM_TIMEFRAMES)Period()) + " - Up-Line Crosses Down-Line from Above.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Aroon Up & Down Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = Time[0];
		LastAlertDirection = -1;
	}
}

The same code for MT5 Aroon Up & Down looks like this:

if (((TriggerCandle > 0) && (time[rates_total - 1] > LastAlertTime)) || (TriggerCandle == 0))
{
	string Text;
	// Up-Line Crosses Down-Line from Below
	if (((AroonUpBuffer[rates_total - 1 - TriggerCandle] > AroonDnBuffer[rates_total - 1 - TriggerCandle]) && (AroonUpBuffer[rates_total - 2 - TriggerCandle] <= AroonDnBuffer[rates_total - 2 - TriggerCandle])) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))
	{
		Text = AlertText + "Aroon Up & Down: " + Symbol() + " - " + EnumToString(Period()) + " - Up-Line Crosses Down-Line from Below.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Aroon Up & Down Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = time[rates_total - 1];
		LastAlertDirection = 1;
	}
	// Up-Line Crosses Down-Line from Above
	if (((AroonUpBuffer[rates_total - 1 - TriggerCandle] < AroonDnBuffer[rates_total - 1 - TriggerCandle]) && (AroonUpBuffer[rates_total - 2 - TriggerCandle] >= AroonDnBuffer[rates_total - 2 - TriggerCandle])) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != -1))))
	{
		Text = AlertText + "Aroon Up & Down: " + Symbol() + " - " + EnumToString(Period()) + " - Up-Line Crosses Down-Line from Above.";
		if (EnableNativeAlerts) Alert(Text);
		if (EnableEmailAlerts) SendMail(AlertEmailSubject + "Aroon Up & Down Alert", Text);
		if (EnableSoundAlerts) PlaySound(SoundFileName);
		LastAlertTime = time[rates_total - 1];
		LastAlertDirection = -1;
	}
}

Same as before, substitute TriggerCandle for rates_total — 1 — TriggerCandle and time[0] for time[rates_total — 1] if the indicator uses buffers that are set as series. Again, rates_total — 2 — TriggerCandle would have to be changed to TriggerCandle+ 1 in that case too.

Let’s illustrate the alert generated with these conditions with this screenshot:

Adding Alerts to Aroon Up & Down - Cross Conditions Example

Complex

Of course, the variety of alerts is not limited by the three types described above. Some alerts can have multiple dependencies (e.g. one line crossing the price while two other lines cross each other), other alerts might depend on time, volume, additional calculations, or a combination of various factors. It is even possible to add alerts to indicators that do not use buffers or plot anything on chart.

Such cases are not covered by this DIY guide. Some basic cases can be easily derived from the code snippets offered above while difficult cases are nontrivial ones and demand special approach and extra attention. However, you will certainly learn to add such complex alerts after some practice with the elementary ones.

Summary

In the end, I would like to summarize the alert-adding process with a simple list of steps:

  1. Add the predefined input parameters just below the latest extern or input statement in the indicator’s source code.
  2. Identify the buffer names that represent the indicator’s plot on chart.
  3. Insert the appropriate alert conditions code just above the latest return(0); inside start() function or return(rates_total); inside OnCalculate function.
  4. Replace the buffer names with those that you identified in the second step.

Update 2016-12-21: I have updated the code snippets with correct examples. Previous versions would produce unlimited number of alerts if TriggerCandle was set to 0 (alert on the most current candle).

If you still have some questions about adding alerts to custom MetaTrader indicators or if you want to share your own tips for doing it, please use the commentary form below.

55 Responses to “How to Add Alerts to MetaTrader Indicators”

  1. Maria

    Muchas Gracias, lo entendi todo.

    Reply

  2. zaki

    dear sir ,
    i have one problem my indicator shows repaint…..
    i want to add extra source code file like … source code file of refresh in every minute …is that possible…
    plz kindly reply me.
    i am waiting u r reply.
    thanks

    Reply

    Andriy Moraru Reply:

    Sorry, but I don’t understand your request. Why would you want to add some extra code files to your repainting indicator?

    Reply

  3. zen

    Hi I have a question,
    I’m trying to get an alert to my ADX, everytime DI+ and DI- hitting a value, say 20, I wish to get notified. However the alert is acting strangely it is reapeating the alert over and over again when it does cross the value, it would be realy awesome if you could explain to me what exactly I have to do to fix the problem.

    Thanks in regards

    Reply

    Andriy Moraru Reply:

    Could you please share your indicator source code file and post a link here? So I could look at the problem?

    Reply

  4. zen

    Thank you for your fast response, I’m using the casual Average Directional Movement Index, you can find the whole script in your mt5 Indicators>Examples, I don’t know how to link it but I linked all the critical parts you mentioned in the blog

    inputs & buffers
    https://postimg.org/image/o9wx7vwml/

    alert condition
    https://postimg.org/image/a2i9sesx9/

    Reply

    Andriy Moraru Reply:

    You can share your whole code via http://pastebin.com/ or a similar website.

    Reply

  5. zen

    ah great, there we go

    http://pastebin.com/hRpeCwRc

    Reply

    Andriy Moraru Reply:

    Thanks! I have found an error in the code (mine). Fixed version is here:
    http://pastebin.com/qYnZQ7Ep

    I have also updated the post to prevent such problems with alerts for other users.

    Thanks for reporting the problem!

    Reply

    zen Reply:

    Thank you for your fast response. I hope I set all the parameters correctly, your code is a lifesaver!

    Reply

  6. syed yasir alam

    HELO
    AS u have shown how to add alert for aroon UP and DOWN
    I want to create MACD cross over alert what shoild I do..?

    Reply

    Andriy Moraru Reply:

    Look at the AroonUpDown example and replace the AroonUpDown buffers with the MACD’s signal and main line buffers.

    Reply

  7. Wolfgang

    Thank you very much for your comprehensive post regarding how to code alerts for MT4/MT5 custom indicators.

    Unfortunately, I am currently stuck trying to add an alert to a channel indicator. What I want to do is fairly straight-forward. The alert should be triggered by price on the current candle equaling a certain channel level (in some instances only when price approaches from above, in others only from below).

    To illustrate, please see: http://pastebin.com/McTZw0F6

    I would be grateful, if you could give me advise on how to manipulate the code in order to create said alert.

    Reply

    Andriy Moraru Reply:

    You need to change “==” to “>=” when you want an alert of a price crossing a level from above. And you need to change “==” to “< =" when you want an alert of a price crossing a level from below. Also, you need to check whether the price was above/below the level a period before. For example, the first alert condition in your code should be changed like this:

    if ((MA_upper_Buffer1[TriggerCandle] >= Bid) && (MA_upper_Buffer1[TriggerCandle + 1] < Bid) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))

    Reply

  8. Wolfgang

    That did the trick! A great many thanks to you.

    Despite the risk of coming across as impertinent, could I ask you to give me an idea on how to add a function that pauses the alert for a certain time period (say five minutes, or until the current bar has finished) after it has been triggered?

    Merci beaucoup.

    Reply

    Andriy Moraru Reply:

    Just add LastAlertTime != Time[0] to the conditions. Like this:

    if ((MA_upper_Buffer1[TriggerCandle] >= Bid) && (MA_upper_Buffer1[TriggerCandle + 1] < Bid) && (LastAlertTime != Time[0]) && ((TriggerCandle > 0) || ((TriggerCandle == 0) && (LastAlertDirection != 1))))

    It will make it trigger only once on the current bar.

    Reply

  9. Wolfgang

    Again, vielen Dank.

    Really, having at least some basic understanding of computer code seems to be indispensable.

    Reply

  10. Patrick

    Great article, thanks for sharing.

    What I would like to know is, is it possible to add the option so you can select custom alert sounds instead of the default alert.wav?

    Reply

    Andriy Moraru Reply:

    Yes, just replace alert.wav with the filename of your choice.

    Reply

  11. Mel

    I am a complete technophobe, but I would like to set up an alert when 10ema crosses 20ema. I would appreciate your help

    Reply

    Andriy Moraru Reply:

    You would probably need a custom indicator coded for that.

    Reply

  12. Tricia

    I have a channel indicator that works well, but I would like to add alerts to it when the candle enters the retracement zone of the channel. I understand your steps, but how do I access the code on the indicator so as to add the alerts? Hope you understand my question.

    Reply

    Andriy Moraru Reply:

    Right-click on the indicator in the Navigator window of your platform and select Modify:

    If you there is the source code file for the indicator in your platform, it will open it. Otherwise, you have only an executable (.ex4) and you have to ask the author of the indicator for the source code file (.mq4).

    Reply

  13. Ice

    Thank you sir! But I have a problem: the alert repeats on every new bar:(

    https://pastebin.com/9c84G2YF

    Reply

    Andriy Moraru Reply:

    The problem is because the indicator is written incorrectly – the alert code you’ve added is fine. To fix the issue, just add these two lines to between the current lines 117 and 118:

             ExtMapBuffer5[i] = 0;
             ExtMapBuffer6[i] = 0;

    Also, in case you do not know, this indicator is repainting the arrows – it only draws them 3 bars into the future. E.g., if there is a turn in line, it waits 3 bars to confirm it and then draws an arrow like it appeared 3 bars ago. This also means that you will never get an alert for such an arrow if you set TriggerCandle to 1. If you want to get arrow alerts here, your TriggerCandle should be equal to SignalHP.

    Reply

  14. Ice

    Wow, thanks a lot!

    Reply

  15. justin

    I can get the alert to sound in my own chosen wav file, can you look through it? The wav i want to be played when the pop up box also comes is “Bicycle-Bell-Ringing.wav”

    heres the whole code, it for when stochastics above/below 80/20 and cross back below
    https://pastebin.com/NSbDriRS

    Reply

    Andriy Moraru Reply:

    Please do not submit such huge pieces of code in comments. Either upload your indicator somewhere and share a link or use pastebin.

    As for your questions:

    For PlaySound() to work with your custom .wav file, the file has to be located in /Sounds/ subfolder of your platform’s data folder.

    To change what sound is used when Alert() function is called, go to Toos->OptionsE->Events and change the sound file near Alert:
    How to change default alert sound in MetaTrader 4

    Reply

  16. Daniel Demian

    Andriy.. first of all thanks for sharing your knowledge!
    i use an indicator that have alert code but did not work
    tried to fix as you wrote here, but couldn’t compile then

    Would you mind to help me with it?
    here’s the link
    https://www.mql5.com/pt/code/1910?utm_campaign=codebase.list&utm_medium=special&utm_source=mt5terminal&utm_link=c23d219487dcc91964731d98bd1cdd42&utm_codepage=1046&utm_gid=8881070706134349491&utm_uniq=66D6D7AD-0E29-T-170507

    thank you!!!

    Reply

    Andriy Moraru Reply:

    I do not code on request. As far as I can see, that indicator already has alerts added.

    Reply

    Daniel Demian Reply:

    I did not want to be disrespectful, I do not know anyone who program mql5, the way you explained with this post just thought that at a quick glance you could see what is wrong in the code that does not work the alert and give me a tip How to fix it! Forgive me if I was pretentious, here was the only place I found some good material for this problem !!! thank you

    Reply

    Andriy Moraru Reply:

    You can start a thread about it in our forum about MetaTrader indicators – perhaps, someone will be able to help you out there.

    Reply

    Daniel Demian Reply:

    thank so much

    Reply

  17. DougW

    Thanks for taking the time and patience to write this out. I’ve been trying to understand it for quite awhile. It takes someone like you to completely explain it and that’s not easy to find. I appreciate it.

    Reply

  18. Robert

    Thanks for the post, unfortunately I think I may have made an erro, as I cannot seem to get the script to work. I have pasted it at and would love if you could let me know where I have gone wrong. Apologies for the most likely silly error!
    https://pastebin.com/70UG9t3B

    Reply

    Andriy Moraru Reply:

    Why do you do this?

       ArraySetAsSeries(ExtMainBuffer,false);
       ArraySetAsSeries(ExtSignalBuffer,false);
       ArraySetAsSeries(ExtHighesBuffer,false);
       ArraySetAsSeries(ExtLowesBuffer,false);
       ArraySetAsSeries(low,false);
       ArraySetAsSeries(high,false);
       ArraySetAsSeries(close,false);

    It will not work if arrays are not set as series. If you want to use such arrays, then you have to modify the alert conditions accordingly. For example, the number of the latest bar is no longer 0, it is rates_total-1, and the number of the pre-last bar is no longer 1, it is rates_total-2.

    Reply

  19. Nick

    Hey buddy,
    Great article. I would like to attach a file with this message. How do I do that?

    Reply

    Nick Reply:

    I keep getting errors. How do you add alerts for red or blue dot signals?

    #property description "Draws signals based on the cross of the stochastic above 80(blue) below 20(red) default"
    #property description" K Period and D Period / Main Line & signal line."
    #property description "User can set the level the signal is drawn on the inputs tab."
     
     
    //----
    #property indicator_separate_window
    #property indicator_buffers   6
    //----
    #property indicator_minimum   0
    #property indicator_maximum 100
    #property indicator_color1 Yellow
    #property indicator_style1 STYLE_DOT
    #property indicator_color2 White
    #property indicator_color3 DodgerBlue
    #property indicator_color4 Red
    #property indicator_width3 2
    #property indicator_width4 2
    #property indicator_level1 80
    #property indicator_level2 20
    //---- input parameters
    //nice setings for trend = 35,10,1
    extern string note1="Stochastic settings";
    extern int       KPeriod   =5;
    extern int       KPeriod2 = 5;
    extern int       Slowing   =3;
    extern int       DPeriod   =3;
    extern int       DPeriod2 = 3;
    extern string note4="0=sma, 1=ema, 2=smma, 3=lwma";
    extern int       MAMethod =0;
    extern string note5="0=high/low, 1=close/close";
    extern int       PriceField= 1;
    extern string note6="overbought level";
    extern int       overBought=80;
    extern string note7="oversold level";
    extern int       overSold  =20;
    //--- Inputs for stochastic cross level 
    input color Buy_Dot_Color = clrDodgerBlue;
    input color Sell_Dot_Color = clrRed;
    double input Cross_From_Below_Level = 10;
    double input Cross_From_Above_Level = 90;
     
    //---- buffers
    double KFull[];
    double DFull[];
    double Upper[];
    double Lower[];
    double Buy_Point[];
    double Sell_Point[];
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    int init()
      {
       SetIndexBuffer(0,DFull);
       SetIndexBuffer(1,KFull);
       SetIndexBuffer(2,Upper);
       SetIndexBuffer(3,Lower);
       SetIndexBuffer(4,Buy_Point);
       SetIndexBuffer(5,Sell_Point);
       SetIndexStyle(4,DRAW_ARROW,EMPTY,3,Buy_Dot_Color);
       SetIndexStyle(5,DRAW_ARROW,EMPTY,3,Sell_Dot_Color);
       SetIndexArrow(4,159);
       SetIndexArrow(5,159);
       SetIndexLabel(1,"Fast");
       SetIndexLabel(2,NULL);
       SetIndexLabel(3,NULL);
    //----
       DPeriod=MathMax(DPeriod,1);
         if (DPeriod==1) 
         {
          SetIndexStyle(0,DRAW_NONE);
          SetIndexLabel(0,NULL);
         }
         else 
         {
          SetIndexStyle(0,DRAW_LINE);
          SetIndexLabel(0,"Slow");
         }
       string shortName="Stochastic X ("+KPeriod+","+Slowing+","+DPeriod+","+maDescription(MAMethod)+","+priceDescription(PriceField);
       if (overBought < overSold) overBought=overSold;
       if (overBought    0)      shortName =shortName+","+overSold;
       IndicatorShortName(shortName+")");
       return(0);
      }
    //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    int deinit()
      {
       return(0);
      }
    //+------------------------------------------------------------------+
    //| Custom indicator iteration function                              |
    //+------------------------------------------------------------------+
    int start()
      {
       int    limit;
       int    i;
    //----   
       int counted_bars = IndicatorCounted();
       if(counted_bars  0)   counted_bars--;
       limit = Bars - counted_bars;
       double Rsi_rule = iRSI(Symbol(),0,14,0,i);
     
       if(counted_bars==0) limit-=1+MathMax(2,MathMax(KPeriod,DPeriod));
     
       for(i=limit; i>=0; i--)
         {
          KFull[i]=iStochastic(NULL,0,KPeriod,DPeriod,Slowing,MAMethod,PriceField,MODE_MAIN,i);
          DFull[i]=iStochastic(NULL,0,KPeriod2,DPeriod2,Slowing,MAMethod,PriceField,MODE_SIGNAL,i);
    //----
          if (KFull[i] > overBought) { Upper[i]=KFull[i]; Upper[i+1]=KFull[i+1]; }
            else                       
            { 
             Upper[i]=EMPTY_VALUE;
             if (Upper[i+2]==EMPTY_VALUE)
               Upper[i+1] =EMPTY_VALUE; 
            }
          if (KFull[i] < overSold)   { Lower[i]=KFull[i]; Lower[i+1]=KFull[i+1]; }
            else                       
            { 
             Lower[i]=EMPTY_VALUE;
             if (Lower[i+2]==EMPTY_VALUE)
               Lower[i+1] =EMPTY_VALUE; 
            }
     
            //--- Stochastic Crossing Up Below 10 Signal
     
           if( KFull[i] DFull[i] )
     
           {
             Buy_Point[i] = KFull[i];
     
           } 
           //--- Stochastic Crossing Down Above 80 Signal 
     
           if ( KFull[i] > Cross_From_Above_Level && KFull[i] < DFull[i])
           {
             Sell_Point[i] =KFull[i];
           }
     
         }
    //----
       return(0);
      }
    //+------------------------------------------------------------------+
    string priceDescription(int mode)
      {
       string answer;
       switch(mode)
         {
          case 0:  answer="Low/High"   ;break;
          case 1:  answer="Close/Close";break;
          default: answer="Invalid price field requested";
             Alert(answer);
         }
       return(answer);
      }
    //+------------------------------------------------------------------+
    //|                                                                  |
    //+------------------------------------------------------------------+
    string maDescription(int mode)
      {
       string answer;
       switch(mode)
         {
          case MODE_SMA:  answer="SMA" ;break;
          case MODE_EMA:  answer="EMA" ;break;
          case MODE_SMMA: answer="SMMA";break;
          case MODE_LWMA: answer="LWMA";break;
          default:        answer="Invalid MA mode requested";
             Alert(answer);
         }
       return(answer);
      }
    //+------------------------------------------------------------------+

    Reply

    Andriy Moraru Reply:

    I don’t see any code here that would add alerts.

    Reply

    Andriy Moraru Reply:

    Please use pastebin.com to share large pieces of code.

    Reply

  20. Bruce L

    Great article !!!! I successfully added alerts to my Keltner indie :)

    Reply

  21. Nigel

    Hi,
    Thanks for the article, it’s great! I would like to add a sound alert to the force index (mt5), but I’m having difficulty understanding step 3, alert conditions, where exactly to add it and how to change the code to get a sound alert when price crosses levels at 6000 and -6000, please could you help me?
    Thanks…

    Reply

    Andriy Moraru Reply:

    In case of Forex Index, ExtForceBuffer is the buffer name. You should be placing your alert conditions after this line:

    ExtForceBuffer[i]=tick_volume[i]*(ExtMABuffer[i]-ExtMABuffer[i-1]);

    And repeat them after this line:

    ExtForceBuffer[i]=volume[i]*(ExtMABuffer[i]-ExtMABuffer[i-1]);

    Reply

    Nigel Reply:

    I tried to add the code you gave for levels into the force index code in the positions you advised with the intension of editing where nessecary to get the desired results but when i hit compile it brings up number of errors and warnings, errors are all ‘undeclared identifier’ and warnings are all ‘implicit conversion of ‘number’ to ‘string”.

    Reply

    Andriy Moraru Reply:

    You need to make sure you follow the instructions provided in the tutorial.

    Reply

    Nigel Reply:

    I’ve gone over the instructions again and copied the code verbatim, but I’m still getting 2 errors, both ”Coppock’ – undeclared identifier’. I’m not any good with coding so I have no idea how to fix these errors…

    Reply

    Andriy Moraru Reply:

    Unfortunately, I cannot read people’s minds. If you share your code via pastebin.com, I would be able to look at it and help you.

    Reply

    Nigel Reply:

    https://pastebin.com/8UWdWxgn Here is the code in pastebin.com. Hope you can help. Thanks…

    Andriy Moraru Reply:

    What is that Coppock buffer you are trying to use in your alert conditions?

  22. Nigel

    I copied the section of code in the tutorial and added the conditions to the force index indicator. I didn’t add or remove anything just applied the example code in the appropriate places.

    Reply

    Andriy Moraru Reply:

    You need to follow the steps 2 and 3 of the tutorial. I have already replied to you with the buffer name you need to check, so you can skip step 2. Copying example code into a different indicator will not work.

    Reply

  23. Ravi

    Hi Andriy,
    You taught me ‘how to fish’. Now I just created alert for two indicators with your instructions here and it’s working fine. Thank you very much for your great post.

    Reply

    Andriy Moraru Reply:

    I am glad it helped you!

    Reply

Leave a Reply

required
required (will not be published)
optional