{
Function: _StdDevMean (Standard Deviation )
Purpose: Calculate the mean and standard deviation in single function using an alternative
algorithm to calculation standard deviation described in Wikipedia.
Discussion: The TS standard deviation functions do not ouput the mean used in calculating the
standard deviation. Therefore, in many custom routines that use both mean and
standard deviation, such as Bollinger Bands and Z-Score, there is duplication of
the mean calculation.
This routine returns both the mean and the standard deviation in a single function
and therefore avoids the necessity of performing a repeat calculation of the mean.
Source: Casey (TS forums) found this method, described in Wikipedia. Goose improved the
code and created a single version that would permit Length to vary.
Author: MarkSanDiego
Updated: 08/28/08 original version
02/19/09 alternative method of calculating standard deviation implemented
02/21/09 documentation improved
09/13/09 code cleaned
04/06/10 made Divisor intrabarpersist, since may be initialized during BarStatus(1) <> 2
Usage: Put the following in the calling routine:
_______________________________________________________________________________________________________________
inputs:
Price(Close),
Length(100), // length used to measure average and standard deviation
DataType(1), // = 1 for Variance and standard deviation of entire population;
// = 2 for Variance and standard deviation of sample of population
vars:
oMean(0), // average price; oAvg = Average(Price, Length)
oStdDev(0); // standard deviation of price; oSD = StandardDev(Price, Length)
Usage:
value1 = _StdDevMeanFC(Price, Length, DataType, oMean, oStdDev);
_______________________________________________________________________________________________________________
}
inputs:
Price(NumericSeries),
Length(NumericSimple), { length used to measure average and standard deviation (MUST BE >= 2 but MAY VARY) }
{ Numeric or NumericSeries required if Length is allowed to vary }
DataType(NumericSimple), { = 1 for Variance and standard deviation of entire population; }
{ = 2 for Variance and standard deviation of sample of population }
{ outputs: }
oMean(NumericRef), { average price; oMean = Average(Price, Length) }
oStdDev(NumericRef); { standard deviation of price series; oSD = StandardDev(Price), Length) }
variables:
j(0),
x(0),
LastLength(0), { Length used in prior function call. Allows avoiding using Length[1], which is slower. }
rLen(0), { inverse of Length. Multiplication executes slightly faster than division }
intrabarpersist Divisor(0), { divisor used for variance of entire/sample population }
{ must be intrabarpersist since initialization may occur when BarStatus(1) <> 2 }
Sum(0), { sum used to calculate Mean }
SumSq(0), { sum of squares of (Price - oMean) }
MeanSq(0);
{ INLINE CODE STARTS HERE: Function _StdDevMean }
{ uncomment this section when extrcting this function for in-line code }
{
inputs:
Price(Close),
Length(20), { length used to measure average and standard deviation }
DataType(1); { = 1 for Variance and standard deviation of entire population; }
{ = 2 for Variance and standard deviation of sample of population }
vars:
Divisor(0),
rDiv(0),
Sum(0),
SumSq(0),
rLen(0),
MeanSq(0),
oMean(0), { average price; oAvg = Average(Price, Length) }
oStdDev(0); { standard deviation of price; oSD = StandardDev(Price, Length) }
}
once begin
{ adjust Divisor according to DataType and validate }
switch DataType begin
case 1:
{ StdDev of entire population requires Length >= 1 }
Divisor = Length;
case 2:
if Length < 2 then RaiseRunTimeError("_StdDevMean: StdDev of sample of population requires Length >= 2");
Divisor = Length - 1;
default:
RaiseRunTimeError("_StdDevMean: DataType must be 1 (Population) or 2 (Sample)");
end;
end;
If Length > 0 then begin
if Length <> LastLength then begin
rLen = 1 / Divisor;
Sum = 0;
SumSq = 0;
for j = 0 to Length - 1 begin
x = Price[j];
Sum = Sum + x ;
SumSq = SumSq + x * x;
end;
LastLength = Length;
end else begin
x = Price[Length];
Sum = Sum + Price - x ;
SumSq = SumSq + Price * Price - x * x;
end;
oMean = Sum * rLen;
MeanSq = SumSq * rLen;
x = MeanSq - oMean * oMean;
if x > 0 then
oStdDev = SquareRoot( x )
else
oStdDev = 0;
{ INLINE CODE STOPS HERE }
_StdDevMean = oStdDev;
{ Length < 1 results in no calculation being done. This avoids testing for Length > 1 before calling function }
end else begin
oMean = 0;
oStdDev = 0;
_StdDevMean = 0;
end;