When generating alerts in an indicator or signal (that is, trading strategy), we have different options for when the alert should fire. But how do we combine an alert that generates at most once per bar with efficient code that also only runs once per bar?

In this article:

Generating MultiCharts alerts at most once per bar

We generate MultiCharts alerts programmatically with the Alert() keyword (MultiCharts Wiki, 2012a). Before this keyword can fire alerts, we need to enable the script’s alert setting. Depending on how we’ve manually configured MultiCharts alerts, Alert() can trigger an audio alert, notification window, and/or email alert (MultiCharts Wiki, 2013).

Besides enabling the ‘Enable Alerts’ checkbox to turn on the script’s alert setting, there are three settings below that option for configuring when the alert should fire:

Example of enabling alerts of a MultiCharts indicator or strategy

With that ‘Alerts Conditions Check’ option we specify when the alert generated by Alert() can fire: when the bar closes, with every tick, or once per bar.

But besides that manual option, we can also use code to have our script generate alerts once per bar only. This has a couple of benefits. First, we don’t have to configure that ‘Once Per Bar’ setting by hand. This especially helps when we’ve added the script to multiple charts already and now we want to change how often it generates alerts. Without adding a few lines of programming code to get a once per bar alert, we’d have to change the script’s manual alert setting on each and every chart.

A second benefit is that, if we programmatically control which alert generates when, we can combine different alerts in the same script. For instance, we can limit a particular alert to once per bar while having another alert in that same script potentially fire with each price update.

The third, and perhaps most important, benefit is that using code to limit an alert to once per bar can make our script run more efficient. That’s because, as soon as the once per bar alert fired, we don’t need to perform computations related to the alert anymore. Especially when trading a high time frame, that can save thousands of times executing some block of code.

That latter advantage is also something that isn’t possible with the ‘Once Per Bar’ manual alert option. With that setting, MultiCharts still calculates everything related to the alert – it just won’t fire the actual alert anymore for that bar.

Let’s see what the requirements are for generating an alert once per bar, programmatically.

Quick example: using code to generate an alert once per bar

There are a couple of ways in which we can use code to programmatically generate an alert at most once per bar. But regardless of the specific way we implement, we have to create a variable that’s updated during the price bar with some value that allows us to see whether the alert already generated on that bar or not.

By default, however, PowerLanguage variables only keep the value that we store in them when the bar closes. When we update a variable’s value while the price bar hasn’t closed, then this value isn’t remembered till the next calculation and thereafter. That would be problematic since then we cannot track whether the alert already generated on the bar.

Luckily, we can override that counter-intuitive PowerLanguage behaviour with IntrabarPersist. When that keyword is placed before a variable, that variable keeps any value that we assign to it during an intra-bar script calculation – as opposed to the default behaviour of only keeping the value assigned to it during an on bar close calculation (MultiCharts Wiki, 2012b).

And so when we create our variable that tracks whether the alert already triggered, we place IntrabarPersist before it like this:


Variables:
    IntrabarPersist alertTriggered(false);

Here we create the alertTriggered true/false variable and give it a default value of false. With IntrabarPersist, this variable retains the value that we assign to it during an intra-bar calculation. With IntrabarPersist, alertTriggered would return the value it had on the close of the previous bar.

The next step in generating an alert once per bar is to check the value of that variable. And then to only generate an alert programmatically with Alert() when the variable indicates the alert hasn’t fired yet. After using Alert() to generate an alert, we need to change the variable’s value to something that prevents the alert from generating again on the same bar.

For example:


if (alertTriggered = false) then begin

    Alert("Once per bar alert message");

    alertTriggered = true;

end;

Here we use an if statement to check whether the alertTriggered variable is false. When it is, we take that as a sign that there isn’t an alert generated on this bar yet. And so we use Alert() to generate an alert programmatically. After that we switch the alertTriggered variable to true. Since that invalidates the if statement, during the next script calculation the code inside the if statement doesn’t execute again.

However, now our alertTriggered variable remains true for other price bars too, meaning alerts won’t fire on those bars. And so we have to reset the variable once per bar, for instance when the price bar closes:


if (BarStatus = 2) then
    alertTriggered = false;

The BarStatus keyword returns a numerical value that indicates the status of the price update currently processed by the script (MultiCharts Wiki, 2014). That way we can programmatically determine whether the current tick is the bar’s opening tick, closing tick, or a price update that falls between.

