While we often fire alerts based on price action, another helpful way is to trigger alerts based on strategy data like the currently open market position. That makes it possible to monitor if a strategy opens, closes, increases, decreases, or reverses a position. How do we implement that in PowerLanguage?

In this article:

Triggering MultiCharts alerts based on the strategy’s position

We generate alerts programmatically with the Alert() keyword (PowerLanguage Keyword Reference, 2016), provided we manually enabled the script’s alert setting. Then an alert can appear as a notification window, audio alert, and/or email alert (MultiCharts Wiki, 2013), depending on the alert configuration.

While we typically generate alerts based on price action – such as a moving average crossover alert – we can actually generate an alert for anything that’s accessible in PowerLanguage. For instance, we might trigger an alert when automated trading is disabled or when there’s a possible data feed issue.

Another way is triggering an alert when the strategy’s market position changes. That makes tracking the strategy’s behaviour easy. That helps when we have a new strategy and want to keep a close eye on its real-time behaviour. With this kind of monitoring it’s also easier to manually intervene when the strategy increases, decreases, or closes positions incorrectly.

We can retrieve a strategy’s current position by combining two PowerLanguage keywords. The first is MarketPosition, which returns a numerical value to indicate the direction of the strategy’s current position (PowerLanguage Keyword Reference, 2016). When the strategy is long, MarketPosition returns 1; when short, it returns -1; and no open position makes the keyword return 0 (PowerLanguage Keyword Reference, 2016).

Besides the direction, we also have to get the position size so we can see if the position size increased or decreased. For this we use CurrentContracts, a keyword that returns an absolute value with the strategy’s current position size (PowerLanguage Keyword Reference, 2016).

Note: Both the MarketPosition and CurrentContracts keywords fetch position information from the chart or portfolio, not from the broker. That means these keywords can also be used during backtesting or when the strategy runs on real-time data without automated trading enabled.

Combined, MarketPosition and CurrentContracts can tell us a lot about the strategy’s position. Let’s look at a programming example to see how we can use that information to generate alerts with.

Example: generating alerts when the strategy’s position changes

The example signal below generates an alert whenever the strategy opens, increases, or decreases a long or short position. For this it monitors the current and previous values of the MarketPosition and CurrentContracts keywords.

But the signal doesn’t perform other tasks. And so for submitting orders we’ll need to add other signals to the chart or portfolio. This is possible because MultiCharts combines multiple signals automatically into a single strategy (MultiCharts Wiki, 2016). This way we don’t have to replicate code in other signals. Instead, we simply add our example signal to any chart or portfolio where we want it to generate alerts based on the strategy’s market position.

The image below shows an example of the alerts generated by this signal. After we discuss the code we’ll take a closer look at its behaviour.

Example alert triggered when the strategy's position changes

[IntrabarOrderGeneration = true];

Variables:
    MP(0),
    IntrabarPersist prevMP(0),
    positionNow(""),
    prevPosition("");

