When a strategy performs automated trading, we rely on it to accurately manage our position at the broker. But in some cases, the position that the strategy thinks it has can differ from the actual open position at the broker. How do we generate an alert when such a mismatch happens?

In this article:

Firing an alert when the chart and broker position don’t match

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

When we use alerts, most often we’ll trigger them based on price action. We can also use alerts for risk management, however. An example of that is firing an alert when there’s no real-time data to help identify possible data feed issues. For automated trading strategies, another risk is a mismatch between the strategy position according to MultiCharts and the broker’s open position.

Let’s explore what that means and how we can programmatically check for it. Then we’ll look at triggering alerts when that mismatch happens.

What causes a position mismatch between MultiCharts and the broker?

A position mismatch happens when the MultiCharts strategy has a different position than actually is open at the broker (MultiCharts Wiki, 2014). This is problematic because the strategy then thinks it has a certain position while the actual open position is something else. And so when our signal manages the position, it doesn’t trade the actual open position but only what it thinks that position is.

Say we’re long 8 contracts at the broker. But our MultiCharts strategy thinks we’re long 5 contracts. Now when our signal generates an exit long order to close the position, it submits an order to sell 5 contracts (instead of the required 8). This way we end up holding 3 open long contracts when we wanted to go flat.

A position mismatch can be caused by (MultiCharts Wiki, 2014):

  • Automated trading in asynchronous mode. With this type of automated order execution, the strategy doesn’t assume the broker position starts flat. Instead, the strategy calculates on historical price bars to see what orders it would have generated. Then it assumes that all those orders were actually executed at the broker (MultiCharts Wiki, 2016b), while also acting as if there were no other orders executed for that symbol at the broker. These assumptions of asynchronous automated trading can easily cause a difference between the strategy and broker position.
  • Combining manual with auto trading. Manual orders happen without the knowledge of a trading strategy. And so when we submit an order by hand for the same instrument that the strategy trades (whether it’s through MultiCharts or the broker’s software), then a position mismatch is practically guaranteed to happen.
  • Trading from multiple charts. When automated trading strategies on multiple charts trade the same symbol at the same broker independent of each other, it’s a matter of time before a position mismatch occurs.
  • When an order’s final status is not received. When an automated trading strategy places an order but MultiCharts doesn’t receive that order’s final status (like whether the order is filled or cancelled), then the strategy assumes the order didn’t execute. However, when the broker did fill that order but just didn’t communicate that to MultiCharts, then the automated trading strategy ends up managing a position different from the broker’s open position.

And so a position mismatch can be caused by something we did accidentally or by a miscommunication between the broker and MultiCharts. Let’s see how we can use code to check if there’s a position mismatch, and then trigger an alert when that happens.

Checking for a MultiCharts position mismatch in PowerLanguage

To see if there’s a mismatch between the position in MultiCharts and the one at the broker, we can compare the following two keywords (PowerLanguage Keyword Reference, 2016):

  • The MarketPosition keyword returns the direction of the strategy’s current position: 1 for long, -1 for short, and 0 when flat. When we multiply that value with the CurrentContracts keyword (which returns the current position size), we get a value that signals both the direction and position size that the strategy according to MultiCharts has.
  • We can compare that value with MarketPosition_at_Broker. That keyword returns the position at the broker for the current symbol: a positive value signals the long position size, a negative value the short position, and 0 is returned when the broker’s position is flat.
Note: MarketPosition_at_Broker returns the strategy’s open position when the signal that executes that keyword has automated order execution enabled (PowerLanguage Keyword Reference, 2016). With automated trading disabled, the signal cannot access the open position at the broker.

This means there’s a position mismatch when the product of MarketPosition and CurrentContracts differs from what’s returned by MarketPosition_at_Broker while the strategy has automated trading enabled.

As an example, let’s say we’re short 8 contracts and the broker and MultiCharts position match. In that case, both MarketPosition * CurrentContracts and MarketPosition_at_Broker return -8. But when we manually sell short 2 contracts for the same symbol that the strategy trades, MarketPosition * CurrentContracts keeps returning -8 (because the MultiCharts strategy is not aware of that manual order). The MarketPosition_at_Broker keyword, on the other hand, returns -10 then.

Now let’s see how we can trigger alerts whenever there’s a position mismatch between MultiCharts and the broker.

Example: generate alerts for a mismatched trading position

The example signal below generates an alert whenever the position on the chart differs from the position at the broker. We configure the script with two input options. With ‘SecondsBetweenAlerts’ we specify how many seconds there need to be between successive alerts; that way we prevent many alerts happening quickly after each other.

Now when a mismatch happens, the ‘LatencySeconds’ input specifies a ‘pause’ before the alert generates. This way we don’t get alerts for a temporarily position mismatch due to order latency. This also addresses that we can expect a position mismatch for the time period between when the strategy submits the order and the broker reports back to MultiCharts. By not generating an alert in this small time window, we prevent false position mismatch alerts.

