A one-function version of the A/D Oscillator:
Let us look at Larry Williams' Oscillator, the A/D Oscillator.
One could write it in Perl Fast Mode as
sub ComputeADOscillator1 {
my($v,$w,$range,$alpha,$i,$n);
$alpha = 0.3;
$n = getNumDays();
$v=0;
for($i=$n-1;$i>=0;$i--) {
$range = getHigh($i)-getLow($i);
if($range<1e-6) {
$w=0.5;
} else {
$w = (getHigh($i) - getOpen($i) + getClose($i) - getLow($i) )/2/$range;
}
if($i == $n-1) {
$v = $w;
} else {
$v = (1-$alpha)*$w +$alpha*$v;
}
}
return $v;
}
Let us take this apart and see how it works.
sub ComputeADOscillator1 {
This line declares a new indicator ComputeADOscillator1. For VB users, please consult corresponding example code provided in studylib.vbs.
my($v,$w,$range,$alpha,$i,$n);
This line declares that there are variables $v, $w, $range, $alpha, $i, and $n which will be used in this indicator. If I forget to declare all of my variables, then I can get incorrect values based on someone else using the same name for a different purpose. A variable is a place holder. $alpha, for example, will be used to hold the parameter 0.3. Whenever I use $alpha, the program will automatically substitute the value 0.3.
The lines
$alpha = 0.3;
$n = getNumDays();
set the variables $alpha to be 0.3 and the variable $n to be the number of days of data for the stock in question.
The statement
$v=0;
tells the program to initially set $v to be zero. It will hold the current value of the exponential moving average.
for($i=$n-1;$i>=0;$i--) {
Tells the program to start with $i being the value $n-1(the earliest day on file) and repeat the following steps through 0 (the current day.)
$range = getHigh($i)-getLow($i);
For each day, we compute the $range as the high minus the low.
if($range<1e-6) {
$w=0.5;
} else {
$w = (getHigh($i) - getOpen($i) + getClose($i) - getLow($i) )/2/$range;
}
If there was no trading, then $w is assigned the neutral value of 1/2. If there was trading, then $w is given the by the buying power selling power scaled by the range.
All we have left to do is the exponential moving average
if($i == $n-1) {
$v = $w;
} else {
$v = (1-$alpha)*$w +$alpha*$v;
}
We first check to see if this is the first day on file. If it is, then we set the average to be the only value. From there on we average each day's value with the previous day's average.
}
The closing curly bracket tells the program that these are all the statements to repeat for each day on file.
The remaining lines
return $v;
}
tell the program that the value to display for the indicator is stored in $v and that the scan is complete.
This is a one-day-at-a-time method. For each day, we compute all corresponding values, and then proceed to the next day. When we are all done, we return the current day.
Explaining to the computer how to compute an exponential moving average every time you want to write an indicator is a bit tedious, so the next two examples demonstrate ways to get around it.
See Study Example 2 for more information.