We can generate MultiCharts alerts programmatically and even use code to cancel alerts before they fire. But how do we reactivate a previously cancelled alert?

In this article:

Turning a cancelled MultiCharts alert back on

Alerts are a helpful tool to notify us of certain condition, like a moving average crossover. We generate alerts programmatically with the Alert() keyword (MultiCharts Wiki, 2012a), although we do need to enable the manual alert settings beforehand. Once enabled, alerts can generate as a notification window, audio alert, and/or email alert (MultiCharts Wiki, 2013).

After we’ve generated an alert in our script with Alert(), we can use the Cancel Alert keyword combination to programmatically cancel alerts (MultiCharts Wiki, 2012d). That way we can prevent an alert from firing when later on in the script, during the same script calculation, something comes up that invalidates the alert condition.

There’s also an undocumented SetAlertState() keyword. That keyword enables or disables generating alerts during the current script calculation (MultiCharts Support, personal communication, March 31, 2016). With SetAlertState(false) we turn off alerts for the current script calculation, and can turn them back on later with SetAlertState(true).

Note: We can use SetAlertState(true) for more things than just programmatically enabling a previously cancelled alert – it also fires an alert, regardless of whether we’ve cancelled an alert previously. And so SetAlertState(true) generates an alert just as Alert() does.

With that behaviour of SetAlertState() we can ’re-enable’ an alert that we’ve previously cancelled with Cancel Alert. When we do, the custom alert message that we originally specified with Alert() will be lost (meaning, a ’re-activated alert’ fires without an alert message).

Tip: There may be a situation or two in which Cancel Alert and SetAlertState() are actually useful. But we’re better of not using these keywords because they make the code harder to read, understand, and debug. See rewriting code so that Cancel Alert and SetAlertState() aren’t needed for an alternative to these keywords.

Example: cancel alert and reenable programmatically

In the example indicator below we colour price bars whose high is a 10-bar highest high. On those bars, we generate an alert programmatically. But when that new high happens on an even bar number, we’ll cancel the alert with Cancel Alert. However, if the bar’s volume is above its 10-bar moving average, we’ll ‘reactive’ the cancelled alert with SetAlertState().

As that short description shows and like mentioned above, Cancel Alert and SetAlertState() result in hard-to-follow code – even the brief indicator below is actually a good example in how these keywords make code unnecessarily complicated.

The image below gives an example of the alerts generated by the indicator. After discussing the code, we’ll discuss the indicator’s behaviour, alerts, and text output it generates in the PowerLanguage Editor.

Example of the alert message generated by the MultiCharts script

Variables:
    evenBarNum(false),
    barNumStr(""),
    newHigh(false);
    
newHigh = (High = Highest(High, 10));

// Colour the bars with 10-bar highs forest green
if (newHigh) then
    PlotPaintBar(High, Low, Open, Close, "PaintBar", RGB(34, 139, 34));

if (CheckAlert and newHigh) then begin 

    barNumStr = Text(NumToStr(Symbol_CurrentBar, 0), " - ");
    
    // Trigger an alert
    Alert("This bar's high is a new 10-bar high");
    
    Print(barNumStr, "10 bar high!");
    
    // Turn off alerts on even bar numbers
    evenBarNum = (mod(Symbol_CurrentBar, 2) = 0);
    
    if (evenBarNum) then begin
    
        Print(barNumStr, "This is an even bar, cancelling alert now");
            
        Cancel Alert;
        
        // But turn on the alert again when the volume is above its 10-bar SMA
        if (Ticks > AverageFC(Ticks, 10)) then begin
        
            Print(barNumStr, "Volume is above its 10-bar average. ", 
                "Turning the alert back on again.");
        
            SetAlertState(true);
        
        end;
    
    end;

end;

We start the example by creating three variables:


Variables:
    evenBarNum(false),
    barNumStr(""),
    newHigh(false);

evenBarNum is a true/false variable initially set to false, and we use it later when determining whether a bar number is an even number or not. The second variable, barNumStr, is an empty string variable by default (""). We’ll use it later on when formatting the bar number to a text; that saves us from having to do that repeatedly. The third and last variable, newHigh, is set to true later on when a new 10-bar high happened (and false otherwise).