if (CheckAlert) then begin

    MP = MarketPosition * CurrentContracts;
    
    positionNow  = NumToStr(MP, 0);
    prevPosition = NumToStr(prevMP, 0);
    
    // Alerts for when the strategy is flat now
    if (MP = 0) then begin
    
        if (prevMP > 0) then
            Alert("The strategy went from long to flat.")
        else if (prevMP < 0) then
            Alert("The strategy is now flat (from short previously).");
    
    end 
    
    
    // Alerts for when there's an open long position now
    else if (MP > 0) then begin
    
        // .. when the previous position was already long
        if (prevMP > 0) then begin
        
            if (prevMP < MP) then
                Alert("The strategy's long position increased from " + 
                    prevPosition +  " to " + 
                    positionNow + " contracts.")
            else if (prevMP > MP) then
                Alert("The strategy's long position decreased from " + 
                    prevPosition + " to " + 
                    positionNow + " contracts.");
                    
        end 
        
        // .. when the previous position was short
        else if (prevMP < 0) then begin
        
            Alert("The strategy's position went from short " + prevPosition + 
                " contracts to long " + positionNow + " contracts.");
        
        end 
        
        // .. when the previous position was flat
        else if (prevMP = 0) then begin
        
            Alert("The strategy opened a long position of " + positionNow + 
                " contracts while being flat previously.");     
        
        end;
    
    end
    
    
    // And alerts for when the strategy is short now
    else if (MP < 0) then begin

        // .. when the previous position was already short
        if (prevMP < 0) then begin
        
            if (prevMP < MP) then
                Alert("The strategy's short position decreased from " + 
                    prevPosition + " to " + 
                    positionNow + " short contracts now.")
            else if (prevMP > MP) then
                Alert("The strategy's short position increased from " +  
                    prevPosition + " contracts to " + 
                    positionNow + " short contracts now.");
        
        end
        
        // .. when the previous position was long
        else if (prevMP > 0) then begin
        
            Alert("The strategy's position went from long " + prevPosition +
                " contracts to short " + positionNow + " contracts.");
        
        end
        
        // .. when the previous position was flat
        else if (prevMP = 0) then begin
        
            Alert("The strategy opened a short position of " + positionNow + 
                " contracts while being flat previously.");
        
        end;

    end;    
    
    // Update the 'prevMP' variable for the next script calculation
    prevMP = MP;

end;

We begin with the IntrabarOrderGeneration attribute set to true. That makes the signal process every real-time tick (MultiCharts Wiki, 2012). With this our signal can check how the strategy’s market position changed from one script calculation to the next.

Then we declare several variables:


Variables:
    MP(0),
    IntrabarPersist prevMP(0),
    positionNow(""),
    prevPosition("");

We make two numerical variables here: MP and prevMP. The first will hold the strategy’s current position, and prevMP tracks what the strategy’s position was the last time the signal calculated. By comparing those two variables later on we can see if (and how) the position changed.

We place the IntrabarPersist keyword before prevMP. That keyword makes the variable retain its value from one intra-bar script calculation to the next (PowerLanguage Keyword Reference, 2016). This overrides the default PowerLanguage behaviour, which entails that variables only update to a new value when the bar closes. Since we want to use the prevMP variable to access the strategy’s market position as it was during the previous intra-bar script calculation, we declare it as IntrabarPersist.

The other two variables, positionNow and prevPosition, are both text variables. These are used when we format the strategy’s current and previous position size to a string.

After making the variables we arrive at the script’s actual code. All that code is inside the following if statement:


if (CheckAlert) then begin

    // ...

end;

Here we use CheckAlert to programmatically check if alerts are enabled. That keyword returns true when the ‘Enable Alerts’ checkbox is on and when the bar currently processed by the script is the last of the data series (PowerLanguage Keyword Reference, 2016). By using CheckAlert here the code inside the if statement only executes when we can actually generate an alert.

Inside the if statement, we first compute the strategy’s position and format that information to a string:


MP = MarketPosition * CurrentContracts;

positionNow  = NumToStr(MP, 0);
prevPosition = NumToStr(prevMP, 0);

We set the MP variable to the strategy’s current position size, which we retrieve by multiplying the strategy’s direction (MarketPosition) with its position size (CurrentContracts). This makes MP hold one of three values: a positive value that signals the strategy’s long position size, a negative value with the number of contracts the strategy is short, or 0 when the strategy has no open position. We’ll use those three kind of values later on when generating alerts.

To include the current and previous position size as nicely formatted numbers in any alert, we convert the MP and prevMP variables to a string here with the NumToStr() keyword. That keyword has two parameters: a number to convert to a string and how many decimals that value should get (PowerLanguage Keyword Reference, 2016). Here we format those position sizes with 0 decimals, and store them in the positionNow and prevPosition variables for easy access later on.

(The prevMP variable is set to a value later on in the script. For now, know that this variable holds the strategy’s position of the previous time the script calculated.)

Next a big chunk of the signal’s code is an if/else statement that generates alerts based on how the strategy’s open position changed. First we have the following if statement:


if (MP = 0) then begin

    if (prevMP > 0) then
        Alert("The strategy went from long to flat.")
    else if (prevMP < 0) then
        Alert("The strategy is now flat (from short previously).");

