The Environment.ApplicationCode property returns an enumerated value that indicates the environment (chart, Scanner/Watchlist, or Portfolio Trader) in which the script runs (PowerLanguage .NET Help, n.d.). We can access this property in indicators, signals, portfolio, and function scripts.

Environment.ApplicationCode returns a value from the EApplicationCode enumeration, which contains the following values (PowerLanguage .NET Help, n.d.):

Enumerated value Description
EApplicationCode.Charting Returned when the script calculates on a price chart.
EApplicationCode.Scanner Returned when the script runs in the Watchlist/Scanner window.
EApplicationCode.Portfolio Returned when the script calculates in the Portfolio Trader.
EApplicationCode.Unknown Returned when MultiCharts .NET cannot determine in which environment the script runs.

The Environment.ApplicationCode property is currently the only code element that uses the EApplicationCode enumeration.

Example: only draw trend lines on price charts

The example indicator below uses Environment.ApplicationCode to programmatically draw a trend line on price charts only. This prevents the MultiCharts .NET error message that triggers when we try to programmatically make a trend line in the Scanner/Watchlist or Portfolio Trader.

An additional benefit of Environment.ApplicationCode is that it can make our example indicator more flexible. For example, in the Scanner/Watchlist the script could plot the price values it would otherwise draw a trend line between on the price chart.

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

namespace PowerLanguage.Indicator
{
    [SameAsSymbol(true)]
    public class TradingCode_Reference_Indicator : IndicatorObject
    {
        public TradingCode_Reference_Indicator(object _ctx) : base(_ctx) { }

        private ITrendLineObject highestHighLine;

        protected override void StartCalc()
        {
            highestHighLine = null;
        }

        protected override void CalcBar()
        {
            if ((Bars.Status == EBarState.Close) &&
                (Environment.ApplicationCode == EApplicationCode.Charting))
            {
                double highestHigh = Bars.High.Highest(20);

                // Draw trend line if it doesn't exist yet;
                // otherwise, update the trend line's location
                if (highestHighLine == null)
                {
                    highestHighLine = DrwTrendLine.Create(
                        new ChartPoint(Bars.Time[10], highestHigh),
                        new ChartPoint(Bars.Time[0], highestHigh));

                    // Configure the line's appearance
                    highestHighLine.Color    = Color.Green;
                    highestHighLine.Size     = 2;
                    highestHighLine.ExtLeft  = true;
                    highestHighLine.ExtRight = true;
                }
                else
                {
                    highestHighLine.End   = new ChartPoint(Bars.Time[0], 
                        highestHigh);
                    highestHighLine.Begin = new ChartPoint(Bars.Time[10], 
                        highestHigh);
                }
            }
        }
    }
}

When we add this indicator to a chart, it looks like:

Example of drawing a MultiCharts .NET trend line programmatically

Without checking the value of Environment.ApplicationCode before creating a trend line programmatically, the example indicator triggers the “invalid pointer” error message when it runs in the Scanner/Watchlist:

MultiCharts .NET error message due to drawing in the wrong context

Example: only use portfolio data in the Portfolio Trader

The example signal below retrieves the portfolio’s net profit with the Portfolio.NetProfit property. But since MultiCharts .NET generates an error message when we access that property on price charts, we use Environment.ApplicationCode to make sure the script only accesses Portfolio.NetProfit in the Portfolio Trader.

This example also shows how we can use Environment.ApplicationCode to make a script behave differently depending on the environment in which it runs. (Or, in other words, not having to make a script for the Portfolio Trader and a near-identical one for price charts.)

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

namespace PowerLanguage.Strategy
{
    public class TradingCode_Reference_Strategy : SignalObject
    {
        public TradingCode_Reference_Strategy(object _ctx) : base(_ctx) { }

        protected override void CalcBar()
        {
            if (Bars.LastBarOnChart)
            {
                // Output the strategy's net profit, 
                // depending on the script's environment
                if (Environment.ApplicationCode == EApplicationCode.Charting)
                {
                    Output.WriteLine("On the chart, the strategy's profit is: {0}",
                        NetProfit.ToString("N2"));
                }
                else if (Environment.ApplicationCode == EApplicationCode.Portfolio)
                {
                    Output.WriteLine("And in the Portfolio Trader," + 
                        " this strategy's profit is: {0}",
                        Portfolio.NetProfit.ToString("N2"));
                }
            }
        }
    }
}

When we add the example signal to a chart and run it in the Portfolio Trader, it prints something like the following in the ‘Output’ tab of the PowerLanguage .NET Editor:

On the chart, the strategy's profit is: -218,66
And in the Portfolio Trader, this strategy's profit is: -3.950,83

Notes for Environment.ApplicationCode

While Environment.ApplicationCode returns the script’s environment, the Environment.ChartWindowHWND property returns the unique identifier of the window that the script runs in (which is often much more specific).


In terms of script calculation stage, we can access the Environment.ApplicationCode property in the StartCalc(), CalcBar(), StopCalc() and Destroy() override methods (MultiCharts, 2014).


Tips for Environment.ApplicationCode

Drawing arrows (DrwArrow.Create()), text boxes (DrwText.Create()), and trend lines (DrwTrendLine.Create()) programmatically is only possible when the script runs on a price chart. If we try to make a drawing in the Portfolio Trader or Scanner/Watchlist, MultiCharts .NET generates the “invalid pointer” error message (see image below).

Luckily, with Environment.ApplicationCode we can check whether a script runs on a chart (EApplicationCode.Charting) before executing code that creates a drawing. (Also see the first example above, which uses this approach to only draw a trend line when the indicator runs on a chart.)

Error message caused by making a drawing in the wrong MultiCharts .NET environment

When we try to use portfolio methods and properties (like Portfolio.NetProfit) outside of portfolio scripts, MultiCharts .NET generates an error message saying that code cannot be used outside of the Portfolio Trader (see image below).

To prevent those “portfolio functions can only be used in portfolio backtester” errors, use the Environment.ApplicationCode property to check whether a script runs in the Portfolio Trader (EApplicationCode.Portfolio) before executing portfolio-specific code. (See the second example above for how.)

MultiCharts .NET error message caused by accessing portfolio data on the chart

Summary

Features of Environment.ApplicationCode
Name Environment.ApplicationCode
Description Returns a value from the EApplicationCode enumeration that specifies in which environment the script runs.
Category Environment information
Type property
Returns An EApplicationCode enumerated value
Usable in Indicator, signal, portfolio, and function scripts
Available since (beta release date) MultiCharts .NET 8.0 (July 31, 2012)
Related code elements
Environment.CalcReason Returns a value from the CalculationReason enumeration that specifies what triggered the current script calculation.
Environment.ChartWindowHWND Returns the window handle of where the script currently calculates.
Environment.IsAutoTradingMode Returns whether the strategy’s automated order execution setting (that is, auto trading) is on or off.
Environment.IsRealTimeCalc Returns whether the script currently calculates on real-time data or not.
Environment.Optimizing Returns whether the strategy is currently being optimised on (genetic, exhaustive, and walk-forward optimisation).
Environment.OrderConfirmationRequired Returns, when the strategy’s auto trading is enabled, whether manual order confirmation is on or off.

References

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

PowerLanguage .NET Help (n.d.). Retrieved on September 27, 2016, from http://www.multicharts.com/downloads/PowerLanguage.NET.chm