When the script calculates a price update that marks the closing tick of the bar, BarStatus returns 2 (MultiCharts Wiki, 2014). Here we use that situation to reset the alertTriggered variable back to false. That way, during the subsequent price bar, the script can generate an alert again.

Let’s see how we can use a similar approach in an example indicator to have an alert fire at most once per bar.

Example: once-per-bar alerts based on an instrument’s volume

In the indicator below we trigger two kinds of alerts. The first generates whenever the bar’s volume crossed above its 10-bar SMA (Simple Moving Average). Given that this condition compares the current bar’s value with that of the previous bar, this alert can happen several times per bar. The second alert that we program fires based on the ratio of up and down volume, and we code this alert so that it can happen at most once each bar.

With those two different alerts in the same script, the example indicator also shows how to combine an alert that’s triggered once per bar with one that can fire repeatedly during the same bar. A glimpse of how those alerts look is given by the image below. After discussing the code, we’ll examine the indicator’s behaviour more closely.

Example of alerts generated by the MultiCharts script

Inputs:
    Volume_Average_Length(10),
    Up_Down_Volume_Ratio(2);

Variables:
    IntrabarPersist alertBarNumber(0),
    volSMA(0), upDownRatio(0);

// Compute average volume and plot values
volSMA = AverageFC(Ticks, Volume_Average_Length);

Plot1(Ticks, "Volume", Blue);
Plot2(volSMA, "Avg volume", DarkGreen);

// Trigger alert whenever volume crosses over the 
if (Ticks crosses over volSMA) then
    Alert("Volume (" + NumToStr(Ticks, 0) + 
        ") crossed over its average @ " +
        NumToStr(volSMA, 0));

// Compute the ratio of up to down volume
if (DownTicks > 0) then
    upDownRatio = UpTicks / DownTicks
else
    upDownRatio = 0;

// Generate a once per bar alert based on the up/down volume ratio
if (upDownRatio >= Up_Down_Volume_Ratio) and 
    (CurrentBar > alertBarNumber) then begin

    SetPlotColor(1, Red);

    Alert("Upvolume is " + NumToStr(upDownRatio, 2) + 
        " times as large as the down volume.");

    alertBarNumber = CurrentBar;

end;

We begin by creating a couple of input options and numerical variables:


Inputs:
    Volume_Average_Length(10),
    Up_Down_Volume_Ratio(2);

Variables:
    IntrabarPersist alertBarNumber(0),
    volSMA(0), upDownRatio(0);

The first input option is named Volume_Average_Length and we give it a default value of 10. This input configures later on the length of the volume moving average. The other input, Up_Down_Volume_Ratio, begins with a default of 2 and specifies the up/down volume ratio at or above which an alert happens. By using input options here, we can easily change these values by hand in the indicator’s settings without having to edit and recompile the script.

The first variable we make is alertBarNumber, and we mark it as IntrabarPersist. That makes it retain any value that we assign it during an intra-bar script calculation (MultiCharts Wiki, 2012b). Doing so overrides the default behaviour of only remembering the value stored in the variable when the bar closed. We’ll use alertBarNumber later on to track whether an alert has already been generated on the current bar or not.

With the volSMA variable we store the average volume later on, and upDownRatio will hold the computed ratio between up and down volume.

Next we compute the average volume and create the indicator’s plots:


volSMA = AverageFC(Ticks, Volume_Average_Length);

Plot1(Ticks, "Volume", Blue);
Plot2(volSMA, "Avg volume", DarkGreen);

The volSMA variable is updated here to the value returned by AverageFC(). That function that calculates a simple moving average with two parameters: a series of values to compute on and a number that sets the moving average’s length in number of bars. Here we set those parameters to the Ticks keyword (which returns the bar’s total volume) and Volume_Average_Length, our input option that we gave a standard value of 20.

Note:

A counter-intuitive PowerLanguage feature is that the Volume keyword returns the bar’s up volume on tick, volume, and time-based charts with a resolution less than 24 hours (MultiCharts Wiki, 2012i). The Ticks keyword, on the other hand, returns the bar’s total volume (meaning, up volume plus down volume) (MultiCharts Wiki, 2015). That’s why we use Ticks here instead of the more obvious Volume keyword.

