MultiCharts .NET attributes that affect a strategy’s order behaviour include IOGMode for submitting orders intra-bar and ExitFromOneEntryOnce for reusing an exit order numerous times. But these attributes still require real-time ticks to occur before orders can be submitted. How can we submit orders whenever we want?

Sending orders for any script calculation with AllowSendOrdersAlways

A C# attribute is a way to add metadata to code elements like classes (Dorman, 2010) and doing so influences how these operate (e.g., see Stephens, 2014). Such attributes are used in MultiCharts .NET to set script options programmatically.

One of these attributes is AllowSendOrdersAlways (see PowerLanguage .NET Help, n.d.). When this attribute is set to true, autotrading orders can always be generated – even when a symbol’s bar status is -1 or the equivalent EBarState.None enum value (see Henry MultiCharts, 2014; MultiCharts Wiki, 2014a; PowerLanguage .NET Help, n.d.).

Bar status in MultiCharts .NET explained: open, inside, close, or none

A symbol’s bar status indicates the status of the current price in the bar of the specified data series that’s currently processed by the script (see MultiCharts, 2014; MultiCharts Wiki, 2014b). For example, when the primary data series’ current tick is the bar’s closing price, then Bars.Status returns EBarState.Close (see PowerLanguage .NET Help, n.d.).

Other bar status values are EBarState.Open (for opening ticks), EBarState.Inside (for ticks that are within a bar), and EBarState.None for undefined bar statuses (MultiCharts Wiki, 2014b; PowerLanguage .NET Help, n.d.). Those undefined bar statuses can happen in two situations: when a script periodically recalculates with RecalcLastBarAfter() while the bar is closed and no opening tick has been received yet or when bars from multiple data series don’t align (Henry MultiCharts, 2012, 2014; MultiCharts Support, personal communication, February 10, 2015).

When a bar status is not defined (EBarState.None), orders cannot be send by design (Henry MultiCharts, 2012). But that behaviour can be changed with the AllowSendOrdersAlways attribute so that orders can be submitted at any time.

Setting the AllowSendOrdersAlways attribute in MultiCharts .NET

Set AllowSendOrdersAlways to true to allow orders to be generated always:

[AllowSendOrdersAlways(true)]
public class Example_AllowSendOrdersAlways : SignalObject
{
    // Strategy code
}

And set the attribute to false to only submit orders during the opening, inside, or closing status of a price bar:

[AllowSendOrdersAlways(false)]
public class Example_AllowSendOrdersAlways : SignalObject
{
    // Strategy code
}

The default behaviour of no order generation for undefined bar statuses applies when the attribute is missing from the code (see MultiCharts Wiki, 2014a). There’s no manual option for AllowSendOrdersAlways — it can only be set programmatically.

Example: using AllowSendOrdersAlways to generate orders on illiquid instruments

One benefit of AllowSendOrdersAlways is that orders on relatively illiquid instruments can be generated with periodic script recalculations instead of having to wait for a new tick. An example of this is EUR/CZK:

MultiCharts .NET AllowSendOrdersAlways - example

Sending orders with periodic script recalculations can be done as follows:

[AllowSendOrdersAlways(true), IOGMode(IOGMode.Enabled)]
public class Example_AllowSendOrdersAlways : SignalObject
{
    public Example_AllowSendOrdersAlways(object _ctx) : base(_ctx) { }

    private IOrderMarket marketBuy, marketSell;

    protected override void Create()
    {
        marketBuy = OrderCreator.MarketNextBar(new
            SOrderParameters(Contracts.Default, EOrderAction.Buy));

        marketSell = OrderCreator.MarketNextBar(new
            SOrderParameters(Contracts.Default, EOrderAction.Sell));
    }

    int counter = 0, noneBars = 0;

    protected override void CalcBar()
    {
        if (Environment.CalcReason == CalculationReason.Timer)
        {
            if (StrategyInfo.MarketPosition == 0)
            {
                Output.WriteLine("BarStatus: {0}. Number of None bars: {1}."
                    + " Submitting buy order",
                    Bars.Status,
                    noneBars);

                marketBuy.Send();
                counter = 0;
            }

            if (StrategyInfo.MarketPosition > 0 && counter > 25)
            {
                Output.WriteLine("BarStatus: {0}. Number of None bars: {1}."
                    + " Submitting sell order",
                    Bars.Status,
                    noneBars);

                marketSell.Send();
            }

            counter++;
        }

        if (Bars.Status == EBarState.None)
            noneBars++;

        ExecControl.RecalcLastBarAfter(new TimeSpan(0, 0, 1));
    }

