Open main menu

4.1 How Indicators and Signals are Calculated

Contents

Basics

In MultiCharts .NET all studies (indicators and signals) are applied to the chart via the Insert Study window. Indicators can be applied to any chart symbol by clicking the right mouse button on the subchart to see the shortcut menu and selecting Insert Study. The constructor and the Create() method for study classes will be executed once when a study is selected, now indicators will create plots and signals will create orders. The StarCalc() method of study class is called every time before the calculation starts. The script begins to work through all of the historic bars of the symbol and on each bar the CalcBar() method is called. After the calculation of all historic bars, studies switch to the Real-time calculation on Close of every bar mode. For indicators, calculation on every tick received in real time can be selected. To do so, right-click on the chart to see the shortcut menu, select Format Indicators, select the indicator, then select Format, select the Properties tab and check the Update on Every Tick check box. For signals, calculation on every tick received in real time is activated by enabling the IOG option. To do so, right-click on the chart to see the shortcut menu, select Format Signals, select the signal, then select Format, select the Properties tab and check the Enable Intra-Bar Order Generation check box.

For Advanced Users

MultiCharts. NET is a multithread application and it is important to know in which threads studies are created, executed and deleted. There is a main thread (UI) and working threads, where the calculation of indicators and signals is executed.

Important! Please keep in mind that most methods and basic class properties of indicators, signals and functions are not thread-safe. It means that simultaneous work from several threads (which are created explicitly or implicitly) with methods and properties may lead to incorrect inner data and as the result to crashes in program. It is done in order to speed up calculation.

Starting from the moment of applying a study to a chart, scanner or portfolio, several stages occur before receiving the calculation results.

Construction.The Create() method

During this stage a new study object is created. Study object is created in the main thread and includes constructor and the Create() method calling. This process can be managed by the user through declaring and implementation of the method:

protected override void Create();

The Create() method is called first and only one time, immediately after the creation of a new study object. Here, the following is available: variables creation methods, adding plots function for indicators and strategy order creation factory:

  • PowerLanguage.CStudyControl.CreateSimpleVar and PowerLanguage.CStudyControl.CreateSeriesVar for variable creation (please see description of these variables below).
  
 private VariableObject<string> m_testVar;
        private VariableSeries<Double> m_seriesVar;
        private VariableSeries<Double> m_seriesVar2;

        protected override void Create()
        {
            m_testVar = (VariableObject<string>)CreateSimpleVar<string>();
            m_seriesVar = (VariableSeries<double>)CreateSeriesVar<double>();
            m_seriesVar2 = new VariableSeries<Double>(this);
        }
  • Adding plots to an indicator, for example, for MACD indicator:
private IPlotObject Plot1;

        protected override void Create() {
            Plot1 =
                AddPlot(new PlotAttributes("MACD", 0, Color.Cyan,
                                           Color.Empty, 0, 0, true));
        }
  • Strategy and signal order creation, using the OrderCreator property, for example, for RSI signals:
private RSI m_RSI;
        private VariableSeries<Double> m_myrsi;
        private IOrderMarket m_RsiLE;


        protected override void Create(){
            m_RSI = new RSI(this);
            m_myrsi = new VariableSeries<Double>(this);
     m_RsiLE = OrderCreator.MarketNextBar(new SOrderParameters(Contracts.Default, "RsiLE", EOrderAction.Buy));
        }

Please note, that all the listed methods and properties will be available ONLY at the stage of study construction (the Create() method). If they are used in the initialization or calculation stages, the study will compile and will be ready for application, but if applied to a chart or scanner window, they will generate an error message.

For example, plot addition is taken out of the Create() method in StarCalc():

       private IPlotObject Plot1;

 	protected override void StartCalc() {
            Plot1 = 
                AddPlot(new PlotAttributes("MACD", 0, Color.Cyan,
                                           Color.Empty, 0, 0, true));
        }

If this study is applied to a chart or a scanner, a new study will be created, but when it comes to the initialization stage (the StarCalc() method), the AddPlot instruction, which can be applied only in the Create() method, will be detected and the study will switch to offline mode. The following error message will appear:

Error message. Caption: "Error in study "MACD" :"; Message: "Unaccessible property(method): AddPlot. Construct only."

There are properties, available from the moment of object construction through its full life cycle:

  • Graphic renderers of the following objects: texts, trend lines, arrows – these are the properties of DrwText, Drw, TrendLine, DrwArrow.
  • The read-only Output property gives access to the Output window that displays study logs.
  • The read-only Alerts property gives access to alerts (pop-up messages, sound signals and e-mails).
  • The read-only Name property is the study name.


