Before a MultiCharts indicator or signal can generate alerts, its ‘Enable Alerts’ checkbox option has to be enabled. But if we forget to turn on that option, the script won’t be able to fire any alert. That can be a problem when we rely on a script’s alerts for important information. So how do we create some kind of notification that alerts are turned off?

In this article:

Checking if alerts are enabled and triggering MultiCharts errors

We generate alerts programmatically with the Alert() keyword (PowerLanguage Keyword Reference, 2016), although for that we’ll need to enable the script’s alerts. Then, depending on the manual alert settings, alerts can appear as a notification window, audio alerts, and/or email alert (MultiCharts Wiki, 2013).

Currently, it’s not possible to programmatically enable or disable a script’s alerts. That means we’ll have to manually turn on the ‘Enable Alerts’ checkbox before the script can generate alerts (see image below), and we’ll have to do that on each chart, portfolio strategy, or Scanner/Watchlist window in which the script runs.

Enabling alerts by hand in MultiCharts

Unfortunately, sooner or later we’ll forget to enable that manual alert setting, leaving us to wonder why the alerts don’t fire even though the alert conditions do happen. Besides that annoyance, it’s also problematic when we rely on the script to generate important alerts (like with alerts for possible real-time data feed issues or when automated trading gets disabled). And so we might think that everything runs smoothly since no alerts trigger, but only to later learn that there was an issue but that the script’s alerts were disabled.

Creating a notification when the script’s alerts are disabled is one way to prevent that. One kind of notification are run-time errors with a specific error message, which we trigger with the RaiseRunTimeError() keyword (PowerLanguage Keyword Reference, 2016).

A run-time error is an error that happens while the code runs, often due to some kind of unexpected value or data. Those errors differ from compile-time errors, which are the errors that happen when we mistype or misuse a piece of code (Liberty & MacDonald, 2009; Sempf, Sphar, & Davis, 2010).

Those errors that we trigger with RaiseRunTimeError() have the same appearance as MultiCharts’ error message, like this one that can happen when configuring email alert settings:

Example of a run-time error message in MultiCharts

There are a couple of benefits with those red error messages. First, RaiseRunTimeError() can trigger an error message regardless of the script’s settings. And so when alerts are disabled, we can still create a notification window. Another advantage is that those red error windows don’t go away unless we click on them. That makes them a lot harder to miss.

RaiseRunTimeError() also has an important disadvantage: when we execute the keyword in a script, MultiCharts turns off that script. That means we’ll need to manually re-enable the script again. Should the error happens again after that, we’ll need to turn on the script again (and so on).

Note: We can also stop the execution of a MultiCharts script with the Abort keyword (PowerLanguage Keyword Reference, 2016), which has the same effect as RaiseRunTimeError(). However, with Abort we cannot specify an error message. Since error messages without an explanation or message quickly become confusing and annoying, it’s best to use RaiseRunTimeError().

Because RaiseRunTimeError() stops the script, we’re better off limiting this keyword to important situations – like when the script’s alerts are disabled, even though we rely on the script to generate prompt notifications of possible issues.

Before generating an error message in those cases, we’ll first need to programmatically check whether the script’s alerts are enabled. There are two keywords for that (PowerLanguage Keyword Reference, 2016):

  • The AlertEnabled keyword returns true when the ‘Enable Alerts’ setting of the script is enabled and returns false when that checkbox is disabled.
  • The CheckAlert keyword returns true when the script’s alert settings have been enabled and the script currently calculates on the last bar of the data series. On all other price bars or when the alerts are disabled, this keyword returns false.

And so AlertEnabled checks the alert setting status on every price bar whereas CheckAlert only does that for the last price bar.

Below we look at a script that generates error messages when alerts are turned off. Since alerts can only fire on the last bar (PowerLanguage Keyword Reference, 2016), we use CheckAlert to see if RaiseRunTimeError() should generate an error message.

Example: generating an error when alerts aren’t enabled

In the example indicator below we create a notifying error message whenever the script’s ‘Enable Alerts’ option is turned off. Besides generating an error message, RaiseRunTimeError() also turns off the script. To make our indicator a bit more user friendly, we use a 60-second grace period before triggering the error. That gives enough time to enable the script’s alert setting after we added the indicator to the chart.

The image below shows how that error message looks like. After discussing the code we’ll look closer at the indicator’s behaviour.

Example of the error message generated by MultiCharts when alerts are off

Inputs:
    TimeOut_Seconds(60);

