## Популярные книги

# Chapter 3 Building a Nest

You have seen what to do when there are two possible outcomes, but what happens if you have

three or more choices to decide between? The If() function can only examine a condition and

return one of two results. However, the result returned is a data array. It does not have to be a

single number. It could be a function, an equation, or another If(). Consider the following

format:

IF ( condition 1 , Result A, IF ( condition 2, Result B,

Result C) )

If condition 1 is true, Result A is used. However, if condition 1 is false, condition 2 is then

examined and a choice made between Result B and Result C.

Put in everyday terms, suppose you are at a snack bar in a movie theater. You would really like

the large chocolate bar. Unfortunately, it costs five dollars and you are not sure you have that

much. Before you look in your wallet, you also notice the theater sells jelly beans and roasted

peanuts. Both of these are the same price and only cost three dollars. Your decision on what to

buy can be written as:

IF ( I have five dollars or more, buy chocolate bar, IF ( I

want something crunchy, buy peanuts, buy jelly beans ) )

This format of putting one If() function inside another If() is called nesting. Any place a formula

or function calls for a data array, you can place an If(). You can also put an If() function inside

an If()that is already inside another If(). This can get kind of confusing. The most common

result is to forget how many If()s have been used and not put enough closing parentheses.

MetaStock will give you a warning that it is missing one, but will not know where it is suppose

to go. Try using the following format:

If ( condition 1,

result A,

If ( condition 2,

result B,

result C

),

)

This is a method of organizing If()s that is borrowed from several computer programming

languages. The If() and its condition are given on one line. The two possible results are

indented by several spaces on the lines below. The closing parenthesis is put directly under the

If() on a line below the last result. When a result is another If(), the entire function is written the

same but indented several spaces further.

Obviously you do not need to do this with simple If() formulas, but the example above is given

below without any of the extra spaces.

If ( condition 1, result A, If ( condition 2, result B,

result C ) )

Which of these would you rather work with? Before you answer, remember that an actual

formula will have functions and mathematical comparisons instead of the words “condition” and

“result.” In a MetaStock formula; spaces and extra lines do not affect how a formula is

calculated. They do, however, make your formula easier to read.

Exercise 11:

Before you start to think all of this discussion on nested If()s is confusing and of no practical use,

suppose you wanted a formula to let you know when a security’s price rises ten percent or more

in 5 periods, but only if the security is above its 13-period simple moving average. To make

things more interesting, instead of plotting a 1 and a 0, plot the actual rate of change when this

condition is true and a 0 when it isn’t. Write a formula to do this and name it ROC Wave. Look

at formula 18 for the answer.

Formula 18:

Formula 18 in English

If the close is greater than a 13-period simple moving

average, and if the 5-period rate-of-change is greater than

or equal to 10, then plot the 5-period rate-of-change,

otherwise plot a 0

Formula 18 is written in the expanded format referred to earlier. It could also be written as:

If( C > Mov( C, 13, S), If( ROC( C, 5, %) >= 10, ROC( C,

5, %), 0),0)

When displaying formulas with nested If()s, this document will use the expanded version for

ease of reading. When writing your own formulas, use whichever version you prefer. If you

have a hard time finding and correcting some errors in your formula, try expanding it. The only

place MetaStock does not allow you to add a space or an extra line is between a function’s name

and its opening parenthesis. Everywhere else, add as much space as you need to make the

formula easy for you to read.

Functions get into the nest

Just like If()s can be nested, other functions can also be nested. Most functions require a data

array as part of their parameters. Instead of putting one of the price fields or a number, you can

insert another function. Consider the following.

Exercise 12:

A stock you are following is changing prices erratically. It will gain a few points one day and

drop some the next. The exact amount of each day’s move varies. Before investing your money,

you would like to get a feel for how much it is likely to move in one day. This might be

accomplished by a moving average of a 1-day price change. Write a formula to do this and name

it Average Price Change. Use a 20-period simple moving average and points for the rate of

change. Look at Formula 19 for the answer.

Formula 19:

Formula 19 in English

A 20-period simple moving average of a 1 day rate-ofchange

The ROC() function is simply inserted in the Mov() function where a data array was asked for.

This can be applied to any function that accepts a data array.

