Here is an indicator that plots horizontal lines on the chart at a certain percent value above and below the last price.
The request for this indicator came up in the Tradestation Community Forum a few weeks ago.
You can download the coding for free, but I am also going to go through the creation process step by step for those of you with the intention to learn how to program in EasyLanguage and reuse code snippets that simplify and speed up the development of future indicators or strategies.
The programming is done in Object Oriented EasyLanguage (OOEL).
Step 1: Code header and namespace references
Being neat programmers, we want to add a header to the top of our coding.
In order to structure the coding, we make use of #region and #endRegion. These regions can be expanded/collapsed and help keeping an overview of the coding. They do also reflect in the Outline that you can open on the left side of the editor.
Our very top executable statements must be the referencing of the namespaces we are going to use. This is done with the reserved word using followed by the namespace.
By doing this, we can easily access the classes, methods, properties, events etc. from the specified namespace.
The namespace elsystem.drawing contains the class Color which we will use a little later to color the lines
Without referencing the namespace, we would have to explicitely specify the complete qualified name every time we want to use the class Color.
Example with referencing the namespace:
The second namespace we want to reference is elsystem.drawingobjects for it containing the TrendLine and DTPoint classes.
Step 2: User inputs and variables
In order to allow us some flexibility without the need to touch the code for every little adjustment, we specify the following inputs:
Reference Price: Price that is used as the basis to calculate the range. E.g. close, open, MedianPrice, etc. Percent: The percent value of the range from the input Reference Price. Color of the upper/lower lines: Color names of the lines. See available colors here. Opacity of the lines: Value from 0-255 to control the opacity of the lines Weight of the lines: Value from 0-6 to control the weight of the lines
I usually have variables that represent the inputs. Although it is possible to work with the inputs, it saves CPU load to work with variables.
The variables are declared with <type> <name> followed by their initial value in brackets.
Step 3: Methods to structure and encapsulate reusable code
The necessary preparation is finally done and we can go on with the programming of actions :)
We want to have two methods for the indicator:
Method void AnalysisTechnique_InitMain()
This method is called only once in the processing of the indicator. We use it to assign the user inputs to their fellow variables.
At times, it does also make sense to convert the user inputs in the initial assignment to their respecitve fellow variable. We are going to do this here with iPercent which we will calculate into a multiplier for the price. By doing this calculation only once, we save the processing load when the code runs on all of the bars and in real-time maybe even on every tick.
I always use this method in my coding to perform initial preparing tasks that need to be done only once.
Method TrendLine TL_Modify(TrendLine licTLObj, DTPoint liStartDT, DTPoint liEndDT, Color liColor)
The method TL_Modify returns a TrendLine object and expects four parameters. Namely a TrendLine object, a DateTimePoint (DTPoint) representing the start of the line, a DateTimePoint (DTPoint) representing the end of the line and a Color object.
The method is called modify, as it does both, the creation and the update processing of the TrendLine.
It simply checks if the TrendLine object passed via the parameter licTLObj is still null, which represents its initial value. If so, a TrendLine with constant properties is created first.
The DTPoint class is used to define a drawing object point based on a bar date/time stamp and a price value. Drawing objects positioned with a DTPoint will move along with the bars they are anchored to when the chart is scrolled.
Step 4: Main Program
In the final step of this indicator programming, we create the 'main program'. That is how I call the region that is processed on every bar's close or every tick.
As we have organized and encapsulated reusable parts of the coding already, this is a rather small part. Which in turn is a sign of proper code structuring.
First we make sure our initial preparatory method AnalysisTechnique_InitMain() is run at first. This is important, as it is preparing for the remainder of the processing.
Without it running first, the variables giPercentMultUp, giPercentMultLo, giTLColorUp, giTLColorLo are still in their initial values which would lead to false calculations and in the case of the giTLColorUp, giTLColorLo to runtime exceptions. Class objects that are null can't be used and trying to read or edit their properties is causing the program to raise an exception.
Putting it within the once statement makes sure it is only executed only once.
Next, we check if iRefPrice has changed compared to its prior value.
That is a performance measure and it saves the computer from processing the coding block within Begin/End when nothing is going the change in the price position of the lines.
If the price has changed, the new prices of the upper and lower range is calculated.
Having our variables giPercentMultUp and giPercentMultLo prepared already, it is a simple multiplication with the user input iRefPrice.
Having the prices of the upper and lower level of the range at hand, we call the method TrendLine TL_Modify for both the upper and the lower TrendLine variable.
We pass the respective Trendline object, two DTPoints starting from the current bar's DateTime plus the respective price and for the last parameter the respective color.
The returned TrendLine object is assigned back to gTLUpper/gTLLower. As already said, this is not necessary, since passing the object variable into the method is referenced. That means we do not pass a copy of the object but the object itself, every change of the object inside the method directly reflect on the original.
Here is an example of how the indicator looks like applied on a chart:
Consider if you really need to have it recalculated on every price tick. If it is sufficient to have the lines for the prior bars' Reference Price, than you want to uncheck "update value intra-bar" within in the 'General' tab of the 'Format Indicator' dialog.
Generally, having multiple indicators on multiple charts, processing on every tick is adding up substantially.
There is a wide variety of values that can be used for the input Reference Price.
Here is an incomplete list of possible inputs:
PrevClose¹ Close of the previous trading session (settlement price)
OpenSession(Autosession, 0) Open of the current session. Replace the 0 with the number of sessions ago to reference. E.g. 1 for the open of the prior session.
HighSession(Autosession, 0) High of the current session. Replace the 0 with the number of sessions ago to reference. E.g. 1 for the high of the prior session.
LowSession(Autosession, 0) Low of the current session. Replace the 0 with the number of sessions ago to reference. E.g. 1 for the low of the prior session.
CloseSession(Autosession, 0) Close of the current session. Replace the 0 with the number of sessions ago to reference. E.g. 1 for the close of the prior session.
¹Quote fields do not reference history. In Chart Analysis, they will only plot a value from the current bar forward.
Download the complete free code from our member area here.
Feel free to post your thoughts and questions in the comment section.