Sometimes a trading strategy calculates when its price bar has closed. The standard behaviour is not to submit orders in that exceptional situation. But how do we make our strategy even submit orders then?

In this article:

Generating orders at any time with the AllowSendOrdersAlways attribute

A PowerLanguage attribute is a keyword that enables or disables a certain feature of the script. They’re applied when the source code compiles and cannot be changed during run-time (e.g., MultiCharts Wiki, 2012d). That means that, when an attribute is added to a script, we can only change the feature it affects by setting the attribute to true or false and then recompiling the script. Given that most attributes have no manual equivalent setting (including AllowSendOrdersAlways), adjusting the attribute value in the code is something that we’ll do often.

PowerLanguage attributes can be placed anywhere in the script. However, their typical location is in the top of the script. For instance, here we started the script with the IntrabarOrderGeneration and RecoverDrawings attributes:

Example location of MultiCharts attributes in a script

So what does AllowSendOrdersAlways do? This attribute, when set to true, allows a trading strategy to always submit orders – even when the bar status of the primary data series is undefined (MultiCharts Wiki, 2014a). That’s important because, a MultiCharts strategy by default does not submit orders during that kind of bar status. To understand what an ‘undefined bar status’ means, let’s first look at what bar status is.

MultiCharts indicators and strategies calculate based on historical and real-time prices (MultiCharts Wiki, 2015b). A data series’ bar status refers to how the price that’s currently processed by MultiCharts relates to the price bar. Those bar statuses indicate that a script calculates on the bar’s opening tick, its closing tick, or a tick that falls inside the bar’s body (MultiCharts Wiki, 2014b).

However, sometimes when the price bar of the strategy’s data series has closed, the script can still (re)calculate. In that case when the script calculates without a price update, the bar status is undefined (Henry MultiCharts 2015b). That counter-intuitive case can happen with the following situations (e.g., Henry MultiCharts 2015a, 2015b):

  • When the price bar has closed, but a periodic recalculation happens due to RecalcLastBarAfter(). That keyword forces the script to recalculate every certain number of seconds even when there’s no price update (MultiCharts Wiki, 2014c).
  • When the price bar has closed, but the strategy recalculates due to a broker event (like an order filled or market position change).
  • When the price bar has closed and the script calculates to process price bars from additional data series.
Note: Since MultiCharts strategies currently can only be applied to and generate orders on the first data series (MultiCharts Wiki, 2012c), undefined bar statuses of additional data series don’t affect order generation.
Tip: By default, always enable the AllowSendOrdersAlways attribute (especially whenever you use intra-bar order generation). That allows the strategy to submit (market) orders regardless of what triggered the strategy’s calculations, and also prevents unfilled orders from being cancelled when an undefined bar status occurs.

Programmatically enabling or disabling AllowSendOrdersAlways

To allow a strategy to generate orders regardless of bar status, we enable the AllowSendOrdersAlways attribute by setting it to true:


[AllowSendOrdersAlways = true];

When the AllowSendOrdersAlways attribute is missing from the script’s code or set to false, then orders are only generated on ticks inside the bar and on the bar’s open and close price (MultiCharts Wiki, 2014a). We can make that default behaviour explicit by setting the attribute to false:


[AllowSendOrdersAlways = false];

Note that we can only configure this behaviour programmatically; the AllowSendOrdersAlways attribute has no manual equivalent option.

Example: multiple MultiCharts data series and generating trading orders

Now let’s look at a simple strategy that works with AllowSendOrdersAlways. In this example we trade the chart’s first data series based on the Exponential Moving Average (EMA) of the second data series. The code for this is:


[AllowSendOrdersAlways = false];

Variables:
   averagePrice(0),
   buySignal(false),
   sellSignal(false);

averagePrice = XAverage(close, 15) of Data2;

// Generate signals
buySignal  = (Close Data2 > averagePrice) and 
    (Close[1] Data2 <= averagePrice[1]);
    
sellSignal = (Close Data2 < averagePrice) and 
    (Close[1] Data2 >= averagePrice[1]);

// Submit orders
if (MarketPosition(0) = 0 and buySignal = true) then 
    buy ("EL") 1 contracts next bar at market;
    
if (sellSignal = true) then
    sell ("XL") 1 contracts next bar at market;

We start by setting the AllowSendOrdersAlways attribute to false so that orders won’t be generated when the price bar of the first data series is undefined. Note that this attribute, like any PowerLanguage attribute, needs to be placed between square brackets ([ and ]).

After that we create several variables:


Variables:
   averagePrice(0),
   buySignal(false),
   sellSignal(false);

We’ll store the EMA values in the averagePrice variable while the buySignal and sellSignal true/false variables will track the strategy’s entry and exit conditions.

Then we calculate the EMA:


averagePrice = XAverage(close, 15) of Data2;

Here we assign the averagePrice variable the value returned by XAverage(). That function computes the EMA and requires two values: the data to calculate on and the moving average length in number of bars. We set those to the close variable and a literal value of 15 to calculate the 15-bar EMA of closing prices.

After the XAverage() function, we place of Data2. PowerLanguage keywords (like close) and functions by default refer to the data series that the script is added to. Trading strategies, however, can only be applied to the first data series. Because of that we use the Data2 keyword to specify that the XAverage() function should calculate on the second data series and not the first (see MultiCharts Wiki, 2012a).

We subsequently use that EMA value when setting the values of the buySignal and sellSignal variables:


buySignal  = (Close Data2 > averagePrice) and 
    (Close[1] Data2 <= averagePrice[1]);
    
sellSignal = (Close Data2 < averagePrice) and 
    (Close[1] Data2 >= averagePrice[1]);

