Situation
You want to know how to use a buy stop order, with, for example, a buy stop price 10 points from the current bar.

Programming example

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using ATCenterProxy.interop;

namespace PowerLanguage.Strategy
{
    public class Example_BuyStop : SignalObject
    {
        private IOrderPriced buyOrder;
        private IOrderMarket sellOrder;
        private double buyStopPrice, oneTick;

        [Input]
        public int BuyStopOffset { get; set; }

        public Example_BuyStop(object _ctx) : base(_ctx) { }

        protected override void Create()
        {
            buyOrder = OrderCreator.Stop(new SOrderParameters(
                Contracts.Default, "BuyStop", EOrderAction.Buy));

            sellOrder = OrderCreator.MarketThisBar(new SOrderParameters(
                Contracts.Default, "ExitLong", EOrderAction.Sell));

            BuyStopOffset = 100; // Default value for input
        }

        protected override void StartCalc()
        {
            Output.Clear(); // Clear PowerLanguage Editor log

            oneTick = Bars.Info.MinMove / Bars.Info.PriceScale;
        }

        protected override void CalcBar()
        {
            // Generate the buy stop price on the first bar of the day
            if (Bars.Time[0].Date != Bars.Time[1].Date)
            {
                buyStopPrice = Bars.High[0] + (oneTick * BuyStopOffset);

                Output.WriteLine("{0} - Current bar high: {1}, buyStopPrice: {2}",
                    Bars.Time[0].ToString("d-M HH:mm:ss"),
                    Bars.High[0],
                    buyStopPrice);
            }

            // When flat, submit buy stop order
            if (StrategyInfo.MarketPosition == 0)
            {
                buyOrder.Send(buyStopPrice);

                Output.WriteLine("{0} - Submitting buy stop @ {1}",
                    Bars.Time[0].ToString("d-M HH:mm:ss"),
                    buyStopPrice);
            }

            // Exit long position during the last bar of the session
            if ((StrategyInfo.MarketPosition > 0) && (Bars.LastBarInSession == true))
            {
                sellOrder.Send();
            }
        }
    }
}

Output of programming example

Applied to a chart, the strategy looks similar to:

Example of buy stops in MultiCharts .NET

With the following output corresponding to the above displayed trades:

3-12 02:00:00 - Current bar high: 1,3546, buyStopPrice: 1,3556
3-12 02:00:00 - Submitting buy stop @ 1,3556
3-12 04:00:00 - Submitting buy stop @ 1,3556
3-12 06:00:00 - Submitting buy stop @ 1,3556
3-12 08:00:00 - Submitting buy stop @ 1,3556
4-12 02:00:00 - Current bar high: 1,35943, buyStopPrice: 1,36043
4-12 02:00:00 - Submitting buy stop @ 1,36043
4-12 04:00:00 - Submitting buy stop @ 1,36043
4-12 06:00:00 - Submitting buy stop @ 1,36043
4-12 08:00:00 - Submitting buy stop @ 1,36043
4-12 10:00:00 - Submitting buy stop @ 1,36043
4-12 12:00:00 - Submitting buy stop @ 1,36043
4-12 14:00:00 - Submitting buy stop @ 1,36043
4-12 16:00:00 - Submitting buy stop @ 1,36043
4-12 18:00:00 - Submitting buy stop @ 1,36043
5-12 02:00:00 - Current bar high: 1,35911, buyStopPrice: 1,36011
5-12 02:00:00 - Submitting buy stop @ 1,36011
5-12 04:00:00 - Submitting buy stop @ 1,36011
6-12 02:00:00 - Current bar high: 1,36723, buyStopPrice: 1,36823
6-12 02:00:00 - Submitting buy stop @ 1,36823
6-12 04:00:00 - Submitting buy stop @ 1,36823
6-12 06:00:00 - Submitting buy stop @ 1,36823
6-12 08:00:00 - Submitting buy stop @ 1,36823
6-12 10:00:00 - Submitting buy stop @ 1,36823
6-12 12:00:00 - Submitting buy stop @ 1,36823
6-12 14:00:00 - Submitting buy stop @ 1,36823

Stop orders in MultiCharts .NET

Compared to market orders, a stop order has only a few differences. This example combines a buy stop order with a sell market order to see these differences.

The programming code starts with declaring two order objects, buyOrder and sellOrder:

private IOrderPriced buyOrder;
private IOrderMarket sellOrder;
private double buyStopPrice, oneTick;

