MultiCharts trading strategies calculate, by default, on the close of each price bar (MultiCharts Wiki, 2015b). But sometimes a lot happens before the bar closes. So how can a strategy calculate more often than that?
In this article:
- Intro: generating intra-bar orders with
- Differences between intra-bar order generation enabled and disabled
- Programmatically enabling or disabling intra-bar order generation
- Configuring intra-bar order generation by hand
- Example: creating an intra-bar order generation strategy in MultiCharts
- Charts: the effect of intra-bar order generation disabled and enabled
Generating intra-bar orders with the IntrabarOrderGeneration attribute
An attribute is a PowerLanguage keyword that affects how the script operates by enabling or disabling a certain feature. They’re applied when the script’s source code compiles and cannot be changed during script run-time (MultiCharts Wiki, 2012a). That means that once we’ve programmatically added an attribute to our script, we cannot manually change the feature it affects. Instead, we then need to set the attribute to
false to enable or disable its feature.
Some attributes (like
IntrabarOrderGeneration) have an equivalent manual setting, however. But most attributes affect features that we can only set programmatically (like
ProcessMouseEvents does). Attributes can be placed anywhere in the script, but their typical and advised location is in the top of the script. For instance, here we started the script with the
So what does
IntrabarOrderGeneration do? This attribute, when set to
true, allows a trading strategy to calculate and generate orders intra-bar (MultiCharts Wiki, 2012a). This means that when we enable this attribute (which is commonly abbreviated to IOG; MultiCharts Wiki, 2015b), a strategy can react to price changes that happen inside a price bar. To see why that’s beneficial, let’s look at the differences between IOG turned on and off.
Intra-bar order generation enabled versus disabled
MultiCharts trading strategies have IOG disabled by default, and this affects a strategy as follows (MultiCharts Wiki, 2015b):
- On historical data the script is calculated on bar close. A generated order is then submitted on the close of this bar or on the open of the next. These orders can be filled at a bar’s open, high, low, or close price.
- On real-time data the script also calculates on bar close, with orders being placed for the open of the next bar. Pending orders can be filled at any real-time tick that satisfies the order execution conditions.
When we enable IOG, the strategy behaves as follows (MultiCharts Wiki, 2015b):
- On historical data with the Bar Magnifier (discussed below) disabled, our strategy calculates four times per bar (on the bar’s open, high, low, and close prices). An order can be generated on any of these four calculations, and can be filled on any price that’s inside the bar’s range and that satisfies the order’s execution conditions.
- On historical data with the Bar Magnifier feature enabled, an IOG-enabled strategy calculates on the open of the main data series, then on the open, high, low, and close of each bar set by the Bar Magnifier’s resolution, and then on the close of the main data series. An order can be generated on any of these calculations, and that order can be filled on the first price that meets the order execution logic. Only the exact prices of the main bar and Bar Magnifier bars are used for filling the order.
- On real-time data, the strategy calculates on every tick, which allows the script to react to every price update. An order can be filled on any tick that satisfies the conditions for order execution.
In other words, when IOG is disabled anything that a strategy does (from submitting an order and drawing a trend line to generating an alert) is done once per bar. When IOG is enabled, the script calculates several times per bar and can also perform its actions while a bar hasn’t closed yet.
That also makes an IOG strategy less dependent on the chart’s time frame since it calculates more often than a strategy without IOG that has to ‘wait’ till the bar closes.
next barwill now be submitted on the next tick and will not necessarily execute on the open of the next bar.
More precise backtesting with the Bar Magnifier
The Bar Magnifier is an option that emulates the price movement within a bar more precisely (MultiCharts Wiki, 2013), which makes the backtest results of IOG-enabled strategies more accurate (MultiCharts Wiki, 2015b).
An example of the benefit of the Bar Magnifier is when a profit target and stop-loss order execute on the same bar. With the Bar Magnifier, MultiCharts can then see how the price bar was formed and which of these orders was executed first. As such, we can think of the Bar Magnifier as a replay of how the price bar was formed, and that ‘replay frequency’ can be set to a number of ticks, seconds, or minutes in its settings.
The Bar Magnifier isn’t available for the Portfolio Trader and cannot be enabled programmatically. To configure it, we right-click on the chart and select ‘Format Signals’:
Then we click on ‘Properties’ to configure the settings of all signals applied to the chart:
This opens the ‘Strategy Properties’ window in which we move to the ‘Backtesting’ tab to enable the Bar Magnifier with its preferred precision:
Toggling intra-bar order generation programmatically in MultiCharts
Now back to the
IntrabarOrderGeneration attribute. We use this attribute to enable IOG programmatically as follows:
[IntrabarOrderGeneration = true];
And when we set this attribute to
false, intra-bar order generation is disabled:
[IntrabarOrderGeneration = false];
By default, MultiCharts strategies have intra-bar order generation turned off (MultiCharts Wiki, 2015b).
Setting MultiCharts’ intra-bar order generation settings by hand
A signal’s intra-bar order generation settings can also be set manually, and that allows us to configure the same signal differently on multiple charts. However, that setting can only be changed when the
IntrabarOrderGeneration attribute isn’t added to the script’s code (MultiCharts Wiki, 2012a).
To set a signal’s IOG settings, we first right-click on the chart and select ‘Format Signals’:
This opens the ‘Format Objects’ window. Here we select the strategy whose IOG settings we want to change and then click ‘Format…’:
We’re now presented with the ‘Format Signal’ window that’s used to configure a signal’s options. Here we select the ‘Properties’ tab that lists several intra-bar order generation settings:
To have the script calculate and submit its orders intra-bar, we select the ‘Enable Intra-Bar Order Generation’ checkbox. Now we can also set the two additional options listed under ‘Entries’ and ‘Exits’:
These options help to prevent a flood of orders when intra-bar order generation is enabled. The three ‘Entries’ choices affect how many positions may be opened: one entry per bar for the current signal, one entry per bar for all signals added to the chart, or a certain amount of entries per bar for all the chart’s signals.
Exit orders are configured with three options below ‘Exits’: the current signal may exit once per bar, all signals on this chart may exit once per bar, or any exit from any signal may happen several times per bar.
IntrabarOrderGenerationattribute is enabled, we still need to configure them manually if they should act differently than their default settings (one entry for all signals and one exit for all signals per bar; see previous image).
By the way, the ‘Entries’ and ‘Exits’ settings are closely related to the ‘Position limits’ setting. That’s because, before a signal can generate multiple orders per bar in the same direction, the ‘Position limits’ setting needs to allow pyramiding. We change that setting in the ‘Strategy Properties’ window, which is opened by right-clicking on the chart, selecting ‘Format Signals’ followed by pressing ‘Properties’.
Why are the intra-bar order generation settings greyed out?
Since PowerLanguage attributes are applied during compilation and cannot be changed when the script is in use (MultiCharts Wiki, 2012a), we cannot alter the main intra-bar order generation setting when its attribute is present in the script’s code. And so when
IntrabarOrderGeneration is set to
false, the ‘Enable Intra-Bar Order Generation’ setting is greyed out:
Likewise, when the
IntrabarOrderGeneration attribute is enabled, we cannot turn off that ‘Enable Intra-Bar Order Generation’ setting:
So if we want to change that intra-bar order generation setting by hand, we’ll need to remove the
IntrabarOrderGeneration attribute from our code first.
Creating an intra-bar order generation strategy in MultiCharts
Now let’s turn to a programming example that uses the
IntrabarOrderGeneration attribute. The example strategy opens a position at the first bar of the day and goes flat in the five minutes before the end of trading. Before we look at how this example script behaves with intra-bar order generation enabled, let’s first create a version that does not generate orders intra-bar:
[IntrabarOrderGeneration = false]; // Enter at the first bar of the day if (MarketPosition(0) = 0) and (Date <> Date) then Buy ("Enter Long") 1 contracts next bar at market; // Exit before the close if (Time_s >= 215500) and (Time_s <= 220000) then Sell ("Time Exit") all contracts next bar at market;
We begin with the
IntrabarOrderGeneration attribute set to
false to only have the strategy calculate on bar close. Note that we place this attribute between square brackets (
]); otherwise, PowerLanguage generates the ‘assignment is only for variables or array elements’ error message.
An if statement then evaluates two conditions:
if (MarketPosition(0) = 0) and (Date <> Date) then Buy ("Enter Long") 1 contracts next bar at market;
The first condition checks if the value returned by
MarketPosition(0) equals 0. That keyword returns, with a zero between its parentheses, a number indicating the strategy’s current market position: 0 for flat, -1 for short, and 1 for long (MultiCharts Wiki, 2015c). And so whenever
MarketPosition(0) equals 0, the strategy currently is flat. With this condition we prevent pyramiding: the buy order that’s below the if statement is now only submitted when the strategy is flat.
The second condition in our if statement is whether the current bar’s date (
Date) is unequal to (
<>) the date of the previous bar (
Date), which happens on the first bar of a trading day. Since both conditions are combined with the
and keyword, both need to be true the if statement’s entire condition is true.
When the strategy is flat and the current bar is the first of the trading day, we submit an enter long order with the
Buy keyword (MultiCharts Wiki, 2012c). The order name is specified as “Enter long” with a position size of
1 and submitted as a market order on the next bar (
next bar at market).
The next if statement in our example is used to exit the long position:
if (Time_s >= 215500) and (Time_s <= 220000) then Sell ("Time Exit") all contracts next bar at market;
Here we also evaluate two conditions that we also combine with
and. The first checks whether
Time_s returns a value that’s greater than or equal to (
>=) 215500. That
Time_s keyword returns the bar’s closing price in 24-hour HHmmss format (MultiCharts Wiki, 2012d), so a time like 21:57:30 is returned as the 215730 number. The value that we check
Time_s against is 215500 (so 21:55:00 or 9:55 p.m.).
The second condition, in turn, evaluates if the current bar’s time (
Time_s) is less than or equal to (
<=) 220000 (22:00:00 hour or 10 p.m.). By combining both conditions, we’re in effect looking for a 5-minute time period: the bar’s time needs to be between 21:55 and 22:00 before the if statement’s code is executed. That time period is just before the close of trading of the instrument that we add our script to (see below).
When both of those conditions are true, we submit an exit long order with the
Sell keyword (MultiCharts Wiki, 2012e). The order is named “Time Exit” and we have it close the entire long position (
all contracts) with a market order (
next bar at market).
The effect of intra-bar order generation in MultiCharts PowerLanguage
The above example, when added to a an EuroStoxx 50 future chart, looks like:
As we can see here, our strategy doesn’t behave as intended: positions aren’t opened on the first bar of the day and, even worse, positions are kept overnight and not exited before the close of trading.
However, let’s change the first line of the example to the following:
[IntrabarOrderGeneration = true];
We keep the rest of the script unchanged and recompile it. Now as the same time period as the previous charts, the strategy behaves as follows:
Now the strategy performs as it should: positions are opened at the start of the trading day and exited at the close of trading. Why is that?
When intra-bar order generation is turned off, the strategy calculates on bar close and submits
next bar orders for the next price bar (MultiCharts Wiki, 2015b). In our case, that means the long order is generated on the day’s first bar (but submitted for the next bar) while the exit long order generates at the end of trading, but executes on the next bar (which is the first bar of the next day).
With intra-bar order generation turned on, however, the strategy calculates four times per bar (at the bar’s open, high, low, and close price) on historical data. During any of those calculations, an order can be generated and subsequently be filled on the next calculation (MultiCharts Wiki, 2015b). For our example, this means that the long order generates at the open of the first bar of that day (and fills during the three remaining calculations on that bar). Likewise, when our exit long order generates on the last bar of trading, there still several calculations left on that same bar to fill the exit long market order.
To learn about other PowerLanguage attributes that affect trading strategies, see
AllowSendOrdersAlways to submit orders regardless the script’s calculation reason and
SameExitFromOneEntryOnce to reuse exit orders.
IntrabarOrderGeneration attribute enables (when set to
true) or disables (
false) a signal’s intra-bar order generation (IOG). A strategy can calculate multiple times per bar when that feature is enabled, instead of just once per bar (which is the default behaviour). The advantage of intra-bar order generation is that a strategy can react to price changes happening inside a bar, which allows a strategy to perform its actions (like submitting an order or generating an alert) when the price bar still develops. When intra-bar order generation is enabled, orders that are marked as
next bar can be executed the next time a strategy calculates; that doesn’t necessarily has to be the next bar but can also be the same bar.
MultiCharts Wiki (2012a, August 31). IntrabarOrderGeneration. Retrieved on November 28, 2015, from http://www.multicharts.com/trading-software/index.php/IntraBarOrderGeneration
MultiCharts Wiki (2012b, February 23). Signal Settings. Retrieved on November 30, 2015, from https://www.multicharts.com/trading-software/index.php/Signal_Settings
MultiCharts Wiki (2012c, February 19). Buy. Retrieved on December 11, 2015, from http://www.multicharts.com/trading-software/index.php/Buy
MultiCharts Wiki (2012d, February 28). Time_s. Retrieved on December 12, 2015, from https://www.multicharts.com/trading-software/index.php/Time_s
MultiCharts Wiki (2012e, February 19). Sell. Retrieved on December 12, 2015, from https://www.multicharts.com/trading-software/index.php/Sell
MultiCharts Wiki (2013, May 21). Bar Magnifier. Retrieved on December 11, 2015, from https://www.multicharts.com/trading-software/index.php/Bar_Magnifier
MultiCharts Wiki (2015a, May 4). How Scripts Work. Retrieved on November 30, 2015, from http://www.multicharts.com/trading-software/index.php/How_Scripts_Work
MultiCharts Wiki (2015b, May 15). How Signals are Calculated. Retrieved on December 11, 2015, from https://www.multicharts.com/trading-software/index.php/How_Signals_are_Calculated
MultiCharts Wiki (2015c, July 22). MarketPosition. Retrieved on December 12, 2015, from https://www.multicharts.com/trading-software/index.php/MarketPosition