end 

Here we evaluate whether the MP variable equals (=) 0. When that’s the case, the strategy is currently flat and the code inside this if statement executes. What we don’t know, however, is whether the strategy was already flat or just closed a long or short position.

To figure that out, a nested if/else statement evaluates whether the prevMP variable was greater than (>) 0 or less than (<) 0. In the first case, we know that the strategy was long previously; in the second case, the strategy had a short position during the previous script calculation.

Either way, we use the Alert() keyword to generate an alert. The alert message that we generate here depends on the value of prevMP. When the strategy was long previously (prevMP > 0), we generate an alert saying the strategy went from long to flat. And when short earlier (prevMP < 0), the triggered alert has the message that the strategy is now flat (from short).

Besides being currently flat, the strategy can also have an open long position. That’s something we address in the following else if statement:


else if (MP > 0) then begin

    // .. when the previous position was already long
    if (prevMP > 0) then begin
    
        if (prevMP < MP) then
            Alert("The strategy's long position increased from " + 
                prevPosition +  " to " + 
                positionNow + " contracts.")
        else if (prevMP > MP) then
            Alert("The strategy's long position decreased from " + 
                prevPosition + " to " + 
                positionNow + " contracts.");
                
    end 
    
    // .. when the previous position was short
    else if (prevMP < 0) then begin
    
        Alert("The strategy's position went from short " + prevPosition + 
            " contracts to long " + positionNow + " contracts.");
    
    end 
    
    // .. when the previous position was flat
    else if (prevMP = 0) then begin
    
        Alert("The strategy opened a long position of " + positionNow + 
            " contracts while being flat previously.");     
    
    end;

end

Here we first check if the strategy’s current market position (MP) is greater than (>) 0, which it is when there’s an open long position. What we don’t know yet, is how this open long position might have changed. And so we figure that out with a nested if/else statement that checks the strategy’s previous market position (prevMP).

That code addresses how the long position changed. While we know that the strategy is currently long (that is, MP > 0), there are several ways in which that open position may differ compared to the last time the script calculated:

  • The strategy could have been long previously (meaning, prevMP > 0). When the strategy is long now and also long previously, the open position could have changed in two ways:
    • The previous position was smaller than the current (prevMP < MP). That happens when the strategy increased its long position (like from 5 to 8 contracts), and we use Alert() to generate an accompanying alert message.
    • The previous position was bigger than the current (prevMP > MP). This occurs when the strategy decreased its long position (for example by taking a partial profit). In that case we use Alert() to generate an alert saying the long position decreased.
  • The strategy could have been short previously (prevMP < 0). Given that the strategy is now long, the position went from short to long. And so we include that information in the alert message.
  • The strategy could have been flat previously (prevMP = 0). When being long now, that means the strategy went from flat to long and we then uses Alert() to trigger an alert with that information.

Each of those alert messages use prevPosition and positionNow. Earlier, we set those string variables to the previous and current position. By including this information in the alert messages, we can see how the long position changed each time the alert fires (see the images further down below for how the alerts look like).

But besides being flat or long, the strategy can also have an open short position. To generate alerts for that situation, we use the following collection of if statements:


else if (MP < 0) then begin

    // .. when the previous position was already short
    if (prevMP < 0) then begin
    
        if (prevMP < MP) then
            Alert("The strategy's short position decreased from " + 
                prevPosition + " to " + 
                positionNow + " short contracts now.")
        else if (prevMP > MP) then
            Alert("The strategy's short position increased from " +  
                prevPosition + " contracts to " + 
                positionNow + " short contracts now.");
    
    end
    
    // .. when the previous position was long
    else if (prevMP > 0) then begin
    
        Alert("The strategy's position went from long " + prevPosition +
            " contracts to short " + positionNow + " contracts.");
    
    end
    
    // .. when the previous position was flat
    else if (prevMP = 0) then begin
    
        Alert("The strategy opened a short position of " + positionNow + 
            " contracts while being flat previously.");
    
    end;

end;