The example signal doesn’t generate orders; instead, it relies on the chart’s other signals for that. This works because, when we add several signals to the same chart, MultiCharts combines them into a single strategy (MultiCharts Wiki, 2016a). This way we don’t need to replicate the example’s code into another script, but can just add the example signal to whichever chart or portfolio we want to use it on.

An example of the position mismatch alert is shown below; after discussing the code we’ll take a closer look at the script’s behaviour.

Example alerts generated by the MultiCharts script

[IntrabarOrderGeneration = true];

Inputs:
    LatencySeconds(1),
    SecondsBetweenAlerts(30);

Variables:
    mp(0),
    IntrabarPersist mismatchTime(ComputerDateTime),
    IntrabarPersist lastAlertTime(0),
    secondsSinceMismatch(0),
    secondsSinceAlert(0);

mp = MarketPosition * CurrentContracts;

secondsSinceAlert = (ComputerDateTime - lastAlertTime) /
    ELTimeToDateTime_s(1);

// When auto trading, check if there's a market position mismatch
if (GetAppInfo(aiStrategyAuto) = 1 and 
        mp <> MarketPosition_at_Broker and
        secondsSinceAlert >= SecondsBetweenAlerts) then begin

    // Calculate the number of seconds since the last mismatch
    secondsSinceMismatch = (ComputerDateTime - mismatchTime) / 
        ELTimeToDateTime_s(1);
    
    // Only generate an alert when the mismatch has occurred for longer than
    // the number of seconds specified with the input option
    if (secondsSinceMismatch >= LatencySeconds) then begin
        
        Alert("Position mismatch: the strategy's position is " +
            NumToStr(mp, 0) + 
            " contracts while the position at the broker for " + 
            ExchListed + ":" + SymbolName + " is " +
            NumToStr(MarketPosition_at_Broker, 0) + 
            " contracts.");
            
        lastAlertTime = ComputerDateTime;

    end;
    
    // Update the time of the current mismatch for the next calculation
    mismatchTime = ComputerDateTime;

end;

// Recalculate every second to keep the signal accurate and up-to-date
RecalcLastBarAfter(1);

We begin with the IntrabarOrderGeneration attribute set to true. That way the signal can process every real-time incoming price tick instead of only calculating on bar close (MultiCharts Wiki, 2012a). For us, this means the signal can generate a position mismatch alert much sooner.

Then we create two input options and several variables:


Inputs:
    LatencySeconds(1),
    SecondsBetweenAlerts(30);

Variables:
    mp(0),
    IntrabarPersist mismatchTime(ComputerDateTime),
    IntrabarPersist lastAlertTime(0),
    secondsSinceMismatch(0),
    secondsSinceAlert(0);

The LatencySeconds input option sets a grace period: when a position mismatch occurs, we wait this number of seconds before generating an alert. This gives the broker a bit of time to fill an order and report back to MultiCharts. With the SecondsBetweenAlerts input we set how many seconds there need to be between consecutive alerts; with its default value of 30 we wait half a minute before firing another alert.

The first of the 5 numerical variables is mp, and we use this one to store the strategy’s current position. With the mismatchTime and lastAlertTime variables we track when the position mismatch happens and when the last alert generated. That allows us to calculate how long ago those events happened. We’re going to store the current number of seconds since those events in the secondsSinceMismatch and secondsSinceAlert variables.

We declare the mismatchTime and alertTime variables as IntrabarPersist. With that keyword, the variable keeps whichever value is stored in it – regardless of whether its value is updated during an intra-bar or on-bar-close calculation (PowerLanguage Keyword Reference, 2016).

While it makes sense that a variable remembers its value, by default PowerLanguage variables don’t keep their value from one intra-bar script calculation to the next. Only the value that’s assigned to the variable when the bar closes is remembered. This makes it possible to compare the value at close with the historical bars, but it doesn’t allow for tracking a variable’s value from one intra-bar script calculation to the next.

Since the mismatchTime and alertTime variables can update with each calculation and should keep whichever value is stored in them, we set them to IntrabarPersist. That makes them accurately hold the time of when the last mismatch and alert happened. (The other three variables are calculated anew each time the script calculates, and we don’t need to access their previous values. That’s why they don’t use IntrabarPersist.)

By the way, the default value of the mismatchTime variable is the computer’s current date and time (ComputerDateTime). This prevents that the script immediately generates an alert when automated trading is enabled. When we give that variable a regular default value of 0, a mismatch alert triggers immediately when we use the signal. That’s because the time difference between the current time and zero is bigger than the number of seconds set by the LatencySeconds input option.

The actual logic of the script first calculates the current position size and then determines how long ago the last alert happened:


mp = MarketPosition * CurrentContracts;

secondsSinceAlert = (ComputerDateTime - lastAlertTime) /
    ELTimeToDateTime_s(1);

Here we store the strategy’s current position (MarketPosition * CurrentContracts) in the mp variable. Then we calculate the number of seconds since the last alert happened (with that info we can limit the number of alerts later on). For that we first subtract the time of when the last alert happened (lastAlertTime) from the computer’s current time.

We get that latter with the ComputerDateTime keyword, which returns its value in DateTime format. Numerical values in that format consist out of an integer portion that reflects the number of days since January 1, 1900, and a decimals portion that represents the time elapsed since midnight (PowerLanguage Keyword Reference, 2016). Since that makes a DateTime value hold both a date and time of day, we can calculate time differences with them.

However, the difference between ComputerDateTime and lastAlertTime is a DateTime value too. That still doesn’t tell us how many seconds ago the last alert happened. And so to convert that DateTime difference to a seconds amount, we divide it by ELTimeToDateTime_s(1). That keyword translates a time in HHmmss format to its DateTime equivalent (PowerLanguage Keyword Reference, 2016). Since with that format 1 represents one second, ELTimeToDateTime_s(1) gives the DateTime equivalent of one second. And by dividing the DateTime difference with that value, we get the number of seconds that the last alert happened – which is what we store in the secondsSinceAlert variable for use later on.

Next is an if statement that contains the majority of the signal’s code:


if (GetAppInfo(aiStrategyAuto) = 1 and 
        mp <> MarketPosition_at_Broker and
        secondsSinceAlert >= SecondsBetweenAlerts) then begin

    // ...

end;

Before the code inside this if statement executes, three true/false expressions have to be true. Since we combine those with the and logical keyword, each one has to be true before the if statement’s condition is true too (MultiCharts Wiki, 2012b). Even when one expression is false, the code inside the if statement won’t execute.

Since the MarketPosition_at_Broker keyword only retrieves the broker position when auto trading is on (PowerLanguage Keyword Reference, 2016), we use the first expression to evaluate whether automated trading is enabled. We check that by seeing if the GetAppInfo() keyword and the aiStrategyAuto parameter return a value equal to (=) 1, which it does when automated trade execution is on (PowerLanguage Keyword Reference, 2016).

The second expression checks for the actual position mismatch. For that we evaluate if the current position in MultiCharts (which we stored in the mp variable) is unequal to (<>) the position for the current symbol at the broker. We get that latter with the MarketPosition_at_Broker keyword.

The third and last expression evaluates whether the secondsSinceAlert variable holds a value greater than or equal to (>=) the SecondsBetweenAlerts input. That input has a value of 30 and secondsSinceAlert holds the number of seconds since when the last alert fired. And so this expression is true when the last alert happened at least 30 seconds ago. With this we prevent that the script generates a lot of alerts quickly after each other.

When all three expressions are true, the code the code inside the if statement executes. That code first calculates how many seconds ago the position mismatch happened:


secondsSinceMismatch = (ComputerDateTime - mismatchTime) / 
    ELTimeToDateTime_s(1);

Here we use the same approach as when we calculated the number of seconds since the last alert. That is, we subtract the time of when the position mismatch happened (which we’ll store later on in the mismatchTime variable) from the computer’s current time (ComputerDateTime). Then we divide that DateTime difference with the DateTime value of one second (ELTimeToDateTime_s(1)) to get the number of seconds since the position mismatch, which we store in secondsSinceMismatch.

Once we know how long the position between MultiCharts and the broker differs, we compare that value with the order latency (LatencySeconds). That way we can figure out whether the mismatch likely happened due to regular latency or something else before we generate an alert:


if (secondsSinceMismatch >= LatencySeconds) then begin
    
    Alert("Position mismatch: the strategy's position is " +
        NumToStr(mp, 0) + 
        " contracts while the position at the broker for " + 
        ExchListed + ":" + SymbolName + " is " +
        NumToStr(MarketPosition_at_Broker, 0) + 
        " contracts.");
        
    lastAlertTime = ComputerDateTime;

end;

This if statement checks whether the duration of the position mismatch in seconds (secondsSinceMismatch) is greater than or equal to (>=) the LatencySeconds input option, which has a default value of 1. When the position mismatch lasts for that number of seconds, a notification generated by the Alert() keyword is in place.

Inside that keyword’s parentheses we specify an alert message that consists out of static text with different dynamic values, combined with the addition operator (+). We convert the mp and MarketPosition_at_Broker dynamic values to a string with NumToStr(). That keyword requires two parameters: the number to convert to text, and how many decimals that number should get (PowerLanguage Keyword Reference, 2016). Here we convert both values with 0 decimals, and with that the strategy’s market position (mp) and broker position (MarketPosition_at_Broker) appear as a nicely formatted integer in the alert message.

