Situation
You want to exit your strategy’s position prior to the session close so you won’t hold a position overnight.

Programming example

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

namespace PowerLanguage.Strategy
{
    [IOGMode(IOGMode.Enabled)]
    public class Example_ExitBeforeClose : SignalObject
    {
        private IOrderMarket shortOrder, coverOrder;
        private TimeSpan exitTime;
        private bool prevLastBarOfSession;

        [Input]
        public string ExitTime { get; set; }

        public Example_ExitBeforeClose(object _ctx)
            : base(_ctx)
        {
            // Set the input to a default value
            ExitTime = "17:20";
        }

        protected override void Create()
        {
            shortOrder = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default,
                "EnterShort", EOrderAction.SellShort));
            coverOrder = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default,
                "TimeExit", EOrderAction.BuyToCover));
        }

        protected override void StartCalc()
        {
            // Convert the string to TimeSpan
            exitTime = ConvertToTime(ExitTime);
        }

        protected override void CalcBar()
        {
            // Open a short position on the first bar of the session
            if (!Bars.LastBarInSession && prevLastBarOfSession)
            {
                shortOrder.Send();
            }

            // Close the position  
            if ((StrategyInfo.MarketPosition < 0) && TimeToExit())
            {
                coverOrder.Send();
            }

            prevLastBarOfSession = Bars.LastBarInSession;

            // Recalculate the strategy every 15 seconds
            ExecControl.RecalcLastBarAfter(TimeSpan.FromSeconds(15));
        }

        // Check to see if the position should be closed
        private bool TimeToExit()
        {
            // On real-time data, we use the computer time
            if (Environment.IsRealTimeCalc == true)
            {
                if (DateTime.Now.TimeOfDay >= exitTime)
                    return true;
                else
                    return false;
            }
            // Else, when backtesting, use the bar time
            else
            {
                if (Bars.TimeValue.TimeOfDay >= exitTime)
                    return true;
                else
                    return false;
            }
        }

        // Convert a string to a TimeSpan structure
        private TimeSpan ConvertToTime(string timeToConvert)
        {
            DateTime dt = DateTime.ParseExact(timeToConvert, "H:mm",
                System.Globalization.CultureInfo.InvariantCulture);

            return dt.TimeOfDay;
        }

        // Recalculate the last bar when performing the recalculation
        protected override void OnRecalcLastBarAfterEvent()
        {
            this.CalcBar();
        }
    }
}

Output of the programming example

Applied to a chart this example looks like:

Example of exiting a MultiCharts .NET position before the close

Exiting positions prior to the close of trading

The GenerateExitOnClose() method in MultiCharts .NET generates a market order which closes the current position upon the session close (MultiCharts, 2013). However, this method submits the order literally on the session close, which gives the risk that the order is not (completely) executed. Therefore we will not use that method in this example.

Two things added to this example are important for exiting a position prior to the close. First, intra-bar order generation is turned on (line 9). This enables the strategy to send orders during the bar instead of just at the close of the bar. This prevents the issue where the session close happens at the same time as the bar close. Note: you may also want to turn on the Bar Magnifier for more backtesting precision.

Second, by forcing the strategy to be recalculated at least once every 15 seconds (line 57), we ensure that our exit order is also send when the instrument is (relatively) illiquid and there are no incoming ticks. See in this context also the article ‘How to force a recalculation of a strategy or indicator?’.

MultiCharts .NET programming example

We start with adding an input for the exit time and assigning this string a default value (lines 16-24). Then, in the StartCalc() method (lines 34-38), we converted this string to a TimeSpan structure, using a custom method named ConvertToTime(), which is in lines 81-88 of the example. See the article ‘How to trade only during certain times with a trading strategy?’ to learn more about this method and the TimeSpan structure.

In the CalcBar() method, the open short order is send on every first bar of the session:

// Open a short position on the first bar of the session
if (!Bars.LastBarInSession && prevLastBarOfSession)
{
    shortOrder.Send();
}

This is done by using the property Bars.LastBarInSession, which returns true if the bar is the last bar of the session and false in all other cases. Since we save this property to a Boolean variable on every bar (line 54), we can use the saved value to refer the previous bar’s value. By doing so, we can check whether the current bar is the first bar of the session or not.

Submitting exit orders in MultiCharts .NET

When there is an open position and the TimeToExit() method returns true, the exit position order is submitted:

// Close the position  
if ((StrategyInfo.MarketPosition < 0) && TimeToExit())
{
    coverOrder.Send();
}

This TimeToExit() method is implemented as follows:

// Check to see if the position should be closed
private bool TimeToExit()
{
    // On real-time data, we use the computer time
    if (Environment.IsRealTimeCalc == true)
    {
        if (DateTime.Now.TimeOfDay >= exitTime)
            return true;
        else
            return false;
    }
    // Else, when backtesting, use the bar time
    else
    {
        if (Bars.TimeValue.TimeOfDay >= exitTime)
            return true;
        else
            return false;
    }
}

This method differentiates between the calculation based on incoming real-time data (in which case Environment.IsRealTimeCalc returns true) and the calculation based on historical data.

When the strategy is calculated on real-time data, the computer time (DateTime.Now) is used to determine whether it is time to close a position. Otherwise we have the risk that the position does not get closed when the instrument is (relatively) illiquid, since a period of no real-time price updates also mean that there are no recent time stamps.

If you want to use the time of the last real-time price update, use Bars.StatusLine.Time.TimeOfDay. If you use Bars.TimeValue.TimeOfDay you get the closing time of the bar and not the most recent price update.

When the calculation is done on historical data, the TimeToExit() method uses the current time of the bar (i.e. Bars.TimeValue) to determine whether or not the position should be closed.

Recalculating a MultiCharts .NET script periodically

In the last part of the CalcBar() method the RecalcLastBarAfter() method is called:

// Recalculate the strategy every 15 seconds
ExecControl.RecalcLastBarAfter(TimeSpan.FromSeconds(15));

This ensures that the strategy is recalculated at least once per fifteen seconds, again to prevent the risk that an illiquid instrument does not have enough price updates to send the exit order in a timely manner.

References

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