Variables:
    startTime(ComputerDateTime),
    secondsSinceStart(0);
    
// If the script's alerts are disabled, we countdown 
// to creating a run-time error
if (AlertEnabled = false) then begin

    // Compute the time difference since starting the script
    secondsSinceStart = (ComputerDateTime - startTime) /
        ELTimeToDateTime_s(1);
        
    // Trigger the error when more than the specified amount of time
    // has passed and the alert setting still isn't enabled
    if (secondsSinceStart > TimeOut_Seconds) then
        RaiseRunTimeError("This script's alerts are not enabled!");

    RecalcLastBarAfter(1);

end;

// Generate an alert with how much higher or lower the close is
if (Close > Open) then
    Alert("Close of " + NumToStr(Close, 1) + " is " +
        NumToStr(Close - Close[1], 1) + " points higher.")

else
    Alert("Close of " + NumToStr(Close, 1) + " is " +
        NumToStr(Close - Close[1], 1) + " points lower.");

We start by creating an input option and two variables:


Inputs:
    TimeOut_Seconds(60);

Variables:
    startTime(ComputerDateTime),
    secondsSinceStart(0);

The TimeOut_Seconds input sets the grace period in number of seconds before the indicator generates the error message for when the ‘Enable Alerts’ option is disabled. By using an input option here we can easily change the number of seconds, without having to edit and recompile the script’s code.

The first numerical variable is named startTime and set to the value returned by ComputerDateTime. That keyword returns the computer’s date and time in the DateTime numerical format (PowerLanguage Keyword Reference, 2016). Of that format, the integer portion represents the number of days since January 1, 1900, while the fractional part corresponds to the portion of the day passed since midnight (PowerLanguage Keyword Reference, 2016). That way DateTime values represents both a date and time of day. What makes DateTime values handy is that we can use them for time calculations (like counting down to generating an error message).

We give the startTime numerical value not a default value of 0 but set it to ComputerDateTime. The reasoning behind this is the following. Each time a script starts calculating from the first bar to the last, the script’s variables are given their default value. And so those variables reset whenever we add a script to the chart, turn it off and back on, or change a script setting. In our case that means startTime holds the computer time of when we added the script to the chart, which allows us to later on determine whether the 60-seconds time out period passed or not.

The second numerical variable that we make is named secondsSinceStart. This one is used later on when we calculate how many seconds passed between the time stored in startTime and the computer’s current time.

The first part of the indicator is an if statement that programmatically checks if alerts are enabled:


if (AlertEnabled = false) then begin

    secondsSinceStart = (ComputerDateTime - startTime) /
        ELTimeToDateTime_s(1);

    if (secondsSinceStart > TimeOut_Seconds) then
        RaiseRunTimeError("This script's alerts are not enabled!");

    RecalcLastBarAfter(1);

end;

This if statement’s condition uses AlertEnabled to see whether the script’s ‘Enable Alerts’ setting is enabled. We evaluate whether that keyword’s value equals (=) false, which it does when the script calculates on the last bar with the script’s ‘Enable Alerts’ option disabled (PowerLanguage Keyword Reference, 2016).

In that situation, we first calculate how many seconds ago the script became active. For that we first subtract the startTime variable from the computer’s current time (ComputerDateTime). Because those are both DateTime values, that subtraction results in a DateTime value too.

Unfortunately, that doesn’t tell us how many seconds passed. And so we divide that DateTime difference by the DateTime value of 1 second, which we get with the ELTimeToDateTime_s() keyword and a value of 1 between its parentheses (PowerLanguage Keyword Reference, 2016). We then store that computed number of seconds in the secondsSinceStart variable.

Then there’s another if statement inside the if statement that checks whether alerts are disabled:


if (secondsSinceStart > TimeOut_Seconds) then
    RaiseRunTimeError("This script's alerts are not enabled!");

This code checks whether the number of seconds ago that the script became active (secondsSinceStart) is greater than (>) the ‘pause’ period specified with the TimeOut_Seconds input option. Only when more than 60 seconds passed (the input’s default value), we execute the RaiseRunTimeError() keyword to generate a run-time error. With the message between that keyword’s parentheses we say that the script’s alerts aren’t enabled (see the image above or further below for how that error message looks).

By the way, that error message also appears when alerts are disabled (from enabled previously). And so the code doesn’t require that alerts were off to begin with. Instead, simply each time when the script’s alerts are disabled, the error message appears (after the TimeOut_Seconds grace period).

The last piece of code inside the if statement that checks whether alerts are disabled is:


