Tidbits - MetaStock Charting - Loops
If you use MetaStock as your chosen program to support your charting analysis, you may have
noticed that the MetaStock formula language is an array based language which has no loop
based commands like FOR/NEXT.  The way MetaStock overcomes this shortcoming is by
building functions (like MOV, SUM etc.) that can accept data arrays.  The upshot of this, is that
you can build loops within a single function, though you have very limited control over how that
loop executes within that function due to other limitations within the MetaStock function.  I shall
use the implementation of Dr Elder's SafeZone Stop for long/bought positions to illustrate.

From a calculation point of view we need to:
  1. Determine whether the stock price has reached a lower low than the previous day;
  2. If yes, calculate the penetration;
  3. Calculate an average (simple moving) down penetration based on the lookback period
    chosen and the number of times the price has reached a lower low than the previous day;
  4. Multiply this average by a factor of between 2-3
  5. Then calculate today's stop by deducting the (4) from yesterday's low.

To simplify coding, I shall use a lookback period go 15 days with a multiplication factor of 2.  
The challenge here is to perform task #3, where a nested loop is needed to:
  • Identify which days the current day low is less than the previous day's low; and
  • Perform a count on the days that this occurs, as the average is based on the number of
    days the downward penetration occurs and not the lookback period.

The following MetaStock code (as an indicator) almost works:

DnAvg:= Mov( if(L < ref(L,-1), ref(L,-1) - L, 0), 15, S); {Wouldn't it be nice - 1 loop}
MagAvg:= 2 * DnAvg;
BuyStop:= L - MagAvg;


By being able to insert IF statements into a function, a nested loop has been created in
MetaStock.  The problem with the above is that the MOV function in MetaStock, the periodicity
must be a constant, and thus the average is always calculated based on the lookback period
and not the number of times the event that is being measured (downward penetration) occurs.  
Without any loop commands, we need to generate 2 functions to do the nested loops, namely:

NumOfDn:= Sum(L < Ref(L, -1), 15); {Loop 1 - to count the number of times an event occurs}
SumofDn:= Sum(if(L < ref(L,-1), ref(L,-1) - L, 0), 15); {Loop 2 - do the sum of the event}
DnAvg:= SumOfDn / NumOfDn; {This is the limitation of doing loops the MetaStock way}

MagAvg:= 2 * DnAvg;
BuyStop:= L - MagAvg;


So there you have it, loops in MetaStock, most probably neater and more intuitive than a loop
language like TradeStation, just not as flexible or powerful.