Skip to content

Custom indicator lifecycle

Sample code structure

This article will guide you through the code structure and explain the logic behind events and lifecycle for a cTrader indicator. To access custom indicators, open the Local tab in the Algo app.

Image title

As an example, you can create a new indicator named "LifeCycle Test" with the following sample code available in the code editor window.

Image title

To reset to the boilerplate version, copy the code below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
    [Indicator(AccessRights = AccessRights.None)]
    public class LifeCycleTest : Indicator
    {
        [Parameter(DefaultValue = "Hello world!")]
        public string Message { get; set; }

        [Output("Main")]
        public IndicatorDataSeries Result { get; set; }

        protected override void Initialize()
        {
            // To learn more about cTrader Algo visit our Help Center:
            // https://help.ctrader.com/ctrader-algo/


            Print(Message);
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = 
        }
    }
}

At a glance, the code structure includes only two methods, the Initialize() method and the Calculate() method. Click Build to proceed with testing this indicator. We will add an additional method called OnDestroy() and explain its purpose later.

The initialisation event

When a cTrader indicator is first attached to a chart or when the user changes any of the parameter settings, an indicator instance is recreated and the Initialize() method is called. It is used to initialise any variables you plan to employ in your indicator. You can also define and reference additional indicators to create a single indicator using formulas from other indicators.

By default, the new code template includes a parameter setting called Message with the value of "Hello world!".

1
2
[Parameter(DefaultValue = "Hello world!")]
public string Message { get; set; }

In the Initialize() method, there is a line of code to print this message to the log.

1
Print(Message);

To demonstrate the Initialize() method, add an indicator instance by clicking Plus icon next to the Build icon and selecting a symbol. If you click More in the indicator row and choose Add an instance, the EURUSD symbol with the h1 timeframe will be added automatically.

Image title

Note

Adding an instance in cTrader Algo is the same as attaching an indicator to a chart in the Trade application.

Now, open the Log tab in Trade Watch panel under the chart. As you can see, the message "Hello world" has been printed.

Image title

Every time the indicator is first added to a chart or when a parameter is changed, the chart is refreshed and the Initialize() method is called again. Type a different message in the Parameters section to see the log entry update accordingly.

Image title

Calculate indicator output

The Calculate() method is called for each index of historical data and on each incoming tick. For example, if the current chart has 1000 bars, the Calculate() method will be called for index 0, 1, 2, and so on, up to a maximum of 999.

1
public override void Calculate(int index)

The Calculate() method can be called multiple times per second during periods of high volatility or fewer times when the market is flat. To test how it works, you can add a line of code to the body of the Calculate() method to print the index value that is being passed into the method for each new data tick. Do not forget to click Build each time after adding changes in the code editor window.

1
Print("Index: " + index);

To switch from the code editor window to the chart, click the added indicator instance. If you open the Log tab in Trade Watch panel, you will see the values printed for each index passed into the method.

Image title

The OnDestroy() method

The OnDestroy() method is called when the indicator is removed from a chart and is no longer needed. You will need to implement this method, as it is not added by default when you create a new indicator.

1
2
3
4
protected override void OnDestroy()
        {
            base.OnDestroy();            
        }

This method is useful for programmers, as it allows them to release unmanaged resources and perform finalisation tasks. It helps prevent memory leaks and ensures the indicator does not retain resources after removal. Examples include closing connections to external data feeds, releasing large data objects, and other operations that free memory.

Summary

In summary, the Initialize(), Calculate() and OnDestroy() methods illustrate different stages of the custom indicator lifecycle. By adjusting the sample code in the Algo app, you are free to decide how to initialise indicator variables, calculate the indicator output, and run finalisation tasks.

Subscribe to our YouTube channel