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
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
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.
AllowSendOrdersAlwaysattribute (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
[AllowSendOrdersAlways = true];
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
[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 Data2 <= averagePrice); sellSignal = (Close Data2 < averagePrice) and (Close Data2 >= averagePrice); // 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 (
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
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.
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 = (Close Data2 > averagePrice) and (Close Data2 <= averagePrice); sellSignal = (Close Data2 < averagePrice) and (Close Data2 >= averagePrice);
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
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 Data2) closed below or at (
<=) the level of the EMA (
averagePrice). 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,
true and a value of
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 Data2 >= averagePrice). When such a crossover happened, the
sellSignal variable is assigned
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
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:
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:
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.
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.
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