Before Ticks returns the current bar’s volume (and not the bar’s 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 select ‘Format [symbol name]‘. This opens the ‘Format Instrument’ window, and there in the ‘Settings’ tab we locate the ‘Build Volume On’ option:

Configuring the 'Build Volume On' option in MultiCharts

After calculating the average volume, we plot both the bar’s volume and average volume with Plot1() and Plot2(). Both keywords accept a range of parameters, of which we use three: the value, name, and colour of the plot (MultiCharts Wiki, 2012c).

With the Plot1() statement we display the Ticks values on the chart. We name this plot “Volume” and set its colour to the Blue standard MultiCharts colour. The second Plot2() keyword plots the volSMA variable, with a name of “Avg volume” and in the DarkGreen colour.

Then we generate the first of the script’s alerts:


if (Ticks crosses over volSMA) then
    Alert("Volume (" + NumToStr(Ticks, 0) + 
        ") crossed over its average @ " +
        NumToStr(volSMA, 0));

The if statement evaluates whether the current bar’s volume (Ticks) crossed above (crosses over) the 10-bar volume average (volSMA). That crosses over keyword combination returns true when, on the current bar, the value on its left is greater than the value on its right while, on the previous bar, the left value was less than or equal to the right value (MultiCharts Wiki, 2012d). When such a cross over didn’t happen, crosses over returns false.

Note: We compare here if the bar’s volume crossed above the average, relative to how the volume and average were on the previous bar. That condition can happen more than once during the same bar because, once the bar’s volume crossed above its average, that’s still the case during subsequent price updates. And that makes it possible for the Aler() keyword to fire more than once per bar.

When that cross over happens, the code below the if statement executes. That code generates an alert programmatically with the Alert() keyword. Inside the keyword’s parentheses we specify an alert message that consists out of fixed text (like "Volume (") and dynamic numerical values formatted to a string.

We format those Ticks and volSMA values with NumToStr(), a keyword that requires two parameters: the numerical value to convert to a string and how many decimals that formatted text should get (MultiCharts Wiki, 2012e). By setting that second argument to 0 here, both values convert to a zero decimal string. (The previous image or the image further down below shows how those generated alerts look like.)

Next we calculate the up/down volume ratio prior to using this value to generate the other alert:


if (DownTicks > 0) then
    upDownRatio = UpTicks / DownTicks
else
    upDownRatio = 0;

We access the bar’s up and down volume with DownTicks and UpTicks. These keywords, despite their name, return the bar’s volume (and not tick count) when the chart’s ‘Build Volume On’ option is set to ‘Trade Volume’ (e.g., MultiCharts Wiki, 2012f). (The data feed has to provide both up and down volume for us to calculate the up/down ratio.)

To prevent a division by zero error message, an if/else statement checks whether DownTicks is greater than (>) 0 before calculating the ratio. If it is, we update the upDownRatio variable to the result of dividing UpTicks with the value of DownTicks. If there’s no down volume (meaning, DownTicks isn’t bigger than 0), then we assign that variable a value of 0. With that value, there also won’t be an alert generated based on the up/down ratio.

Generating those alerts is done with the next if statement:


if (upDownRatio >= Up_Down_Volume_Ratio) and 
    (CurrentBar > alertBarNumber) then begin

    SetPlotColor(1, Red);

    Alert("Upvolume is " + NumToStr(upDownRatio, 2) + 
        " times as large as the down volume.");

    alertBarNumber = CurrentBar;

end;

This if statement’s condition evaluates two true/false expressions that are combined with and. That logical keyword only returns true when the value on its left and the value on its right are true too; otherwise, when one or both values are false, then the result combined with and is false too (MultiCharts Wiki, 2012g).

With the first expression we check whether the up/down ratio (upDownRatio) is greater than or equal to (>=) the Up_Down_Volume_Ratio input option, that we gave a standard value of 2 earlier. And so the first part of the if statement’s condition requires that the current bar’s up volume is two times (or more) the bar’s down volume.

The second expression is whether the current bar number (CurrentBar) is greater than (>) the value stored in alertBarNumber. Since we update that variable inside the if statement, that expression is only true once per bar. That’s because, during the next calculation on the same bar, alertBarNumber already holds the value of CurrentBar. This way we ensure that the code inside the if statement (which generates an alert) only executes once per bar.

With both expressions true, the if statement’s code begins with changing the colour of the first plot to Red. That way the volume values appear in a different colour when the up/down ratio is greater than or equal to our input option. We change that plot’s colour with SetPlotColour(), a keyword that requires two parameters: the number of the plot to change and the new colour (MultiCharts Wiki, 2012h).

Then we generate an alert with Alert(). Inside the parentheses of this keyword we use the + operator to combine static text with a dynamic value (upDownRatio), which we format to a 2-decimal string with NumToStr(). After that we update the alertBarNumber variable to the current bar number (CurrentBar). Given that this invalidates the if statement’s condition for other calculations during the same bar, all code inside the if statement only executes once per bar. That also means that any calculations placed inside this if statement only execute when the alert hasn’t fired yet, but then won’t calculate on the current bar again.

After programming the script in the PowerLanguage Editor, we still need to set the first plot to a histogram instead of the default line. That’s, unfortunately, not something we can do programmatically. Instead, we have to right-click somewhere in the text area of the PowerLanguage Editor and choose ‘Properties’. This opens a window with the indicator settings, and there in the ‘Chart Style’ tab we set the ‘Type’ of the volume plot to ‘Histogram’:

Setting a plot's style to 'Histogram' in MultiCharts

After changing and confirming that setting we save and compile the script.

Example: generating volume and up/down volume alerts

Now let’s see how our example indicator behaves on the chart. First, its input options are the following:

Example of the input options of the MultiCharts script

To have the indicator generate alerts, we need to enable the script’s alert settings like so:

Configuring the alert settings of the MultiCharts indicator

We set the ‘Alert Conditions Check’ option to ‘Every Tick’. That allows the script to fire an alert whenever the Alert() keyword executes. But since our code already limits how many up/down ratio alerts can be triggered, we won’t have multiple of those alerts on the same bar. By the way, should we choose the ‘Once Per Bar’ option, then only one of the alerts that we’ve programmed can generate per bar – but both alerts can then not fire on the same bar.

The example indicator looks like this when added to a chart:

Example chart of the MultiCharts volume indicator

And the alerts that the script makes appear as follows:

Example alerts that triggered once per bar in MultiCharts

Here we see that there are several alerts about the volume crossing above its average on the same bar, but only one alert about the up versus down volume.

Summary

The Alert() keyword generates MultiCharts alerts programmatically, but we do need to enable the script’s alert settings for that. While there’s a manual option that allows one alert per bar, implementing this programmatically has several benefits. Like allowing us to generate a particular alert once per bar, while another alert in the same script can generate multiple times per bar. And we can make the script run more efficient by not performing certain calculations when the alert already fired. One approach to generate an alert once per bar is to use a true/false variable that’s set to true when the alert is generated with Alert(). Then when the bar closes (which we can check with BarStatus), we reset the variable so the next bar can again generate one alert. Another approach is storing the current bar number in a variable when we generate the alert. Since the bar number changes once per bar, each time that variable holds the same value as the current bar number, we know that the alert already fired. Regardless of the approach, those variables need to be marked as IntrabarPersist. That way they remember the values assigned to them during an intra-bar calculation. Otherwise, the default behaviour of PowerLanguage means that the variable will only keep the value that we assign to it on bar close.

Learn more:


References

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

MultiCharts Wiki (2012b, August 11). IntraBarPersist. Retrieved on May 8, 2016, from https://www.multicharts.com/trading-software/index.php/IntraBarPersist

MultiCharts Wiki (2012c, February 19). Plot. Retrieved on May 9, 2016, from https://www.multicharts.com/trading-software/index.php/Plot

MultiCharts Wiki (2012d, February 19). Cross. Retrieved on May 9, 2016, from https://www.multicharts.com/trading-software/index.php/Cross

MultiCharts Wiki (2012e, February 13). NumToStr. Retrieved on May 9, 2016, from https://www.multicharts.com/trading-software/index.php/NumToStr

MultiCharts Wiki (2012f, February 28). DownTicks. Retrieved on May 9, 2016, from https://www.multicharts.com/trading-software/index.php/DownTicks

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

MultiCharts Wiki (2012h, February 19). SetPlotColor. Retrieved on May 9, 2016, from https://www.multicharts.com/trading-software/index.php/SetPlotColor

MultiCharts Wiki (2012i, 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 (2014, August 12). BarStatus. Retrieved on May 3, 2016, from https://www.multicharts.com/trading-software/index.php/BarStatus

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