RecalcLastBarAfter(1);

The RecalcLastBarAfter() keyword makes the script recalculate on the last bar every certain number of seconds (PowerLanguage Keyword Reference, 2016). Here we use the keyword with 1, and with that the script periodically recalculates every second.

We use RecalcLastBarAfter() here because of the following. When the indicator is added to an instrument, we don’t know whether the market is active with lots of price updates, slow, or perhaps even closed. But our script still needs to issue an error message after 60 seconds, regardless of the instrument’s activity. And so we force a periodic script calculation with RecalcLastBarAfter(). That way we can be sure that, even when the market is slow or closed, we still get our error message around a minute after adding the script to the chart.

Besides triggering those error messages, the indicator generates alerts too. We do that in the second part of the script:


if (Close > Open) then
    Alert("Close of " + NumToStr(Close, 1) + " is " +
        NumToStr(Close - Close[1], 1) + " points higher.")

else
    Alert("Close of " + NumToStr(Close, 1) + " is " +
        NumToStr(Close - Close[1], 1) + " points lower.");

This if/else statement evaluates whether the bar’s closing price (Close) is greater than (>) its open (Open). When that happens, we trigger an accompanying alert message. For a bar that doesn’t close higher (the else portion of the if/else statement), a different alert fires.

Both Alert() statements generate an alert with a similar message, and those messages consist out of fixed strings (like "Close of ") and dynamic numerical values. Formatting those numerical values is done with NumToStr(). That keyword requires two parameters: the number to convert to text and how many decimals that converted number should get (PowerLanguage Keyword Reference, 2016). The values that we include in the alert messages are the bar’s closing price and its difference compared to the previous bar (Close - Close[1]), both printed as a 1-decimal string.

Example: trigger an error when alerts are disabled

Now let’s see how the above example indicator behaves. When we add it to the chart, we start with the following manual alert settings:

Starting with the indicator's alerts turned off

We can use the indicator’s input option to configure how long the script waits till generating an alert:

Input option of the MultiCharts example indicator

When we add the script to the chart without checking the ‘Enable Alerts’ checkbox, initially nothing happens. But after 60 seconds, the following run-time error triggers:

Example of the error message generated by the script

Such an error also turns off the script that generated it. We can see that on the chart: the indicator’s name now appears with a shaded background in the Status Line:

MultiCharts script turned off due to the run-time error

This feature of the RaiseRunTimeError() keyword means that, besides using the correct alert settings, we now also have to re-enable the indicator. Let’s first change the manual alert settings. For that we right-click on the script’s name and select ‘Format [script name]…’:

Opening the settings of the MultiCharts indicator

This brings up the ‘Format Study’ window. There we navigate to the ‘Alerts’ tab where we can enable the script’s alerts as well as configure the alert settings. Here we check the ‘Enable Alerts’ checkbox and have the script generate one alert per bar, with the ‘On Bar Close’ setting below ‘Alert Conditions Check’:

Configuring the alert settings by hand

To re-enable the indicator, we simply left-click on its name in the chart’s Status Line. That turns the script back on and removes the shaded background:

Re-enabling the MultiCharts indicatoro on the chart

The indicator now doesn’t trigger errors anymore when 60 seconds after its initial calculation passed. Instead, the indicator fires alerts like:

Examples of alerts generated by the MultiCharts indicator

Besides triggering those attention-grabbing (and possibly annoying) error windows when alerts aren’t enabled, we can also create a notifying text box whenever alerts are disabled.

Summary

We generate MultiCharts alerts programmatically with Alert(), but this keyword does require that we enabled the script’s alert setting. While we can use the AlertEnabled and CheckAlert keywords to see whether that option is turned on, we cannot toggle the state of the ‘Enable Alerts’ checkbox programmatically. And so we’ll have to enable that option by hand. When our script uses alerts to communicate important information (like when monitoring a strategy or data feed), then we might want to generate an error message when the script’s alerts are disabled. That way we don’t end up thinking there isn’t an issue, with only to later learn that there was a problem but with alerts disabled we couldn’t get notified. We use the RaiseRunTimeError() keyword to trigger an error message in that situation. Besides creating a red error box, that keyword also turns off the script. Since that can be annoying, one way to make RaiseRunTimeError() behave more user friendly is by giving ourselves a bit of time to configure the script’s alerts properly.

Learn more:


References

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

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

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

Sempf, B., Sphar, C., & Davis, S.R. (2010). C# 2010 All-In-One for Dummies. Hoboken, NJ: John Wiley & Sons.