Here we see that the buy stop order uses the IOrderPriced order interface (line 11) while the sell market order uses the IOrderMarket interface (line 12).

We also added a buyStopPrice double variable here to store the buy stop price and a oneTick variable that will later on in the example hold the value of the price movement of one tick.

Furthermore, an input was added to easily change the buy stop offset value (lines 15-16). This value is used later on to calculate the amount of ticks the buy stop price is above the high of the current bar.

[Input]
public int BuyStopOffset { get; set; }

Creating trading order objects in MultiCharts .NET

In the Create() method the two order objects were initialised (lines 20-29):

protected override void Create()
{
    buyOrder = OrderCreator.Stop(new SOrderParameters(
        Contracts.Default, "BuyStop", EOrderAction.Buy));

    sellOrder = OrderCreator.MarketThisBar(new SOrderParameters(
        Contracts.Default, "ExitLong", EOrderAction.Sell));

    BuyStopOffset = 100; // Default value for input
}

Here we see another difference between using market orders and using stop orders. The stop order uses the OrderCreator.Stop() method while a market order needs to use OrderCreator.MarketThisBar() or OrderCreator.MarketNextBar() (MultiCharts, 2013). In this example, since we are going to exit the long position on the last bar of the session, OrderCreator.MarketThisBar() is used for generating the sell market orders.

During automated trading you might want to close the position several minutes prior to the session close to ensure that the order is executed. See the article 'how to exit a position prior to the close?' for how to do that.

We also set the BuyStopOffset integer to a default value of 100 in the Create() method (line 28). Since in my case the signal is applied to a forex symbol with fractional pips (see the image above), the multiplication by hundred results in 10 pips.

Calculating the price movement of a tick

Next we arrive at the StartCalc() MultiCharts override method, in which we first clear the PowerLanguage Editor output tab and then calculate the price movement of one tick:

protected override void StartCalc()
{
    Output.Clear(); // Clear PowerLanguage Editor log

    oneTick = Bars.Info.MinMove / Bars.Info.PriceScale;
}

After that the CalcBar() method is implemented, in which three code segments can be identified. First, the buy stop price is generated:

// Generate the buy stop price on the first bar of the day
if (Bars.Time[0].Date != Bars.Time[1].Date)
{
    buyStopPrice = Bars.High[0] + (oneTick * BuyStopOffset);

    Output.WriteLine("{0} - Current bar high: {1}, buyStopPrice: {2}",
        Bars.Time[0].ToString("d-M HH:mm:ss"),
        Bars.High[0],
        buyStopPrice);
}

With the relational operator 'unequal to' operator (!=) this if statement checks whether or not the date of the current bar is unequal to the date of the previous bar. If that conditional expression evaluates to true, which it is for the first bar of every day, the buy stop price is calculated and information to keep track of the strategy is outputted to the PowerLanguage Editor output log.

Submitting a buy stop order in MultiCharts .NET

The next code segment submits the buy stop order if there is no open market position:

// When flat, submit buy stop order
if (StrategyInfo.MarketPosition == 0)
{
    buyOrder.Send(buyStopPrice);

    Output.WriteLine("{0} - Submitting buy stop @ {1}",
        Bars.Time[0].ToString("d-M HH:mm:ss"),
        buyStopPrice);
}

By using the StrategyInfo.MarketPosition property conditionally in the if statement (line 52), we ensure that the buy stop order is only submitted as long as there is no open position. Since orders are cancelled by MultiCharts .NET when they are not resubmitted, this assures that our buy stop order is cancelled as soon as a new position is opened (see e.g., MultiCharts Wiki, 2012).

Note that we also need to specify the buy stop price when submitting the order (line 54) — another difference compared with using regular market orders.

And finally, in the last code segment in the CalcBar() method, the long position is closed on the last bar of the session:

// Exit long position during the last bar of the session
if ((StrategyInfo.MarketPosition > 0) && (Bars.LastBarInSession == true))
{
    sellOrder.Send();
}

See the article stop-limit orders in MultiCharts .NET to learn about working with stop-limit orders.

References

MultiCharts (April 2013). MultiCharts .NET Programming Guide (version 1.0). Retrieved from http://www.multicharts.com/downloads/MultiCharts.NET-ProgrammingGuide-v1.0.pdf

MultiCharts Wiki (February 2012). Buy. Retrieved from http://www.multicharts.com/trading-software/index.php/Buy on December 7, 2013