To understand how this is possible, go back to the definition of a data array. It was defined as a

series of values. Examples were given of the different price fields. A data array can also be

defined as a constant. When a data array location is given a fixed number, all calculations of the

formula use that number. The number does not change and so it is called a constant. You have

already used constants. While writing the If()s in chapter 2, the results were either 1 or 0. These

numbers are constants.

A data array is also the result of any function’s calculation. A moving average returns a series of

numbers that is plotted by MetaStock. Those numbers are a data array. The same is true for the

Rate of Change and every other function in MetaStock’s formula language. Each one returns a

numerical value for each period it is calculated. Those values make an array of data the can be

plotted in a chart or used as part of a larger calculation. Here is another exercise that

demonstrates this concept:

Exercise 13:

Back in chapter 1 when functions were first introduced, the MACD() function was mentioned.

Here is the full command:

MACD

SYNTAX macd()

FUNCTION Calculates the predefined MACD indicator.

EXAMPLE The formula "macd()" returns the value of

the MACD indicator (i.e., the solid line).

As you can see, this is just the solid line part of the MACD indicator. The dotted signal line that

appears when this indicator is plotted in MetaStock is not given by this function. That requires a

separate formula. The dotted line is actually a 9-period exponential moving average of the

MACD. How would you calculate this line in an indicator? Write a formula to do this and name

it MACD Signal Line. Look at formula 20 for the answer.

Formula 20:

Formula 20 in English

A 9-period exponential moving average of the MACD

Functional IFs

Just like If()s can use other If()s and functions for their data arrays, functions can use other

functions and If()s. An If() returns a data array of values. The only difference is that the If()’s

array is dependent on a conditional clause. The resulting value can be used any place a function

calls for a data array.

Exercise 14:

Consider formula 19, Average Price Change. Suppose you wanted to vary the ROC() function

based on the RSI. When the 14-period RSI is getting near its overbought and oversold regions,

the rate of price change might be far more important than when the RSI is in its mid-ranges.

Taking such a premise as truth, you might wish to use a 1-period rate of change in the

overbought and oversold ranges and a 3 period rate of change elsewhere. Write a formula to do

this and name it Variable ROC Average. Use the same 20-period moving average and treat

values above 70 and below 30 as the overbought and oversold ranges. Look at Formula 21 for

the answer.

Formula 21:

Formula 21 in English

A 20-period simple moving average of the function: if the

14-period RSI is greater than 70 or the 14-period RSI is

less than 30, plot a 1-period rate of change, otherwise plot a

3-period rate of change

The If() condition here looks for any RSI value in the overbought or oversold range. This

formula could have been written differently. The If() could have been turned around to read:

If (((RSI(14)<=70) AND ( RSI(14)>=30)),

ROC(C, 3, $),

ROC(C, 1, $)

)

Now the If() looks for no overbought and oversold ranges. The result is the same even if the

values have been switched. Notice however, that the equals sign was added to the second

version of the If(). The conditions of the formula said that values above 70 and below 30 were

overbought and oversold. This means that 70 and 30 are not themselves overbought or oversold.

Thus the second version had to include the values of 70 and 30 as possible true conditions.

To put this in a real life condition, picture yourself walking down a street around Christmas time.

You know you still need to get one more present and it will cost you exactly five dollars,

including tax. On the corner ahead of you is a Santa ringing a bell for donations to the Salvation

Army. Being a charitable soul you want to donate some money, but you must save the five

dollars. Written as an If() statement, this situation could read:

IF ( money > $5, donate some, do not donate)

or it could be written:

IF ( money <= $5, do not donate, donate some)

Both are correct. They just look at the problem from different directions.

I can't believe it ate the whole thing

You have seen how functions and If()s can be nested but nesting can also include embedding a

whole indicator. Back in chapter 1, you created the indicator Daily Range. This indicator can be

referenced in other formulas through the Fml() function

Formula Call

SYNTAX fml("FORMULA_NAME" )

FUNCTION Calculates the value of another formula.

The formula can be referenced using the

FORMULA_NAME in quotes.

When referencing a formula's name, the

name must be contained in quotation marks

(e.g., fml( "Secret A")).

If you change a formula's name, you must

also change any fml() calls that reference

that formula.