Besides the strategy and broker position, we also make the alerts more meaningful by including the current symbol and its exchange. We retrieve that information with the ExchListed and SymbolName keywords (PowerLanguage Keyword Reference, 2016).

With the alert generated, we update the lastAlertTime variable to the current time (ComputerDateTime). This way we can, on the next script calculation, determine how long ago the alert happened. That prevents the script from firing multiple alerts quickly after each other.

Then we set the mismatchTime variable to the computer’s time:


mismatchTime = ComputerDateTime;

This line of code comes after the if statement that generates the alert, but is still inside the if statement that checks whether automated trading is enabled with a position mismatch and 30 seconds since the last alert.

That means mismatchTime updates when there’s a valid position mismatch. By giving the mismatchTime variable a new value here, we can, on the next script calculation, determine if there’s a position discrepancy that lasts longer than 1 second (which is the value of the LatencySeconds input option). As we saw previously, we use that situation as the basis for generating an alert.

We end the example signal with this:


RecalcLastBarAfter(1);

The RecalcLastBarAfter() keyword periodically recalculates the script (PowerLanguage Keyword Reference, 2016). With a value of 1 between its parentheses, this keyword makes the script calculate at least once per second. This keeps our signal up to date and triggers alerts in a timely manner, even when trading is slow and there aren’t that many price updates that initiate a script calculation.

MultiCharts alerts for a broker position mismatch

Let’s see how our example signal behaves in real time. Before the script can generate any position mismatch alert, we’ll need to enable the alert setting like so:

Configuring the alert settings of the MultiCharts strategy

Since we didn’t add code that generates orders to the example script, other signals on the same chart need to do that. Below, we added the example signal to the chart alongside the ‘Channel Breakout LE’ and ‘Channel Breakout SE’ standard MultiCharts strategies:

Example chart with the MultiCharts signals applied

Now whenever the market position on the chart doesn’t match the broker position, the signal generates an alert like the following:

Example alert generated for a MultiCharts broker position mismatch

These alerts continue to appear as long as there’s a position mismatch. But since we configured the seconds between successive alerts with the ‘SecondsBetweenAlerts’ input option, those consecutive alerts are at least 30 seconds apart:

Repeated broker position alerts generated by the MultiCharts script

By the way, we can visually verify whether there’s a position match or mismatch with the Order and Position Tracker window. (To open that window, click on the ‘View’ menu item and select ‘Show Order and Position Tracker Window’. Alternatively, click on the ‘File’ menu item, move to ‘New’, and select ‘Order and Position Tracker Window’.)

To see the position mismatch, we look at the ‘Positions Match’ column in the ‘Strategy Positions’ tab of the Order and Position Tracker. When the position of the strategy and the one at the broker are the same, this column shows ‘True’; when there’s a mismatch, ‘False’ appears in that column (MultiCharts Wiki, 2015).

Broker position match in the MultiCharts Order and Position Tracker Broker position mismatch in the MultiCharts Order and Position Tracker

Another way to track a strategy’s position with alerts is to trigger an alert when the strategy’s position changes.

Summary

We generate MultiCharts alerts programmatically with Alert(), but that does require that the ‘Enable Alerts’ setting is turned on. When a trading strategy has automated trade execution enabled, a mismatch can happen between what the strategy thinks the position is and the actual open position at the broker. Causes for that include using asynchronous automated trading, combining manual trading with automated trading, and MultiCharts not receiving all order information from the broker. To create an alert that warns us when there’s a position mismatch, we need to do several things. First we’ll have to determine the current position of the strategy according to the signal script. We retrieve that by multiplying the MarketPosition and CurrentContracts keywords. Then we’ll need to get the open position for the current symbol at the broker, which we retrieve with the MarketPosition_at_Broker keyword when the strategy’s automated trading is enabled. Then when the strategy’s position differs from the broker, we generate an alert with that information. We can improve those alerts in two ways. First, by giving the strategy a second or so to account for order latency. That way we won’t generate an alert when the MultiCharts strategy was just waiting to hear back from the broker. Second, by keeping a certain number of seconds between successive alert messages so we don’t get flooded in alerts.

Learn more:


References

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

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

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 (2014, June 11). Why There Is Mismatch On Strategy Positions Tab. Retrieved on September 1, 2016, from http://www.multicharts.com/trading-software/index.php/Why_There_Is_Mismatch_On_Strategy_Positions_Tab

MultiCharts Wiki (2015, October 21). Order and Position Tracker. Retrieved on September 1, 2016, from http://www.multicharts.com/trading-software/index.php/Order_and_Position_Tracker

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

MultiCharts Wiki (2016b, June 14). Auto Trading. Retrieved on September 2, 2016, from http://www.multicharts.com/trading-software/index.php/Auto_Trading

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