Then we figure out whether the current bar is the 10-bar high, and colour the price bar when it is:


newHigh = (High = Highest(High, 10));

if (newHigh) then
    PlotPaintBar(High, Low, Open, Close, "PaintBar", RGB(34, 139, 34));

We set the newHigh variable to a true/false expression that evaluates whether the high of the current bar (High) equals (=) the highest high of the recent 10 bars (including the current bar).

That latter is something we compute with Highest(), a function that requires two parameters: a series of data to get the highest value from and a numerical value that specifies the number of bars to calculate on. Here we set those arguments to high prices (High) and 10 to retrieve the 10-bar highest high. That highest high also includes the current bar. That’s why we evaluate if the current bar’s high equals the 10-bar highest high, instead of checking whether the current bar’s high crossed above the 10-bar high.

That just updated newHigh variable is then used in an if statement. When that variable is true, the PlotPaintBar() keyword in the if statement executes. That keyword makes a ‘painted’ price bar, which is like a regular price bar but with a colour over it. PlotPaintBar() requires several parameters: the price values of the painted bar (that we set to the current bar’s values with High, Low, Open, and Close), the plot name ("PaintBar"), and the colour of the painted bar (MultiCharts Wiki, 2012e).

We specify that colour with the RGB() keyword, which requires a red, green, and blue colour component value and returns the colour value for those three primary colours combined (MultiCharts Wiki, 2012f). With values of 34, 139, and 34, RGB() returns the forest green colour.

With those coloured price bars, we can see on which historical and real-time bars the alert condition happens. The rest of the script’s code is placed inside the following if statement:


if (CheckAlert and newHigh) then begin 

    // ...

end;

This if statement evaluates two expressions, which we combine with the and logical keyword. That keyword only returns true when the value on its left and the value on its right are both true; when one or both values are false, the result combined with and is false too (PowerLanguage Keyword Reference, 2016).

The first expression is the CheckAlert keyword to check whether the script’s alerts are enabled. That keyword returns true when we’ve manually enabled the script’s alert settings and the current bar is the last bar of the data series (MultiCharts Wiki, 2012b). With CheckAlert as a requirement before the code in the if statement executes, we prevent doing calculations related to generating an alert when the script’s alerts aren’t even enabled.

And since we only want to generate alerts with new 10-bar highest, we add the newHigh variable to the if statement’s condition. Combined, CheckAlert and newHigh ensure the code inside the if statement only executes when alerts can fire and the alert condition happens. As such, for a large majority of the script calculations the code inside the if statement never executes.

The if statement’s code begins with the following:


barNumStr = Text(NumToStr(Symbol_CurrentBar, 0), " - ");

Alert("This bar's high is a new 10-bar high");

Print(barNumStr, "10 bar high!");

Here we update the barNumStr variable to a string formatted with the Text() and NumToStr() keywords. The first keyword performs string concatenation (that is, combining several pieces of text together in a longer string), while the second formats a number to a text value with a certain number of decimals (MultiCharts Wiki, 2012g, 2012h).

The number that we convert to text here is the Symbol_CurrentBar keyword, which returns the bar number that the script currently calculates on (MultiCharts Wiki, 2012i). We use NumToStr() to format that numerical value to a string with zero decimals, and that makes it appear later on nicely. We also add the " - " string after that formatted text. With that separate the output that we’re going to generate later on becomes clearer.

Next we generate an alert message with Alert(). Inside this keyword’s parentheses we place a static text that notify us of a new 10-bar high. To track that event, we use the Print() keyword to output information to the Output tab of the PowerLanguage Editor (MultiCharts Wiki, 2012j). The printed information is the barNumStr variable (which we just assigned the bar number with a small separator) and the "10 bar high!" text. Since we’re also going to print information later when we cancel and re-active alerts, the Output tab of the code editor gives us a log of how the indicator behaves.

After generating an alert, the next piece of code can cancel that alert:


    evenBarNum = (mod(Symbol_CurrentBar, 2) = 0);
    
    if (evenBarNum) then begin
    
        Print(barNumStr, "This is an even bar, cancelling alert now");
            
        Cancel Alert;
        
        // ...
    
    end;