This part is much like how we dealt with long positions. First we check whether the strategy is short (that is, MP < 0). Then we explore the three ways in which the short position can differ compared to the last time the script calculated:

  • The strategy could have been short the previous time the script calculated (prevMP < 0). When the strategy is short now and was short previously, the open position can differ in two ways:
    • The previous short position had a bigger position size than the current position. Because negative values of the MP and prevMP variables signal the size of the short position, we check to see if the previous position (prevMP) was less than (that is, more negative) than the current (MP). When that’s the case, we trigger an alert saying the short position decreased in size.
    • The previous short had a smaller position size than the current position. This happens when the strategy’s position on the previous script calculation was bigger than (that is, ‘less short’) the current market position (prevMP > MP). When that occurs we use Alert() to generate an alert saying how much the short position increased.
  • The strategy could have been long previously (prevMP > 0). Since the strategy is short now (MP < 0), that means the strategy’s direction reversed from a long to short position. And so we use Alert() to generate an alert saying so.
  • The strategy could have been flat previously (prevMP = 0). In that case the strategy just opened a short position and that becomes the message of our alert.

To make the comparisons between the current and previous position work, we update the prevMP variable at the end of each script calculation:


prevMP = MP;

After the signal processes the code that generates alerts based on its position, we set the prevMP variable to the strategy’s current market position (MP). By doing this at the end of the script, the next time the signal calculates the prevMP holds the strategy position of the previous script calculation. That makes is possible to compare how the then-current market position differs from the previous position.

Generating alerts when the MultiCharts market position changes

Now let’s see how the above signal behaves. When we add the script to the chart, we enable the strategy’s alerts like this:

Configuring the alert settings of the MultiCharts strategy

Since our example script doesn’t submit trades, we add other signals to the chart for that. MultiCharts already includes several example signals, and for the images below we add the ‘Channel Breakout LE’, ‘Channel Breakout SE’, ‘TimeExit (Bars) LX’, and ‘TimeExit (Bars) SX’ signals to the chart. Those signals trade price breakouts and exit a position after a certain number of bars. They make the chart look like:

Multiple MultiCharts signals added to the price chart

Here we see that the strategy is currently short due to two ‘ChBrkSE’ short orders. The last of these generated just a moment ago. Since that changes the strategy’s market position, our example signal generates the following alert:

Example alert generated by the MultiCharts strategy

Now when the strategy closes two short contracts, like with the ‘TimeBarsSX’ order here:

Chart with MultiCharts closing two short contracts

Then our example signal generates the following alert:

Alert triggered when the strategy closes 2 short contracts

And when the ‘TimeBarsLX’ order closes an open long position like so:

Example chart: MultiCharts closing a long position

Then we get an alert message like the following:

Example alert after closing an open long position in MultiCharts

To learn more about generating MultiCharts alerts based on the strategy’s position, see firing an alert when the strategy’s position doesn’t match the broker’s position.

Summary

We can generate MultiCharts alerts programmatically with Alert() when the ‘Enable Alerts’ option is enabled. A strategy position can change in several ways, from simply going long or short to increasing, decreasing, or reversing an existing position. To figure out how the position changed, we need to get the strategy’s current position. For that we multiply the MarketPosition and CurrentContracts keywords. The first of these returns the strategy’s direction: 1 for long, -1 for short, and 0 when flat. The second keyword returns the current position size as a positive value (or 0 when flat). The product of these two keywords gives us both the direction and size of the position. With that value stored in a variable we can, on the next script calculation, see how the current market position changed compared to the previous script calculation. When that shows a changed position, we use Alert() to trigger an alert saying how the position changed. For this to work the variable that holds the previous market position needs to be declared with IntrabarPersist. Otherwise, that variable only holds the value of the last time the price bar closed and won’t remember its value from one intra-bar script calculation to the next.

Learn more:


References

MultiCharts Wiki (2012, August 31). IntraBarOrderGeneration. Retrieved on September 1, 2016, from http://www.multicharts.com/trading-software/index.php/IntraBarOrderGeneration

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

MultiCharts Wiki (2016, February 22). How Scripts Work. Retrieved on September 1, 2016, from http://www.multicharts.com/trading-software/index.php/How_Scripts_Work

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