Custom indicators in Protrader
Introduction
Since the creation of computed technical analysis we’ve seen hundreds of indicators created and thousands of modifications to these indicators. Regardless of the huge selection of indicators available, a trader may want to make his own custom indicator or make some graphical displays for better trading decisions. In the Protrader terminal we can use indicators that are written in the platform language C#. Additionally, indicators can be created in the popular MQL4 language.
Fortunately, creating and modifying indicators in Protrader doesn’t require top-level programming knowledge. Anybody with basic programming experience can do it. For good results in a short amount of time you can analyze the code of indicators that already work, make some changes, and then check reference and help materials as needed.
Moving Average Fan, a visual indicator for trends.
The majority of traders use moving averages to define market trends. A huge number of average types and different applications for averages have been invented. From this we can learn that an “ideal” indicator type and optimal period for each any single chart probably does not exist. But what if we could apply a few moving averages with different periods? Like in the example below, I added a few exponential moving averages, each time increasing the period by one. I used periods from 2 to 17. In order to avoid searching for the indicator each time after you’ve added your first one, you can find your newly added indicator at the top of the chart, right-click, and select duplicate indicator to add more.
Moving Average Fan, EUR/USD on a 20 Tick Chart
What happened is what we call a “Moving Average Fan.” When there is some strong price action (price goes up or down) the averages grow separate from each other and the fan opens up. When the trend weakens, the averages come close to each other. If there isn’t a trend then the averages will sort of randomly be intertwined with each other. These properties of the moving average fan can be used effectively for manual trading in order to estimate the potential strength and direction of trends.
If you want to apply the fan to building an automated trading system, you can total the number of “ordered averages” in relation to the number of “disordered averages.” Fundamentally, this could be used to measure the relative strength of a trend or make some trading decisions. So if we already have some good averages on the chart why should we use a custom one? To answer this question (and give you a general idea of the way you should be thinking when you make your own trading systems) we need to consider some basic “what if” situations. What if we need to change all of the periods in order to track a larger overall trend? What if we need to increase the step between periods? Would that require us to change the properties of each average? Also, how much time are we willing to waste each time we want to add a bunch of indicators to a chart? If we can make a custom indicator we can answer all of these questions. So let’s begin.
Creating a custom indicator
In order to do this quickly, check Tools menu and launch AlgoStudio – the full-cycle development environment that is included in the Protrader Desktop platform – and choose “New Module” from the main submenu. Choose C# and make the module type an indicator. Click next and choose a name “FanMovingAverages “ (really any name works) then press create. This will show the basic indicator form where we need to add our logic. Let’s take a look at the text below more closely.
using System; // Directions for C#, using System.Collections; // that allow it to use using System.Collections.Generic; // necessary types using System.Text; // without full instructions using System.Drawing; using PTLRuntime.NETScript; namespace FanMovingAverages // The namespace is // the title of your project { /// <summary> /// FanMovingAverages // this is a description of the // indicator /// /// </summary> public class FanMovingAverages : NETIndicator // This says that class FanMovingAverages inherits the class NETIndicator. // All the basic logic will follow from the higher class so we // only have to add our own functions. { // This is the opening bracket of the class. If contains a section of block // code. The brackets should always be left if opening a class and right if // closing public FanMovingAverages() // This is a function where the // indicator properties are written : base() { #region // Initialization base.Author = ""; base.Comments = ""; base.Company = ""; base.Copyrights = ""; base.DateOfCreation = "02.09.2013"; base.ExpirationDate = 0; base.Version = ""; base.Password = "66b4a6416f59370e942d353f08a9ae36"; base.ProjectName = "FanMovingAverages"; #endregion base.SetIndicatorLine("line1", Color.Blue, 1, LineStyle.SimpleChart); // This defines the line // type and settings base.SeparateWindow = false; // Defines whether the // indicator is on chart // or separate window. // true – separate window, // false – on the chart. } /// <summary> /// This function will be called after creating /// </summary> public override void Init() // A function which is called // one time upon creating an // indicator. // Here you can make some // beginning definitions or // add some code that should // work constantly not // connected with quotes. { } /// <summary> /// Entry point. This function is called when new quote comes /// </summary> public override void OnQuote() { } /// <summary> /// This function will be called before removing /// </summary> public override void Complete() { } } // The closing operator brackets for FanMovingAverages. }
Next check Script Navigator from View menu. In Examples→ Csharp Indicators→ MovingAverages.cs grab first Class EMA. Now we need to find the necessary fragments. Look for:
1. Input Parameters:
[InputParameter("Period of Exponential Moving Average", 0)] public int MaPeriod = 2; // EMA period by default 2 [InputParameter("Sources prices for MA", 1, new object[]{ "Close", PriceType.Close, "Open", PriceType.Open, "High", PriceType.High, "Low", PriceType.Low, "Typical", PriceType.Typical, "Medium", PriceType.Medium, "Weighted", PriceType.Weighted} )] public PriceType sourcePrice = PriceType.Close;// Input data for calculating the indicator // by default this is the CLOSE.
2. Function that defines beginning of indicator line from function Init():
SetIndexDrawBegin(0, MaPeriod);
3. The main logic of indicator from function OnQuote():
// Receiving these prices: double price = GetPrice(Symbol, Period, 0, SourcePrice, GetFieldType(Symbol)); // We check if there are more bars on the graph than moving average // periods. If that is true, the below happens. int count = BarsCount(Symbol, Period); if (count > MaPeriod) // Checking condition. If it passes, we can // make some calculations. { // Calculation of coefficients double k = 2.0 / (MaPeriod + 1); // Getting the previous value of the EMA. double prevEMA = GetValue(0, 1); SetValue(0, 0, prevEMA + k * (price - prevEMA)); // Setting current // value for EMA. } else SetValue(0, 0, price); // This code runs if the previous // condition wasn’t met. The indicator value is set // to the current price.
Now we need to copy necessary parts of the code into our file FanMovingAverages.
Here’s what should happen:
using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Drawing; using PTLRuntime.NETScript; namespace FanMovingAverages { /// <summary> /// FanMovingAverages /// /// </summary> public class FanMovingAverages : NETIndicator { public FanMovingAverages() : base() { #region // Initialization base.Author = ""; base.Comments = ""; base.Company = ""; base.Copyrights = ""; base.DateOfCreation = "02.09.2013"; base.ExpirationDate = 0; base.Version = ""; base.Password = "66b4a6416f59370e942d353f08a9ae36"; base.ProjectName = "FanMovingAverages"; #endregion base.SetIndicatorLine("line1", Color.Blue, 1, LineStyle.SimpleChart); base.SeparateWindow = false; } [InputParameter("Period of Exponential Moving Average", 0)] public int MaPeriod = 2; [InputParameter("Sources prices for MA", 1, new object[]{ "Close", PriceType.Close, "Open", PriceType.Open, "High", PriceType.High, "Low", PriceType.Low, "Typical", PriceType.Typical, "Medium", PriceType.Medium, "Weighted", PriceType.Weighted} )] public PriceType sourcePrice = PriceType.Close; // Calculation will be performed on // Close prices /// <summary> /// This function will be called after creating /// </summary> public override void Init() { SetIndexDrawBegin(0, MaPeriod); } /// <summary> /// Entry point. This function is called when new quote comes /// </summary> public override void OnQuote() { // Getting current price double price = GetPrice(Symbol, Period, 0, SourcePrice, GetFieldType(Symbol)); // Checking, if current amount of bars // more, than period of moving average. If it is // then the calculation is possible int count = BarsCount(Symbol, Period); if (count > MaPeriod) { // Calculation of a coefficient double k = 2.0 / (MaPeriod + 1); // Getting previous EMA double prevEMA = GetValue(0, 1); SetValue(0, 0, prevEMA + k * (price - prevEMA)); } else SetValue(0, 0, price); } /// <summary> /// This function will be called before removing /// </summary> public override void Complete() { } } }
All that remains is to press F6, in order to compile our text into performing code. If we did everything correctly we’ll get a “Compile succeeded” message. While compiling, AlgoStudio reveals mistakes by saying something like “Compile error.” For example if we forgot a bracket the code won’t be compiled correctly. Instead we’ll see an error with a notification in the text editor where we need to fix something. Not all mistakes can be caught by the compiler. For example, while the program is running there could be a division by zero or an attempt to get data from outside an array. Therefore, in certain places where this could happen I recommend that you do your own checking.
Now lets add this indicator to a chart. In the list of custom indicators we can now see our FanMovingAverages. So double click it and it you will see the settings. Install a period and press OK, and we can see a familiar EMA. At the moment we only see one. The routine operation is now finished, so we can be a bit more creative. Go back to AlgoStudio and let’s add a few more averages to form a fan by doing the following:
base.SetIndicatorLine("line1", Color.Blue, 1, LineStyle.SimpleChart); base.SetIndicatorLine("line2", Color.Blue, 1, LineStyle.SimpleChart); etc…until base.SetIndicatorLine("line10", Color.Blue, 1, LineStyle.SimpleChart);
The input parameter we can rename “FirstMaPeriod.” It will be our first period in the fan.
[InputParameter("Period of first Exponential Moving Average", 0)] public int FirstMaPeriod = 2;
Now we add the step between periods.
[InputParameter("Step", 1)] public int Step = 1;
And now to avoid adding this code 10 times we can use a loop:
for(int i=0; i<10; i++) // For is a loop operator. i is an integer variable // i=0 is the starting point for the loop. // i<10 defines the length of the loop. // i++ is an increment which increases the operator by // 1. This means our loop will be working until the // variable I is equal to 10. Then it will stop. int period = FirstMaPeriod + i * Step; // This calculates the EMA period // depending on the number and step if (count > period) { // Calculation of a coefficient double k = 2.0 / (period + 1); // Getting previous EMA double prevEMA = GetValue(i, 1); // Here we use i as a parameter // in order to get the previous // definition of the EMA with // the number i SetValue(i, 0, prevEMA + k * (price - prevEMA)); // getting the value // of an EMA with a // number and i } else SetValue(i, 0, price); // if there aren’t enough // bars for calculating the EMA, // we set the definition of the EMA with i // equal to the current price }
Additionally, we can modily function Init() to set beginning of all indicator lines. It's done with help of cycle also:
public override void Init() { // Calculation of the maximum EMA period int maxEmaPeriod = FirstMaPeriod + 9 * Step; for(int i=0; i<10; i++) { // This function sets the start of the display // of the indicator line with variable i SetIndexDrawBegin(i, maxEmaPeriod); } }
Now we’ve added all needed components to our code so let’s compile again and check it out on the graph.
Moving Average Fan, EUR/USD, 20 tick chart, default parameters, FirstMaPeriod=2, Step=1.
Now we can change the starting period and step as we wish.
Moving Average Fan, EUR/USD, 20 tick chart, default parameters, FirstMaPeriod=5, Step=3.
If you don’t like the color of the line or thickness then go back to the function SetIndicatorLine("line1", Color.Blue, 1, LineStyle.SimpleChart). If you change Color.Blue to Color.Red, and change 1 to 2 you will get a red line with thickness of 2 pixels.
Moving Average Fan, EUR/USD, 20 tick chart, changes to SetIndicatorLine
You can also use different patterns with increasing EMA periods. For example use a series of Fibonacci numbers, etc…
Conclusion
As you can see, making a new custom indicator is not really that difficult. More detailed info about programming in C# can be found at http://msdn.microsoft.com. By creating custom indicators you can modify well-known methods of technical analysis (some of which were developed long before computers and programming were even around) and also apply some modern analysis methods and time series forecasts.