EXAMPLE The formula "fml("Secret A") *

fml("MyMACD")" calculates the value of

the formula named "Secret A" multiplied by

"MyMACD."

When using this function, it is absolutely necessary to spell the name of the indicator the same as

it is spelled in the indicator builder. MetaStock is extremely picky about this and even an extra

space can cause problems. As a result, it is highly recommended to use the Functions button in

the indicator builder when inserting a Fml() function. If you have never used this feature before,

please do the following steps to see how it is done.

1) Go to the indicator builder and start a new indicator

2) After typing in the name, click in the large formula window

3) With the cursor blinking in the formula window, the Functions button in the bottom right

corner is enabled

4) Click the Functions button

5) On the left hand side, click on Custom indicators

6) The right hand side now contains a list of all your custom indicators. Double-click on one to

insert it into the new formula

The Paste Functions dialog should have closed and the selected function is now included in an

Fml() function in the formula window.

Exercise 15:

Application of this is as easy as any other indicator, apart from all the trouble of entering the

function. Assume you wanted an indicator to tell you when the daily range grew wider than 1.

Write a formula to do this and name it Wide Range. Use an If() and the Daily Range indicator to

write such a formula. Look in formula 22 for the answer.

Formula 22:

Formula 22 in English

If the result of the formula “Daily Range” is greater than 1,

plot a 1, otherwise plot a 0

Use Them Anywhere

The Fml() function is just like any other function and returns a data array. This value can be

used in any other function that accepts a data array. The Fml() can be combined in If()s as

shown above or referenced in other functions.

Using this function, you can create what programmers call subroutines. Subroutines are part of a

larger formula that is separated from the rest. This might be done if the overall formula is

extremely long or complex. A subroutine is also used if a section of a formula uses the same

mathematical expressions several times.

In MetaStock, each subroutine, or sub-formula, is written as a separate indicator. These are then

combined into a single indicator which functions as if the entire formula had been written in it

instead of multiple sub formulas.

The Fml() function is also used in the other formula based tools of MetaStock. By calling a

custom indicator, you do not have to retype the formula each time you wish to use it. This can

save a lot of time and allows you to change the formula in one place and not have to chase down

all the other places where you used it to keep things consistent.

Don’t go in Circles

A Fml() function allows your formula to reference another formula. True to the nesting

philosophy, the formula can reference another formula. This can continue building a deeper and

deeper nest. However, any formula in this nest cannot reference an earlier formula. Thus if

formula A referenced formula B; formula B cannot reference formula A.

The reason this cannot be done is dictated by how MetaStock calculates the formulas. Using the

formulas A and B mentioned above, here is how MetaStock would attempt to evaluate them.

When you plot formula A in a chart, MetaStock looks at the formula and begins to run all he

calculations. When it gets to the reference to formula B, it stops formula A’s calculations and

starts calculating formula B. If it then read a reference to formula A, it stops calculating formula

B and starts calculation formula A from the beginning.

As you can see, MetaStock is now going in circles. In traditional programming languages, this

would be called and endless loop. MetaStock, however, can detect when such a loop starts and

will stop calculating the indicator. It will then display an error that it has detected a circular

reference. The only way to resolve this is to write the formula to not reference itself.

Another drawback to the Fml() function is that sub-formulas take longer to calculate. Reading

the additional formulas as they are called slows down MetaStock’s calculations. The more subformulas

referenced the greater the slow down. Please also be aware that faster computers with

large amounts of memory may not be noticeably affected.

Try playing with different ways to nest functions. Go through the review questions and re-read

any parts of this chapter you did not understand. Nesting functions and If()s is a major part of

more advanced MetaStock formulas. From this point on, nesting functions and / or If()s will be

required. If you are ever confused by any of this, please refer back to this chapter.

Review Questions

1. Which of the following can be put in a formula where a data array is required:

a) MACD()

b) C

c) any If() function

d) 10

2. What is wrong with the following custom indicators:

formula 1

Mov( C, 9, E) + Fml(“formula 2”)

formula 2

(H - L) * Fml(“formula 1”)

3. True or False, there is no reason not to nest formulas using the Fml() function.

4. What is the recommended way of entering formula names in the Fml() function?

5. True or False, any function can be nested in any other function.