    protected override void OnRecalcLastBarAfterEvent()
    {
        this.CalcBar();
    }

    //> BarStatus: None. Number of None bars: 482\. Submitting buy order
    //> BarStatus: None. Number of None bars: 513\. Submitting buy order
    //> BarStatus: None. Number of None bars: 544\. Submitting buy order
    //> BarStatus: None. Number of None bars: 575\. Submitting buy order
    //> BarStatus: Inside. Number of None bars: 577\. Submitting sell order
}

We start with setting AllowSendOrdersAlways to true. This attribute also requires intra-bar order generation (Andrew MultiCharts, 2014) because otherwise orders would only be generated on bar close (EBarState.Close), and so the IOGMode attribute is also enabled. Then two IOrderMarket market orders are declared (marketBuy and marketSell), which are subsequently created in the Create() method.

After that two integer variables are declared and set to zero: counter will keep track of the number of periodic recalculations and is used for the exit, while noneBars will count the number of script calculations with a EBarState.None undefined bar status. This latter gives an idea of the amount of script calculations on which we normally couldn’t send an order.

Calculating the strategy and submitting orders in MultiCharts .NET

The strategy’s logic is implemented in the CalcBar() method. In it we begin with an if statement that checks if the script’s calculation reason (Environment.CalcReason) equals CalculationReason.Timer, which it does when a periodic recalculation is performed. We deliberately check for this condition because it increases the odds of coming across EBarState.None so that AllowSendOrdersAlways’s effect can be noticed.

Inside that if statement a nested if statement checks whether there’s no open market position, in which case StrategyInfo.MarketPosition returns 0 (see MultiCharts, 2014). When flat, the bar status of the primary data series (Bars.Status) and the number of undefined bar statuses (noneBars) is outputted to the PowerLanguage .NET Editor. The marketBuy order is then submitted with its Send() method and the counter variable is reset to zero so that it can start counting towards the exit.

The exit order is submitted when there’s an open long position (StrategyInfo.MarketPosition will then return a positive value larger than 0; MultiCharts, 2014) and counter is greater than 25. Then we again output data with Output.WriteLine() before calling the sell order’s Send() method.

Below that nested if statement the counter variable is incremented with 1 with the postfix increment operator (++) and an if statement checks whether the current bar status equals an undefined bar status (EBarState.None). When it does, the noneBars variable is also increased with 1.

Periodically recalculating a strategy in MultiCharts .NET

The script’s periodic recalculation is done by calling the ExecControl.RecalcLastBarAfter() method with a TimeSpan of 1 second. After this time interval has elapsed, MultiCharts .NET will execute the OnRecalcLastBarAfterEvent() method (PowerLanguage .NET Help, n.d.). And in that method we execute CalcBar() again by calling it with the this keyword, which refers to the current instance of an object (Liberty & MacDonald, 2009) that is in this case our Example_AllowSendOrdersAlways example strategy.

This periodic recalculation ensures that the strategy is calculated every so often even with the absence of incoming real-time ticks, which enables the strategy to send orders during ‘slow’ periods or on relatively illiquid instruments.

Other MultiCharts .NET attributes that change how a trading strategy’s orders operate are CalcAtOpenNextBar, IOGMode, and ExitFromOneEntryOnce.

Summary

With the AllowSendOrdersAlways attribute orders can be submitted at any time, even when a bar’s status is undefined due to a script’s recalculation before a new bar has formed or when data series bars are unaligned.


References

Andrew MultiCharts (2014, April 16). Code on to cancel orders at session end before after hours – forum discussion. Retrieved on February 5, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=1&t=46449#p104194

Dorman, S. (2010). Sams Teach Yourself Visual C# 2010 in 24 Hours. Indianapolis, IN (USA): Sams/Pearson Education.

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

Henry MultiCharts (2014, September 9). What in the world could be wrong with this picture?! – forum discussion. Retrieved on February 5, 2015, from http://www.multicharts.com/discussion/viewtopic.php?f=1&t=46827#p108056

Liberty, J. & MacDonald, B. (2009). Learning C# 3.0: Master the Fundamentals of C# 3.0. Sebastopol, CA: O’Reilly Media.

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

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

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

PowerLanguage .NET Help (n.d.). Retrieved on November 18, 2014, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm

Stephens, R. (2014). C# 5.0 Programmer Reference. Indianapolis, IN: John Wiley & Sons.