Guide to Developing EFS Indicators

ICE Data Services -

Guide to Developing eSignal Indicators

 

Developing indicators within eSignal is one of the first steps to developing your own custom trading system.eSignal indicators are designed to plot and return values to the chart as
well as the cursor window.Indicators can return information to the price chart or a new indicator pane (a new window) � but not both at the same time.

 

There are relatively few tricks to creating custom indicators within eSignal.This guide will
walk you through the basics and even teach you some more advanced topics.

 

Indicator Basics

 

All eSignal EFS files step through the chart (from oldest bar to newest bar � or left to right)
and executes your code.� The code (or eSignal Formula Script � EFS) is a set of instructions that are executed in order (top to bottom).�

 

Within the EFS code, developers control variables, conditions and execute any functions necessary with a series of simple commands.The structure of these commands and of the
order of the commands is critical to the accuracy and execution of your proposed systems.

 

Let�s begin by learning some of the EFS components�

 

Components of the eSignal EFS File.

 

preMain()

 

preMain() is a required function of all EFS files.It acts as a �Setup� routine for your code.Within preMain(), you should include the necessary code to accomplish the following for your custom indicator.

 

Set The Study Title:

 

setStudyTitle("Your Indicator Title");

 

You should include the setStudyTitle in all of your EFS files.This statement plots the title
text onto the chart or indicator pane.If you don�t want any text to be displayed, simply comment out this line by placing �//� at the beginning of the statement.

 


Set The Cursor Window Title:

 

setCursorLabelName("Indicator Value 1");

 

