The default behaviour of MultiCharts .NET trading strategies is to generate orders on bar close so that these can be filled in the next bar. But how can we generate orders a bit sooner?

Changing a strategy’s calculation mode with CalcAtOpenNextBar

C# attributes are a mechanism for adding custom information to code elements (Albahari & Albahari, 2012). In MultiCharts .NET these attributes are used to change certain script settings.

One attribute is CalcAtOpenNextBar, which influences how a strategy processes historical bars as follows (Henry MultiCharts, 2013; MultiCharts, 2014):

  • When CalcAtOpenNextBar is set to false or not added to the script, the strategy generates orders on bar close, which are then submitted for, and can be filled in, the next bar. This is the default calculation mode, in which both MarketThisBar and MarketNextBar orders can be used.
  • When CalcAtOpenNextBar is set to true, the strategy generates orders on bar open. These are then submitted for, and can be filled in, the current bar. In this calculation mode only MarketNextBar orders can be used.

Despite the name of the attribute (‘calculate at open next bar’), the script is still calculated in the context of the current bar (MultiCharts, 2014). Bars.Close[0], for example, returns with CalcAtOpenNextBar enabled the current bar’s closing price and not the closing price of the next bar.

CalcAtOpenNextBar can only be set programmatically – there isn’t an equivalent manual setting.

When to use CalcAtOpenNextBar – and how to access the future price bar?

When CalcAtOpenNextBar is enabled, the open and time of the next bar become accessible (but not other data from the next bar). This allows for strategies where you enter a position on the next bar’s open, but only when this open isn’t below the previous bar, for example. Orders are also submitted a bar earlier with this attribute enabled, although the IOGMode attribute for intra-bar order generation with the Bar Magnifier can also do that.

Accessing the next bar’s open can be done with Bars.Open[-1] (or the equivalent Bars.OpenNextBar()), while the time of the next bar is accessible with Bars.Time[-1] or Bars.TimeNextBar() (MultiCharts, 2014). Note that this only works with the attribute enabled; otherwise, the ‘trying to access future data’-error is triggered:

MultiCharts .NET CalcAtOpenNextBar: future data error

Setting the CalcAtOpenNextBar attribute in MultiCharts .NET

Set CalcAtOpenNextBar to true to generate orders on the bar’s open and to access the opening price:

[CalcAtOpenNextBar(true)]
public class Example_CalcAtOpenNextBar : SignalObject
{
    // Strategy code
}

To generate orders on bar close, set the attribute to false:

[CalcAtOpenNextBar(false)]
public class Example_CalcAtOpenNextBar : SignalObject
{
    // Strategy code
}

The default behaviour is generating orders on bar close and submitting them for the next bar, which applies when the CalcAtOpenNextBar attribute isn’t defined (see MultiCharts, 2014).

Example: using CalcAtOpenNextBar to submit orders on the current bar

The following example (and the images further below) show the effect of CalcAtOpenNextBar:

[CalcAtOpenNextBar(true)]
public class Example_CalcAtOpenNextBar : SignalObject
{
    public Example_CalcAtOpenNextBar(object _ctx) : base(_ctx) { }

    private IOrderMarket buyOrder, sellOrder;

    protected override void Create()
    {
        buyOrder = OrderCreator.MarketNextBar(new 
            SOrderParameters(Contracts.Default, EOrderAction.Buy));
        sellOrder = OrderCreator.MarketNextBar(new
            SOrderParameters(Contracts.Default, EOrderAction.Sell));
    }

    protected override void CalcBar()
    {
        // Use this code when CalcAtOpenNextBar is set to true
        bool downBar   = (Bars.Close[0] < Bars.Open[0]);
        bool lowerOpen = (Bars.Open[-1] < Bars.Close[0]);

        // This code is used when CalcAtOpenNextBar is set to false
        //bool downBar   = (Bars.Close[1] < Bars.Open[1]);
        //bool lowerOpen = (Bars.Open[0] < Bars.Close[1]);

        // Submit orders
        if (downBar && lowerOpen)
        {
            buyOrder.Send();
        }
        else if (StrategyInfo.MarketPosition > 0)
        {
            sellOrder.Send();
        }
    }
}

We begin with setting CalcAtOpenNextBar to true, after which two IOrderMarket orders are declared: buyOrder and sellOrder. These are made in the Create() method with OrderCreator.MarketNextBar() where they’re set to the default amount of contracts (meaning that the ‘Strategy Properties’ window value is used) and marked as a buy (EOrderAction.Buy) and sell (EOrderAction.Sell) order.

Setting the entry conditions for CalcAtOpenNextBar enabled or not

The strategy’s logic is implemented in the CalcBar() method. Two Boolean variables make up our entry conditions: downBar and lowerOpen. The first is assigned true when the current bar’s close (Bars.Close[0]) is lower than its open (Bars.Open[0]). And lowerOpen is assigned true when the next bar’s open (Bars.Open[-1]) is below the current bar’s close.

Should we set CalcAtOpenNextBar to false, those two statements need to be changed since Bars.Open[-1] isn’t allowed then. To do so, the commented lines need to be uncommented, while the two preceding lines need to be commented out. Then downBar is determined in the context of the previous bar (with Bars.Close[1] and Bars.Open[1]) and lowerOpen checks to see if the current bar’s open (Bars.Open[0]) is below the previous close.

The subsequent if-else statement submits buyOrder with its Send() method when both the downBar and lowerOpen variables evaluate to true, and the sellOrder is submitted when there is an open long position. For this latter the StrategyInfo.MarketPosition property is used, which returns a numerical value indicating the strategy’s current market position with negative values for short positions (MultiCharts, 2014).

The effect of CalcAtOpenNextBar enabled or not

When the above example has CalcAtOpenNextBar enabled, orders are submitted on the bar’s open immediately after the entry condition happened:

MultiCharts .NET CalcAtOpenNextBar - enabled

With the attribute set to false, orders are submitted on the bar’s close and executed a bar later. This introduces a delay of 1 bar:

MultiCharts .NET CalcAtOpenNextBar - disabled

By the way, should an attribute be changed while the strategy is already added to the chart, the script needs to be removed and re-added to see the effect of the updated code (see Henry MultiCharts, 2014).

When a strategy should react to every price change within a bar, and not just submitting orders on the bar’s open, the intra-bar order generation attribute needs to be used.

Summary

The default behaviour of trading strategies is to generate orders on bar close and submit them for the next bar. But when CalcAtOpenNextBar is enabled, orders are generated on the bar’s open and submitted for that same bar. With this attribute enabled, we can also reference the next bar’s open (Bars.Open[-1] or Bars.OpenNextBar()) and time (Bars.Time[-1] or Bars.TimeNextBar()).


References

Albahari, J. & Albahari, B. (2012). C# 5.0 in a Nutshell: The Definitive Reference (5th edition). Sebastopol, CA: O’Reilly Media.

Henry MultiCharts (2013, April 30). How do I use OrderCreator.MarketThisBar? – forum discussion. Retrieved on January 28, 2015, from https://www.multicharts.com/discussion/viewtopic.php?f=19&t=16058&p=65324#p65421

Henry MultiCharts (2014, December 11). MultiCharts .NET FAQ – forum discussion. Retrieved on January 25, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=19&t=45848#p111375

MultiCharts (2014). MultiCharts .NET Programming Guide (version 1.1). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.1.pdf