Guide To Developing eSignal Strategies



Guide To Developing

eSignal Indicators

By Brad L. Matheny



Developed for:

Interactive Data Corp.

November 2002

Introduction….

Developing indicators within eSignal is one for 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 our 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. If the setDefaultBarFgColor statement is not placed within your code, the default color will be “Blue”, line width will be “1” and line type will be solid.

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 al well.

Available color types are…

white – RGB(0xFF, 0xFF, 0xFF)

black – RGB(0x00, 0x00, 0x00)

darkgrey – RGB(0x40, 0x40, 0x40)

grey – RGB(0x80, 0x80, 0x80)

lightgrey – RGB(0xC0, 0xC0, 0xC0)

navy – RGB(0x00, 0x00, 0x80)

blue – RGB(0x00, 0x00, 0xFF)

aqua – RGB(0x00, 0xDD, 0xDD)

cyan – RGB(0x00, 0xFF, 0xFF)

teal – RGB(0x40, 0x80, 0x80)

darkgreen – RGB(0x00, 0x40, 0x00)

green – RGB(0x00, 0x80, 0x00)

lime – RGB(0x00, 0xFF, 0x00)

olive – RGB(0x66, 0x66, 0x00)

khaki – RGB(0xCC, 0xCC, 0x00)

brown – RGB(0x80, 0x40, 0x40)

purple – RGB(0x99, 0x66, 0xCC)

red – RGB(0xFF, 0x00, 0x00)

magenta – RGB(0xFF, 0x00, 0xFF)

maroon – RGB(0x80, 0x00, 0x00)

fuschia – RGB(0xF, 0x00, 0xFF)

yellow – RGB(0xFF, 0xFF, 0x00)

lightyellow – RGB(0xFF, 0xFF, 0x40)

paleyellow – RGB(0xFF, 0xFF, 0x80)

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. The reason you would choose to use these functions are to draw “extreme” level indicators for your indicator – like the 80/20 lines for Stochastics or RSI.

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 what 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 the 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 their 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.

Developers can also create an EFS file that returns NOTHING to the chart. In this case, developers would simply place a single return statement at the end of their code.

return;

Developing Your First Custom Indicator….

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

Our example 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).

I propose developing our indicator to track the difference between two (user-defined) moving averages. I know 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 our 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

2. 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 our 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 I’m 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.

var study1 = null;

var study2 = null;

function main(vLength, vFactor) {

if (vLength == null) {

vLength = 7;

}

if (vFactor == null) {

vFactor = 3;

}

// create the MA studies for our indicator

if (study1 == null) {

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

}

if (study2 == null) {

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.

In the example above, we are using the built-in study, MAStudy, to return the value of a moving average of the price action. Within eSignal, you have the ability to deploy and use a multitude of built-in indicator functions within your code. Below is a list of available built-in functions…

AccDistStudy()

 

ADXDMStudy(Length)

 

ATRStudy(Length)

 

BollingerStudy(Length, PriceSource, StandardDeviation)

 

CCIStudy(Length, PriceSource)

 

ChopStudy(Length)

 

DonchianStudy(Length, Offset)

 

EnvelopeStudy(Length, Offset, PriceSource, Exponential, EnvelopePercent)

 

LinearRegressionStudy(PriceSource, NumBars, StandardDeviation)

 

MAStudy(Length, Offset, PriceSource, MovingAverageType)

 

MACDStudy(FastLength, SlowLength, SignalSmoothing, PriceSource, SimpleMA)

 

MoneyFlowStudy(Length)

 

MOMStudy(Length, PriceSource)

 

OBVStudy()

 

OscStudy(FastLength, SlowLength, PriceSource, Exponential)

 

ParabolicStudy(Start, Increment, Max)

 

PercentRStudy(Length)

 

ROCStudy(Length, PriceSource)

 

RSIStudy(Length, PriceSource)

 

StochStudy(%Klength, %Ksmoothing, %Dlength)

 

JurikDMXStudy(Length)

 

JurikJMAStudy(Smooth, Phase, Offset, PriceSource)

 

JurikRSXStudy(Length, PriceSource)

 

JurikVELStudy(Length, PriceSource)

Now, let’s get into some more advanced topics – like…

• 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);

}

var study1 = null;

var study2 = null;

function main(vLength, vFactor) {

if (vLength == null) {

vLength = 7;

}

if (vFactor == null) {

vFactor = 3;

}

// create the MA studies for our indicator

if (study1 == null) {

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

}

if (study2 == null) {

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, vMA1m, 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.

The EFS file above used global variables (study1 and study2), declared outside the main function, to control the Moving Average studies. Within the main function, vMA1 and vMA2 are declared as local variables.

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.

So, 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 I can offer 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() < high(-1)){

// 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 () > low (-1)){

// Pivot low Pattern

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

// 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);

}

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download