We cancel alerts arbitrarily on even bar numbers. But for that we first need to figure out if the current bar has an even bar number or not. For that we set the evenBarNum true/false variable to an expression that checks whether the value returned by mod() equals (=) 0.

That mod() keyword requires two numerical parameters and returns the arithmetic remainder (also called modulus) of dividing the first number by the second (MultiCharts Wiki, 2012k). This way we can see whether a number divides evenly into another. An example of this keyword is mod(25, 3), which returns 1 because 25 divided by 3 returns 8, with a remainder of 1.

Now if we compute the bar number modulo 2 (as we do here), then this operation returns 0 (meaning, no remainder) whenever the bar number is an even multiple of 2. So with the bar number being 12, mod(12, 2) returns 0 (because 12 / 2 = 6 with no remainder). This way we can use mod() to see whether the current bar number (returned by Symbol_CurrentBar) is an even bar number or not.

Based on how we use mod(), that also means evenBarNum is assigned true whenever the current bar number is an even number (and false otherwise). After that we evaluate this variable in an if statement, and so that if statement’s code only executes when the current bar has an even number.

That if statement code begins with Print() saying we’re going to programmatically cancel the alert. Then we use Cancel Alert to actually prevent a previously generated alert from firing (MultiCharts Wiki, 2012d). For our example indicator, this means that when there’s a new 10-bar high, our script generates an alert. But when that new high happens on an even bar number, then Cancel Alert cancels that alert.

To make it more confusing, there’s another nested if statement that can programmatically re-enable the alert again:


if (Ticks > AverageFC(Ticks, 10)) then begin

    Print(barNumStr, "Volume is above its 10-bar average. ", 
        "Turning the alert back on again.");

    SetAlertState(true);

end;

The condition of this if statement evaluates whether the volume of the current bar (Ticks) is greater than (>) the 10-bar average volume. We calculate that latter with AverageFC(). That function requires two arguments: a series of values to compute on and a number that sets the length of the average. Here we have the function work with the volume of price bars (Ticks) for a length of 10 bars.

Note:

On tick, volume, and time-based charts (with resolutions below 24 hours) the Volume keyword only returns the bar’s up volume (MultiCharts Wiki, 2012m), oddly enough. The Ticks keyword does return the bar’s total volume (up volume plus down volume) (MultiCharts Wiki, 2015). That’s why we use Ticks here instead of the more intuitive Volume keyword.

To have Ticks return volume (and not tick count), the chart’s ‘Build Volume On’ option has to be set to ‘Trade Volume’ (MultiCharts Wiki, 2015). To find that setting, right-click on a price bar of the instrument and choose ‘Format [symbol name]‘. This opens the ‘Format Instrument’ window, and there in the ‘Settings’ tab we find the ‘Build Volume On’ option:

Example of configuring the Trade Volume setting in MultiCharts

Now when the above if statement’s condition evaluates to true, we use Print() to output the current bar number (barNumStr) and a static text saying the alert is turned back on again. That alert ‘reactivation’ is done with SetAlertState(true).

So when our indicator generates a 10-bar highest high alert, Cancel Alert cancels that alert when it happens on an even bar number. But if that even bar’s volume is above its 10-bar moving average, then SetAlertState() re-enables our alert. (To reiterate, code becomes clearer when we do not use Cancel Alert and SetAlertState() in a MultiCharts script.)

Example: generating, cancelling, and re-activating MultiCharts alerts

Now let’s see how our above example indicator behaves on real-time data. First, when we add the script to a chart it colours price bars like this:

Example chart of the MultiCharts indicator

When a new 10-bar high happens, the bar is coloured green. The script then also generates the following alert message in the Output tab of the PowerLanguage Editor:

531 - 10 bar high!

The alert generated alongside those 10-bar highs looks like:

Example of the alerts generated by the MultiCharts example indicator

But when a 10-bar high happens on an even bar number, then we programmatically cancel the alert with the Cancel Alert keyword combination. We track that behaviour by having the script print a message like the following:

412 - 10 bar high!
412 - This is an even bar, cancelling alert now

Now when the alert is cancelled while the bar’s volume is above its 10-bar average, then we use SetAlertState() to turn the alert back on. In that case the indicator prints the following to the Output tab:

528 - 10 bar high!
528 - This is an even bar, cancelling alert now
528 - Volume is above its 10-bar average. Turning the alert back on again.

Now that SetAlertState() has re-enabled the alert message, our alert can still fire. When it does, however, the alert doesn’t have its message anymore:

Example of a previously cancelled alert that's turned back on

The above discussion of the example script also shows that using Cancel Alert and SetAlertState() in the same script makes the code hard to follow and understand. To prevent unclear code, see rewriting code so that Cancel Alert and SetAlertState() are unneeded.

Summary

We generate alerts programmatically with Alert(), but before this keyword can fire an alert we need to enable the script’s alert settings. The Cancel Alert and SetAlertState(false) keywords cancel alerts, while SetAlertState(true) fires an alert (and with that we ’re-enable’ an alert cancelled earlier). And so when a script calculates and triggers an alert with Alert(), we prevent that alert from firing by executing the Cancel Alert or SetAlertState(false) keyword. Later on in the script we then can conditionally re-enable the alert with SetAlertState(true). All these actions have to be done during the same script calculation; otherwise, the alert already fired (and cannot be cancelled anymore) or there’s no alert generated that can be turned back on (in that case, when we use SetAlertState(true) we generate an alert that doesn’t match with a previously cancelled alert). While Cancel Alert and SetAlertState() give additional features for programming alerts, they also make code harder to read, understand, and debug. Because their behaviour can be replicated with a simple true/false variable and if statement, we’re better off not using those keywords.

Learn more:


References

MultiCharts Wiki (2012a, February 7). Alert. Retrieved on April 27, 2016, from http://www.multicharts.com/trading-software/index.php/Alert

MultiCharts Wiki (2012b, February 7). CheckAlert. Retrieved on April 27, 2016, from http://www.multicharts.com/trading-software/index.php/CheckAlert

MultiCharts Wiki (2012c, February 26). AlertEnabled. Retrieved on March 11, 2016, from http://www.multicharts.com/trading-software/index.php/AlertEnabled

MultiCharts Wiki (2012d, February 7). Cancel Alert. Retrieved on April 26, 2016, from http://www.multicharts.com/trading-software/index.php/Cancel_Alert

MultiCharts Wiki (2012e, February 19). PlotPaintBar. Retrieved on April 27, 2016, from https://www.multicharts.com/trading-software/index.php/PlotPaintBar

MultiCharts Wiki (2012f, February 19). RGB. Retrieved on April 27, 2016, from https://www.multicharts.com/trading-software/index.php/RGB

MultiCharts Wiki (2012g, February 9). Text. Retrieved on April 27, 2016, from http://www.multicharts.com/trading-software/index.php/Text

MultiCharts Wiki (2012h, February 13). NumToStr. Retrieved on April 27, 2016, from http://www.multicharts.com/trading-software/index.php/NumToStr

MultiCharts Wiki (2012i, September 20). Symbol currentbar. Retrieved on April 27, 2016, from https://www.multicharts.com/trading-software/index.php/Symbol_currentbar

MultiCharts Wiki (2012j, February 13). Print. Retrieved on April 27, 2016, from https://www.multicharts.com/trading-software/index.php/Print

MultiCharts Wiki (2012k, February 13). Mod. Retrieved on April 30, 2016, from https://www.multicharts.com/trading-software/index.php/Mod

MultiCharts Wiki (2012l, September 20). Symbol currentbar. Retrieved on April 30, 2016, from https://www.multicharts.com/trading-software/index.php/Symbol_currentbar

MultiCharts Wiki (2012m, February 28). Volume. Retrieved on September 8, 2016, from http://www.multicharts.com/trading-software/index.php/Volume

MultiCharts Wiki (2013, May 10). Using Alerts. Retrieved on March 7, 2016, from https://www.multicharts.com/trading-software/index.php/Using_Alerts

MultiCharts Wiki (2015, November 20). Ticks. Retrieved on September 8, 2016, from http://www.multicharts.com/trading-software/index.php/Ticks

PowerLanguage Keyword Reference (2016). Retrieved on May 25, 2016, from http://www.multicharts.com/trading-software/images/c/c6/PowerLanguage_Keyword_Reference.pdf