Situation
You want to create a trading strategy that takes into account the number of bars since the previous position and the number of bars in the current position.

Code example

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

namespace PowerLanguage.Strategy
{
    public class Example_TradeBasedOnBarCount : SignalObject
    {
        private IOrderMarket buyOrder;
        private IOrderMarket sellOrder;

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

        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()
        {
            // Go long if: there are no trades or when the last position
            // was closed more than 5 bars ago, and the current position is
            // not older than 25 bars.
            if ((TotalTrades == 0) || (BarsSincePreviousPosition() > 5) &&
                (BarsInCurrentPosition() < 25))
            {
                buyOrder.Send();
            }

            // Exit long if the current position is open for more than 25 bars
            if ((StrategyInfo.MarketPosition != 0) && (BarsInCurrentPosition() > 25))
            {
                sellOrder.Send();
            }
        }

        // The BarsInCurrentPosition() method returns the number of bars
        // since the first trade of the current position
        private int BarsInCurrentPosition()
        {
            if (StrategyInfo.MarketPosition == 0)
                return -1;

            return Bars.CurrentBar - Positions[0].OpenTrades[0].EntryOrder.BarNumber;
        }

        // The BarsSincePreviousPosition() returns the number of bars
        // since the last trade of the previous position
        private int BarsSincePreviousPosition()
        {
            if (TotalTrades == 0)
                return -1;

            int tradesPrevPos = Positions[1].ClosedTrades.Count - 1;

            return Bars.CurrentBar -
                Positions[1].ClosedTrades[tradesPrevPos].ExitOrder.BarNumber;
        }
    }
}

MultiCharts .NET programming example

Let’s take a closer look at two methods used in the example. The first method, BarsInCurrentPosition(), returns the number of bars in the current position:

// The BarsInCurrentPosition() method returns the number of bars
// since the first trade of the current position
private int BarsInCurrentPosition()
{
    if (StrategyInfo.MarketPosition == 0)
        return -1;

    return Bars.CurrentBar - Positions[0].OpenTrades[0].EntryOrder.BarNumber;
}

If there is no market position, this method returns -1. By choosing a negative number, instead of the default value of an integer (0), we can distinguish that situation from one where the position is opened on the current bar, which would give a value of 0.

When there is an open market position, the difference between the current bar and the bar number of the entry order of the current position is returned. This last part is retrieved by using properties from the read-only collection of strategy positions (that is, Positions[x]).

Determining how many bars ago a position was closed

Another method in the example is the BarsSincePreviousPosition() method:

// The BarsSincePreviousPosition() returns the number of bars
// since the last trade of the previous position
private int BarsSincePreviousPosition()
{
    if (TotalTrades == 0)
        return -1;

    int tradesPrevPos = Positions[1].ClosedTrades.Count - 1;

    return Bars.CurrentBar -
        Positions[1].ClosedTrades[tradesPrevPos].ExitOrder.BarNumber;
}

When the TotalTrades value is zero, meaning that no trades have (yet) been closed, this method returns -1.

In all other cases, first the integer tradesPrevPos is assigned the number of closed trades in the previous position (i.e. Positions[1]). We add a - 1 here since the count value of a list is not zero-based, while a list on the other hand is zero-based. In other words, the length of a list starts counting at 1, while the first index of a list is 0. Not subtracting one from a list length is a common error, and would have give the following error message in this example:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

The last statement of this method returns the difference between the current bar number and the bar number of the last exit order of the most recent position.