You will also need to define the label for the �returned� value of your indicator.� If your indicator returns more than
one value, you will need to add multiple setCursorLabelName statements in your preMain().For each value your
indicator returns, you will need to add a definition to the setCursorLabelName statement (�0� for the first, �1� for
the second and so on.� An example is below.

 

setCursorLabelName("Value1", 0);

setCursorLabelName("Value2", 1);

 

The two statements above define �Cursor Window Labels� for two values that are returned by our EFS file.So,
when your EFS indicator returns the values, the first value will be displayed in Value1 and the second in Value2.
If our indicator only returns one value, then the second line (or any other label definition) is ignored.

 

Set The Label/Indicator Color:

 

setDefaultBarFgColor(Color.red);

 

An optional statement, setDefaultBarFgColor, allows developers to control the color of the indicator and the color
of the label in the cursor window.This statement is optional, so it does not need to be included within your code,
but it often helps to color code the returned values of the indicator.

 

Just like with the setCursorLabelName statement, the setDefaultBarFgColor statement should be defined for any
returned label name statements.Thus, if you have two setCursorLabelName statements in your code, you should
have two setDefaultBarFgColor statements as well.

 

Available color types are�

 

Color.red

Color.blue

Color.green

Color.yellow

Color�..

 

Multiple color statements are also defined by adding the corresponding label order number to the end of the
statement � just like with the setCursorLabelName statement.�
An example is below�

 

setDefaultBarFgColor(Color.red, 0);

setDefaultBarFgColor(Color.blue, 1);

 

 

 

 

Set The Indicator Min/Max values:

 

setStudyMin(-10);

setStudyMax(10);

 

The setStudyMin and setStudyMax statements allow you to define the absolute minimum and maximum levels
of your custom indicator.If you do not know what the minimum and maximum values of your indicator are, then
simply omit these statements from your preMain().eSignal will automatically scale your indicator within the
maximum and minimum range of your indicator.

 

To use the setStudyMin and setStudyMax statements, simply add the statements to the preMain() function and
declare the values for the MINIMUM and MAXIMUM of your custom indicator.

 

Using the addBand function:

 

addBand(30, PS_SOLID, 1, Color.RGB(0,0,0));

addBand(70, PS_SOLID, 1, Color.RGB(0,0,0));

 

The addBand function allows developers to place horizontal bands on the indicator pane.For example, if you
were to develop an indicator that ranged from zero to one hundred in value, you might want to place bands at
20 and 80 � as extreme boundaries.

 

Adding bands is as simple as adding a new statement for each band you wish to include in your indicator.
When placing an addBand statement into your preMain() function, remember to change the first variable to the
value you want the band to appear at in the indicator pane.

 

addBand(Band Level, Line Type, Line Width, Color);

 

In this instance, we would want to add two band statements (at our 20 and 80 levels) and probably start out
with them both in black.� The code would look as follows�

 

addBand(20, PS_SOLID, 1, Color.RGB(0,0,0));

addBand(80, PS_SOLID, 1, Color.RGB(0,0,0));

 

Notice: Color.RGB(0,0,0) is just another way of saying Color.black.With all color statements, developers can
replace the default color definitions with user-defined color codes by using the Color.RGB(Red, Green, Blue)
option.� With this optional color definition, developers are required to use individual color values that represent
the colors for Red, Green and Blue.Different combinations can produce a wide variety of color hues.


Using setPriceStudy:

 

SetPriceStudy(true);

 

The use of setPriceStudy() determines if your indicator will plot ON the price chart or within the indicator pane.
If your indicator is designed to plot on the price chart, then developers MUST include setPriceStudy(true) in
the preMain() function. �If your indicator is designed to plot in an indicator pane, then developers MUST omit
the setPriceStudy() statement from the preMain() function.

 

main()

 

main() is a required function of all EFS files.This function is the �main� routine for your code. �Developers will
write code within the main() function to calculate and execute the indicator/strategy/graphics or other actions.
Within main(), you should include the necessary code to accomplish whatever tasks are necessary to calculate
and plot your custom indicator.

 

Notice:� Additional sub-functions are available to the developers to better define code segments and to develop
modular application.

 

Returning the Indicator values:

 

Return (Value);

return new Array (Value1, Value2,�);

 

Your custom indicators MUST return at least one value � otherwise, the indicator will not plot on the chart or
indicator pane.� The return function allows developers to define which values are returned from the main()
function to the chart.

 

To return a single value, developers must include a single return statement at the end of the main() function�

 

Return value1;

 

To return multiple values from your code, developer must include a single return statement that returns an array
of values at the end of their main() function�

 

return new Array (value1, value2, value3,�);

 

Notice:Any value returned by the Return statement will be plotted on the chart or on the indicator pane.Thus, developers may need to separate individual functions of their indicators into multiple EFS files in order to
properly display the information on the chart or indicator pane.

Developing Your First Custom Indicator�.

 

The first step in developing a custom indicator is to attempt to define what type of indicator you are going to
try to develop.� For this example, we�ll start with a velocity indicator.

 

Our example of a velocity indicator will attempt to monitor the market�s ability to accelerate in bullish and
bearish modes.� The first indicator we�ll develop will be designed to only return positive values (numbers greater
than or equal to zero).

 

Let�s propose developing our indicator to track the difference between two (user-defined) moving averages.�
Some of you may consider this �not really a velocity indicator�, but this is a good place to start for people
learning to develop new indicators.

 

Developing the preMain() Function:

 

The first process of developing a new indicator is to answer some basic questions�

 

  1. Will our indicator plot on the price chart or on an indicator pane?

Answer: On the Indicator Pane

  1. Do we know the range of the values that will be returned by our indicator?

Answer: No. We have no idea as of yet.

 

So, now we know what needs to be in the preMain() function.All we need is the study
title and the cursor window label name.An example of our preMain() function for our
indicator is�

 

function preMain() {

����� setStudyTitle("Velocity");

����� setCursorLabelName("Velocity");

}

 

We don�t need to add anything else at the moment, because we don�t know how our new indicator will react.All we need to do is add labels to our code to assist us in identifying
our code.

 

Developing the main() function:

 

Developing the main() function is a little more difficult, but it is still rather simple to
understand.The first thing we need to do is determine what user-defined variables we
need for our function.The variables we�re going to define for our indicator are�

 

VLength=� the length of our initial short-term Moving Average.

VFactor=� the multiplier of vLength to be used to calculate our long-term Moving
Average.

 

Defining a user-input is simple, but we also need to check the input value for an
erroneous value or missing value immediately after the main() function starts.So our
first main() code might look like�.


 

function main(vLength, vFactor) {

�� if (vLength == null) {

���� vLength = 7;

�� }

�� if (vFactor == null) {

���� vFactor = 3;

�� }

 

return;

}

 

For every user-input, we need to check for a �null� input, or missing initial value, then define the initial values
(if necessary).� You can see from the examples (above), that creating the user-input is as simple as adding them
between the �()� of the main() function (separated by commas).For every user-input, you also need to add the
code to check and verify the value of the input.

 

So, at this point, we have begun to create our custom indicator, but it will do nothing yet � we have not
developed the code to calculate, test and return the indicator values.Let�s get started.

 

The process of our proposed velocity indicator is to calculate a short-term moving average � based on a user
input, then calculate a second moving average based on a factor of the first moving average � this also will be
a user input.Then, we�ll calculate the difference between the short-term moving average and the long-term
moving average.This will give us a relevant indicator for trend direction and strength.

 

function main(vLength, vFactor) {

�� if (vLength == null) {

���� vLength = 7;

�� }

�� if (vFactor == null) {

���� vFactor = 3;

�� }

 

// create the MA studies for our indicator

��var study1 = new MAStudy(vLength, 0, "Close", MAStudy.WEIGHTED);

��var study2 = new MAStudy(vLength * vFactor, 0, "Close", MAStudy.WEIGHTED);

 

//� Get the values of the Moving Average studies����

��� var vMA1 = study1.getValue(MAStudy.MA);

��� var vMA2 = study2.getValue(MAStudy.MA);

 

//� Test our variables for null values/returns.

//� If vMA1 or vMA2 = null, then RETURN (nothing)

// �||� is a Boolean �OR� statement

����� if((vMA1 == null) || (vMA2 == null))�

����� ����� return;

 

// Return the short-term average � the long-term average.

�� return (vMA1 - vMA2);

}

That�s it.You�ve just created your first indicator.It is not as difficult as you might think � is it?

 

Now, let�s get into some more advanced topics, such as

 

  • Returning arrays of variables to the cursor window
  • Using price variables
  • Returning text variables to the cursor window
  • Returning price action to the cursor window

 

All of these are easily addressed by changing just a few lines of our code.Let�s start
with �How to return an array of variables�.First, what is an �Array�?It is simply a list of variables that you want to return to the cursor window.� The only thing a developer needs
to do to return an Array of variables is change the RETURN line and address the new
variables in the preMain() function.Let�s look at an example (below)�

 

function preMain() {

����� setStudyTitle("Velocity");

// Define the returned value labels in the cursor window

����� setCursorLabelName("Velocity",0);

����� setCursorLabelName("MA1",1);

����� setCursorLabelName("MA2",2);

// Set colors for the returned values in the cursor window

����� setDefaultBarFgColor(Color.blue,0);

����� setDefaultBarFgColor(Color.red,1);

����� setDefaultBarFgColor(Color.red,2);

}

 

function main(vLength, vFactor) {

�� if (vLength == null) {

���� vLength = 7;

�� }

�� if (vFactor == null) {

���� vFactor = 3;

�� }

 

// create the MA studies for our indicator

var study1 = new MAStudy(vLength, 0, "Close", MAStudy.WEIGHTED);

var study2 = new MAStudy(vLength * vFactor, 0, "Close", MAStudy.WEIGHTED);

 

//� Get the values of the Moving Average studies����

��� var vMA1 = study1.getValue(MAStudy.MA);

��� var vMA2 = study2.getValue(MAStudy.MA);

 

//� Test our variables for null values/returns.

//� If vMA1 or vMA2 = null, then RETURN (nothing)

// �||� is a Boolean �OR� statement

����� if((vMA1 == null) || (vMA2 == null))�

����� ����� return;

 

// Return the ARRAY of variables to the cursor window.

�� return new Array(vMA1 - vMA2, vMA1, vMA2);

}


 

The Difference between �Global� Variables and �Local� Variables

 

As we begin to develop more and more complex indicators and trading systems, it will become important to
know the difference between a �Local� variable and a �Global� variable � and where/why you want to use them.
As developers, we want to develop our indicators based on logical progressions or mathematic calculations.�
Either way, we may need to include some variables that stay active throughout the entire instance of our code
and still other variables that are only temporary.This is the primary difference between �Global� (variables that
stay active throughout the entire use of your code) and �Local� (variables that are created, used and destroyed
within a specific function) variables.

 

The difference in variable �life� is called �Scope�.� Scope should be understood as �the lifetime of your declared variable�.Local variables have �limited scope� � only for use within the function they are declared.Global
variables have �unlimited scope� � they can be used/modified anywhere within your code.

 

Global variables�.

������ �.� Are declared outside the main() and preMain() functions

������ �.� Are available within any portion of your code

������ �.� Can be manipulated by other functions within your code.

������ �.� Carry previous values to the next instance of your code.

 

Local variables�.

������ �.� Are declares within the main() or other function

������ �.� Are only available within the function they are declared.

������ �.� Are only available for use AFTER being declared.

 

If you are trying to declare a new �temporary� variable for use within your code, you would want to declare it
within your function (above your use of the variable).

 

If you are trying to declare a new �global� variable (one that will be used to control global logic within your
code or one that needs to continue through the entire scope of your code), then you would want to declare it
above your main() function.

 

Here is an example of the variable declarations.� Notice the global variables are declared outside the main()
function.

 

function preMain() {

��

}

 

var NewGlobalVariable;

 

 

function main() {

��

 

var NewLocalVariable;

 

return;

}

 

Creating Additional Functions To Handle Specific Tasks

 

As we begin to develop more and more complex indicators and trading systems, it will become necessary to
develop unique functions within your code to accomplish specific tasks.The reasons why you would want
to create a new function to complete a certain tasks might include�.

 

1.      Functions simplify your code by creating a single source code (function) that can be called
throughout your program.

2.      Functions allow you to segment your code into easily to understand �groups of orders� and make
it easier to debug problems.

 

Some things you might look for in your code that indicates you should start using functions�.

 

1.      Your code uses the same code segment over and over again (throughout different sections of
your code).These �repeat� code segment can be simplified into a function.

2.      Similar tasks can be grouped into a single function.� Simply by passing your new function a
�parameter�, your function can accomplish multiple tasks.

3.      Most graphic calls can be grouped into a single function.

4.      Most trading system logic can be grouped into a single function.

 

Rules For Creating Additional Functions

 

1.      New functions should always be created �before� the preMain() and main() functions � at the
top of your EFS file.

2.      New functions should be given a unique name.

3.      Function �Parameters� should be handled just like �User-Inputs� � checking for null entries.

 

Here is an example of an additional function declared within an EFS file�

 

function rnd(value) {

//� Rounds a price value to two decimal places

�� value *= 100;

�� return Math.round(value,2) / 100;

}

 

function preMain() {

��

}

 

function main() {

��

return rnd(close());;

}

 

 

 

 

 

 

Using Price Values in your EFS code.

 

You�re probably asking �how do we address price variables in our code� (for use with price patterns, indicator
patterns and buy/sell signal patterns).Well, here we go�� Let�s learn about how to compare and use price
values in an EFS file.

 

All price variables are easily accessible in any EFS by simply using �

 

����� open()

����� high()

����� low()

����� close()

 

These automatic variables return the current bar�s price action.Remember, the current bar changes from oldest
to newest as the EFS is running through your chart.� To access older bar information, developers simply add a
numeric parameter to designate how many bars in the past to offset the price variable (-1 = one bar in the past,
-3 = three bars in the past).

 

����� open(-1)= the open of the previous bar.

����� high(-1)= the high of the previous bar.

����� low(-1)= the low of the previous bar.

����� close(-1)= the close of the previous bar.

 

Using this information to create a price pattern is simple.We would create a compound �if� statement using
�Boolean� operators (such as �&&� (AND) and �||� (OR)).The best advice that can offered about complex �if� statements and Booleans is �Always use parenthesis to separate or join your complex conditions�.

 

An example of these types of statements would be�

 

if (high() == high(-1)) {

// Japanese Candlestick Tweezers Tops

//� This pattern occurs when two bars have the same HIGH price.

Do something

}

 

if ((high(-2) < high(-1)) && (high(-1) < high()){

// Pivot High Pattern

//� This pattern occurs when a single bar forms with a higher high

//� than the previous and subsequent bar.

Do something

}

 

if ((low(-2) > low (-1)) && (low (-1) > low ()){

// Pivot low Pattern

//� This pattern occurs when a single bar forms with a lower low

//� than the previous and subsequent bar.

Do something

}

 

 

 

 

 

Using debugPrintln to debug your EFS code.

 

Now that we�ve shown you how to begin creating your own indicator (which will help lead you to create your
own trading system), it might be wise to show you how to debug errors in your code.� ESignal provides a couple
of tools for you to debug your code and coding logic.There are really three types of errors that you may
experience when trying to develop EFS code�

 

1.      Syntax Errors -Syntax Errors are errors in the coding language � very similar to grammatical errors
in a letter or spelling errors.These normally occur when a user mis-spells a function or uses an incorrect
function parameter.Other instances where a syntax error may occur is with �Case Sensitivity�.EFS code
is VERY case sensitive.

2.      Logic Errors � These types of errors are normally user created where the code is instructing
something to change/happen � when it should not.For example, let�s say we create code to do something
if the price is above a moving average variable (close() > vMA).If we make a mistake and reverse the
�greater than� sign or make it �greater than or equal to�, then our logic is messed up and our code will
not operate effectively.� The �syntax checker� within eSignal will not identify these errors, so the user
must attempt to identify these problems.

3.      Assignment Errors � These types of errors normally happen in the �use of� and �conditional
statements� including variables.� One problem that is common is the mixing of �=� and �==�.The single
�equal� sign (�=�) is used to assign a variable a value.The double �equal� sign (�==�) is used to test the condition of a variable value.Often, developers will mix-up the use of these operators, resulting is
ineffective code.� Also, these errors are not identified as errors of �syntax�, so it is up to the user to identify/resolve these errors.

 

ESignal does provide a �syntax checker� that will check your code for grammatical errors and some spelling
errors.Simply click on the �Check mark� button within the editor and your code will be verified for syntax
errors.Any potential problems will be presented in the �Output Window�.� To view the output window, simply
click on the TOOLS menu, then click on OUTPUT WINDOW.

 

ESignal also provides users with the ability to write information into the output window for debug and system
reporting abilities.This function is called debugPrintln().Users can place any information necessary into the debugPrintln statement � variables, text, date/time.Developers should place the debugPrintln statement into
portions of the code they believe are not operating properly to assist in debugging the code.

 

Examples�

 

DebugPrintln(�Sample text : �+close()+� : �+variable);

 

DebugPrintln(variable1+� : �+variable2+� : �+variable3);

 


 

Example Code : Matheny Enterprises (Velocity Indicator)

 

/**********************************************************************
Copyright � Matheny Enterprises 2002. All rights reserved.

**********************************************************************/

 

function preMain() {

����� setStudyTitle("Ment Velocity");

����� setCursorLabelName("Ment Velocity");

}

 

function main(vLength, vFactor, vSTDLength) {

�� if (vLength == null) {

���� vLength = 7;

�� }

�� if (vFactor == null) {

���� vFactor = 3;

�� }

�� if (vSTDLength == null) {

���� vSTDLength = 11;

�� }

 

// create the MA studies.

��var study1 = new MAStudy(vLength, 0, "Close", MAStudy.WEIGHTED);

��var study2 = new MAStudy(vLength * vFactor, 0, "Close", MAStudy.WEIGHTED);

 

//� Get the values of the MA studies����

��� var vMA1 = study1.getValue(MAStudy.MA);

����� var vMA2 = study2.getValue(MAStudy.MA);

 

//� Test for null returns.

����� if((vMA1 == null) || (vMA2 == null))

����� ����� return;

 

 

�� return (vMA1 - vMA2);

}

Indicator Building Tips�.

 

�          Remember to use the setCursorLabelName() in the preMain() to identify your
returned variables.

�          Remember to use the setDefaultBarFgColor() to color each returned value.This helps developer to identify conditions as they change within your indicator.

�          Remember to use the setPriceStudy(true) if your indicator will return/plot values on
the price chart and not on a separate indicator pane.

�          Remember to test all user-inputs for �null� parameters before attempting to execute your EFS
code.

�          Remember to create a user input for setComputeOnClose() within your indicator.This
allows you to quickly and easily change the indicator to/from real-time mode.

�          Remember to create all indicator �logic� variables as Global Variables.These variables need
to be global as they will be manipulated by your code and control the logic of your indicator as it
progresses.

�          Remember to create all indicator �temporary� variables as Local Variables.These are variables
that will created, used by your code, then dumped.

�          Remember to create the proper return statement for your indicator

 

 

Coding examples:

 

Testing for the current bar�

 

If (getCurrentBarIndex() == 0) {

�� //Do something

}

 

Testing for a new bar formation (using the �time� of the bar)�

 

//�First, declare a global variable to keep track of the last �time� of the previous bar(s).

var nLastRawTime;

 

If (getvalue(�rawtime�,0) != nLastRawTime) {

�� //New Bar � so do something

 

nLastRawTime = getvalue(�rawtime�,0);

}

 

 

 

 

 

 

 

 

Written by Brad L. Matheny for eSignal, A division of Interactive Data Corporation, November 2002.