Both of these variables are given a true/false value based on two conditions that are joined together with and. That keyword returns true when both conditions are true and false when one or both of them are false (MultiCharts Wiki, 2012b).

The two conditions that set the buySignal value are the following. First we check if the second data series’ close (Close Data2) is greater than (>) the EMA that we stored in the averagePrice variable. The other condition is whether the previous bar of the second data series (Close[1] Data2) closed below or at (<=) the level of the EMA (averagePrice[1]). By combining these two conditions, we’re checking whether the price of the second data series crosses above its moving average. If that’s the case, buySignal holds true and a value of false otherwise.

The sellSignal variable is given its value likewise, although here we check if the second data series crossed below its EMA. That happens whenever the current bar’s closing price (Close Data2) is less than (<) the EMA and when the previous bar’s closing price was above or at that EMA (Close[1] Data2 >= averagePrice[1]). When such a crossover happened, the sellSignal variable is assigned true and false in all other cases.

After that we submit enter long and exit long orders:


if (MarketPosition(0) = 0 and buySignal = true) then 
    buy ("EL") 1 contracts next bar at market;
    
if (sellSignal = true) then
    sell ("XL") 1 contracts next bar at market;

We submit our market orders with two if statements here. The first checks whether MarketPosition(0) equals (=) 0 and if the buySignal variable is true. That MarketPosition keyword, with a value of 0 between its parentheses, returns an integer that specifies the strategy’s current position (MultiCharts Wiki, 2015a). Whenever that number is 0, the strategy is flat. With that condition we only send an order whenever there isn’t an open position yet (which prevents pyramiding into a position). The generated order is an enter long (buy) order with a position size of 1 (1 contracts), submitted as a market order on the next bar (next bar at market).

The second if statement processes the sellSignal variable to conditionally submit an exit long (sell) order named “XL”. Since the sell keyword exits a long position but won’t open a new position (MultiCharts Wiki, 2012e), we don’t check the strategy’s current market position before submitting this order. The order itself is submitted for the next bar and has a size of 1.

Submitting MultiCharts trading orders with multiple data series

Our above example looks like this when added to a chart with CME’s E-mini S&P 500 and 6E (EUR/USD) futures:

Effect of a MultiCharts strategy with AllowSendOrdersAlways disabled

While this position seems legit, several traders were missed on a closer look. For instance, just after 16:00 hour the EUR/USD crossed above its moving average and an EMA crossover also occurred after 19:00 hour. The two trades that were generated here (labelled ‘EL’ and ‘XL’) happened when the E-mini S&P 500 price bar aligned with a EUR/USD bar. However, any signal that happened between the E-mini S&P 500 bars wasn’t traded.

Now, let’s enable the AllowSendOrdersAlways attribute of our programming example:


[AllowSendOrdersAlways = true];

We recompile the script without making other changes. When we now look at the same time period as the previous chart, each EMA crossover is traded:

Effect of enabling a MultiCharts strategy's AllowSendOrdersAlways attribute

This happens because, when AllowSendOrdersAlways is enabled, orders can also be submitted when the first data series’ bar status is undefined (MultiCharts Wiki, 2014a). One situation in which that bar status happens is when the bar of the first data series has closed, but the script still calculates to process the second data series. Thanks to AllowSendOrdersAlways we can also generate trades when the price bars of multiple data series don’t align nicely.

Other PowerLanguage attributes that affect trading strategies are IntrabarOrderGeneration that allows a strategy to calculate several times per bar and SameExitFromOneEntryOnce which makes reusing exit orders possible.

Summary

The AllowSendOrdersAlways attribute (when set to true) allows a strategy to generate orders when its data series’ bar status is ‘undefined’. That bar status occurs when a price bar has closed but the script recalculates nonetheless. Those recalculations can be triggered by a time-based recalculation, a broker event, or when price bars from additional data series are processed. By default, orders aren’t submitted by MultiCharts in those situations. Enabling AllowSendOrdersAlways has the benefit that orders are always (re)submitted regardless of the script’s calculation reason, which prevents market orders from being generated and unfilled orders from being cancelled.


References

Henry MultiCharts (2015a, January 26). closing status of a bar sometimes takes too long – forum discussion. Retrieved on November 26, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=1&t=10642#p112902

Henry MultiCharts (2015b, January 30). closing status of a bar sometimes takes too long – forum discussion. Retrieved on November 26, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=1&t=10642#p113092

MultiCharts Wiki (2012a, February 19). Data. Retrieved on November 27, 2015, from http://www.multicharts.com/trading-software/index.php/Data

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

MultiCharts Wiki (2012c, February 23). Signal Settings. Retrieved on November 30, 2015, from https://www.multicharts.com/trading-software/index.php/Signal_Settings

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

MultiCharts Wiki (2012e, February 19). Sell. Retrieved on January 7, 2016, from http://www.multicharts.com/trading-software/index.php/Sell

MultiCharts Wiki (2014a, December 26). AllowSendOrdersAlways. Retrieved on November 26, 2015, from http://www.multicharts.com/trading-software/index.php/AllowSendOrdersAlways

MultiCharts Wiki (2014b, August 12). BarStatus. Retrieved on November 26, 2015, from https://www.multicharts.com/trading-software/index.php/BarStatus

MultiCharts Wiki (2014c, September 3). RecalcLastBarAfter. Retrieved on January 4, 2016, from https://www.multicharts.com/trading-software/index.php/RecalcLastBarAfter

MultiCharts Wiki (2015a, July 22). MarketPosition. Retrieved on November 28, 2015, from https://www.multicharts.com/trading-software/index.php/MarketPosition

MultiCharts Wiki (2015b, May 4). How Scripts Work. Retrieved on January 4, 2016, from http://www.multicharts.com/trading-software/index.php/How_Scripts_Work