The Dynamic Market Lab The Dynamic Market Lab right border
Knowledge Base » Examples and Formulas » Loop Conversion 2

The previous example was easy because in step 4, the loop translated directly into a single indicator. Next we ask: What if the loop we want to convert does not logically represent an existing indicator? At first glance it may appear as though we are out of luck, but that is actually not the case!

To illustrate this, we will now convert the following EasyLanguage formula containing a loop:
Inputs: MP((H+L)/2);

{The output of CyclePeriod() doesn't matter for this example, it simply represents a period value that varies from bar-to-bar}

periods = CyclePeriod(MP, .18, .1, 1.1);

temp = 0;
For count = 0 to periods - 1 begin
temp = temp + count * (MP[count]);
End;

output = temp / (periods) * (periods+1) / 2;

Notice the difference here from the last example: the term inside the loop uses "count" instead of "(periods - count)".

Step 1.) Separate the loop into as many individual loops as possible, and convert each loop separately.

This loop cannot be separated further.

NOTE: It is often times helpful to include calculations outside of the loop (for example, the last line in the formula above) when trying to convert a loop. This last step is usually a division that calculates an average or something similar. As you saw in the last example, this can be very important for step 3, because it results in output that represents a common indicator. However, there will be other times when it will help to ignore any extra calculations after the loop. You may find it helpful to try it both ways.

Step 2.) If the loop uses a "varying" (non-constant) counter variable, replace it with a constant, preferably a small number, like 3 or 5 (here we use 4).

Inputs: MP((H+L)/2);

periods = 4;

temp = 0;
For count = 0 to periods - 1 begin
temp = temp + count * (MP[count]);
End;

output = temp / 10;

Step 3.) Create an equivelant function in Metastock for the static version of the loop (i.e., a loop with a constant counter).

By using algebraic substitution and stepping through the loop, we can see that this "static version" of the loop in Metastock can be computed as follows:
output := ( MP() + 2*Ref(MP(),-1) + 3*Ref(MP(),-2) + 4*Ref(MP(),-3) ) / (4+3+2+1);

Step 4.) Analyze the logical output of the formula and try to convert it into existing Metastock indicators.

In the last example, this step was fairly easy, but in most cases, it is the most difficult step. When the resulting formula does not represent an "end" indicator, like a WMA, you must think of clever ways to combine indicators to create a formula. This is usually best accomplished by trying to use low-level functions like the Sum() function, and Moving averages, and sometimes the Ref() function. Ultimately, we believe that the best way to accomplish this step is by analyzing this example and others as they will be posted in the future, as the knowledge base grows.

It may help to notice that this indicator could be described as a "Inverse" Weighted Moving Average, since the coefficients for the average (1,2,3,4) go in the reverse direction of a WMA (4,3,2,1). This may be helpful in determining that the formula DOES NOT match an existing indicator. By this we mean that neither Metastock nor ASI has an "Inverse" WMA function. However, it may or may not be helpful for you to think of the indicator in these logical terms when trying to create a solution using existing indicators. Sometimes it may be better to only think of the algebra and programming at hand, instead of what the indicators mean. We suggest that you experiment and use whatever technique comes naturally to you. Also, the steps we take and the end solution are not unique; there may be other ways of solving this problem.

For this example, which is one of the more difficult loop examples we could find, we came up with the following solution:

The goal in this stage is to use successive equalities to represent the static loop from step 3 in terms of existing Metastock Indicators.

We start with this formula we will call A1:
A1 := 5 * ExtFml("ASI.Sum",MP(),4);
Which is equivelant to A2:
A2 := 5*MP() + 5*Ref(MP(),-1) + 5*Ref(MP(),-2) + 5*Ref(MP(),-3);

Next, we have formula B1:
B1 := 10 * ExtFml("ASI.WMA",MP(),4);
which is equivelant to B2:
B2 := 10 * ( 4*MP() + 3*Ref(MP(),-1) + 2*Ref(MP(),-2) + Ref(MP(),-3) ) / (4+3+2+1);

Now if we subtract formula B2 from from A2 and divide the result by 10 (or 4+3+2+1), we get:
output := MP() + 2*Ref(MP(),-1) + 3*Ref(MP(),-2) + 4*(MP(),-3) / (4+3+2+1);

Notice that this result is an exact match to the formula from step 3!

Finally, if you subtract B1 from A1 and divide the result by 10, we get:
output := (5 * ExtFml("ASI.Sum",MP(),4) - 10 * ExtFml("ASI.WMA",MP(),4)) / 10;

This is the final solution to step 5, since we have expressed the solution in terms of existing indicators. This allows us to use adaptive inputs to these indicators (step 6) instead of the traditonal static ones.

Step 5.) Compare the output from Steps 3 and 4, and make sure they are equal.

We have shown here that results are logically the same, but you should always test the formulas in Metastock to assure that they are equivelant.

Step 6.) Finally, replace the calls to fixed-period Metastock indicators with calls to the ASI functions, and replace the fixed length with the original "variable loop counter" function.

{ periods should match the output of the CyclePeriod() function in the original EasyLanguage formula}
periods := ExtFml("ADSI.CyclePeriod", MP(), .18, .1, 1.1);
output := (ExtFml("ASI.Sum",MP(),periods) - (periods/2)*ExtFml("ASI.WMA",MP(),periods)) / (periods/2);