Creating an Indicator
Custom Indicators¶
cTrader Automate Indicators are used to aid in manual trading as well as be included in automated strategies (cBots) for indicating trends and providing signals for potential changes in trends.
There have been a number of indicators developed over time by various statisticians and traders alike.
Some of the most popular indicators are included in the platform as built-in indicators and some examples with source code can be found in the indicators tab.
Custom indicators can be created using the code editor. Moreover, you may download custom indicators built by other users from the cTDN Indicators section.
Creating a new Indicator starts with adding a new Indicator template.
1. To add a new template into the code editor click New to the upper right of the Indicator tab. New Indicator will appear to the bottom of the cBots list.
You can rename your Indicator at any time by typing in the new name or by right-clicking the Indicator preview and selecting Rename from the drop-down menu. Alternatively, click on your Indicator and press F2.
The Indicator will be created with the code from the default code template:
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
Initialize Method¶
The Initialize()
method is used to initialize variables mainly such as indicators, data series, lists, etc.
In general, any variables that need to be calculated only once on start-up should be in the initialize method in order not to consume unnecessary resources.
Calculate Method¶
The Calculate(int index)
method is the main method of the indicator.
It is called for each historic bar starting from the beginning of the series up to the current bar and then on each incoming tick.
In the case of multi-symbol/multi-timeframe implementation, it will be called on each tick of each symbol that is used in the indicator.
It is typically used for the calculation of an indicator based on a formula.
For example, it is the difference between the High and the Low prices of each bar. The index parameter represents each bar, ranging from 0 up to the current (last) bar. So, at each bar, the Calculate method will be called and the Result will be assigned with the difference between the High and the Low of that bar.
2. Edit your Indicator using the syntax from the Class View. When done click Build to save changes. You can find the examples of working Indicators below in the Indicators Code Samples section.
3. Now your new Indicator is ready. To start using it click the plus icon (+) and select a Symbol from the drop-down list or using the advanced search.
Alternatively, select Add Instance from the Indicator Quick Menu by clicking on the arrow or right-clicking on an Indicator. In this case, an instance with EURUSD symbol by default will be created.
The new instance of the Indicator will be added below. You can select another Symbol for the Indicator and change the Timeframe.
Also, you can change the Indicator output line type, thickness, or color (Main in the present example).
NaN Arithmetic¶
The following is the code of Detrended Price Oscillator:
1 2 3 4 5 6 7 8 9 10 11 |
|
As you can see we just wrote a general rule for calculation but did not check any boundary conditions.
For example, if we use a moving average of 10 periods, the first 9 values can not be properly calculated. So we can not use this formula for any index less than 9.
Moreover, to calculate the value for a specified index, we use moving average value at index – Periods / 2 – 1. So in general we have to add such condition:
1 2 3 4 5 6 7 |
|
The code of the simple moving average also has to check that index >= Periods
. Moreover, if we use another nested indicator, for example, another type of moving average, this condition must be different.
Source series also may be result of another indicator and contain not calculated values at the beginning. All of these things make indicators development more complex, as we have to think about things that can be automatically handled.
To solve this problem the NaN Arithmetic can be used. Let’s say, if an indicator value is not defined at specified index it has some special value, let’s call it “Not a number” – NaN. If we use this value in our calculation we always get NaN as a result.
If we use not calculated value or value at a negative index from data series, we want it to be NaN.
Fortunately, type for floating numbers – double already has such value: double.NaN
, and it has needed behavior.
When you perform some operations with NaN and usual number you always get NaN, e.g + 1.4 == double.NaN
.
Since DataSeries returns NaN when you request value at negative index, you can miss all these pre-conditions and implement just general indicator calculation rule.
If the result contains NaN at some index, this value can just not be drawn on a chart.
Recursive indicators¶
When you calculate recursive indicator, i.e. indicator which value depends on previous value of this indicator, you must handle NaN values explicitly, for example here is exponential moving average calculation:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
In EMA, where current value depends on the previous one, the first value must be set explicitly.
To check this we use double.IsNaN(previousValue)
method. Note that we cannot use ==
operator like this previousValue == double.IsNaN
because NaN == x always false even if x is NaN.