Initialization. The StartCalc() method

The StartCalc() method is called only once, before the every calculation.

The StartCalc() method is executed in the working thread and can be called repeatedly during the object life cycle (unlike the Create() method). To do this you must initialize the start values for study variables, the inputs for functions used in it and other custom objects in the StartCalc() method.


We can take the ADX indicator as the simplest example. One function, one serial variable and one plot are used here:

       private Function.ADX m_adx1;
       private VariableSeries<Double> m_adxvalue;
       private IPlotObject Plot1;

In object creation stage (Create), we create the the objects of the function and variable and also add a new plot object. In initialization stage (StartCalc) we create the initial value of this variable and initialize the function input with a user input of the indicator itself:

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

        protected override void Create(){
            m_adx1 = new Function.ADX(this);
            m_adxvalue = new VariableSeries<Double>(this);
            Plot1 =
                AddPlot(new PlotAttributes("ADX", 0, Color.Cyan,
                                            Color.Empty, 0, 0, true));
        }

        protected override void StartCalc(){
            m_adx1.Length = length;
        }

In initialization stage there is access to the price data through the Bars property and the BarsOfDate () method.

Also, in this stage other indicator and strategy properties become available:

a) The read-only Environment property – environment information

b) The read-only MaxDataStream property – maximum number of data series, used by the study

c) The bool IsExist method defines whether data series with a specified number exists on the chart (or in portfolio)

d) The read-only ExecInfo property – current calculation context information (calculation data series number, execution offset, MaxBarsBack and MaxBarsForward properties )

e) The read-only ExecControl property – allows the user to interrupt the calculation, recalculate the study, or force the study to calculate over a given period of time

f) The read-only VolumeProfile and VolumeProfileOfDataStream properties – access to volume profile

g) The read-only TradeManager property – access to trade information

h) The read-only StrategyInfo property – access to strategy information

i) The read-only Portfolio property – access to portfolio performance

j) The read-only Commission, InitialCapital, InterestRate, Account, Profile, Slippage properties – current strategy properties

k) The write-only CustomFitnessValue property sets custom value for optimization

l) The ChangeMarketPosition method – market position change without sending an order.

All of the above listed properties and methods are available from the moment of initialization and during the calculation. Calling on them in the construction stage (the Create () method) will result in an error message being generated. For example:

Message: "Unaccessible property (method): ExecControl. Initialize or Execute."

Study Calculation on Data Series.The CalcBar() method

After the previous two stages (Create, StartCals) have finished their operations, let’s move to bar-by-bar calculation of the study. The CalcBar() method will be called on for each bar of the data series, on which the study is applied, from left to right, in its turn. On each bar we have access to the data for that bar and for the previous bars on which the calculation was made (the CalcBar() method was called).

NOTE: All price data series where FullSymbolData of the IInstrument property was used will be available; this will be discussed separately.

Here is a simple example:

	namespace PowerLanguage.Indicator {

    public class _plotAvgPrice : IndicatorObject {

        public _plotAvgPrice(object ctx) : base(ctx) {}
		private IPlotObject Plot1;

        protected override void Create() {
            Plot1 = AddPlot(new PlotAttributes("Close"));
        }

        protected override void CalcBar() {
            Plot1.Set(0, (Bars.HighValue + Bars.LowValue) / 2 );
        }
    }
}

The CalcBar() method is called starting from the first bar of the calculation and all following bars. This means the study calculation is in the context of the current bar, that is why the expression (Bars.HighValue + Bars.LowValue) / 2 will be calculated for the current bar, and Plot1.Set instruction will draw the calculated value also on the current bar. After the calculation on the last bar the final graph of average prices for the whole chart will be generated (scanner will show the last calculated value).

Calculation Stop. The StopCalc() method

This method is called when the study calculation has finished, the study is in off mode or deleted from the price data series. The StopCalc() method can be called in the main or working thread.

Object Removal. The Destroy() method

Study removal is executed in the main thread. The Destroy() method will be called before the removal. This method is called only once during the life circle of an indicator object (signal).

In the calculation process various .NET exceptions can be generated. It can be easily seen during debugging. You should not intercept any exceptions other than yours, as many mechanisms, for example, BarsBack auto detect, are realized through the generation and further processing of a specific exception. Please, remember, that an exception is NOT always an ERROR FLAG!